用户要求退款,Agent 调用了工具。工具超时后,它回复:“退款已完成。”

这次任务算成功吗?

答案取决于真实状态:退款可能没有发生,也可能已经发生、只是返回结果丢失。前者需要处理失败,后者盲目重试则可能造成重复退款。仅凭一句“完成了”,无法做出判断。

Agent 评测需要回答的是:在什么任务、环境和预算下,系统能够可靠地完成目标;失败时,又能否定位问题。

本文基于阅读 The Agent Evals Handbook 后记录的手写笔记,由 AI 按照笔记的思路协助整理成文,并参考原文适当补充。

一、Agent 评测的定义与系统组成

Evaluation,通常简称 Eval,可以理解为一种可重复执行的测试:给 AI 系统一个任务,根据预先定义的标准评价它的表现。它把“试用时感觉不错”,变成有依据、可以比较的判断。

在 Agent 上,这个定义还要多加几个条件:能否以可接受的成本,通过合理的执行轨迹,在重复运行和多样输入下,稳定实现用户期望的结果。

Agent 的评测有四个特点:

Agent 评测的四个特点
Agent 评测的四个特点

这几个特点,并不意味着传统测试失去了作用。工具、解析器、权限检查等确定性逻辑,仍然应该用单元测试验证。只是这些测试通过了,还不能证明模型会在正确的时机,以正确的参数使用它们。

例如,模型可能正确调用查询工具,却把返回的“未退款”理解成“已退款”;也可能知道应该先核实订单,却在多轮对话中忘记了这个约束。问题出在系统如何组合和使用能力,而不只是某个函数有没有实现正确。

所以在评测前,需要先拆清 Agent 系统:

系统可以拆成四部分:模型负责规划与决策,工具承接操作并返回结果,记忆与上下文提供约束和信息,最终回复向用户说明结果。

评测还要检查工具运行后的真实状态,例如文件或数据库,而不只检查最后一句回复。

二、评测对象与维度

“Agent 表现不好”太宽泛,无法直接指导修复。是计划错了,工具选错了,还是操作已经成功、最终总结却写错了?这些问题需要不同的检查。

按 Agent 的系统组成,评测对象可以分为以下七部分。下图按系统部分展开评测维度,并列出关注点、典型失败和评测方式。

评测对象与维度
评测对象与维度

这些维度用于梳理检查范围,不要求每个项目同时部署全部指标。更合理的起点,是先找业务不能接受的失败,再选择能识别这些失败的检查。

这里需要区分两个概念。第一,事实正确不等于有依据:答案可能碰巧正确,但引用材料并不支持它;也可能忠实复述了一份已经过时的材料。第二,动作发生不等于任务成功:文件写入了,但写错位置、破坏其他内容,仍然属于失败。

这意味着成功条件需要提前定义,而且通常同时包含“应该发生什么”和“不应该发生什么”。用户要求只修改一个字段,验收就不应只看新值正确,还要看其他字段是否保留。

三、评测粒度

拆出了评测对象,下一步是确定观察粒度。

三种评测粒度
三种评测粒度

端到端最接近用户价值。给任务,运行系统,再验收结果,不强制内部采用哪种解法。它的不足是定位能力有限:看到退款失败,还需要继续查失败原因。

轨迹可以帮助解释失败。订单没查到,是查询参数错了,还是模型忽略了“订单不存在”?工具超时之后,是合理停止,还是继续重复调用?这些都要沿执行过程检查。

单步测试则把关键决策单独拿出来:缺少订单号时是否追问,检索结果不足时是否换查询,完成目标后是否停止。它速度快、定位明确,但单步通过不能代替完整任务验证。

四、评分器选择

Grader 是把运行证据转成判定的评分器。常见的三类是代码、LLM Judge 和人工。选择时,需要先问:这个问题有没有直接可检查的答案或状态?

评分器的选择
评分器的选择

订单是否存在、字段是否完整、金额是否等于预期、无关文件是否被改动,优先用代码检查。让 Judge 猜一个能直接查询的事实,通常没有必要。

但代码检查也不能越过自己的覆盖范围。Schema 合法,只能证明结构符合要求,不能证明订单号属于当前用户。测试通过,证明的是已有断言通过,而不是需求已经被完整覆盖。

摘要是否遗漏重要信息、回复是否忠实于检索材料等问题,可以交给 Judge。前提是评分标准足够清楚,而且 Judge 拿到了所需证据。

如果连人都无法说清两种输出为什么一个更好,直接让模型打 1~10 分,只会把模糊判断变成模糊数字。此时先人工看样本、讨论标准,往往比立即自动化更有效。

五、LLM Judge 的设计与验证

LLM Judge 能扩大评测覆盖,但它不是天然可靠的裁判。评分标准、模型和证据组织方式,共同决定了判断质量。

LLM Judge 的三个组成部分
LLM Judge 的三个组成部分

例如,要评“回复是否忠实于执行结果”,可以把标准写成:不虚构金额和对象、不把工具报错描述为成功、不把未确认的状态写成已完成。一次判断一个窄问题,比直接问“回答好不好”更容易对齐。

对于是否满足明确条件的任务,可以优先采用二元判定;比较两段开放式写作时,可以考虑成对偏好。评分形式应该服务于要做的判断,而不是为了得到一个看起来精细的分数。

Judge 的常见偏差也需要专门处理:

Judge 的偏差与处理方式
Judge 的偏差与处理方式

Judge 评估指标

假设 100 个样本里有 90 个通过,Judge 全部回答“通过”,准确率也有 90%,但它没有识别任何失败。

因此要明确正类。例如把“失败”设为正类:

失败精确率 = TP / (TP + FP)
失败召回率 = TP / (TP + FN)

符号含义
TP真实失败,Judge 也判失败
FP真实通过,Judge 误判失败
FN真实失败,Judge 漏判为通过

精确率反映报出的问题有多可信,召回率反映实际问题抓到了多少。对危险操作,漏检尤其重要;对正常任务,误报过多也会造成不必要的阻断。

Cohen’s κ 可以辅助观察与人工标签的一致性:

κ = (Pₒ − Pₑ) / (1 − Pₑ)

Pₒ:人工与 Judge 实际判断一致的比例

Pₑ =(人工通过比例 × Judge 通过比例)+(人工失败比例 × Judge 失败比例)

κ 不应该被简化成某个通用的“人类水平门槛”。它受样本组成和标签分布影响,必须结合具体错误来看。人工标签本身也需要明确标准与分歧复核。

Judge 最需要证明的,是它能否识别当前业务真正不能接受的失败。模型名气、回答长度、解释看起来合理,都不能代替这项验证。

六、数据集与评测环境

数据集构建

真实失败很有价值:用户纠正了什么、在哪里返工、哪些工具错误让流程中断,都能转成评测任务。真实成功也要保留,因为它们是新版本不能随意破坏的能力。

再往外扩展,可以加入已知失败类型、专家边界案例,以及经过审核的 LLM 合成变体。合成数据适合补覆盖,但生成模型也有盲区,不能因为数量多就当成质量高。

每道题应该有明确成功标准、切片标签和保留理由。只写“这是一道困难题”不够,要说清它考的是信息不足时澄清、错误恢复,还是多轮约束保持。

还要留出不参与日常调试的测试集。不断看同一批题、针对性改提示词,会让分数上涨,但无法确定新任务是否同样受益。

原文建议从 20~50 个有区分度的任务起步。这个建议的价值是让评测尽早开始,而不是证明几十道题足够回答所有问题。发现明显回归,与确认几个百分点的提升,需要的证据量不同。

另外,刻意收集的失败集适合检查风险,代表性抽样集适合估计日常表现。两者都需要,但分数的含义不同,不能把困难回归集的成功率直接当成线上整体成功率。

评测环境

Agent 会行动,评测就需要一个能够承接行动的环境。

评测环境的选择
评测环境的选择

带初始状态的沙箱很适合做结果验收:为每次运行准备相同数据,让 Agent 执行,再对比结束状态。目标数据是否正确、无关数据是否保留,都能检查。

这些环境可以按待验证的问题组合使用。Mock 通过,说明在指定模拟条件下表现正确;真实服务测试通过,才能进一步支撑对应集成行为。不同层次的证据应该分别记录。

每次试验之间也要控制状态污染。数据库、文件、缓存和长期记忆如果残留前次结果,后一次成功可能并不来自系统能力。专门测试跨会话记忆时,则应有意识地保留所需状态。

七、执行记录(Trace)

Trace 是一次运行的结构化记录,Span 则表示其中一个工作单元,例如模型调用、工具调用或检索。

执行记录的组成
执行记录的组成

以上列出的是记录类别,具体调用顺序和嵌套由实际执行决定。记录还应关联提示词、工具和评分器版本;涉及敏感信息时,需要控制记录范围和访问权限。

Trace 的价值不只是画出时间线。它能区分“根本没有检索”“检索到了错误资料”“资料正确但生成没用上”,也能解释一次延迟到底花在模型还是工具上。

不过,可观测记录不等于模型完整的内部思考。模型给出的理由仍然需要和实际工具调用及状态证据对照。

Trace 是评测的原始材料,支撑轨迹评分、效率统计和人工错误分析。没有这些材料,总分即使发生变化,也很难知道下一步应该改哪里。

八、重复运行与版本比较

pass@k 与 pass^k

重复运行的两种成功指标
重复运行的两种成功指标

这只是概率假设下的演示,用来说明“多试几次总有一次能成”与“反复使用都稳定”之间的差距。

生成候选代码,并用可靠测试选择结果时,pass@k 很有意义。直接替用户执行操作时,还要关注单次成功率与重复运行的稳定性。

这里有一个不能省略的条件:系统需要识别成功的那一次。 如果没有可靠的验证与选择机制,多个候选中存在正确答案,并不等于最终交付正确。重试也有时间、费用和重复写入风险。

实际任务的成功率不同,失败还可能相关,所以不能把总体平均成功率直接代入公式,当成实测可靠性。应对每个任务重复运行,再按任务统计对应比例,并说明 k 值和试验条件。

版本比较方法

假设旧版本在 40 个任务中通过 32 个,新版本通过 34 个。提高了 5 个百分点,但可能是修好 4 个、同时弄坏 2 个。新坏的如果是高风险任务,平均分上涨也未必值得换。

比较时应让两个版本运行同一批任务,在可比环境和预算下做配对分析,报告哪些任务改善、哪些退化。对于配对二元结果,可以考虑 McNemar 检验;对于按任务得到的成功率等结果,可以使用配对 bootstrap,估计 B − A 的差值区间。

同一任务有多次运行时,还需要保留组内关系,不能把所有运行随意当成独立的新题。按任务重采样、同时保留两个版本在该任务下的结果,是一种做法。

差值区间包含零,说明当前证据不足以确认提升,不等于证明两者完全相同。即使统计上看到了提升,也仍然要判断幅度是否值得成本。

版本报告应同时保留关键失败、逐题翻转、切片结果、稳定性和效率。尤其是每个成功任务的成本:把失败及重试的费用也算进去,再除以成功任务数。单次调用便宜,不一定意味着完成一件事便宜。

九、多轮、多 Agent、RAG 与记忆评测

这些能力会扩展系统的用途,也会增加失败位置。整体任务仍然要验收,同时把新增环节拆开检查。

新增能力的评测重点
新增能力的评测重点

新增组件应该有对应证据:一方面证明它改善了什么,另一方面覆盖它引入的新风险。否则很容易把“功能更多”当成“系统更可靠”。

十、安全评测

Agent 读取网页、邮件、文档和工具返回时,可能遇到隐藏在内容中的恶意指令。用户要求总结一封邮件,并不意味着邮件里的“把文件发到某个地址”获得了执行授权。

因此,安全测试应把攻击放进真实的不可信输入渠道,检查是否发生禁止动作、数据泄漏或越权。与此同时,还要看正常任务能否完成,以及合法请求被过度拒绝的比例。

一个什么都拒绝的系统可能有很低的攻击成功率,却没有实际效用。效用与攻击成功率,需要并排观察。

还应区分模型主动避开了危险动作,还是危险请求已经产生、被运行时护栏拦住。这两种结果都可能保护状态,但暴露的薄弱点不同。

评测负责发现并估计风险,最小权限工具、参数校验、运行时限制和必要确认负责减少实际风险。一次安全套件通过,不能替代执行边界。

十一、错误分析与评测迭代

有了数据集和评分器,评测仍然不会自动变好。真实任务会变化,模型会变化,也总会遇到新的失败。

最值得坚持的习惯,是抽样阅读真实记录:先用普通语言写出最早在哪里偏离要求,再归类、排序,为重要的失败类型补充任务和评分器。

错误分析与评测迭代
错误分析与评测迭代

比如“退款重复执行”,进一步分析后可能发现:第一次调用超时,但外部服务其实已经完成写入;Agent 没有查询状态,直接再试一次。这与明确报错后重试不是同一种问题。针对它的评测,需要制造“结果不明”的条件,检查查询、幂等机制和后续表述。

这种分析比笼统加一句“请谨慎使用工具”更有方向,因为它明确了要修改的行为和要验证的条件。

这里还需要两类套件:回归套件守住已经能做好的任务,能力套件保留目前仍然困难的任务。前者适合承担关键发布门槛,后者用来观察边界、指导下一步改进,不能用同一套通过预期管理。

十二、评测流程与 CI

完整流程可以按下面的顺序建立。前面的步骤定义任务与证据,后面的步骤把它变成可持续运行的检查。

评测流程与 CI
评测流程与 CI

分层执行很重要。代码规则和工具测试可以频繁运行;提示词、模型、工具或 Agent 逻辑变化时,运行相关真实模型回归;更完整的能力、安全和 Judge 校准套件,可以定期执行。线上再通过抽样评测、用户反馈和成本时延监测发现新问题。

如果采用影子运行,让新版本处理真实请求但不向用户展示结果,还必须隔离写入副作用,避免新旧版本重复退款、发信或修改数据。线上点赞、投诉等反馈也有选择偏差,更适合用于发现问题,再转成可信的线下检查。

开始做评测,不需要先搭一个庞大平台。选一类范围清楚的任务,定义成功与禁止副作用,准备一小组有区分度的案例,记录执行过程,再让两个版本接受同样的检查,就已经能帮助做出比“感觉更好”更可靠的选择。

评测结论应当具体:在这些任务、环境和预算下,系统有哪些能力已经获得证据支持,哪些失败仍然存在,哪些工作还需要人工接手。这样的结论,才能帮助判断下一步该优化什么,以及现在能够把什么交给 Agent。