跳到主要内容

AI 代码审查漂移:当你的 LLM 审查标准比代码演进得还快

· 阅读需 10 分钟
Tian Pan
Software Engineer

PR 审查仪表盘连续六周显示绿色。机器人捕获率、评论量、开发者的“点赞”反应——一切都很稳定。然后生产环境发生了一起安全事故,事后分析指向一个缺失的空值检查(null-check),而这个检查机器人以前是能捕获到的,大约在两个月前悄然停止了。没有人更改机器人。没有人降级模型。仪表盘从未变动。但标准变了。

这是自动化代码审查在任何产品演示中都不会出现的失效模式。团队采用 LLM 审查器是为了获得一致性——每个 PR 都遵循相同的检查清单,没有资深工程师因“心情不好”而产生的波动,初级贡献者的周转速度也很快——这种一致性在最初的一个季度确实存在。然后系统提示词(system prompt)演变了,模型升级了,few-shot 库积累了,机器人开始使用不同于团队验证时的模型,根据不同的准则来审查不同的代码库。团队对“机器人能捕获什么”的心理模型衰退成了“机器人上周捕获了什么”。

审查器并非单一制品

人们很容易将 LLM 代码审查器视为一个单一的整体:即机器人。但在实践中,它是一系列独立漂移的组件栈,其中任何一个组件都可能在没有发布说明的情况下改变标准。

系统提示词是第一个层面。大多数团队每周都会对其进行迭代。在一位开发者抱怨评论内容太长后,有人添加了“更简洁一些”。在一次险些酿成大祸的事件后,有人添加了“标记缺失的测试”。有人删除了关于代码风格的条款,因为 linter 现在可以处理它了。每次修改都是一个局部合理的微小变化。其总和就是一个两个月内没有人完整读过的准则。

模型是第二个层面。提供商的权重更新现在已成常规——OpenAI、Anthropic 和 Google 都在同一个模型 ID 下发布影响行为的更新,而无需更改版本字符串。即使是固定的快照(pinned snapshots)也不是真正固定的:安全过滤器会更新,解码参数会改变,像 claude-sonnetgpt-5 这样的别名会在提供商滚动新快照时自动升级。别名的订阅者所经历的每一次微小变化,都是一次既没有公告也没有分阶段发布的生产部署。

Few-shot 示例是第三个层面。在权限事故之后,有人添加了一个完美的“抓得好”示例。在一位开发者对琐碎建议(nit)表示反对后,有人添加了一个“不要标记这种风格”的示例。示例对行为的影响比指令更具侵略性,而且它们通常被检入到与系统提示词不同的文件中——或者更糟,被录入到不会在代码审查中产生 diff 的配置 UI 中。

检索增强上下文(RAG)是第四个层面。现代审查机器人会拉取仓库惯例、过去的 PR 决策和代码所有者的偏好。检索索引每晚重建。惯例文档上周二被编辑过。机器人的行为在周三发生了变化。

团队用来验证机器人的评估集(eval set)是第五个层面。评估集本身也在漂移,因为维护它的团队正是标准在发生变化的那个团队。你不能用一把正在变动的尺子来检测这把尺子是否在变动。

捕获率是错误的北极星指标

大多数 AI 代码审查工具的公开基准测试只报告一个核心数字:捕获到的预埋 Bug 百分比。最近的独立评估显示,领先者处于 50–80% 的范围内,其中 Greptile 约为 82%,Bugbot 和 Copilot 在 50% 左右,CodeRabbit 为 44%,而 Graphite 的捕获率较低,但信噪比较高。这些数字每隔几个月就会变动。

那个没有出现在基准测试页面上的数字是二阶导数:自上次机器人更新以来,捕获率变化了多少,以及变化集中在哪些类别?一个平均能捕获 80% Bug 的机器人,可能在空指针问题上捕获率达 95%,而在授权问题上仅为 40%,而一次模型升级可能会翻转这些数字,却不改变总体的捕获率。仅监控核心数字的团队看到的是一条平线。而监控每个类别捕获率的团队,会在事故发生前两周看到授权问题的捕获率崩溃。

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates