为什么不能让 AI 自己评审自己?AI Skill 四层验证体系完整解析
系列:SkillSentry · AI Skill 测评体系从零到一(四)
难度:深入
适合读者:想构建可信测评机制的工程师
📌 一句话摘要:让模型自判卷会产生系统性偏差,本文拆解 AI Skill 四层验证体系如何用独立 Grader Agent 和盲测 Comparator 彻底消除自判卷问题。
🏷️ 推荐标签:AI Skill四层验证 LLM自判卷偏差 独立Grader Agent
问题:为什么不能让模型自己评审自己
让模型自己评审自己的输出,会产生「自判卷偏差」——这是 AI Skill 四层验证体系要解决的核心问题。 最朴素的测评思路:让模型执行任务,然后让模型判断结果是否正确。
这有一个根本缺陷:执行者和评审者是同一个模型。
实验中观察到的现象:
- 同一个用例,with_skill 跑出来通过率 100%,without_skill 也是 100%
- 展开看 evidence,发现很多断言的 evidence 是空的,或者只写了「根据整体输出判断通过」
- 这说明评审是「感觉通过」,不是「有证据通过」
这就是「自判卷偏差」。
解决思路:四层验证,各司其职
四层验证体系的核心思路是:把执行、精确校验、语义评审、盲测对比四件事彻底分开,每层只负责自己最擅长的部分。 每层解决不同的问题,互相补充:
Layer 0: 执行模式分发(v5.0 新增)
→ 检测 Skill 类型(mcp_based / code_execution / text_generation)
→ 选择对应执行模式,分发给 Layer 1
Layer 1: Executor(执行层)
→ 真实执行 Skill,记录所有证据(transcript + response + metrics)
Layer 2a: 字段精确校验(Ground Truth)
→ 从 transcript 直接提取字段值,assertEqual / 正则匹配
→ 不经 LLM,完全客观
Layer 2b: 独立 Grader Agent(语义评审)
→ 独立 LLM 读 transcript + response,找原文 evidence
→ 执行者和评审者完全分离
→ v5.0:支持 MCP / 代码执行 / 纯文本 三种评审标准
Layer 3: 盲测 Comparator + Analyzer(正常路径 + E2E 必跑)
→ Comparator 不知道哪个是 with_skill,纯质量评分
→ Analyzer 解盲,定位胜负根因
Layer 1:Executor
职责:真实执行 Skill,记录完整证据。没有 Layer 1 的 transcript,后续所有验证层都无法工作。
v5.0 新增 Layer 0 — 执行模式自动分发:
在 Layer 1 执行前,系统先检测 Skill 类型并选择对应模式:
| Skill 类型 | 执行模式 | transcript 内容 |
|---|---|---|
mcp_based | 真实 MCP 工具调用 | 完整工具调用记录(入参、返回值、报错) |
code_execution | 真实 Bash/脚本执行 | 命令执行记录 + 输出文件内容 |
text_generation | 纯文本模式 | 模型推理过程 + 最终输出(无工具调用) |
纯文本模式下,transcript 没有工具调用记录,Grader 直接从 response.md 找证据(见 Layer 2b 说明)。
产出文件:
with_skill/outputs/
transcript.md ← 完整执行过程(每步工具调用+入参+返回值+推理)
response.md ← 最终向用户呈现的内容
metrics.json ← 工具调用统计
timing.json ← 执行耗时 + tokens(来自 task notification,只有这一次机会)
timing.json 格式(v5.0 增强):
{
"executor_start_ms": 1711234567000,
"executor_end_ms": 1711234573500,
"duration_ms": 6500,
"total_tokens": 2340,
"input_tokens": 1200,
"output_tokens": 1140
}
关键设计:
- with_skill 和 without_skill 必须在同一轮同时启动,不能先跑一个再回来跑另一个
- timing.json 必须在 task notification 到达时立即保存,错过就永久丢失
- 纯文本模式:
execution_metrics.total_mcp_calls填 0,不影响 Grader 判断
Layer 2a:字段精确校验(Ground Truth)
Layer 2a 是四层中最可信的一层,因为它完全不经过任何 LLM,是纯文本匹配——相当于软件测试里的 assertEqual。 对可以精确匹配的断言做客观验证,不依赖 LLM 判断。
为什么 Layer 2a 是四层中最可信的:无论模型当天状态如何、temperature 怎么设,同一个 transcript 跑 Layer 2a 永远得到同样的结论。不受模型幻觉、评审偏见、随机性影响。这是 Layer 2b 和 Layer 3 做不到的。
适合验证的断言类型:
接口调用次数:saveExpenseDoc 调用了几次(计数)
固定参数值:docStatus == "10"(精确匹配)
链接格式:不含字面占位符 {fdId}(正则)
字段值:fdMonthOfOccurrence 是否等于当前月份计算值(精确匹配)
不适合 Layer 2a 的断言(转交 Layer 2b):
「输出格式是否对用户友好」→ 主观,需要 LLM 评审
「报销主题内容是否合理」→ 语义性,需要 LLM 评审
「错误提示是否清晰」→ 语义性,需要 LLM 评审
产出文件:ground_truth.json
{
"checks": [
{
"assertion": "saveExpenseDoc 参数 docStatus=10",
"method": "transcript_search",
"passed": true,
"evidence": "transcript Step5 入参:{\"docStatus\":\"10\",\"expenseType\":\"1\",...}"
},
{
"assertion": "详情链接不含字面占位符 {fdId}",
"method": "regex",
"passed": false,
"evidence": "response.md 第12行链接中仍含 {fdId} 占位符"
}
]
}
这一层的价值:绑定了最可信的 evidence——直接从 transcript 提取的原文,不经过任何 LLM 推断。
Layer 2b:独立 Grader Agent
独立 Grader Agent 通过强制引用原文 evidence,从根本上消除「感觉通过」的评审方式——找不到原文支持,就是 FAIL。 用独立 LLM 评审语义性断言。
与 Layer 2a 的分工:
- Layer 2a 处理:可以精确匹配的断言
- Layer 2b 处理:需要理解语义的断言
v5.0 新增:三种评审标准按 Skill 类型切换
Grader 收到 skill_type 参数,自动切换对应评审规范:
| skill_type | evidence 来源 | 特殊注意点 |
|---|---|---|
mcp_based | transcript 中的工具调用记录 | 验证入参/返回值/调用次数 |
code_execution | Bash 调用记录 + 输出文件内容 | 验证命令正确性和文件内容 |
text_generation | response.md 原文段落 | 无工具调用,从输出文本找证据 |
纯文本 Skill 的 evidence 规范:
✅ 好的 evidence(纯文本版):
"response.md 第3段:'本次分析覆盖了以下三个维度:1.性能 2.安全 3.可维护性'
——三个维度均已呈现,满足断言"
❌ 不可接受:
"从整体输出来看,内容比较完整"
"AI 似乎理解了用户意图"
Grader Agent 的工作方式:
Step 1:读取 skill_type,选择评审标准
Step 2:读取 transcript.md 或 response.md(根据类型)
Step 3:对每条断言:找原文 → 判定 PASS/FAIL → 必须 quote 具体文字
Step 4:提取隐含 claims 并验证(幻觉检测)
Step 5:读取 user_notes.md(执行者在运行时记录的疑问)
Step 6:批评断言质量(eval_feedback)
Step 7:读取 timing.json,将耗时/Token 数据写入 grading.json
v5.0 grading.json 新增字段:
{
"skill_type": "text_generation",
"timing": {
"executor_duration_ms": 6500,
"total_tokens": 2340,
"input_tokens": 1200,
"output_tokens": 1140
}
}
user_notes.md:执行层(Layer 1)在运行过程中记录的疑问,例如「Step 3 接口返回了异常状态码但未中断,不确定是否符合预期」。Grader 读取这些注记后可以有针对性地重点评审对应断言。
evidence 强制非空的意义:
强制引用原文,消除了「感觉通过」的评审方式。如果找不到原文支持,就是 FAIL。
幻觉检测(最有价值的额外工作):
Grader 不只评审预定义的断言,还会从输出中提取「隐含声明」并逐一核查:
隐含声明:「saveExpenseDoc 调用了一次」
类型:factual
验证结果:true
证据:transcript 中 saveExpenseDoc 出现 1 次(Step5)
隐含声明:「fdMonthOfOccurrence 取当前月份 120260200」
类型:factual
验证结果:false
证据:checkExpenseItem 入参 fdMonthOfOccurrence=120251100(发票月而非提单月)
这里发现的问题,是预定义断言可能遗漏的。
断言质量建议(eval_feedback):
Grader 还会批评断言本身的质量,例如:
「『输出包含报销金额』只检查了存在性,未验证金额与发票一致,幻觉金额也会通过。建议改为:报销金额等于发票识别金额」
Layer 3:盲测 Comparator + Analyzer(正常路径 + E2E 必跑)
盲测 Comparator 通过让评审者不知道哪个是 with_skill,从机制上消除「对好版本更宽容」的评审偏见。 深度比较 with_skill 和 without_skill 的输出质量。
触发规则:正常路径用例(Happy Path)和 E2E 用例完成后必须执行,不可跳过。其他类型用例不触发。
为什么要盲测:Layer 2b 的 Grader 知道哪个是 with_skill,可能存在「对好版本更宽容」的评审偏见。Comparator 不知道 A/B 哪个是 with_skill,只看内容质量打分,消除了这种偏见。
Comparator 评分维度:
内容维度(Content):
正确性(Correctness) 1-5 分
完整性(Completeness) 1-5 分
准确性(Accuracy) 1-5 分
结构维度(Structure):
组织性(Organization) 1-5 分
格式规范(Formatting) 1-5 分
可用性(Usability) 1-5 分
综合得分 = (内容均值 + 结构均值) / 2 × 2(换算 1-10 分)
Analyzer 做什么:Comparator 评完分后,Analyzer 解盲(得知哪个是 with_skill),定位胜负根因,生成可操作的改进建议:
{
"improvement_suggestions": [
{
"priority": "high",
"category": "instructions",
"suggestion": "将含糊的「处理发票」描述替换为明确的 3 步操作序列",
"expected_impact": "消除歧义,防止模型自行发挥"
}
]
}
四层之间的关系
四层验证的关系是:Layer 1 是基础,Layer 2a/2b 互补,Layer 3 是深化——每一层都依赖前一层的产出,缺少任何一层都会留下验证盲区。
Layer 1 是基础
→ 没有 transcript,Layer 2 和 3 都无法工作
Layer 2a 和 2b 互补
→ 精确字段 → Layer 2a,语义内容 → Layer 2b
→ 最终的 grading.json 合并两层结果
Layer 3 是深化
→ 只在重要用例(Happy Path / E2E)上执行
→ 发现 Layer 2 发现不了的质量问题
grading.json 中的 method 字段,标注每条断言来自哪一层:
{"text": "docStatus=10", "passed": true, "method": "ground_truth", "evidence": "..."}
{"text": "输出包含报销主题", "passed": true, "method": "grader", "evidence": "..."}
报告中 [ground_truth] 标签的断言最可信,[grader] 标签次之(需要看 evidence 是否有原文)。
与 skill-creator 的对应关系
我们的四层验证体系借鉴并扩展了 skill-creator 的设计:
| 我们的层 | skill-creator 对应 | 改进点 |
|---|---|---|
| Layer 1 | Step 1(spawn runs)+ Step 3(capture timing) | 增加 transcript 格式规范 |
| Layer 2a | 无(我们新增) | 精确字段校验,来源于软件测试 assertEqual 思路 |
| Layer 2b | agents/grader.md | 汉化,增加 evidence 强制非空约束 |
| Layer 3 | agents/comparator.md + analyzer.md | 汉化,增加 E2E 必须执行 Layer3 的规则 |
小结
| 层 | 解决的核心问题 | 产出 | 可信度 | 触发时机 |
|---|---|---|---|---|
| Layer 0 ✨ | 不同 Skill 类型执行方式不同 | skill_type 分发决策 | — | 每次测评启动时 |
| Layer 1 | 没有真实执行记录,评审无原材料 | transcript + response + metrics + timing.json | 基础 | 每个用例必跑 |
| Layer 2a | LLM 评审精确字段不可靠 | ground_truth.json | 最高 | Layer 1 完成后立即执行 |
| Layer 2b | 执行者自判卷 | grading.json(含 skill_type / claims / timing) | 高 | Layer 1 完成后立即执行 |
| Layer 3 | 评审者知道哪个是「好版本」存在偏见 | comparison.json + analysis.json | 高(盲测) | 仅正常路径 + E2E 用例 |
✨ = v5.0 新增
工程细节:测评进度的可见性设计
测评进度的可见性设计解决的核心问题是:十几个子步骤如果全部暴露给用户,界面会非常嘈杂,5 个里程碑节点恰好对应用户需要参与决策的关键点。 这套四层验证体系有一个配套的工程细节值得单独说一下。
测评工具在启动时写入 5 个 todo,用户在界面上始终可见:
用户层 todo(5 个)——用户在界面上看到的
【1/5】📋 准备阶段:分析 Skill + 收集测评所需信息
【2/5】⚙️ 方案确认:选择模式 + 确认用例清单
【3/5】🚀 执行测评:分批运行所有用例(四层验证)
【4/5】📊 评分分析:汇总指标 + 覆盖率检查 + 质量清单
【5/5】📄 生成报告:输出 HTML 报告 + 解读指引
每完成一个阶段立即标记完成,用户始终知道当前在第几步、下一步需要做什么决策。
这个设计解决的问题:测评流程有十几个子步骤(MCP 检测、规则提炼、用例设计、分批执行……),如果每个步骤都暴露给用户,界面会非常嘈杂。5 个里程碑节点恰好对应「用户需要参与决策的关键点」,其余执行细节由 AI 自动完成,不打扰用户。
下一篇,我们来深入拆解 skill-creator 的源码——它的触发率测评和 description 自动优化循环是怎么实现的。
附录:与 ADK 5 大设计模式的对应关系
SkillSentry 的四层验证体系与谷歌 ADK 的 Reviewer 模式直接对应(独立评审、权责分离),Pipeline 模式驱动整个测评流水线。完整分析见第八篇。
| ADK 模式 | SkillSentry 对应 | 核心解决的问题 |
|---|---|---|
| Reviewer | Grader/Comparator/Analyzer 三个独立 Agent | 执行者自判卷 |
| Pipeline | 阶段零→六的流水线 + 量化准出标准 | 信息不完整时跳步 |
| Invoke | references/ 文件精确触发条件 | 漏读规则或全量读浪费 Token |
| Tool Wrapper | 8 种异常标准话术表 | MCP 不可用时 AI 自由发挥 |
| Generator | 报告前置检查 + 章节强制校验 | AI 跳过关键章节 |
FAQ:关于 AI Skill 四层验证,用户常问的问题
为什么不能让模型自己评审自己的输出?
让执行者和评审者是同一个模型,会产生「自判卷偏差」。实验中可以观察到:同一个用例,with_skill 和 without_skill 的通过率都是 100%,但展开看 evidence 发现大量断言的 evidence 是空的,说明模型在「感觉通过」而不是「有证据通过」。这种偏差会让测评结论完全失去可信度,无论跑多少用例都没有意义。
四层验证体系各层分别解决什么问题?
四层各有分工:Layer 1(Executor)负责真实执行并记录完整 transcript,是其余三层的原材料来源;Layer 2a(Ground Truth)用精确文本匹配校验可量化的字段,不经过任何 LLM,是最可信的一层;Layer 2b(独立 Grader Agent)用独立 LLM 评审语义性断言,强制引用原文 evidence;Layer 3(盲测 Comparator)让评审者在不知道哪个是 with_skill 的情况下打分,消除评审偏见。四层合并的结论比任何单一验证机制都可信。
什么是 Ground Truth 精确校验,和 LLM 评审有什么区别?
Ground Truth 精确校验(Layer 2a)是纯文本匹配,相当于软件测试里的 assertEqual——直接从 transcript 提取字段值,做计数、精确匹配或正则匹配,完全不经过任何 LLM。LLM 评审(Layer 2b)则是让独立 Grader 理解语义、判断断言是否成立。前者的结论不受模型随机性影响,同一个 transcript 永远得到相同结论;后者更灵活,能处理语义性的断言,但可信度依赖 evidence 是否有原文支撑。两者互补,不可替代。
盲测 Comparator 是如何消除评审偏见的?
Comparator 在评分时不知道 A/B 哪个是 with_skill 输出,只看内容质量本身,从六个维度(正确性、完整性、准确性、组织性、格式规范、可用性)独立打分。评分完成后,Analyzer 才解盲——得知哪个是 with_skill——再定位胜负根因并给出改进建议。这种「先盲评,后解盲」的机制,确保评分过程不受「我知道这个是好版本」的主观预期影响。
evidence 字段为什么必须引用原文?
evidence 强制非空是对抗「感觉通过」的核心机制。如果允许 Grader 写「根据整体输出判断通过」这类无来源的评语,那这条断言的判定结果就完全依赖模型当天的状态,不具备可重复性和可审计性。强制引用原文意味着:找到了原文 → PASS;找不到原文支持 → FAIL。这让每一条断言的判定结果都有据可查,报告中的通过率才是真实可信的数字。