给 AI 文档中的行为承诺加一道人工审核
文章提出在 PR 中扫描模型生成文档里的保证性语句,要求人工逐条确认并关联证据。实现由约 80 行 Python 和两个文件组成,补足链接、拼写检查无法验证行为承诺的缺口。
AI 深度解读
AI 可以代写操作步骤,但文档里的「保证不会丢数据」「支持幂等重试」,应该由谁负责?作者提出了一套很小的审查流程:用规则找出承诺行为的句子,再要求人工提供证据并签认,缺少签认就阻止合并。
它值得读的地方,是把 AI 文档审查缩小到一个明确对象:哪些话会让用户据此作出技术决策。不过,这个检查器只能识别部分承诺,也只能确认部分证据条件,离「保证文档正确」还有距离。
审查单位为什么要从段落缩小到句子
作者的核心主张是:模型负责流程说明,人负责行为承诺,检查器负责把需要负责的句子挑出来。
一个章节即使有 90% 都在讲操作步骤,也可能夹着一句「上传是原子的」。原子性(atomicity)在这里指对象不会以只写了一部分的状态被用户看到。这句话会影响调用方的异常处理和一致性设计,不能因为整段读起来通顺就放行。
因此,作者建议先在仓库里写清模型能够修改哪些内容、哪些承诺必须由人负责,并将其作为审查规则。涉及安全状态或金钱的内容,作者要求完全交给人。至于「团队如果不能在 15 分钟内达成一致,就还没准备好使用模型写文档」,这是作者的管理判断,没有实验数据支撑。
接下来,把 Markdown 正文改成一句一行,命令和输出放进围栏代码块,不要按固定宽度硬折行。渲染后的段落可以保持原样,源码里的差异却更容易定位。
例如,Run 开头、要求执行 mk upload ./dist 并等待输出 done 的句子是操作步骤;「上传是原子的」和「相同请求标识下重试是幂等的」则需要审查。幂等(idempotent)指重复请求不会产生额外的重复效果,但这类承诺通常还需要明确适用条件。
值得签认的是会影响用户判断的承诺句,而不只是整篇文档的措辞。
约 80 行 Python,具体拦住什么
作者把方案概括为两个文件、约 80 行 Python:tools/claims.py 负责扫描,docs/claims.signoff.json 负责保存人工签认和证据位置。
扫描器不调用模型,而是维护一份短词表,按命中词分级:
- 3 级表示绝对承诺,包括
always、never、guarantee、guaranteed、zero-downtime。 - 2 级表示属性承诺,包括
safe、safely、atomic、idempotent、supported、compatible、cannot、will not。 - 1 级作为初期可以暂缓处理的提示,包括
instant、fast、secure、only。
下面这段决定一句话的等级:找到所有命中词,取其中最高分。
def score(text):
low = text.lower()
hits = [t for t in LEXICON if re.search(rf"\b{re.escape(t)}\b", low)]
if not hits:
return 0, []
return max(LEXICON[t] for t in hits), hits
要看的是最后一行的 max:同时出现 atomic 和 never,最终就是 3 级,并不累加。
运行入口是 python tools/claims.py docs/*.md --signoff docs/claims.signoff.json。其中 --signoff 指定签认文件,默认也是上述路径;--min-severity 默认是 2,控制阻断门槛;--root 默认是 .,用于解析证据的相对路径。
输出是 JSON,findings 列出文件、行号、等级、命中词、句子指纹、状态和原句,blocked 收集达到门槛却未通过检查的指纹。有阻断项就返回退出码 1,否则返回 0。
状态有三种:没有签认记录是 unsigned,记录中的证据路径不存在是 evidence-missing,通过这两项检查则是 signed。
作者称这种规则检查可以在毫秒级运行,并且重复执行得到一致结果。不过,原文没有提供仓库规模、运行环境或耗时对照;速度属于作者描述,不能当作基准测试结论。
签认怎么跟着句子变化,又会漏掉什么
为了让签认不依赖容易变化的行号,作者给句子计算指纹。这段代码负责建立句子与签认记录之间的对应关系:
def fingerprint(sentence):
norm = re.sub(r"\s+", " ", sentence.lower()).strip()
return hashlib.sha256(norm.encode("utf-8")).hexdigest()[:12]
要看的是归一化那一行:先转小写、合并连续空白,再取 SHA-256 的前 12 个十六进制字符。
原文说任何措辞变化都会产生新指纹,代码实际需要更精确地理解:大小写和空白变化不会触发重新签认,其他文字变化通常会。同一句话出现在不同文件里,也会共用指纹,因为计算没有包含文件路径或上下文。
更大的边界在证据上。程序只调用 .exists() 检查路径存在,没有验证它是否真能证明该承诺,也没有验证签认人的身份,更不会自动执行测试。一份无关文件同样可能满足当前检查。
signed 表示签认记录和证据路径通过了检查,不等于行为已经得到验证。
原文末尾把 MonkeyCode 的免费模型用于起草、免费服务器用于夜间复查,但内容随后截断,没有展开所谓第 5 步。这部分不能据此推导成已经验证过的部署方案。另外,提供的代码中 FENCE 正则出现了断行异常,直接复制前需要修复。
我的判断
我认可它把审查注意力集中到「承诺」上的思路。链接、拼写、风格检查都无法证明上传具备原子性;对关键句要求证据,确实补上了不同的一层检查。
和再用一个模型做语义审查相比,短词表容易读懂,触发原因固定,接入成本也小。但它依赖英文词汇,无法直接覆盖中文文档,还会漏掉没有关键词的承诺,例如「失败后数据保持原样」。反过来,普通说明里出现 only,也未必值得单独签认。
规则的优先级同样需要团队重定。作者要求安全内容由人负责,却将 secure 放在默认不阻断的 1 级;如果只部署脚本,不执行前面的人工分工规则,安全承诺仍可能漏过。
因此,这更适合作为人工审查的提醒机制。作者没有提供漏报率、误报率或与人工审查的对照数据,效果仍是经验之谈。行为测试也不能被替代:测试负责验证某些条件下的行为,签认负责解释文档为什么有资格作出这个承诺。
能拿来做什么
- 给 Node SDK 或接口文档划定一份承诺清单,优先检查重试幂等性、兼容范围和失败后的数据状态,并要求审查者指向相关测试或规范。
- 在 AI 编写 Markdown 的约定里加入一句一行、命令进入围栏代码块,让承诺句更容易定位,后续修改也更容易复核。
- 接入 CI 时先观察
findings,调整适合仓库语言的词表,再用--min-severity 2阻断缺少签认或证据路径失效的条目。 - 审查
signed条目时继续核对证据内容和适用条件;如果多份文档共享同一句话,还要确认它们的上下文是否允许共用签认。