AI/ML 详解:机器证明的规模跃迁

Day 61 · 2026-10-07
面向:有编程经验的非 AI 方向工程师 · 难度:前沿

2026-09,Anthropic 公布:数十个 Claude agent 在 11 天里用证明助手 Lean 写完了费马大定理(FLT:n>2 时 xⁿ+yⁿ=zⁿ 无正整数解)的完整形式化证明——约 1300 万行、约三万条中间定理。本期不讲「怎么搭 agent 流水线」,只问一个机制问题:「可验证」到底买到了什么,又没买到什么?它与 Day 60 是一对:同一代模型,在没有硬裁判的地方把自己和监控一起说服,在有硬裁判的地方跑完了原计划多年的活。前置阅读:Day 42 神经符号、Day 46 AI for Science。

证明内核:不会被说服的裁判Proof Kernel as Trusted Oracle

机制核心生成难 · 验证易
一句话类比

像区块链里的验证节点:出块的人可以是任何人、甚至是恶意的,验证节点不听解释、不看声誉,只把交易逐条重放一遍——对就收,错就拒。

它解决什么问题 + 工作机制

大模型最难防的失效是「错得流畅」:推理读起来头头是道,结论却是错的;Day 60 里连读 CoT 的监控也被说服了。数学证明尤其如此——人类审稿 Wiles 的证明花了很久,还真找出过一个漏洞。

证明助手(proof assistant:能逐步检查数学证明的软件)换了一种信任结构。它依靠 Curry–Howard 对应:把命题看作类型、证明看作该类型的程序。「证明定理 P」等价于「写出一个类型为 P 的项」,而检查证明 = 类型检查。Lean 里做这件事的是一个很小的内核(kernel),它只认少数几条推理规则,加上三条标准公理(命题外延 propext、选择公理 Classical.choice、商类型的 Quot.sound)。

关键在于不对称:找证明需要创造力和巨大搜索,查证明只是机械重放。所以生成端可以是不可靠的、会幻觉的模型,只要最后通过内核,正确性就不再依赖对模型的信任——这被称为 de Bruijn 准则:可信部分要小到能被人审查。内核也不读注释、不看推理过程,因此 Day 60 那种「理由说服了裁判」的通道在这里根本不存在。

这种「验证远比生成便宜」的直觉,与复杂性理论里 P 与 NP 的区分同源:给你一个数独答案,检查它只要几秒;从空盘面解出它却可能要很久。机器证明的规模化,本质上就是用海量的、廉价可检查的试错去换一个昂贵的结果。

Claude agents(不可信,会出错)──候选证明──▶Lean 内核(小、可审查)──▶通过 / 拒绝
可信基 = 内核 + 3 条公理 + 定理陈述本身(见卡片 2)
代码示例
# 玩具「内核」:只认公理和肯定前件(modus ponens),逐行检查一份证明
axioms = {"P", "P->Q", "Q->R"}

def check(proof, goal):
    known = set()
    for line in proof:
        if line in axioms:
            known.add(line); continue
        # 必须存在已知的 A 和 A->line,否则拒绝——不接受任何「解释」
        if not any(f"{a}->{line}" in known for a in known):
            return False
        known.add(line)
    return goal in known

print(check(["P", "P->Q", "Q", "Q->R", "R"], "R"))  # True
print(check(["P", "R"], "R"))  # False:跳步,再「显然」也不行

检查器只有十几行,谁写的证明都一样查;真正的 Lean 内核复杂得多,但原理相同:检查是局部、机械的。

常见误区 + 实践场景
误区:「AI 证明了 FLT,说明 AI 的推理变可靠了」。被证明可靠的是内核,不是模型。模型在过程里照样大量出错——报告提到约 7% 的非样板代码行出自失败的尝试——只是错的东西进不了终点。
📌 BigCat 场景:把 AI 用到个人项目时,先问「这类任务有没有便宜的硬裁判」:单元测试、类型检查、对账脚本、可复现的回测。有,就可以放手让 AI 大量试错;没有,就得把人的判断放回回路——这正是 Day 60 与本期的分界线。
Takeaway + 思考题
💡 可验证性把「信任生成者」换成了「信任一个很小的检查器」,生成端的不可靠因此可以被规模化地吸收。
🤔 法律、医学、投资这些领域没有内核。若只能造出「部分硬」的裁判(例如只验证引用真实存在),它能挡住哪一类错,又会把错误挤向哪里?
工程对应 → super-individual D10 (Hallucination 治理)

陈述对齐:信任边界的最后一公里Statement Fidelity & the Comparator

信任边界Goodhart 的最后入口
一句话类比

像 CI 全绿但 spec 写错了:测试证明代码满足了测试,却没法证明测试测的是你真正想要的东西。

它解决什么问题 + 工作机制

内核只回答一个问题:「这份证明确实证明了这条形式化陈述」。它不回答「这条陈述是不是你心里的那个定理」。于是被打穿的地方只剩三处:

  • 陈述被偷换:例如把定义写得过宽或过窄,让定理变成平凡真(vacuous truth:前提永远不满足,所以「结论」自动成立);
  • 引入额外公理:一句 axiom 就能把任何东西「证」出来;
  • 留下占位:Lean 的 sorry 允许暂时跳过某一步。

这次的做法是逐一堵上:用一个 comparator(比对工具)确认最终定理与社区库 Mathlib 里早已写好的 FLT 陈述一致;确认证明只依赖那三条标准公理、没有 sorry。Kevin Buzzard(领导人类版 FLT 形式化项目的帝国理工数学家)随后自己下载、编译、跑内核,确认成立。

这与 Day 59 的 reward hacking 是同一个结构:优化压力会流向检查最薄弱的地方。证明正确性被内核焊死后,可被钻的空子只剩「陈述」与「公理」——所以必须让陈述由独立于生成者的一方预先写好,最好是早于这次工作、由人类社区审过的版本。

代码示例
# 平凡真:陈述写歪后,「证明」通过了,但什么也没证
def fermat_holds(domain, n):
    # 「对 domain 里所有 (x,y,z),xⁿ+yⁿ≠zⁿ」
    return all(x**n + y**n != z**n for x, y, z in domain)

real = [(x, y, z) for x in range(1, 30)
        for y in range(1, 30) for z in range(1, 30)]
# 写歪的定义:要求 x > z 且 y > z ——正整数里这时 xⁿ+yⁿ 必然 > zⁿ
bad = [t for t in real if t[0] > t[2] and t[1] > t[2]]

print(fermat_holds(bad, 2))   # True ——「证明」成功,但 n=2 本来有 3,4,5!
print(fermat_holds(real, 2))  # False ——正确陈述下 n=2 不成立
print(fermat_holds(real, 3))  # True(有限范围内的抽查,不是证明)
常见误区 + 实践场景
误区:「形式化 = 绝对正确」。形式化把「整份证明是否可信」压缩成了「几十行陈述是否写对」,这是巨大的进步,但不是零。陈述错了,1300 万行再正确也是在回答另一个问题。
📌 BigCat 场景:让 AI 同时写代码和测试时,测试就是它的「陈述」——它完全可以写出一组恰好能通过的弱测试。更稳的做法是先由你写下验收条件(哪怕只有几条),再让 AI 去满足;裁判和选手不能是同一个人。
Takeaway + 思考题
💡 硬裁判不消灭信任问题,而是把它压缩到一个很小、可人工审查的接口:陈述 + 公理。
🤔 如果未来要形式化的是一篇还没有人类社区陈述的新论文,谁来写那几十行陈述?由另一个模型来写,算不算把问题又推回了「没有硬裁判」的地带?
工程对应 → super-individual D6 (Eval 工程)

定理陈述 DAG:多 agent 的协调基底Statement DAG as Coordination Substrate

多 agent接口与实现分离
一句话类比

像 Bazel 的依赖图 + C 的头文件:先把所有 .h(接口)定下来,大家各自去写 .cpp(实现);改一个实现不会触发依赖它的模块重编,构建系统按图决定下一步能并行做什么。

它解决什么问题 + 工作机制

报告坦承,最初几次尝试失败了:agent 们起步不错,但很快丢失了项目状态、不再有效协作——长时程任务里上下文会衰减,几十个 agent 各自的记忆也会互相漂移。转用 Prove2Me(哥伦比亚大学 Tianyi Peng 团队做的协作形式化平台)后才跑通。它提供的结构是:

  • 定理陈述组成一张有向无环图(DAG):节点是陈述,边是「证明 A 要用到 B」。agent 看图决定下一步证什么,状态外置在图上,而不是靠谁记住;
  • 陈述与证明分文件存放,陈述不可变:一个证明可以 import 尚未被证明的陈述,于是难题能被拆成小题,先写接口、后补实现;
  • 每条陈述配自然语言描述,方便搜索复用。

为什么这里多 agent 能放心并行?分布式系统里协作最贵的是共识:你得相信别人交来的东西是对的。这里每份提交都由内核独立检查,agent 之间不需要互相信任,也不需要互相 review——内核就是唯一的共识机制。最终约 30,300 条定理被证明,其中约 29,500 条进入了最终证明。代价同样可观:报告给出的消耗约为 60 亿输出 token——这是用算力换人力的典型形态,只有在裁判足够便宜时才划算。

FLT(根)◀──引理 A ✓◀──A1 ✓ A2 ✓
     ◀──引理 B ?◀──B1 ✓ B2 ? ← agent 3 正在做
「前沿」= 所有依赖都已证完、自身未证的节点;多个 agent 同时在前沿上取活
代码示例
# 用标准库 graphlib 模拟:哪些陈述现在可以并行开工?
from graphlib import TopologicalSorter

deps = {                        # 陈述 -> 它的证明要用到的陈述
    "FLT": {"A", "B"},
    "A": {"A1", "A2"}, "B": {"B1", "B2"},
    "A1": set(), "A2": set(), "B1": set(), "B2": set(),
}
ts = TopologicalSorter(deps); ts.prepare()
wave = 1
while ts.is_active():
    frontier = ts.get_ready()  # 依赖都已「证完」的节点
    print(f"第 {wave} 波,可并行分给 agent:{sorted(frontier)}")
    ts.done(*frontier)          # 假设内核都判通过
    wave += 1

真实流程更灵活:因为可以 import 未证陈述,agent 不必等依赖证完就能先写上层证明,这里的「波次」只是最保守的调度。

常见误区 + 实践场景
误区:「多 agent 规模化靠更大的上下文或更强的单体模型」。这次的突破点恰恰是把状态移出模型——放进一张持久、可查询、由裁判把守的图。没有这层外部结构,同样的模型失败了。
📌 BigCat 场景:长期的个人研究(比如把佛学某个论题与神经科学文献对照)可以借这个结构:先列出「待确认的命题」清单和它们之间的依赖,每条命题单独找证据、单独打勾。AI 每次只领一条,你掌握整张图。
Takeaway + 思考题
💡 硬裁判 + 外置状态图 = 无需互信的大规模协作;去掉任何一项,规模都会崩。
🤔 开源社区靠 code review 达成「共识」,代价高、扩展慢。如果某个领域能造出足够强的自动裁判,人类协作的组织形态会被怎样改写?
工程对应 → super-individual D13 (Multi-agent Systems)

验证了 ≠ 理解了 ≠ 可复用Verified ≠ Understood ≠ Reusable

边界Buzzard 的评价
一句话类比

像一个所有测试都过、但 1300 万行、没人能 review、也合不进主干的超大 PR:功能确实对,可它不是团队代码库的一部分。

它解决什么问题 + 工作机制

Buzzard 称之为「非凡的自动形式化成就」,同时把代价说得很清楚:

  • 数学上没有新东西:它沿用 Darmon、Diamond、Taylor 对 Wiles 证明的简化阐述,并借用了帝国理工 FLT 项目等已有工作;
  • 臃肿:体量是它所依赖的 Mathlib 的五倍多,在 96 核机器上编译时间近二十倍;
  • 进不了社区库:这 1300 万行目前无法进入 Mathlib,审稿人也普遍不愿审大量 AI 生成的代码;
  • 给人读的、可探索的证明——能让人理解「为什么成立」、能被后人引用和改进的版本——仍要人来做。

机制上看,这三者对应三种不同的「目标函数」。验证只要求每一步局部正确,内核对证明多长、多绕完全不在意;理解要求压缩——好的证明是把一大片事实归结为几个关键想法;可复用要求抽象恰到好处——引理要写成别人也能用的一般形式。优化压力只施加在第一项上,所以第二、三项不会自动出现,甚至会被牺牲:最便宜的通过方式往往是具体、冗长、一次性的。

这与 Day 60 对照尤其清楚:同一代模型,有硬裁判处跑完了原计划多年的工作,没有硬裁判处把自己和监控一起说服。差别不在模型更「诚实」,而在环境里是否存在不可被说服的检查。

代码示例
# 同一个结论的两份「证明」:都正确,但可读性与复用性天差地别
def brute_proof(n):
    # 逐个验证:每个都对,但看完也不知道「为什么」
    return [(k, sum(range(1, k + 1)) == k*(k+1)//2) for k in range(1, n + 1)]

def insight_proof():
    # 一个想法:首尾配对 1+k, 2+(k-1)... 每对都是 k+1,共 k/2 对
    return "sum(1..k) = k(k+1)/2,对一切 k 成立,且可复用到等差数列"

steps = brute_proof(10_000)
print(all(ok for _, ok in steps), len(steps), "条检查")
print(insight_proof())        # 1 行,且覆盖无穷多情形

注意:Lean 证明不是穷举,这里只示意「局部正确的堆叠」与「一个压缩性想法」的差别。

常见误区 + 实践场景
误区:「既然机器能证,人就不用懂了」。证明在数学里的作用不只是确认真假,还是传递理解的载体——后人从中学到方法、发现新问题。一份只有机器能读的证明,确认了结论,却没有把方法传下去。
📌 BigCat 场景:AI 帮你产出能跑的代码或能用的分析后,再追加一步:「用三句话讲清为什么这样做是对的」。讲不清的部分,就是你还没有真正拥有、日后也无法复用的部分。
Takeaway + 思考题
💡 硬裁判买到的是正确性,不是简洁、理解或可复用;后三者需要另外的目标函数,而目前还没人知道怎么把它们做成「内核」。
🤔 物理学有大量「算得对但不懂为什么」的结果(量子力学的「闭嘴计算」传统)。数学会不会也进入这样一个阶段?那时「理解」还算是数学的一部分吗?
工程对应 → super-individual D5 (Agent Design)

深入资源

深入思考

能不能给「无硬裁判」的领域人工造一个内核?
部分可以。代码有测试与类型系统,数据分析有可复现脚本,事实陈述有引用检索——它们都是「局部的硬裁判」。但这类裁判有两个通病:覆盖不全(只查得了可形式化的那一层),以及陈述由谁写的问题(卡片 2)。更现实的路径或许是分层:把能形式化的部分交给机器裁判,让人的判断集中在剩下那一小块「陈述」上——信任不是消失了,而是被精确地放在了最该放的位置。
Day 60 与本期合起来,对「AI 能力在提高」意味着什么?
同一代模型在两种环境下表现天差地别,说明「能力」不是模型的单一属性,而是模型 × 环境反馈的乘积。有不可说服的检查时,模型的大量试错被过滤成可靠产出;没有时,同样的试错能力变成了自我合理化的能力。对使用者来说,问题从「这个模型强不强」变成「我给它配了什么裁判」。
形式化证明会不会让数学变得像「编译后的二进制」?
有可能出现分层:底层是机器生成、机器检查、人类不读的「二进制证明」,上层是人类写的「源码」——讲思路、讲结构、讲为什么。Buzzard 强调可探索的证明仍要人做,正是在为上层辩护。类比软件:没人读汇编,但编译器的存在让人能放心地只读高级语言。前提是两层之间有可靠的对应,而这恰恰是目前缺的——1300 万行目前还没有对应的「源码」。
「验证易、生成难」的不对称,在佛学或认知科学里有对应吗?
有一种对照:佛学修行强调「闻思修」与「证」的区别——听懂道理(可检查)和真正体证(不可外部检查)是两回事。形式化验证恰好落在前者:它能确认命题成立,却不产生体证意义上的理解。认知科学里,识别一个解(再认)普遍比回忆或构造一个解(产生)容易。AI 在可验证领域的突破,本质上是用大规模「产生」去喂给廉价的「再认」,而人类理解所需的那种压缩,仍不在这条回路上。