Clean Room Eval
评一个 skill / prompt / 流程到底行不行,靠的不是读它写得好不好,是让它在干净环境里跑真实案例,然后看错在哪里、错得是否有规律。
三个设计前提,每一个都是为了堵住一种自欺:
| 措施 | 堵的是什么 |
|---|---|
| 案例由评测方自己生成,跨领域 | 堵"拿被测方擅长的案例来测"。被测方给的案例天然是它过得去的。 |
| 子 agent 无对话历史、无其他 skill、无任何提示 | 堵上下文污染。主会话里聊过的背景会让子 agent 表现得比真实水平好,上线后没有这些背景,能力就消失。 |
| 只上报多案例共现的问题 | 堵"逐个修单点 bug"。单点 bug 修完还是烂;共性问题才指向根因。 |
何时用
用:要判断一个 skill/prompt/流程的真实能力;改完之后要证明「真的改善了」;怀疑某个产出好是因为上下文喂得好而不是 prompt 本身好。
不用:单个案例调试(直接跑就行);只读代码审查(analyze-only);已知问题要修(prompt-forge)。
硬流程
1. 锁定被测对象与口径
明确三件事,含糊就先问:
- 被测物:哪个文件 / 哪段 prompt / 哪条流程,读它,记下版本或哈希。
- 判定口径:什么算对。口径必须能被第三方复算,「产出质量好」不是口径,「拆出的值互斥且为区间而非点」是。
- 案例数:默认 10。低于 5 不足以谈共性。
被测物版本不可判时,取「评测跑不下去时的兜底」表中以 被测物版本不可判 开头的那一行;判定口径第三方复算不了时,取以 判定口径第三方复算不了 开头的那一行。
2. 自己生成跨领域案例
由评测方生成,不复用被测方或用户给过的案例。
- 领域必须互相远离(消费品 / 硬科技 / 服务业 / 公共事业 / 内容 / 教育 / 金融…),不要 10 个都是电商。
- 难度分布:约 6 常规 + 3 边界 + 1 明显超纲。全是常规案例测不出天花板,全是边界案例测不出基本盘。
- 案例先落盘成清单再开跑,跑完不许增删——事后挑案例等于作弊。
🔴 CHECKPOINT — 案例清单落盘之后、开第一个子 agent 之前,过一遍。任一命中,先按该条自己的动作处理完再开跑;箭头指向兜底表的,按表处理。三件事都落定之后才开跑,开跑之后再补,前面的案例就白跑了。
- 案例清单已经落盘、且跑完前不会再动吗?(跑完再挑案例等于作弊)→ 尚未落盘的先落盘再开跑;已落盘的按落盘版本全量计入,不得事后增删。
- 判定口径还写不成第三方能复算的一句话吗? → 取兜底表中以 判定口径第三方复算不了 开头的那一行。
- 被测物的版本或哈希还没记下来吗? → 取兜底表中以 被测物版本不可判 开头的那一行。
3. 开干净子 agent
每个案例一个子 agent。子 agent 的 prompt 里只准有:被测物全文 + 该案例输入 + 输出格式要求。
禁止塞进子 agent prompt 的东西:
- 主会话的任何对话历史、背景、已知结论;
- 「注意 X」「别忘了 Y」这类提示——这是在替被测物做它本该自己做的事,测出来的是你的提示力不是它的能力;
- 其他 skill;
- 期望答案、参考答案、评分标准;
- 输出数量上限(限制数量会掩盖"拆不全"这个失败模式,让残缺看起来像克制)。
🛑 STOP — 每个子 agent 的 prompt 发出前,对照上面这份禁止清单过一遍。任何一条混进去了,取「评测跑不下去时的兜底」表中以 子 agent 的 prompt 被污染 开头的那一行处理——被污染的样本不是「效果差」,是无效数据。
并发跑。子 agent 之间不得互相看见。开不起来或中途失败,取「评测跑不下去时的兜底」表中以 子 agent 跑不起来或中途失败 开头的那一行处理——那是样本损耗,不是案例不通过。
4. 并行建人类基准
主 agent 在子 agent 跑的同时联网检索:这些案例,业内/人类通常怎么做。找真实的行业分类法、标准、成熟方法论、公开实现,而不是自己凭感觉想一套标准。
没有基准的评测只能说出「我觉得不太好」;有基准才能说出「行业标准分 7 类,它只覆盖了 3 类,漏的都是供应链侧」。检索不到基准时,取「评测跑不下去时的兜底」表中以 检索不到该领域的人类基准 开头的那一行处理,不得凭感觉编一套标准顶上去。
5. 逐例判定
对每个案例记录:输入 / 实际产出 / 基准 / 差异 / 命中的问题标签。 判定只写观察到的事实,此时不要归因、不要提修复方案。
6. 归纳共性
🛑 STOP — 排序之前先接受一个可能的结果:没有共性问题。真没有共性时,正确的报告是「未发现共性问题,基本盘稳定」,不是把单点问题升格成共性凑一份报告。
把问题标签按出现次数排序。没有一个标签达到共现阈值时,取「评测跑不下去时的兜底」表中以 跑完发现没有任何问题标签达到共现阈值 开头的那一行处理。
- 共性问题:≥3 个案例(或 ≥30% 案例)共现 → 进正文,是主要产出。
- 单点问题:1-2 例 → 进附录,一句话带过,不占篇幅。
对每条共性问题给出根因假设并标注证据强度。根因假设要落到被测物的具体段落("SKILL.md 第 3 节的维度模板过强,压过主题语义"),落不到具体位置的根因假设是空话。
7. 报告
## 评测结论:<被测物> @ <版本>
口径:<可复算的判定标准> 案例:N(M 领域) 通过:X/N
### 共性问题
1. <一句话问题>(命中 8/10)
证据:案例 2「咖啡」/ 案例 5「芯片」/ 案例 9「养老社区」均产出「类型构成/应用场景/发展趋势」
基准差距:<检索到的人类做法> vs <实际产出>
根因假设:<被测物具体位置> · 证据强度 高/中/低
### 逐例明细
| # | 领域 | 输入 | 结果 | 命中问题 |
### 附录:单点问题(不构成共性,供参考)
8. 对比模式(证明"真的改善了")
被要求验证改动效果时:必须换一套全新案例,不能重跑旧案例集。
旧案例集在上一轮已经被用来指导修改,在它上面分数必然上升——那测的是过拟合,不是能力。同领域分布、同难度分布、不同具体案例,报告新旧命中率对照。
反模式
污染子 agent
✗ 「你是拆词专家,注意要拆成区间不要拆成点,现在拆解:咖啡」
—— 「拆成区间」正是要测的能力,你替它答了
✓ 「<SKILL.md 全文>」+「拆解:咖啡」
案例复用
✗ 用被测 skill 文档里的示例当测试案例 —— 它一定过
✓ 自己造 10 个跨领域新案例
把单点当共性
✗ 「案例 7 少了个逗号」写进主要发现
✓ 逗号进附录;「8/10 个案例维度雷同」才是主要发现
无基准空评
✗ 「维度划分不够合理」
✓ 「行业标准按帮筒高度/鞋头形态/闭合方式/跟型 4 轴分类,它只用了 1 轴」
事后挑案例
✗ 跑完发现 3 个特别差,说这几个案例出得不好,去掉再算
✓ 案例清单跑前落盘,跑完全量计入
评测跑不下去时的兜底
以上流程假设子 agent 开得起来、基准检索得到、被测物版本可判。下列情况按表处理,不得静默降级结论。
| 触发条件 | 一线修复 | 仍失败兜底 |
|---|---|---|
| 子 agent 的 prompt 被污染(混入了禁止清单里的任何一条) | 该案例作废:清掉污染源重开一个干净子 agent,重跑该案例,并另造一个案例补足数量——补入的案例必须在看到本轮任何产出之前定妥,不得按结果好坏挑选 | 同一个案例连污染两次 → 停用该案例,在逐例明细里标「无效样本」,不计入通过率分母;有效样本跌破 5 时取本表中以 子 agent 跑不起来或中途失败 开头的那一行处理 |
| 子 agent 跑不起来或中途失败(超时、拒绝、环境限制、并发被掐) | 该案例原样重跑一次;仍失败就在逐例明细里标「未完成」,并写明失败原因 | 有效样本跌破 5 → 不出共性结论,只交逐例明细并明说样本量不足以谈共性;不得把「未完成」计为不通过拉低通过率 |
| 检索不到该领域的人类基准(冷门领域、无公开分类法) | 换检索词,并向邻近领域的成熟方法论借(无公开分类法的领域,往往有相邻行业的标准可参照) | 仍无基准 → 该案例「基准差距」列写「无基准」,只用「多例共现」这条腿下结论,报告里把证据强度上限标为中,不得凭感觉编标准 |
| 被测物版本不可判(同名文件多份、无版本标记、评测中途被改) | 取最新一份并记哈希写进报告;能问到用户就直接问 | 仍不可判 → 停止评测:版本不可判的评测结论不可复算,先请用户指定唯一被测版本再开跑 |
| 判定口径第三方复算不了(写的时候就没写清,或跑完才发现) | 把口径重写成可复算的一句话;还没开跑就重写后再开跑,已经跑完就重写后重跑——不得在跑完后悄悄改口径去适配已有产出 | 口径始终无法复算 → 降级为「探索性结论」,报告首段显式声明口径不可复算、结论不可作为改动依据 |
| 跑完发现没有任何问题标签达到共现阈值 | 核对标签是否切得太细:把同根因的标签合并后再排序,往往合并后达标 | 合并后仍无共性 → 照实报「未发现共性问题,基本盘稳定」,附单点问题附录;不得为了交付一份像样的报告把单点升格为共性 |
与其他 skill 的关系
- 上游:
understand-first—— 先确认判定口径没理解错,再开跑。 - 下游:
prompt-forge—— 本 skill 只诊断不修复;拿结论去改是 prompt-forge 的活。被它循环调用。 - 区别于
analyze-only:analyze-only 是静态只读分析,本 skill 要真实执行、要产生新数据。