看看大多数智能体(Agent)评测集是从哪里来的。有人构建了智能体,向团队演示,演示成功了,于是演示脚本就变成了评测套件。那些通过评审的案例,正是有人已经亲眼看到它们运行成功的案例。评测集在构建之初,几乎就是“快乐路径”(Happy path)的录音——即在截屏当天成功运行的那一段工具调用序列。
所以,当仪表盘显示智能体得分为 94% 时,它实际上是在说:它通过了我们能想象到的案例。它完全没有提及搜索 API 在多步计划中途返回 429 错误的情况,或者用户推翻了两轮前设定的约束的情况,亦或是检索结果为空,智能体必须在胡乱猜测和承认不知道之间做出选择的情况。这些情况并非没有通过你的评测。它们压根就没在评测里。
这就是黄金路径偏见(Golden-path bias),除非你刻意对抗,否则它就是智能体评测套件的默认形态。解决方法不是增加案例数量,而是增加不同种类的案例——这些案例应根据失败模式(Failure mode)来选择,从生产环境中收集,并针对刻意引入的故障进行压力测试。
为什么评测集会向演示脚本靠拢
这种偏见并非源于懒惰,而是评测编写过程中自带的“阻力最小路径”。
当你坐下来构思测试案例时,你会写下你能想象到的场景。你想象用户提出了一个清晰的问题,智能体调用了正确的工具,工具返回了干净的数据,智能体组织出了正确的答案。这是一个连贯的故事,所以很容易写下来。至于那种用户提问含糊不清、得到部分答案、重新调整表述,而智能体必须在三轮对话中跟踪这些更正的情况——这很难想象,所以就不会被写下来。
生产数据也有同样的偏差,但原因不同。历史对话记录偏向快乐路径,是因为体验糟糕的用户通常直接离开了。他们不会提交工单,也不会给对话评分。他们直接放弃,而那段追踪记录躺在你的日志里,看起来就像任何其他短会话一样。如果你均匀地对对话记录进行抽样,你就会过度抽样那些进行得顺利的交互,因为那些进行得糟糕的交互由于幸存者效应(Survivorship)而悄无声息地被低估了。
而且一旦评测套件存在,它就会僵化。它变成了回归测试的门槛。每一项改动都必须通过它,所以没有人愿意增加那些会导致绿色数字下降的难题。本该衡量质量的套件变成了一个你需要维护的东西。在生产中发现的新失败模式在提示词中得到了修补,却从未回到评测集中,因为加入它们会让分数看起来更难看。
结果就是,评测套件在一种特定条件下运行同一个工具序列数千次,并将其报告为覆盖率。
“通过”意味着“通过了我们想象中的案例”
对一份合格评测的诚实解读其实很窄。在黄金路径套件上 94% 的通过率告诉你,智能体擅长处理那些已经有人想到并写下来的情况。对于除此之外的一切,它都保持沉默。
这很重要,因为真实用户不会留在快乐路径上。他们会离题,会在对话中途改变话题,会自相矛盾。他们会粘贴格式错误的内容,一次问三个问题,并在中途放弃最初的目标。伯克利(Berkeley)的 MAST 多智能体失败分类法(Cemri et al., 2025)编录了 14 种不同的系统级失败模式——任务偏离、步骤间信息截留、过早终止——其中惊人数量的模式在单个干净请求的层面上是不可见的。它们只有在事情出错时才会出现。
“通过评测”与“在生产中运行良好”之间的差距,恰恰是评测从未涵盖的那组场景。你可以弥补这一差距,但不是通过更多次地运行快乐路径套件。在错误的分布上堆砌数量,只会得到一个更自信的错误答案。一个包含 500 个黄金路径案例的套件并不比 50 个更可靠——它只是以更多的代码位数测量了同样的盲点。
第一步是停止统计案例数量,转而统计失败模式。
覆盖率意味着失败模式,而非案例数量
重新审视这个问题。不要问“我们有多少个测试案例”,而要问“这个智能体有哪些失败方式,以及评测套件实际演练了其中哪些方式”。
将列表明确化。对于典型的使用工具的智能体,它包括以下内容:
工具错误 —— 工具返回了 429、500、超时或格式错误的负载,而不是干净的数据。
空结果 —— 检索或搜索返回空结果,智能体必须在推诿、询问澄清问题或产生幻觉之间做出选择。
矛盾 —— 用户设定了一个约束,几轮之后又设定了一个不兼容的约束。
歧义 —— 请求确实存在多种解读,正确的做法是询问,而非猜测。
超出范围的请求 —— 用户要求的某些事情,智能体应该拒绝而非尝试。
多步偏离 —— 第三步失败了,智能体必须重新规划,而不是守着过时的计划蛮干。
长上下文漂移 —— 当对话变长后,早期给出的指令被忽略了。
现在建立一个覆盖矩阵:一个轴是失败模式,对于每一个模式,看看有多少评测案例真正演练了它。当一个团队第一次诚实地这样做时,矩阵大多是空的。12 种失败模式,其中 10 种案例数量为零。那个空荡荡的矩阵是比 94% 这个数字更有用的产物,因为它准确地告诉了你哪些地方正处于盲目状态。
这也修复了一个更隐蔽的缺陷:单边评估(One-sided evaluation)。如果你只测试“智能体应该调用搜索工具”的案例,你就会优化出一个总是进行搜索的智能体,即便不该搜索时也是如此。Anthropic 在为 Claude 构建搜索评测时的叙述明确提到了这一点——他们构建了双向案例:既有应该触发搜索的查询,也有模型应该根据现有知识回答的查询,这样校准才有对抗性。按失败模式计算覆盖率会强制你包含负面案例,因为“应该拒绝”和“不应搜索”也是失败模式。
收集失败案例,而不是捏造案例 一旦你知道矩阵中的哪些单元格是空的,你就需要案例来填充它们。捏造这些案例很难,而且捏造出来的案例往往显得很生硬。真实的失败案例比任何你凭想象写出的东西都更离奇、更有启发性。所以,请从生产环境中收集它们。
障碍在于幸存者偏差(survivorship skew):糟糕的会话往往被隐藏起来。均匀抽样无法让它们显现。所以,请改用异常信号进行抽样。调出最有可能包含真实失败的追踪记录:异常长的会话、工具错误率较高的会话、自动质量评分较低的对话、用户重复说话或表达沮丧的会话、达到步骤上限的运行。这些信号并不直接告诉你该会话失败了——它们告诉你这值得人类去关注。
然后由人工阅读这些记录。错误分析不是可选的,也无法自动化。在你能为某个失败编写 eval 之前,你必须能够清晰地阐述这个失败是什么,而这源于阅读对话记录。做得好的从业者会将大部分 eval 精力花在这里——阅读、分类和标记真实的失败——而不是构建评分器。对话记录审查能揭示通过率数字无法显示的模式:智能体(agent)道歉并重试完全相同的失败调用,或者在上下文变长时悄悄丢弃用户的约束条件。
将其变成一个常设循环。每一个诊断出的生产环境失败都会变成至少一个全新的 eval 案例,带上完整的上下文,并标记它所属的失败模式。这样,测试套件就会沿着真正重要的维度——失败模式覆盖率——而增长,而不仅仅是在理想路径(happy path)上越变越长。几个月下来,这就是反映现实的 eval 集与反映演示效果(demo)的 eval 集之间的区别。
注入你等不及观察到的故障 有些失败模式太罕见或太危险,无法坐等它们发生。在发布之前,你可能无法获得每一个工具返回每一种错误类型的干净生产案例。对于这些情况,请人为制造失败:故障注入(fault injection)。
这个想法借鉴自分布式系统,在那里,像服务网格(service-mesh)故障注入这样的工具会故意引入错误——延迟、丢包、错误代码——以验证超时、重试和断路器(circuit breakers)是否真的起作用。同样的策略也适用于智能体的工具。将每个工具封装在一个测试套件中,该套件可以根据指令返回 429、500、超时、空结果、截断的有效载荷或错误的数据类型。然后运行智能体并观察它的表现。
这能捕捉到一个特定且常见的 bug。智能体会将工具输出视为文本进行推理。频率限制错误和合法的空结果都以字符串形式出现,模型通常会以相同的方式对待它们——它天生不知道一个意味着“退避并重试(back off and retry)”,而另一个意味着“告诉用户这里没有任何内容”。故障注入能让你在客户发现之前,弄清楚你的智能体是会带退避地重试、回退到另一条路径、询问用户,还是仅仅自信地胡编乱造。
构建一套简单的标准测试,并将每个工具都跑一遍:每个错误代码、空结果、超时、畸形的有效载荷、缓慢的响应。对于多步智能体,在第三步而不是第一步注入故障——有趣的问题在于智能体是会重新规划,还是会继续执行过时的计划。通过标准很少是“任务仍然成功”。而是“智能体以你预期的路径降级”——显现错误、合理重试或利落且干净地交还给用户。
本周该做什么 你不需要为了逃避理想路径偏见(golden-path bias)而重建你的 eval 基础设施。你需要改变你关注的对象。
从矩阵开始。列出你智能体的失败模式,列出目前有多少 eval 案例触及了每一个模式,并接受大多数单元格将是空的这一事实。这个产出物会告诉你目标在哪。然后开启基于异常的抽样,阅读 20 份真实的对话记录,并将你发现的每一个真实失败转化为带标签的 eval 案例。与此同时,将你最重要的三四个工具封装在故障注入套件中,并运行标准测试。
仪表板上的数字可能会下降。这正是重点所在。理想路径上 94% 的成功率从来都不是在衡量智能体是否有效——它是在衡量你想象成功的能力有多强。在一个包含空检索、自相矛盾的用户以及在中途返回 429 的工具的矩阵中,80% 的成功率更有价值,因为这是第一次在衡量你的用户实际会走的路径。
会员专享
余下内容仅对会员开放。 会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
— 完整文章,包含未公开存档的部分 — 可落地的工作框架,附带权衡与决策依据 — 新文章抢先看,先于公开发布 登录以继续阅读→ 随时取消 · 一次订阅,畅读全部