每个评测套件(eval suite)最终都会被精简。有人注意到套件运行需要 9 分钟,每次运行成本 40 美元,而且里面充满了没人记得为什么要写的用例。他们提交了一个名为 “清理陈旧评测用例” 的 PR,删除了 40 条 “看起来不再相关” 的条目,CI 运行时间降到了 4 分钟。PR 获得了点赞。没人反对,因为删除测试看起来就像是在做维护。
这不是维护。每一个评测用例都是团队对自己做出的承诺:这种失败模式不会再静默地发生。 删除用例就意味着撤销了这项保证。通过率没有变化,仪表板依然是绿色的,唯一消失的是团队对这项保证曾经存在过的记忆。六个月后,一次模型迁移重新引入了被删除用例所防范的回归,复盘(postmortem)重新发现了团队已经支付过代价的教训,然后有人写道 “我们应该为此添加一个测试” —— 而这个测试正是之前在清理 PR 中被删除的那个。
这种不对称性正是问题的核心。添加评测用例是可见的工作 —— 它会出现在代码审查中,有作者,通常还会引用某个事故。而删除用例则是不可见的工作,因为一个仍然通过的小型套件看起来绝对比大型套件更好。因此,套件在严密审查下增长,却在缺乏关注时萎缩。这恰恰反了。删除是风险更高的操作,但却是没人审查的操作。
评测套件是承诺的分类账
传统的单元测试套件具有一种宽容的属性:它的大多数用例都是可推导的。如果你删除了一个纯函数的测试,一个胜任的工程师可以通过查看该函数,从头开始编写一个等效的测试。测试编码了在代码中仍然可见的逻辑。
评测套件并非如此运作。其中很大一部分用例是无法从任何地方推导出来的 —— 它们是 从现实中收割而来的。用例之所以存在,是因为特定用户输入了特定内容,模型给出了特定的错误答案,而有人判定这类失败值得防范。这种渊源正是该用例的全部价值所在。输入是一个任意字符串。预期的行为是某人在真实事故的压力下做出的判断。删除该用例,代码库中就没有任何东西可以用来重建它。你不是移除了一项测试;你是移除了一项你再也无法观测到的关于世界的实情。
这就是为什么 “像对待代码一样对待评测数据集,进行版本控制,精简过时用例” 这种标准建议只对了一半。对数据集进行版本控制保留了已删除用例的 内容 —— 你可以通过 git log 找回 JSON 文件。但版本控制无法保留的是 信号。未来的工程师不会去检索一万行数据集历史,想知道某个失败模式是否曾经被测试过。他们看的是当前的套件,发现没有针对他们刚发布的 Bug 的用例,于是得出结论:团队从未考虑过这个问题。被删除的保证在功能上已经消失了,尽管在技术上那些字节是可以恢复的。
因此,与其将套件理解为数据集,不如将其理解为分类账(ledger)。每一行都是一个承诺:我们已经决定这种行为很重要,并且我们致力于检测它的回归。 一个删除了 40 行的清理 PR,就是 40 个被打破且没有记录在案的承诺。
为什么套件会因为错误的原因被精简
精简的压力是真实的,且理由通常在表面上是合理的:
- 成本。 每个用例都是一次 LLM 调用,如果你使用 LLM 评审员(LLM judge),通常需要多次调用。每个 PR 运行数千个用例是一笔实打实的支出。
- 延迟。 一个 9 分钟的评测门控会让工程师养成合并后就走开的习惯,这使门控失去了意义。
- 噪点。 用例会漂移。产品发生了变化,用例的预期输出现在是错误的,它因为与模型质量无关的原因而失败。一个不稳定的用例会削弱对整个套件的信任。
注意这三点的共同之处:它们都是关于用例 成本 的论点。没有一个是关于该用例所编码的保证的 价值 的论点。而进行精简的工程师几乎总是在优化他们能看到的东西 —— CI 时间、API 账单 —— 而忽略了他们看不到的东西,即这种特定失败模式再次发生的概率。
这种信息差距就是组织层面的裂缝。从结构上讲,为了速度而精简套件的人,并不是当保证失效时被传呼(paged)的人。精简人员在本赛程中进行基础设施维护。而错误删除带来的代价则落在未来的值班工程师身上,可能是在另一个季度,甚至在另一个团队,他们无从得知这种失败曾被预料到。清理工作之所以感觉是免费的,恰恰是因为它的账单被寄给了别人。
真正陈旧的用例 —— 其预期输出与当前产品行为相矛盾的用例 —— 应该 被移除。重点不在于套件必须只增不减。重点在于 “这个用例有噪点” 和 “这个保证不再重要” 是两个不同的命题,而清理 PR 将它们混为一谈。
借鉴 API 的弃用生命周期
软件行业在退休(retiring)某些其他方依赖的东西方面已经有了成熟的模式,而且没有人将其仅仅视为“清理”:那就是 API 弃用(API deprecation)。你不会因为流量看起来很低就直接删除一个端点。你会将其标记为已弃用(deprecated),并注明原因和日期;在消费者迁移期间保持其服务;当你最终移除它时,你会返回 410 Gone —— 这一响应明确表示“该内容曾经存在且是故意退休的” —— 而不是返回 404 Not Found,后者表示“这从未存在过”。整个生命周期的设计初衷是将移除变成一个深思熟虑、可审计、多步骤的行为,而不是仅仅按下删除键。
Eval 案例也值得拥有同样的生命周期,因为 Eval 案例也有消费者 —— 每一位未来的工程师,以及每一个被该案例默默保护的未来模型迁移。有四个实践可以直接移植:
1. 先弃用,再删除。 要退休的案例会被标记为 deprecated,并注明原因和日期 —— 例如 “产品规格于 2026-04 变更,预期输出不再有效” —— 并在一个确定的窗口期内保留在套件中,虽然不计入通过率门槛,但依然可见。它将在稍后一个单独的 PR 中被移除,该 PR 的唯一任务就是移除。这能将“修正绿色数值”这一带有干扰性的动机与“退休保证”这一重大的决定分开,从而让每一项都能得到公正的评判。
2. 要求每个案例都有出处(provenance)。 一个案例应该指明它所防范的事件、工单或失败模式。这不是官僚主义;而是让删除操作变得“可评审”的字段。“删除这个案例”是无法回答的。但“删除这个案例,它防范的是 2025-11 的那个由于重试结账导致 Agent 重复收费的事件”,是一个评审者真正可以权衡的问题。没有出处的案例总是最先被修剪掉,不是因为它们毫无价值,而是因为没有人能为他们看不见的东西辩护。
3. 留下墓碑(tombstone)。 当一个案例最终被移除时,留下一个持久的记录 —— 就在测试套件自己的目录中,而不是埋没在 git 历史里 —— 记录失败模式、保护它的案例以及它被退休的原因。未来如果有一位工程师在通过 grep 搜索某个症状时,应该能“撞上墓碑”,并了解到这个失败点曾经被测试过,且是经过深思熟虑后退休的。这就是 Eval 的 410 Gone:它将一个沉默的缺口转化回一个可见的、有解释的决定。什么都搜不到的 grep 无法提供任何教训。
4. 审批流程要与风险挂钩。 退休一个防范用户可见失败(如金钱流动、数据丢失、安全边界)的案例,应该需要与退休该功能本身相同的评审流程。如果发布该功能需要资深人员签核,那么放弃其回归防护也同样需要。清理类 PR 并不是做此类决定的正确场所,由任何刚好有空的人进行单一审批也不是正确的审查级别。
这一切都不需要新工具。它只需要一个带有 provenance 和 status 字段的 schema,一个墓碑文件,以及一条类似于 CODEOWNERS 的规则,将高风险案例的删除路由给正确的评审人。
底层的滞后指标陷阱
删除之所以危险,还有一个更深层的原因,这关乎整个测试套件的形态。大多数 Eval 套件的增长方式都如出一辙:生产环境发生了故障,写了复盘报告(postmortem),添加了一个案例以防故障再次悄悄发生。这是很好的实践 —— 将事故转化为回归覆盖正是复盘文化的意义所在。但它产生了一个没有人明说的结构性后果:套件的形态完全由事故队列决定。 它成了团队已经幸存下来的失败类别的博物馆。
这使得高通过率成了一个穿着前瞻指标外衣的滞后指标。98% 的通过率证明了系统针对“过去”的防御力。对于下一个模型迁移、下一次 Prompt 修改或下一次用户行为转变可能引入的新型失败模式,它只字未提。
删除案例攻击了套件最薄弱的环节。套件已经过度索引了“后视镜”;最容易被修剪掉的往往是那些“老”案例,那些起源事件久远到当前没有工程师记得的案例。而这些案例防范的正是团队遗忘得最彻底的失败模式 —— 也就是说,这些失败模式最有可能在不经意间卷土重来。清理并不会均匀地修剪套件。它系统性地侵蚀了最古老的保证,而这些保证恰恰是制度记忆(institutional memory)已经衰减为零的部分。
解决方法不是“永不删除”。而是以获取案例时同样的深思熟虑去删除。那个案例曾让你付出了一个事故的代价。退休它也应该让你付出一个决定的代价。
周一具体要做什么
你不需要启动一个大项目。你只需要让一个动作变得更难,让另一个动作变得可见。
- 在你的 Eval 案例 schema 中增加两个字段:
provenance(案例存在的原因或事故出处)和 status(active / deprecated)。优先为高风险案例补齐出处;没有来源的案例是无法辩护的。
- 禁止在清理类 PR 中进行删除。 涉及代码或配置更改的 PR 不得删除 Eval 案例。退休应该有其独立的 PR,标题即为该决定。
- 在 Eval 目录下创建一个
tombstones 文件。 每个退休的案例都留下一行记录:失败模式、日期、原因。让它成为未来工程师在 grep 搜索时会撞上的东西。
- 将高风险的删除操作路由给 那些负责签核功能变更的评审人。
- 审计后视偏见(rearview bias)。 标注每个案例是在防范“已知”失败还是在探索“未知”失败。如果第二个数字接近于零,那么你的绿色仪表盘衡量的是针对两个季度前威胁模型的信心 —— 而这是一个无论多么谨慎的删除都无法解决的问题。
一个 Eval 套件是你的团队关于系统如何失败所学到的一切的底层记录。对待删除要像对待它本质上所代表的东西一样:不是在整理家务,而是在退休一个承诺 —— 并且请记录下会议纪要。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部