本章你将学到
- 评审 Agent(review agent)的设计——通用评审与专项评审(安全、架构、性能)的分工;
- LLM-as-Judge 模式:评分标准(rubric)如何设计、如何校准、如何控制偏差;
- 语义级检测:那些计算型传感器抓不到的问题——语义重复代码、冗余测试、过度设计;
- 非确定性管理三件套:评审模型与生成模型分离、多次采样与多数表决、置信度分层;
- 成本控制策略:抽样评审、增量评审、按风险分级触发;
- 信任校准的核心问题——一个概率性的传感器,究竟到什么程度才能据此自动合并。
用 AI 检查 AI,可行吗?
第 11 章讲的计算型传感器有一个共同的天花板:只能捕获"有确定判据"的问题。 但软件质量里有一大片没有确定判据的地带——命名是否清晰、抽象是否得当、有没有过度设计、这段代码是不是"AI slop"、这个改动符不符合团队品味。这些是第 10 章可靠性分级里的第二级"概率捕获",只能靠推理型传感器来捕获。
推理型传感器的核心,就是"用 AI 检查 AI"——让一个 LLM(或一个专门的评审 Agent)去审查另一个 Agent 的产出。这立刻带来一个尖锐的矛盾:
一个本身就是非确定性的传感器,如何产生可依赖的信号?
这正是本章要贯穿回答的问题。答案不是"能"或"不能",而是**"在什么边界内、用什么手段,能把它的信号驯服到可用"**。OpenAI 的实践给了明确参照:他们让 Agent 之间互相评审、跑专门的安全 Agent(如 Aardvark),同时始终把"需要判断"的最终决定留给人类。本章把这套"驯服非确定性"的方法讲透。
本章源级:本章为 B 级。OpenAI 案例明确记载了"Agent 评审 Agent""安全 Agent(Aardvark)""人类只在需判断时介入"等事实(A 级);但评分标准设计、多数表决、置信度分层、信任校准等具体方法,是本书对通用工程实践的框架化整理(B 级),凡属归纳处如实标注。
12.1 评审 Agent 的设计:通用 vs 专项
让 Agent 做评审,第一个设计决策是:用一个"全能评审员",还是用一组"专科医生"? 答案几乎总是后者。
原因和第 2 章讲的上下文限制一脉相承:一个被要求"同时检查架构、安全、性能、命名、测试充分性……"的评审 Agent,注意力会被稀释,每一项都查得浅(这正是第 6 章"过度指导等于没有指导"在评审侧的翻版)。更有效的做法是把评审拆成专项:
- 通用评审:检查基础问题——可读性、命名、明显的逻辑错误、有无"slop"。作为第一道普查。
- 安全专项评审:只盯安全——注入、鉴权缺失、密钥硬编码、危险 API。OpenAI 的 Aardvark 就是这样一个专门的安全 Agent。
- 架构专项评审:只看这次改动是否符合架构意图(第 19 章)——分层是否被打破、抽象是否合理。注意:能被结构测试机械化捕获的,应下沉到第 11 章的计算型传感器;这里评审的是那些无法机械判定的架构品味。
- 性能专项评审:只看有无明显的性能反模式——N+1 查询、不必要的全表扫描、热路径上的重复计算。
每个专项评审 Agent 都有聚焦的上下文和明确的检查清单(这份清单本身就是一个 Skill,第 8 章)。专科化让每个评审员在自己的领域查得更深、误报更少。可以把这套分工列成一张对照表:
| 评审类型 | 聚焦对象 | 典型检查项 | 部署强度 |
|---|---|---|---|
| 通用评审 | 基础质量 | 可读性、命名、明显逻辑错误、slop | 每个 PR 都跑(轻量) |
| 安全专项 | 攻击面 | 注入、鉴权缺失、密钥硬编码、危险 API | 触碰敏感路径必跑 |
| 架构专项 | 结构意图 | 分层是否被打破、抽象是否合理(机械可判定的下沉到结构测试) | 改动核心模块时跑 |
| 性能专项 | 热路径 | N+1 查询、全表扫描、热路径重复计算 | 改动数据访问/循环时跑 |
这张表也顺带回答了一个常见困惑:专项不是越多越好。每加一个专项评审都要花模型调用的成本(§12.5),因此专项的粒度应当与你项目真实的失效分布匹配——把评审预算投在"最常出问题、且出问题代价最高"的少数几个维度上,而不是机械地为每个质量属性都配一个评审员。
回扣 Harness:专项评审是第 5 章 Ashby 定律的直接应用——用多样化的传感器去匹配多样化的问题。指望一个通用评审员抓住所有类型的问题,等于用单一手段去对抗多样的失效,必然漏网。
12.2 LLM-as-Judge 模式
推理型传感器最常见的形态,是 LLM-as-Judge(把 LLM 当裁判):给模型一段产出和一套标准,让它输出"是否合格 / 评分 / 问题列表"。要让这个裁判可用,关键在三件事:评分标准、校准、偏差控制。
评分标准(Rubric)设计
绝不能只问"这段代码好不好"——这种开放式提问会得到飘忽不定、无法复现的答案。必须给出结构化的评分标准(rubric):把"好"拆解成一组可逐条判断的具体维度,每个维度给出明确的档位描述和正反例。
- 差的提问:"评价这段代码的质量。"
- 好的 rubric:"逐项检查:① 命名是否准确反映意图(给 0/1 分并附例);② 是否有未处理的错误路径;③ 是否存在与现有工具重复的手写实现……"
rubric 把一个模糊的整体判断,拆成一组更接近"有判据"的小判断——这是把第二级问题尽量往第一级靠拢的努力。一份可用的 rubric 通常长这样(以"手写工具函数审查"为例):
| 维度 | 0 分(不合格) | 1 分(合格) | 判据说明 |
|---|---|---|---|
| 命名达意 | 名称与实际行为不符/需读实现才懂 | 从名称即可推断意图 | 附一个反例函数名 |
| 重复检测 | 与现有共享工具包功能重叠却手写 | 复用了已有工具或确无可复用者 | 指向应复用的现有 API |
| 错误路径 | 存在未处理的失败分支 | 所有失败路径都有明确处理 | 列出遗漏的分支 |
| 复杂度匹配 | 为简单需求引入多余抽象 | 复杂度与需求相称 | 说明多余在哪 |
每一格都写清"什么算 0、什么算 1、判据是什么",裁判就从"凭感觉打分"变成"逐格对照"——这既提高了可复现性,也让它的判断可被人类复核。rubric 越接近"有判据",裁判的方差越小。
校准(Calibration)
裁判给的分要有意义,就必须校准:用一批人类已经打过分的样本(有好有坏)去测这个裁判,看它的判断和人类是否一致。如果裁判把人类认为差的判成好、或反之,就要调整 rubric 或提示词,直到它的判断与人类基准对齐。没有经过校准的 LLM-as-Judge,其分数不可信。
举个校准的实操:你挑 20 个 PR,其中 10 个人类判过"该打回"、另 10 个"可通过",让裁判逐个判。假设它在"可通过"上全对,却把 10 个"该打回"里的 3 个判成了通过——吻合率 17/20=85%,但更要命的是那 3 个漏放里有一个是安全问题。这时你不会因为 85% 这个总分就满意,而要针对性地在 rubric 里补一条安全维度、或换一个更强的评审模型,再重测,直到漏放(尤其是严重漏放)降到可接受。校准盯的从来不只是总吻合率,更是"往哪个方向错"。
偏差控制
LLM 裁判有一些已知的系统性偏差,必须主动控制:
- 长度偏差:倾向于给更长的答案打更高分——即使长不等于好;
- 位置偏差:在对比两个方案时,倾向于偏好排在前面(或后面)的那个;
- 自我偏好:倾向于偏好和自己生成风格相似的产出(这也是 §12.4 要"评审模型不同于生成模型"的原因之一);
- 谄媚:倾向于附和提示里已表露的倾向。
控制手段包括:打分时要求先给理由再给分(迫使它基于证据)、对比评审时交换位置各评一次、明确在 rubric 里叮嘱"长度不作为评分因素"等。
12.3 语义级检测:抓计算型抓不到的东西
推理型传感器真正不可替代的价值,在于捕获那些语义层面的问题——计算型传感器对它们无能为力,因为它们没有确定的语法判据。三类最典型:
- 语义重复代码:两段代码长得不一样、但做的是同一件事。计算型的重复检测(基于 token/AST 相似度)只能抓"长得像"的复制粘贴,抓不到"语义等价但写法不同"的重复。而这恰恰是 Agent 高发的问题——它常常不知道已有一个工具函数,就又手写了一遍(OpenAI 的"黄金原则"之一正是"优先用共享工具包而非手写辅助函数")。只有理解语义的 LLM 才能识别出"这俩其实是一回事"。
- 冗余测试:Agent 为了凑覆盖率或"多多益善",产出大量测试了同一件事的重复用例,徒增维护负担却不增加实际保障(呼应第 11 章的覆盖率陷阱)。语义评审能识别"这几个测试其实是一个测试"。
- 过度设计:为一个简单需求引入了不必要的抽象层、配置项、泛型、设计模式。这是"意图与实现不匹配"的一种,没有语法判据,只能靠理解意图的评审来识别——它问的是"这个复杂度值得吗",而这需要判断。
这三类问题都是代码熵增的源头(第 23 章"熵管理"),且都无法被计算型传感器捕获。推理型传感器在这里是唯一可行的自动化手段——虽然是概率性的。
12.4 非确定性管理
现在直面本章的核心矛盾:推理型传感器本身是非确定的(同样输入可能给出不同判断)。如何从一个"会飘"的传感器里榨出可依赖的信号?三个手段:
模型选型:评审模型可以且应该不同于生成模型
用和生成代码时不同的模型去评审。理由有二:一是规避 §12.2 的"自我偏好"偏差——一个模型容易觉得自己风格的产出是好的;二是不同模型有不同的知识盲区,换一个模型评审,等于多一双"视角不同的眼睛"(又一次 Ashby 定律:多样性)。让写代码的和审代码的不是同一个"人",这条在人类团队里天经地义的原则,在 Agent 团队里同样成立。
多次采样与多数表决
对同一个产出,让裁判评多次(或让多个裁判各评一次),然后按多数表决取结论。单次判断可能因随机性走偏,但多次判断的多数结果显著更稳定。这是用"重复采样"把非确定性信号的方差压下来的经典手段——代价是成本翻倍(见 §12.5)。
一个直观的例子:让裁判对同一个 PR 独立评 5 次,得到"通过/通过/打回/通过/通过"——4:1,按多数表决判"通过",同时那 1 票"打回"的理由值得作为提示留给人看。但如果 5 次结果是"通过/打回/通过/打回/通过"这种 3:2 的胶着,本身就说明这是个"模型也拿不准"的边界情况——该走下面的"低置信度升级给人",而不是硬按多数表决放行。
置信度分层
不要让裁判只输出"通过/不通过",而要让它输出带置信度的判断,据此分层处理:
- 高置信度通过 → 可进入自动合并候选(§12.6);
- 高置信度拒绝 → 打回 Agent 自纠错(第 10 章回路);
- 低置信度 / 意见分歧 → 升级给人类判断。
置信度分层的意义在于:它把"确定的部分"自动化、把"不确定的部分"老实交给人——这正是第 10 章可靠性分级的落地,防止你把一个概率性判断当成板上钉钉的结论。
还有一条贯穿三个手段的通用约束:强制裁判给出可核查的证据。要求每一条评审意见都必须附上具体的文件与行号、引用真实存在的代码片段——给不出证据的意见直接丢弃。这一条看似简单,却能同时压住两类噪声:裁判凭空编造的幻觉批评(引用不存在的代码,一校验即穿帮),以及泛泛而谈的模板化建议("建议增加测试覆盖"这类放之四海皆准的废话)。证据要求把裁判的输出从"不可验证的观点"变成了"可机械校验的断言"——相当于在推理型传感器的出口处,又套了一层廉价的计算型过滤。
12.5 成本控制策略
推理型传感器每跑一次都要花模型调用的钱和时间,比计算型传感器贵几个数量级。因此不能对所有产出、所有改动都做全量推理评审——那样成本和延迟都无法承受。三条成本控制策略:
- 抽样评审:不是每个 PR 都全量评审,而是按比例抽样,用抽样结果监控整体质量趋势(类似质检抽检)。适合低风险的大批量改动。
- 增量评审:只评审**本次改动(diff)**及其直接影响面,而不是每次都重读整个文件/模块。这既省成本,也让评审更聚焦。
- 按风险分级触发:这是最重要的一条。把评审强度与改动的风险挂钩——碰到支付、鉴权、数据迁移等高风险路径,触发全套专项评审(安全+架构+多次采样);碰到文档、样式、低风险工具代码,用轻量甚至跳过。风险分级让你把昂贵的推理预算花在最该花的地方。
回扣 Harness:成本控制策略与第 10 章"部署位置谱系"是配套的。推理型传感器因为贵,天然不该放在 Agent 内循环(每次编辑都跑不起),而适合放在提交前/集成前,并用"增量 + 按风险触发"把成本压到可接受。第 14 章会给出一个统一的成本模型来量化这些权衡。
12.6 信任校准:何时可以据此自动合并
最后落到最实际、也最需要谨慎的问题:推理型传感器给了绿灯,能不能就自动合并、不要人看了?
答案是一个渐进的信任校准过程,而非一刀切的"能"或"不能":
- 影子模式(shadow mode)起步:先让推理型评审只输出意见、不做决定,同时人类照常评审。积累一段时间,比对"评审 Agent 的判断"与"人类的最终决定"的吻合度。
- 在低风险区先放开:当某一类低风险改动上,评审 Agent 的判断与人类高度一致(且几乎无漏放的严重问题)时,才在这一类上允许"高置信度通过即自动合并"。
- 高风险区永远留人:涉及安全、资金、数据、不可逆操作的改动,无论评审 Agent 多有信心,都保留人类最终确认——这是第 10 章第三级"意图类问题"和第 25 章"安全边界"的要求。
- 持续监控与回退:自动合并放开后,必须持续监控"逃逸缺陷率"(自动合并后仍出问题的比例)。一旦升高,立即收紧信任边界。
这里的关键是把"信任"变成一个可衡量的工程量,而非一句拍脑袋的决定。至少要盯三个指标:
- 吻合率(agreement rate):评审 Agent 的判断与人类最终决定的一致比例——影子模式阶段用它决定能否放开;
- 逃逸缺陷率(escaped-defect rate):放开后漏放的严重问题比例——这是最关键的安全指标,宁可保守也不该让它飙升;
- 误报率(false-positive rate):评审 Agent 把好改动判成坏的比例——它不危险但伤效率,过高会让人开始忽略它的意见(第 10 章说的"训练系统忽略红灯")。
这三个指标应当按风险分类分开统计(低风险区的逃逸缺陷率可容忍度远高于高风险区),并随时间绘成趋势线——它们就是你"该不该再放开一点"或"该不该立即收紧"的决策依据。
举一个放开的实操判断:某类"纯前端样式改动"在影子模式跑了一个月,评审 Agent 与人类吻合率 96%、逃逸缺陷率为 0——这类就可以放开"高置信通过即自动合并"。而"数据库迁移"这类哪怕吻合率也有 90%,只要它逃逸的哪怕一次就可能是不可逆的数据损坏,就永远留人。这说明放开的依据从来不是单看吻合率高低,而是"这类改动一旦漏放,代价是否可承受"。
OpenAI 的整体姿态印证了这条路径:他们让 Agent 大量自主评审、响应反馈、甚至自行压缩合并 PR,采用"最低限度阻塞门禁 + 廉价的事后纠正"——但这建立在该仓库特定的结构和工具投入之上,且始终"人类在环、只在需要判断时介入"。他们自己也警告:这套行为"高度依赖该仓库的特定结构,不应假定可无投入地普适"。
回扣 Harness:信任校准的本质,是不断测量一个概率性传感器的可靠性,并据此动态调整对它的授权范围——这本身就是一个掌舵回路(第 5 章)。你不是一次性决定"信不信 AI 评审",而是持续地、按领域、按风险,测量并校准这份信任。把它当常数是危险的,把它当一个需要持续监测的变量才是工程的姿态。
本章要点
- 推理型传感器捕获"无确定判据"的第二级问题(命名、抽象、过度设计、slop、语义重复),是计算型传感器的必要补充;核心矛盾是"非确定的传感器如何产出可依赖的信号"。
- 评审 Agent 应专科化:通用评审 + 安全/架构/性能专项,各带聚焦上下文与检查清单——这是 Ashby 定律(多样性匹配多样性)在评审侧的应用。能机械判定的应下沉到计算型传感器。
- LLM-as-Judge 三要点:结构化 rubric(把"好"拆成可逐条判断的维度)、用人类样本校准、主动控制长度/位置/自我偏好/谄媚等偏差。未校准的裁判分数不可信。
- 语义级检测是推理型的不可替代价值:语义重复代码、冗余测试、过度设计——都无语法判据,只能靠理解意图的 LLM 捕获,是熵增的主要来源。
- 非确定性管理三件套:评审模型≠生成模型(避自我偏好、增视角)、多次采样多数表决(压方差)、置信度分层(高置信自动化、低置信升级给人)。
- 成本控制三策略:抽样评审、增量评审(只看 diff)、按风险分级触发(把昂贵推理花在高风险路径);推理型传感器宜放提交前/集成前而非内循环。
- 信任校准是渐进过程:影子模式起步 → 低风险区先放开自动合并 → 高风险区永远留人 → 持续监控逃逸缺陷率并动态收放。信任是需要持续测量的变量,不是常数。
动手练习
- 给你的评审拆专项。 如果你现在用一个"大而全"的评审提示词,把它拆成通用 + 至少一个专项(建议先做"安全"或"架构"),为专项写一份聚焦的检查清单(rubric),对比拆分前后评审的深度与误报率。
- 校准一个 LLM 裁判。 准备 10 段代码(5 段你认为好、5 段你认为差),让你的评审 Agent 逐一打分,统计它与你判断的吻合率。针对它判错的样本,修订 rubric 或提示词,再测一次,观察吻合率是否提升。
- 设计你的自动合并信任边界。 按 §12.6 为你的项目画一条线:哪些类型的改动可以在"评审 Agent 高置信通过"时自动合并、哪些必须留人?并想清楚你要用什么指标(逃逸缺陷率)来监控这条线、在什么信号下收紧它。
承上启下:计算型(第 11 章)与推理型(本章)两类传感器都讲完了。但无论哪一类,它们回传的信号最终都要被一个特定的"消费者"读取——而这个消费者,已经从人类变成了 LLM。这个转变,要求我们重新设计所有工具的输出。第 13 章「面向 LLM 的信号设计」 将展开这个小而关键的主题:报错信息如何写才能被 Agent 直接消费、如何在错误里嵌入修复指引(OpenAI 的"正向提示注入")、信号如何分级,以及那些"人看得懂但 Agent 会误解"的反面案例。