27—AI Skill 测评如何避免确认偏误:盲测对比与解盲分析

上一篇讨论的是"人工 Skill 相比裸模型和自生成 Skill 是否真的有价值"。只要进入对比,就会遇到一个评估偏差:评审者一旦知道哪份输出来自 with_skill,就容易把预期写进结论。

因此 SkillSentry 在 standard/full 中把对比分成两步:Comparator 先盲测 A/B 输出质量,Analyzer 再解盲归因到 SKILL.md 的具体规则。本文讲的就是这两个步骤为什么要分开。

说明:本文中的 A/B 是 Comparator 随机分配的盲测标签,不等同于上一篇三条件对比里的条件 A(without)、条件 B(curated)和条件 C(self-generated)。这里的 A/B 只表示「两份待比较输出」,目的是隐藏哪份来自 with_skill

为什么需要盲测

SkillSentry 的核心问题是:这个 Skill 真的有用吗?

通过率只能告诉你「Skill 有没有完成任务」,但不能告诉你「没有这个 Skill 时,AI 是不是也能完成」。

如果没有 Skill 时 AI 也能做对,那这个 Skill 的价值就是零。

这就是三条件对比范式的核心------但对比时有一个陷阱:确认偏误


确认偏误:为什么直接对比不可靠

假设你同时看到两份输出,并且知道哪份来自 with_skill:

css 复制代码
Output A(with_skill):格式整齐,字段完整
Output B(without_skill):格式稍乱,但信息基本正确

你的判断可能是:「A 明显更好------格式规范、结构清晰。」

但如果你不知道哪份来自 with_skill,你可能会注意到:「B 虽然格式稍乱,但回答了一些 A 没有回答的边界问题。」

这就是确认偏误------当你知道预期答案时,你会无意识地降低对预期答案的标准、提高对非预期答案的标准。

Comparator 的解法:在不揭盲的情况下评判,消除这种偏误。


Comparator:盲测评判

核心设计

css 复制代码
输入:
  - output_a_path:标记为 A 的输出
  - output_b_path:标记为 B 的输出
  - eval_prompt:原始测评 prompt
  - expectations:断言列表(可为空)

关键约束:
  Comparator 不知道 A 和 B 哪个是 with_skill
  A/B 的分配是随机的(有时 with_skill 是 A,有时是 B)

随机分配 A/B 标签进一步确保了盲性------如果 with_skill 总是 A,评判者可能无意识地偏向 A。

评分体系:10 分制 rubric

Comparator 从两个维度评分:

内容维度(Content)

  • 正确性(1-5):信息是否准确
  • 完整性(1-5):是否回答了所有要素
  • 准确性(1-5):细节是否精确

结构维度(Structure)

  • 组织性(1-5):信息是否有逻辑层次
  • 格式规范(1-5):格式是否清晰易读
  • 可用性(1-5):用户能否直接使用

综合得分 = (内容均值 + 结构均值) / 2 × 2 → 10 分制

按 Skill 类型调整评分维度

skill_type 额外维度
mcp_based 字段完整性、工具调用正确性、链接可用性
text_generation 规则遵守度、内容准确性、格式规范
code_execution 命令执行正确性、文件生成完整性、错误处理

这保证了评分对不同类型的 Skill 有针对性。

Verdict:三档判决

less 复制代码
A 得分 > B 得分 → winner: "A"
B 得分 > A 得分 → winner: "B"
差距 < 0.5 分  → winner: "TIE"

设计原则:有决断力。TIE 应该是极少数情况------如果两份输出真的无法区分,那本身就是一个重要发现(说明这个 Skill 对该用例增益为零)。

text_generation Skill 的特殊处理

纯文本生成的 Skill(如写邮件、生成报告)评判起来最难------两份输出表面上可能很相似,都是通顺的文字。

Comparator 对这类 Skill 的判决标准:

有 Skill 指导的输出是否严格遵守了 SKILL.md 的特定规则(格式要求、字数限制、禁止内容、必须包含的结构),而没有 Skill 指导的输出则随意发挥?

评分时重点看:

  • 是否有 H2 章节结构(如 SKILL.md 要求)
  • 是否在字数限制内
  • 是否遵守了「不得出现 XX」的禁止规则
  • 若两份在规则遵守度上无差异 → TIE 是合理结论

Analyzer:解盲分析

角色转换

Comparator 完成盲测后,Analyzer 执行「解盲」------知道了 A/B 对应关系后,做因果分析:

markdown 复制代码
输入:
  - winner + winner_is_with_skill(解盲信息)
  - evaluated_skill_path(被测 Skill)
  - with_skill_transcript_path(完整执行记录)
  - without_skill_transcript_path
  - comparison_result_path(Comparator 的盲测结论)

两种解盲结果

正常情况:winner_is_with_skill = true

复制代码
with_skill 赢了 → Skill 有正面增益
分析方向:
  - 为什么赢了?Skill 中哪些指令导致了更好的行为?
  - 改进建议:锦上添花,进一步优化

异常情况:winner_is_with_skill = false

复制代码
without_skill 赢了 → Skill 反而拖累了输出 ⚠️
分析方向:
  - 为什么输了?Skill 中哪些规则是有害的?
  - 改进建议:优先级最高(Skill 有明确有害规则需要移除)

分析流程

vbnet 复制代码
Step 1: 读取 Comparator 盲测结论(理解评判维度和理由)
Step 2: 读取 SKILL.md(理解指令设计意图)
Step 3: 读取双方 transcript(对比执行模式差异)
Step 4: 识别胜出原因(Skill 的哪些指令产生了正面效果)
Step 5: 识别失败原因(缺少什么导致了更差的行为)
Step 6: 生成改进建议(优先级排序,可操作)

改进建议的结构

每条建议包含四个要素:

json 复制代码
{
  "priority": "high",        // high/medium/low
  "category": "instructions", // instructions/tools/examples/error_handling/structure/references
  "suggestion": "在 saveExpenseDoc 调用前加断言:docStatus 必须为 '10'",
  "expected_impact": "防止 Agent 误将草稿提交为正式审批"
}

六个 category

类别 含义 示例
instructions SKILL.md 文字指令改动 「增加约束:禁止使用 CSV 中的静态编码」
tools 增加/修改脚本或工具 「增加 validate_input.py 校验输入格式」
examples 补充示例 「增加边界情况的正确输出示例」
error_handling 错误处理指导 「MCP 超时时应重试一次,而非直接放弃」
structure SKILL.md 结构重组 「将硬性前置检查从文档中间移到开头」
references 新增参考文件 「增加 field_mapping.json 避免 Agent 猜测字段名」

指令遵循率

Analyzer 还输出一个「指令遵循率」评分(1-10):

json 复制代码
"instruction_following": {
  "winner": {
    "score": 9,
    "issues": ["Step 1.2 文件上传后验证被跳过(非关键)"]
  },
  "loser": {
    "score": 3,
    "issues": [
      "未调用 queryExpenseItems,直接使用 CSV 静态编码",
      "docStatus 设为 20 而非 10",
      "saveExpenseDoc 成功后未构建详情链接"
    ]
  }
}

这个分数直接反映了 Skill 的指令清晰度------如果 with_skill 的指令遵循率只有 5 分,说明 SKILL.md 写得不够清晰,AI 读了但没做对。


在 Pipeline 中的位置

Comparator 和 Analyzer 只在 standard/full 模式下触发:

makefile 复制代码
Pipeline:
smoke:    [...] → grader-report → done
quick:    [...] → grader-report → done
standard: [...] → executor-without → comparator → grader-report → gate → publish
full:     [...] → executor-without → comparator → analyzer → grader-report → gate → publish

为什么 quick 不跑对比?

对比需要 without_skill 的执行记录------这意味着每个 eval 要跑两遍(一遍有 Skill、一遍无 Skill),时间和开销翻倍。quick 模式定位是「快速验证」,翻倍不可接受。

当前版本的 baseline 规则更精确:

模式 without_skill Delta
smoke mcp_based 默认跳过 N/A
quick mcp_based 默认跳过 N/A
standard 默认保留可比较 baseline computed / partial / N/A
full 默认保留可比较 baseline computed / partial / N/A

所以这篇讨论的是"如何量化增益",不是说每次测评都必须跑 comparator/analyzer。


数据流

bash 复制代码
executor 产出:
  eval-N/run-R/with_skill/outputs/transcript.md + response.md
  eval-N/run-R/without_skill/outputs/transcript.md + response.md

comparator 输入:
  随机选择一个 run 的 with_skill 和 without_skill 输出
  随机分配为 A/B

comparator 输出:
  eval-N/comparison.json(盲测结论)

analyzer 输入:
  comparison.json + 解盲信息 + SKILL.md + 双方 transcript

analyzer 输出:
  eval-N/analysis.json(因果分析 + 改进建议)

实际案例

以报销 Skill 测评为例:

Comparator 盲测结论

json 复制代码
{
  "winner": "A",
  "reasoning": "A 的输出包含完整的报销主题、金额、收款账户、资源用量明细和可用的详情链接。B 缺少收款账户字段,详情链接含字面占位符 {fdId},无法直接使用。",
  "rubric": {
    "A": {"overall_score": 9.0},
    "B": {"overall_score": 5.4}
  }
}

解盲后得知:A = with_skill

Analyzer 输出

json 复制代码
{
  "winner_strengths": [
    "SKILL.md Step5 S3 明确断言『链接中不得包含 {fdId} 字面占位符』,Agent 因此在输出前做了校验",
    "workflow.md 提供了 fdMonthOfOccurrence 精确计算公式,避免了计算错误"
  ],
  "loser_weaknesses": [
    "无 Skill 指导时 Agent 不知道需要调用 queryExpenseItems,直接用 CSV 静态编码",
    "无 docStatus 约束,Agent 将 docStatus 设为 20(直接提交),违反只保存草稿要求"
  ],
  "improvement_suggestions": [
    {
      "priority": "high",
      "category": "instructions",
      "suggestion": "明确:资源用量类型 fdExpenseItemId 必须来自 queryExpenseItems 接口,禁止使用 CSV 编码",
      "expected_impact": "消除直接使用 CSV 编码的行为"
    }
  ]
}

价值:从「A 比 B 好」到「好在哪里、因为 SKILL.md 的哪条指令」------这才是可操作的洞察。


与 Grader 的关系

Grader Comparator + Analyzer
问的问题 「这个输出满足断言吗?」 「两个输出哪个更好?为什么?」
评判方式 逐条断言 pass/fail 整体质量 10 分制
是否需要对照 不需要(只看 with_skill) 需要(比较 with vs without)
输出 通过率 胜负 + 归因 + 建议
用途 准入判定(能不能上线) 增益量化(值不值得上线)

两者互补:

  • 通过率高 + 对比赢 = 放心上线
  • 通过率高 + 对比输/平 = Skill 可能有冗余规则(做对了不是因为 Skill)
  • 通过率低 + 对比赢 = Skill 方向对但断言太严
  • 通过率低 + 对比输 = Skill 有问题,需要修

设计决策:为什么分成两步

为什么不让一个 Agent 同时做盲测 + 分析?

1. 保证盲性的纯粹性

如果同一个 Agent 先盲测再解盲,它可能在盲测阶段就「猜到」哪个是 with_skill(比如输出格式明显更规范的那个)。分成两个独立的 Agent,物理隔离了盲性。

2. Comparator 的判断可以被审计

独立的 comparison.json 是可审计的------如果解盲后发现 Comparator 判错了(盲测说 B 好,但 B 是 without_skill),这本身就是一个重要信号:说明 Skill 在这个用例上没有增益。

3. 串行依赖是自然的

Analyzer 必须知道 Comparator 的结论才能做归因分析------这是逻辑上的依赖,不是人为拆分。


FAQ

Q:如果 Comparator 判了 TIE,Analyzer 还需要跑吗?

需要。TIE 意味着「Skill 对这个用例没有可观测的增益」------Analyzer 需要分析为什么没有增益,是 Skill 覆盖不到这类场景,还是 AI 本身就能做好。

Q:随机分配 A/B 的种子是什么?

eval_id + run_id 作为种子的 hash。保证同一个 eval 的不同 run 分配一致,但不同 eval 之间随机。

Q:对比测试的开销大吗?

Comparator 读两份输出 + 做评分:~3K token/eval Analyzer 读 transcript + 做分析:~5K token/eval 33 个 eval 全跑:约 264K token,属于中等资源用量。实际消耗会随输出长度、transcript 大小和模型上下文而变化,这里只作为量级估算。

这就是为什么只在 standard/full 模式下才触发------在完整测评已有较高 token 消耗的基础上增加一次对比分析,用来换取增益量化和改进建议。


下一篇:用外部框架校准自己的测评链路

盲测和解盲解决的是「对比结论如何减少偏见」。但一套测评体系是否完整,还需要放到更通用的 Agent Skill 评估实践里自查:原始 transcript 是否是唯一证据源、硬规则是否能脱离 LLM 验证、报告是否能回溯、版本变化是否能检测退化。

下一篇会用一个四层评估框架来反查 SkillSentry:哪些地方已经做对了,哪些地方还需要补齐。


来源:agents/comparator.md、agents/analyzer.md、SkillSentry contract。

相关推荐
Flynt1 小时前
配置Chrome DevTools MCP,我在Windows上折腾了两个晚上
ai编程·claude·mcp
想要成为糕糕手2 小时前
Harness Engineering:大模型时代的“马鞍”——从记忆层开始,让AI真正为你所用
面试·ai编程·claude
深蓝AI2 小时前
从零搭建 MCP Server:用 Python 把任意数据源接入 Claude
aigc
老程序猿2 小时前
AI 的「狼来了」,该不该信?一次真正感受到「恶意提示词」的误报
aigc·ai编程
狂师2 小时前
比 Playwright 更给力,推荐一个AI Agent的浏览器自动化开源项目!
前端·开源·测试
AI袋鼠帝3 小时前
开源「仓颉.Skill」2.0,你现在可以蒸馏任何视频!
开源·aigc
AI袋鼠帝3 小时前
懂事的Agent已经自己看屏幕干活了!效率起飞~
aigc
Warson_L14 小时前
独立开发推荐安装的skills
ai编程