面向 Agent 的 AI 评测(eval):是什么,怎么写
AI 评测是给模型或 Agent 的表现打分的测试。本文讲清 Agent 评测与 LLM 评测的区别、三类评分器,以及用七个步骤写出一个评测。
-
——AI 评测就是给 AI 系统出的一道测试题:把输入交给模型或 Agent,让它跑起来,再用代码、LLM 裁判或人工给它打分。
-
——LLM 评测打分的是一次回答;Agent 评测打分的是一整次运行,包括调用了哪些工具、传了什么参数、留下了什么状态、最后回了什么话。这是因为 Agent 完全可能做错了事,却回一句听起来很对的话。
-
——评 Agent 要看结果,而不是死抠它走的每一步路径——Agent 经常用你没想到的方式把事做成。只有那些必须始终成立的规则才去查路径,比如写操作之前先核实、扣费最多扣一次。
-
——能检查的东西一律用代码评分器;LLM 裁判只用来评判剩下的文字质量。在用裁判卡住发布之前,先用 30 到 50 条人工标注的样本把它校准好。
-
——每个 Agent 任务多跑几遍,报告 pass^k——也就是每一次都解出来的任务占比。在 τ-bench 里,GPT-4o 单次能解出约 61% 的零售任务,但八次全部成功的只有约 25%。
AI 评测就是给 AI 系统出的一道测试:你喂给它输入,让它自己跑,然后用代码、用另一个模型或用人来给它做的事打分。LLM 评测只给一次回答打分。Agent 评测则给一整次运行打分:用了哪些工具、传了什么参数、留下了什么状态、最后收尾的回复是什么。这个差别决定了评测该怎么写。因为 Agent 可能根本没调退款工具,就回一句「您的退款正在路上」;而只看回复的评测,会把这次运行判为通过。
本文先讲清评测由哪些部分组成,说明 Agent 评测和 LLM 评测有什么区别,介绍三类评分器,然后用七个步骤手把手写一个 Agent 评测,并附上一个可以照着改的完整示例。
AI 评估的组成
Anthropic 的 agent 评估指南(Demystifying evals for AI agents ↗,2026 年 1 月)用了一套现在大多数评估工具都通用的术语。这套词值得采用,因为“评估失败了”这句话,可能指的是下面任何一种情况:
| 术语 | 是什么 | 客服 agent 的例子 |
|---|---|---|
| 任务(Task) | 一个测试用例:一个输入,加上成功的标准 | “订单 A1042 到货时是坏的,能退款吗?”成功标准:A1042 上有一笔 59.00 美元的退款 |
| 试验(Trial) | 对任务的一次尝试。agent 每次运行结果会有波动,所以一个任务要跑多次 | 5 次中的第 3 次 |
| 评分器(Grader) | 给试验某个方面打分的逻辑 | “A1042 上恰好存在一笔退款” |
| 记录/轨迹(Transcript / trace) | 一次试验的完整记录:消息、工具调用、工具返回结果、最终回复 | check_refund_policy → issue_refund(order_id="A1042", amount_usd=59.0) → 回复 |
| 结果(Outcome) | 试验结束后世界的真实状态 | 退款表里的那一行数据,而不是嘴上说退了 |
| 套件(Suite) | 一起运行的一组任务 | 120 个客服任务,按路由打了标签 |
一个任务可以有多个评分器,而且通常应该有。一个检查退款是否存在,一个检查是否先查了政策,一个检查回复有没有解释时间线——三者失败的原因各不相同,你需要知道是哪一个出了问题。
LLM 评估 vs agent 评估
两者的术语有重叠,经常被混着用,但它们评的东西不一样。
| LLM 评估 | Agent 评估 | |
|---|---|---|
| 评分单元 | 对一个 prompt 的一次回复 | 一次运行:多次模型调用、工具调用和结果 |
| 可能出什么问题 | 文本错误、跑题或格式错乱 | 用错工具、参数传错、跳过步骤、重复动作、谎报成功,再加上 LLM 评估能抓到的所有问题 |
| 证据在哪 | 输出的文本 | 先看轨迹和结果,再看文本 |
| 确定性 | 不同样本之间有波动 | 波动更大:一次工具调用不同,后面每一步都会跟着变 |
实际后果是:agent 最严重的回归,看起来却像正确结果。模型不再调用 notify_security_team,或者报告了一次根本没做过的地址变更,照样能写出流畅、切题的文字。任何只对文本打分的 eval 都会让它通过。切换 LLM 时真正出问题的地方,需要检查完整的变更面。
三种 grader
所有 eval 的 grader 都逃不出三类,一套好的测试会根据任务不同把三类都用上。
| Grader | 示例 | 成本 | 优势 | 劣势 |
|---|---|---|---|---|
| 代码 | Schema 校验、精确匹配、正则、工具调用检查、数据库状态 | 免费、即时 | 确定性,无可争辩 | 只能检查你能精确指定的内容 |
| 模型(LLM 评判) | 评分量表、两两比较、自然语言断言 | 小型评判模型约每 1,000 次调用 $1 | 能处理开放式文本 | 偏向位置、长度和自身措辞;需要校准 |
| 人工 | 专家评审、抽查、标注 | 评审工时 | 基准真值,其他方式的校准都靠它 | 慢、贵,还会因疲劳而漂移 |
三者的顺序很重要。代码能检查的,统统交给代码;剩下的文字质量交给模型;人来写判定标准、标注一份校准样本,并阅读失败案例。LLM-as-a-judge 会深入讲模型 grader,包括评判模型有多准、怎么验证它。
能力 eval 与回归 eval
Eval 回答的是两个问题之一,混在一起会让数字很难读懂。
-
能力 eval 问的是 agent 能做什么。这类测试应该以较低的通过率起步,因为一套 agent 已经能通过的测试,没法体现进步。它们用在构建过程中。
-
回归 eval 问的是 agent 还能不能做到昨天做到的事。这类测试应该接近 100% 通过,任何下降都是信号。每次改动模型、提示词或工具时都要跑一遍。
能力类任务如果 agent 能稳定通过,就可以转入回归测试套件。多数基于模型提供商开发的团队,在回归测试上投入的评估精力往往超出预期,因为变化最频繁的不是自己的代码:模型升级、更换提供商、模型弃用并设定退役日期。
Agent 不是确定性的:pass@k 与 pass^k
同一个 agent 在同一个任务上跑五次,可能得到五份不同的执行轨迹。每个任务只试一次,测到的更多是运气而非真实行为。有两个指标可以描述这种波动:
-
pass@k:k 次试验中至少有一次成功的概率。它随 k 增大而上升,当一次成功就够用时,这个指标最合适——比如编码 agent 的输出还会有人工审核。
-
pass^k:k 次试验全部成功的概率。它随 k 增大而下降,当 agent 直接面对客户时,这个指标最合适,因为每个客户只会经历一次尝试。
两者差距很大。在 τ-bench 中——这是一个让 agent 在书面政策约束下服务模拟零售和航空客户的基准测试——使用 function calling 的 GPT-4o 在单次试验中解决了约 61% 的零售任务,而它的 pass^8(同一任务在全部八次试验中都成功)降至约 25%(Yao 等,2024 ↗)。一个每次试验成功率为 75% 的 agent,连续三次都成功的概率只有 42%(0.75³)。
如何为 AI agent 编写评估
下面七个步骤带你从零搭出一套可以用于发布门禁的测试套件。它们假设 agent 已上线或接近上线。如果你还在原型阶段,先做第 1 步到第 4 步即可。
第 1 步:从真实失败和真实流量出发
不要从想象测试用例开始。先从已经出错的 20 到 50 个案例入手:bug 报告、升级的客服工单、有人标记过的对话记录。Anthropic 的指南也给出同样建议——早期改动的影响很大,一套小规模的测试集就能发现问题。
接着补充真实流量。手写的测试用例覆盖的是你已经想到的情况,生产日志里则包含你没想到的。抽取 100 到 300 条输入,按路由或意图做分层采样,避免冷门但代价高昂的路由被淹没;同时去掉个人信息,剔除近似重复的样本。想了解如何用生产流量搭建黄金评测集、如何记录这些运行,以及需要多少评测用例,可以参考相关章节。
给每条用例打上路由标签和已知边缘情况标签。后续你真正要据以行动的,是各标签下的通过率。
第 2 步:先定义「什么算成功」,再写评分器
用现实世界的状态来描述每个任务「做完」是什么样,而不是看回复怎么说:
-
“订单 A1042 上存在一笔 $59.00 的退款”,而不是“agent 说退款已发出”。
-
“14:00 时段的预约已存在,且没有创建其他预约”,而不是“回复确认了预约”。
-
对于 agent 应该依据指令直接回答的问题,标准是“没有调用任何工具”。
如果你写不出成功标准,评分器就无法检查,同事也无法检查。这说明任务本身有歧义,而不是你需要一个更聪明的评分器。对于有固定答案的任务,把预期结果存在任务里;对于有多种有效答案的任务,存下每个有效答案都具备的属性。
第 3 步:评结果,只在规则所限之处评路径
Agent 经常用你没想到的路径达成正确结果:换一个查询顺序、多搜一次、问一个澄清问题。如果评测要求工具调用必须按精确顺序执行,这些运行就会被判失败,久而久之你会习惯性忽略失败。Anthropic 的建议是:“评 agent 产出了什么,而不是它走了哪条路。”
有一个例外,对会执行动作的 agent 尤其重要。有些路径本身就是规则,违反规则就是失败,哪怕结果看起来没问题:
-
任何写操作之前必须先认证或验证。
-
发放退款前必须先查退款政策。
-
一张卡最多只能扣款一次。
-
绝不调用已废弃或危险的接口。
-
金额必须保持在允许范围内。
把这些写成对执行轨迹的检查,一条规则一项。其余的都放开。
第四步:能用代码判的就用代码,剩下的交给模型裁判,最后靠人工校准
回头过一遍第 2 步定下的成功定义,给每一项检查都分配一个能胜任、且成本最低的评分方式。
代码评分器负责检查最终结果和执行轨迹里的规则:退款记录存在、金额正确、check_refund_policy 在 issue_refund 之前执行、issue_refund 只执行了一次、结构化输出能正常解析。下面是一段不依赖任何框架的 Python 示例代码:
def grade(trial, db):
tools = [call.name for call in trial.tool_calls]
refunds = db.refunds_for(order_id="A1042")
refund_issued = len(refunds) == 1 and refunds[0].amount_usd == 59.00
policy_first = (
"check_refund_policy" in tools
and "issue_refund" in tools
and tools.index("check_refund_policy") < tools.index("issue_refund")
)
# The reply may only claim a refund when one exists.
honest_reply = refund_issued or "refund" not in trial.final_text.lower()
return {
"refund_issued": refund_issued,
"policy_first": policy_first,
"honest_reply": honest_reply,
}
每一项检查单独返回一个结果,不要合并成一个总分。一个任务如果 policy_first 没过但 refund_issued 过了,这和两项都没过的任务,是两种不同的问题。
模型裁判负责代码查不了的东西:回复里有没有说清楚钱什么时候到账,语气适不适合安抚一个着急的客户。每个裁判只盯一条标准,用可观察的行为来描述,并写清什么叫通过:
Criterion: Does the reply tell the customer when the refund will reach them?
It passes if it gives a timeframe or a date. It fails if it says only that
the refund was issued, or gives no timing at all.
Answer PASS or FAIL, then one sentence of reasoning.
人工先手工标注 30 到 50 个 trial,再拿这些标注结果和裁判的判断做对比。每一处不一致,要么说明标准写得含糊,要么说明这个裁判现在还不能信。对新裁判先设成「仅提示、不拦截」:只报告结果,不阻断流程,等对比结果站得住脚再升级。
第 5 步:每个任务多跑几遍
每个任务至少跑三次,风险高的跑五次。面向客户的行为要报 pass^k(连续 k 次全部通过的比例),也就是 agent 每次都做对的任务占比。三次里过两次不算通过,这属于不稳定行为,客户每三次就会撞上一次。
多次试验还能把噪声和真正的回归区分开。如果当前模型在某个任务上自己就前后不一致,那么新模型在这个任务上给出不同结果,本身什么都证明不了。
第 6 步:读执行记录,别只盯分数
总体通过率只能说明有东西变了,说明不了变的是什么。按标签、按评分器把结果拆开,把你关心的路径上每一条失败的执行记录都读一遍。大多数评测 bug 都最先在这里露头:评分器查错了字段、任务的通过条件根本不可能满足、测试用例泄漏进了提示词。
通过的记录也要读几条。一个从不失败的评分器,要么在检查无关痛痒的东西,要么本身就是坏的。
第 7 步:冻结测试集,每次改动都跑一遍
回归测试集只有在保持不动的前提下才能证明东西。把任务和评分器冻结、打上版本号,凡是可能改变行为的改动都要跑一遍:模型名、提示词、工具定义、agent 的代码。两次运行之间如果测试集本身变了,那比的其实是两个都在动的东西。
如果改动是有意为之,比如新增一条路径或修正某个预期,就单独用一个 commit 更新测试集,让下一次比较从已知基线出发。然后把运行接进 CI,这样会让 agent 回归的 pull request 在合并前就失败。CI 中的 LLM 回归测试,相当于在 GitHub Actions 上设一道门禁。
agent 评测中的常见错误
- 评的是「说法」而不是「结果」。「agent 说它订好了时段」不等于真的订好了。去查状态,至少查那个本该改变状态的工具调用。
- 要求精确的执行路径。 把每次工具调用按顺序钉死,会把本来有效的运行判成失败。只钉第 3 步里列出的那些规则。
- 只报一个平均分。「质量下降了 3%」没法修;「退款路径上有 12 个任务跳过了
check_refund_policy」能修。 -
每个任务只跑一次。 你会去追噪声,反而漏掉真正的不稳定行为。
-
从未校准过的评审模型(judge)。 不管评分标准是否合理,评审模型都会给出一个看似确定的分数。所以先拿人工标注的结果校准它。
-
一次改动两处。 同一轮对比里既换了新模型、又重写了提示词,最后谁也说不清分数变化是哪个原因带来的。一次只改一处,测完再改下一处。
用 EvalShift 编写智能体评测
EvalShift 专攻智能体评测中的回归场景,也针对团队测得最少的那类变更:换模型或升级模型。它会把一套冻结的测试集分别跑在现有模型和候选模型上,对每个任务的两边结果打分,再把差异汇总结成结论。
-
任务来自真实流量。 采集 SDK 会记录生产环境的运行过程,
evalshift capture sync会把这些记录转成黄金测试集,每个任务都带着当时调用的工具和期望的工具调用。 -
追踪评分器,不用写代码。
tool_selection和tool_arguments检查调用了哪些工具、传了哪些参数值,trace_invariants则让两个模型都遵守第 3 步定下的规则:
evaluators:
trace_invariants:
- name: refunds_contract
owner: "@support-team"
rules:
- id: policy-before-refund
type: order
before: check_refund_policy
after: issue_refund
- id: one-refund
type: call_count
tool: issue_refund
max_calls: 1
- id: sane-amount
type: arguments
tool: issue_refund
json_schema:
type: object
required: [order_id, amount_usd]
properties:
amount_usd: {type: number, minimum: 0.01, maximum: 500}
-
评审模型先当参考。
llm_judge里的评分标准会把两个模型的回复两两对比,evalshift init会先把这些标准写成非阻断项,等校准完成后再正式启用。 -
结论提前定好。
migration_policy块用来设定预算,比如不变量违例必须为零,或者工具选择分歧最多 10%。这些都在任何人看到具体数字之前就定下来。
需要了解一个限制:EvalShift 不会真的连上线上系统去跑工具。它把生产环境里记录下来的工具返回结果喂给各个模型,因此它评的是模型发出的工具调用本身,而不是调用之后数据库里的状态。针对真实环境的结果检查(例如上面那个 refund_issued 检查)应该放到你自己的预发布(staging)测试里。agents 文档详细介绍了回放机制,trace_invariants 参考文档则列出了全部规则类型。
FAQ
什么是 AI eval?
给 AI 系统写的测试。一个 eval 把输入交给模型或智能体,让它跑完,然后用代码、由另一个模型充当裁判、或人工评审来打分。一组 eval 放在一起跑就是测试套件(suite),它的通过率能说明:改动模型、提示词或工具之后,系统是变好了还是变差了。
LLM eval 和智能体 eval 有什么区别?
LLM eval 只评一个提示词对应的一条回复,通常就是文本。智能体 eval 评的是一整次运行:智能体调用了哪些工具、顺序和参数是什么、运行结束后留下了什么状态、最终回复是什么。智能体 eval 需要在轨迹(trace)和结果两头都设评分器,因为智能体完全可能先做错事,再写出一条听起来很对的回复。
怎么给 AI 智能体写 eval?
从 20 到 50 个真实失败案例,加上一批真实流量样本开始。把成功定义成现实世界里的某个结果,用代码去评这个结果。只对「绝不能跳过的步骤」加轨迹规则。回复质量才用 LLM 裁判。每个任务多跑几遍,读失败的对话记录,然后把整套测试冻结下来,让它能给每一次改动把关。
智能体 eval 该检查工具调用,还是只看最终结果?
主要看结果。智能体经常用你没想到的路径得到正确结果,而严格按固定路径检查会把这类运行判为失败。只有那些每次都必
pass@k 和 pass^k 有什么区别?pass@k 是 k 次试验中至少有一次成功的概率,随着 k 增大而上升。pass^k 是 k 次试验全部成功的概率,随着 k 增大而下降。面向客户的代理应使用 pass^k:在 τ-bench 中,GPT-4o 在一次试验中解决了约 61% 的零售任务,但在全部八次试验中仅解决了约 25%。
继续阅读
-
+如何评估 AI 代理:要衡量的六个维度、要测试的三个层级,以及沙箱、模拟与重放的对比。
-
+评估代理的工具调用:四种工具调用评估器,以及哪些内容不应纳入追踪预期。
-
+LLM 作为评判者:评判者如何工作、准确度如何,以及如何验证一个评判者。
-
+从生产流量构建黄金评估套件:第一步完整指南。
-
+如何在发布前测试 LLM 模型迁移:针对模型变更本身的回归评估。