症状与误诊
一个团队上线了 agent,运行评估套件,看着聚合分数攀升几周后趋于平缓。有时它会突增,然后在没有任何代码变更的情况下于下一次运行中衰减。本能反应是去动架构:换掉 planner、加一个 critic agent、扩大 retrieval 窗口、修改 tool-calling schema。数周的工程投入砸向一个从来不在模型里的问题。
评估集本身已经漂移。条目被就地编辑却没有版本号递增。一个针对少量样本调优的 prompt 模板,悄悄把这些样本吸收进了它的 few-shot 块。一个基于内部文档构建的 retrieval 索引,恰好包含了评估问题及其答案。分数变了,因为测量工具变了,而没人注意到,因为工具从未被当作一件制品来对待。
有帮助的框架是这样的:评估集就是一个数据集。它有作者、来源、许可约束、隐私暴露面、分布和生命周期。把它当作一个谁都能编辑的 JSON 文件夹,是大多数污染的根因。修复之道不是更聪明的模型。修复之道是把应用于训练数据的同一套纪律,应用于你用来测量的东西。
把评估集当作带版本的制品
评估集一旦发布就应当不可变。不是「我们尽量不编辑它」——而是结构上不可变,每次修订都按内容寻址,这样一次运行就能精确记录它是对着什么评分的。
一个可行的机制是清单(manifest),它对每个条目以及整个集合做哈希:
set: agent-tool-use-core
revision: 2024-11-07.3
items_hash: sha256:9f2c...
item_count: 412
retired:
- id: tool-0183
reason: saturated
superseded_by: tool-0411

harness 在运行开始前把 revision 解析为内容哈希,并把该哈希写入结果记录。如果哈希与清单不匹配,运行即中止。这一条约束就消除了一整类缺陷:你上个月对比的分数是对着另一件工具产生的,而现在系统拒绝让你假装不是这样。
不可变性是有代价的。当一个条目确实错了——措辞有歧义、tool-call 轨迹里有过时的 API 签名、一个事实性答案此后已改变——你无法修补它。你只能将其退役并添加替代项,这意味着集合会长出一条谱系,你的历史对比需要把这次替换纳入考量。跳过这套纪律的团队会得到看起来更干净、实则悄悄失去意义的时间序列。这个权衡是真实的,值得点明:你在用便利换取信任自己趋势线的能力。
留出集纪律
评估条目不得出现在开发期间使用的任何 prompt、retrieval 索引、微调语料或 few-shot 样本中。这听起来显而易见,却经常被违反,通常是通过 retrieval。
当一个 agent 对内部文档有 retrieval 步骤,而评估集存放在同一个仓库或同一个向量存储中时,一个语义上接近评估问题的查询就会把评估条目翻出来。agent 于是从评估集而非从能力作答。输出里看不出任何问题;分数就是涨了。
能抓住这一点的手段是金丝雀(canary)。在评估索引中植入正确答案已知、且被标记为金丝雀的条目。将它们与主集分开评分,并把金丝雀命中率作为污染率上报。如果金丝雀被检索到或被正确回答的比率高于随机水平,索引就在泄漏,头条数字就可疑。
金丝雀便宜且不完美。它们能检测经由 retrieval 路径和 prompt 构造的泄漏,但检测不出预训练期间烙进模型权重里的记忆。对此,唯一可靠的信号是时间性的:在模型训练截止之后编写的条目,或从未发布过的私有池中的条目。两者都限制了你能测量的东西,因为私有池无法与公开排行榜对比。这就是权衡——外部可比性对内部可信度。
来源与访问
每个条目都应携带其来源和作者。不是为了署名,而是为了在许可和隐私约束发生变化时能够重新评估它们。两年前允许使用的数据集今天可能不再

访问控制是另一半。评估集应当只对 harness 可读,几乎不对其他任何东西可读。迭代 prompt 的工程师不需要对评估条目的读权限;他们需要的是聚合结果和分片明细。把读权限授予那些工作就是提高分数的人,会制造明显的过拟合动机,哪怕意图良好。
除访问控制之外,记录开发期间每一次触及评估索引的 retrieval。一份显示评估条目在开发会话中浮现的 retrieval 日志就是一次污染事件,无论它是否改变了某个决策。日志让事件事后可审计,而不是不可见。
这里诚实的权衡是速度。限制评估读权限会拖慢调试循环,因为怀疑某个具体失败模式的工程师不能直接打开条目来读。补偿办法是一个单独的、公开可读的开发集,明确不用于上报。两个集合,两种用途,其中一个上锁。
上报实践
一个没有修订版本和污染率的头条数字不是一次测量。它是一个主张。任何发布的分数都应同时携带集合修订版本、内容哈希和由金丝雀得出的污染率。如果污染率不可忽略,该分数应连同这一说明一起上报,而不是作为一个单一数字。
聚合还会掩盖回退。对混合集合取单一平均值,会掩盖某项能力退化而另一项能力提升的事实。按能力分片上报——工具选择、参数构造、多步恢复、拒绝行为——并以与聚合相同的修订纪律上报它们。在一个只有几十个条目的集合上小幅变动的分片不是信号;上报条目数,让读者自行判断。
最后,按计划退役饱和条目。一个当前所有模型都能通过的条目,除了一个好看的基线和被稀释的平均值之外毫无贡献。累积饱和条目会让套件看起来全面,同时让聚合值每个季度都更缺乏信息量。退役它们,在清单中记录退役,并用有区分度的条目替换。
这一切都不光鲜。它是应用于测量工具的数据工程,也是「有意义的分数」与「因为管道动了而动的分数」之间的区别。
封面照片:panumas nikhomkhai / Pexels。