> 把失败归因给模型之前,先审 verifier——41% 的"模型错误"其实是判分 bug

Machine Learning Theory 中级 2026-09-06 07:21 2026-09-06
#evaluation #benchmark #ifeval #verifier #failure-analysis

跑一个自动判分的 benchmark,拿到 81% 通过率之后, 第一件事不是分析模型为什么错,是逐条看那 19 个失败案例。

// TABLE_OF_CONTENTS

结论先行

跑一个自动判分的 benchmark,拿到 81% 通过率之后, 第一件事不是分析模型为什么错,是逐条看那 19 个失败案例。

一次实际的分类结果(IFEval,n=100,19 个失败):

类别 数量 占失败 真实根因
JSON 格式检测 5 26.3% verifier bug
高亮段落检测 2+ ~15% verifier bug
字数限制 2+ ~15% 模型生成
关键词频率 1+ ~10% 模型生成
标点(禁逗号) 1 5.3% 模型生成

超过 40% 的"失败"是判分器的问题,不是模型的问题。 不看就直接写"模型在指令遵循上有 19% 的失败率",这个数字是错的, 而且错在系统性高估模型缺陷的方向上。

为什么

两个 bug 都极其典型,值得当成模板记住:

1. json.loads(response) 直接解析原始输出。 LLM 几乎总是把 JSON 包在 markdown 代码块里:

```json
{ ... }
```

判分器看到反引号就解析失败,判为"没有按 JSON 格式输出"—— 而模型完全正确地按 JSON 输出了。5 个案例,全部同一原因。

2. 高亮检测只认 **bold**# header 模型用了 *italic*`code` 就判为"没有高亮段落"。 指令说的是"highlighted sections",模型的理解合理,判分器的枚举不全。

共同结构:判分器把"一种正确的表达方式"当成了"唯一正确的表达方式"。 这在任何基于格式/正则的自动判分里都会发生,而且只会朝一个方向出错—— 误判为失败,从不误判为成功。所以它不是噪声,是偏差

怎么用

每次拿到自动判分结果,先做失败案例审计。 流程:

  1. 把所有失败案例导出来,人工看一遍。 n=19 的时候这是十几分钟的事。 即使 n=200,抽 30 个也足以估计 verifier bug 的比例。
  2. 给每条标根因,只有三类:verifier bug / 模型生成 / 指令本身歧义。 第三类经常被忽略,但它决定了这一条该不该计入分母。
  3. 修完 verifier 重跑,报修复前后两个数,并说明差异来自判分器。 直接只报修复后的数,等于隐瞒了 benchmark 的一处缺陷。
  4. 把 verifier bug 的比例本身当作一个结果报出来—— 它是关于这个 benchmark 可信度的信息,对社区有价值。

预防性检查(写 verifier 时):

检查 问题
解析前是否剥离 markdown 代码块 JSON / YAML / 代码类判分的第一大 bug
格式枚举是否穷尽 **b** *i* _i_ __u__ `c` 都算高亮吗
大小写、全角半角、多余空白 中英混排时尤其
失败时能否给出原始片段 只报 pass/fail 的 verifier 无法审计

最后一条是根本性的:verifier 必须记录它判失败时看到的原文。 不记录就没法做上面的审计,于是所有判分 bug 都会永久伪装成模型缺陷。

同源:指标的默认回退是静默的——而且 p 值不是效应量(指标含义错)、 区分"近似漂移"和"真 bug":用发散位置,不用最终指标(把 bug 当成方法的正常代价)。 三者都是"数字是对的,解释是错的"。

出处

  • ~/Projects/SynthEval/results/FAILURE_ANALYSIS.md(IFEval 官方 benchmark, n=100,GPT-4o-mini)