跳到主要内容

把一篇论文的规范优先协议拆开跑了一遍

abanana
abanana

· 阅读约 4 分钟

今天在做的事有点特别:前几天刷到一篇 Joel Abenhaim 写的论文,讲的是在无人工代码审查、无预定义测试预言的条件下,让 AI 编码代理靠“规范优先”协议完成了一次大规模架构重构。对象是一个 3,648 个文件、717,725 行代码的生产环境 TypeScript 应用。我第一反应是“这吹得有点大”,第二反应是老规矩——拆开看看,光读结论没用,挑协议里能上手的部分自己跑一遍才算读过。

先把论文里最核心的那个任务说清楚,因为它的难度决定了后面所有数字的意义。任务是拆掉一个核心生命周期不变量:原来系统保证 UI 面板在 AI 请求期间保持打开,目标改成流式生成在面板关闭后仍能存活,重新打开时还要无丢失、无重复地重新附加到同一条实时流。作者自己的评估是,这个变更靠增量重构实际上不可行,传统上得重写。也就是说这不是“让 agent 改个函数”级别的玩具任务。

协议的骨架是这样的,我按执行顺序列出来:

  1. 代理先写出形式化规范;
  2. 14 轮针对源代码审计规范的精化循环;
  3. 原子化实施,配合编译/测试反馈循环;
  4. 冻结规范,再跑 17 轮针对规范审计代码的验证循环。

收敛标准是经验性的:连续两次验证通过且零发现。这条我原样抄进了自己的实验笔记里:

# 收敛判据(照抄论文)
consecutive_clean_audits >= 2 && findings == 0

当然我没有 71 万行的生产应用可以拿来做实验,这个得先老实交代。我做的是把协议的形状搬到自己手头一个小改动上试:先让代理把“改完之后系统应该满足什么”写成一份规范文档,再让它拿这份规范去对着源码挑毛病,改一轮、审一轮。prompt 大概长这样:

这是当前源码的关键部分:<files>
这是你上一轮写的规范:<spec>
逐条对照,指出规范与代码行为不一致的地方,只报告,不修改。

跑下来的体感是:精化循环这一步的价值比我预想的大。第一轮生成的规范看着挺像回事,第二轮对着源码一审就露馅了——好几个它自己写下的保证,代码里根本不成立。论文里 14 轮精化加 17 轮验证,31 次审计通过里纠正了 201 个缺陷,而且全部发生在任何人类执行程序之前。这个“之前”是我觉得整篇论文最值得划线的地方:人不是守门员,人是最后一步。

变更的规模也贴一下:189 个文件被改动,其中 31 个是新文件;把提取阶段算进去,两次提交共涉及 288 个文件,插入 34,770 行,删除 16,422 行。整个流程三天,2,430 美元。第一次会话加上其后约三十次会话,行为符合规范,没观察到 bug。我拿自己那个小实验对照了一下量级,就明白为什么作者说增量重构不可行了——这种改动量摊在“改一点测一点”的节奏里,人先累垮。

有一个坑我自己差点踩,顺手记一下。我一开始把“冻结规范”这步理解成了走形式,想着反正后面还能改。后来才想明白,验证循环审计的是“代码 vs 规范”的一致性,规范要是还在漂移,这个审计就没有锚点,等于白跑。论文把规范冻结放在实施之后、验证之前,顺序是反不得的。我自己的小实验里没冻结规范的那一版,验证循环跑了三轮还在原地打转,冻住之后两轮就收敛了——样本很小,不敢说证明了什么,但至少和论文的顺序对上了。

说句题外话,这篇论文让我比较信服的不是结果数字,是证据的给法:完整规范和原始会话日志全部公开,超过 1,500 页,法语写的,既供人检查过程,也直接提交给语言模型做一致性检查。拿日志喂回模型查一致性这个用法我之前没想过,记下来了,下次审自己的长会话应该用得上。论文本身 8 月 12 日提交第一版,8 月 15 日出了第二版,14 页,4 图 3 表。

划重点:第一,规范优先的实质是把“人审代码”换成“代理审规范、再审代码”,人只在最后介入;第二,冻结规范这一步是验证循环的锚点,不能省;第三,收敛标准可以很朴素,连续两次零发现就够,不需要更玄的东西;第四,判断这类案例可不可信,先看原始日志给不给——给了的,值得花时间拆。这篇就记到这里,你可以挑自己手头一个中等规模的改动,把规范先行的顺序试一遍,哪怕只跑两轮精化,体感也会和直接让它写代码完全不同。

abanana
abanana

把自己踩过的坑整理成一篇能复现的笔记,写给三个月前的自己看。

查看主页 →