评测用例撰写智能体。
每个把智能体送上线的人都卡在同一个瓶颈上——一套手写的四十条评测用例,几个月前就已经失去区分力了——而那个显而易见的解法「拿个模型对着它生成」之所以失败,原因非常具体:让测试生成智能体成立的,是一个免费的判据,而智能体评测没有这样的东西。要造这个智能体,唯一能在生产里活下来的分工很窄:智能体负责生成场景,而答案由某个不是这个智能体的东西持有。
在写下第一行生成器之前,先把判据点出来。
单元测试生成器的正确性信号是白来的。编译器给调用定类型、运行器报告通过或失败,而对回归工作来说,当前行为就是规格——金标准捕获把「这里该返回什么?」变成了「这里今天返回什么?」,无需任何判断。这就是测试生成为何能规模化,以及它的指标为何那么好看。
现在把同样的问题拿去问一次智能体评测:那个退款智能体对这位客户处理得对不对?没有运行器。最有资格回答的,是一个能力大致等于你正想要衡量的那个模型——这就是生成器—验证器差距以人员配置问题的形式登场。所以在动手造任何东西之前,先把词汇定下来:
- 场景是那些输入:用户目标、对话前缀、工具与数据状态,以及任何被注入的逆境。生成便宜、检查其可信度也便宜,而且确实供给不足——这正是你想让智能体成千上万地产出的东西。
- 判据是那个决定「走过这个场景的一条轨迹是否正确」的东西。昂贵、有争议,而且是唯一带着权威的那一部分。这一部分不归智能体所有。
- 评测用例是一个场景与一个判据的绑定。汇报进展时数的是它,而不是场景——一千个没有判据的场景是一次压力测试,不是一套评测集。
那条能避开最昂贵错误的一句话规则:如果用例和评分器出自同一个模型家族,你造出来的系统是在优化评分器。它会无止境地报告改进。这份手册余下的一切,都是把这两份工作隔开的机械装置。
从链路记录里挖形态;再为覆盖这些形态而生成。
一个被要求「生成困难的客服用例」的生成器,产出的是一套看着可信、实则狭窄、一闻就是合成味的用例,而你的智能体全都能过。解法是不再把生成当成发明,而是把它当成从一个你本就拥有的分布里采样:你的生产链路记录。两趟,按这个顺序。
第一趟——把真实流量聚成失败形态。把出了问题的运行捞出来(点了踩、升级到人工、重试风暴、被放弃的会话),按向量聚类,再让智能体为每个簇写一句话命名。你要的是这种名字:「用户给的订单号属于另一个账户」或者「工具返回的是用户最后一次编辑之前的数据」,而不是严重度评分。从几千条链路记录里得出十到三十个被命名的形态是现实的产量,而那份清单才是第一趟真正的交付物。
第二趟——在每个形态内沿命名过的轴生成。这下生成器有地方可去了。给它形态、一条样例链路,以及一份固定的扰动轴清单:
- 缺失或格式错误的输入——某个必填字段不在、日期用了错误的地区格式、一个语法上合法却指向不存在之物的标识符。
- 两种站得住的读法——一个称职的人类会反问一句的请求。这是智能体会悄悄挑一种然后继续往下做的地方。
- 任务中途改目标——用户在第四轮推翻了先前的指令。考的是智能体会重新规划,还是继续执行那个已经死掉的计划。
- 过期或不一致的工具状态——读取返回的值,已经被某次写入取代了。
- 检索数据中的对抗性内容——指令被嵌在一份智能体被要求去总结的文档里。
去重要下狠手——把每个候选场景向量化,凡与已接受用例的余弦距离在一个很紧的阈值之内就丢掉——并自动拒掉任何「正确结果无法用一句话说清」的候选。单这一条拒绝规则,就能滤掉生成器产出中的大部分,而它滤掉的每一条,本来都要花掉一位人工评审者一小时。
三类评分器,以及智能体在每一类里能碰什么。
按每个用例能拿到的最强判据给它们排序,并把人的注意力花在那些爬不上去的用例上:
- 程序化状态断言——账本里存在一笔金额为 X 的退款;工单处于
resolved状态;文件能解析且含三行。确定、重跑便宜、不受评判模型漂移影响。智能体可以起草这些断言,由人类评审那段 diff,就像你评审生成的测试代码那样。目标是把尽可能多的用例挪进这一类——为了让一个用例变得可做状态断言而把它重写一遍,是值得的。 - 评分量表加经过校准的评判模型——用于那些「正确」是一种质量而非一种状态的用例。智能体可以提出量表,但绝不可以提供答案,而且对同一个用例绝不可以两者兼任。只有在你已于一个留出切片上量过它与人类标注的一致度之后,一个评判模型才可被接受;参见评判模型校准与以 LLM 作评判。
- 仅靠人——剩下的残渣。把它保持得很小,但一定要保留,因为它是你的校准锚;你手里没有人类标注切片的那一天,就是评判模型漂移变得不可见的那一天。标注运维是把它跑起来的那套机械装置。
一条硬约束,在代码里执行起来便宜,事后才发现则昂贵:被测模型绝不可以给自己家族当评判,而生成器所用的模型压根不可以当评判。在每个用例上记下生成器模型、评判模型与被测系统模型,并在其中任何两者相同时让这次评测运行失败——要大声失败,不是给个警告。
价值最高的用例,是那些没有正确答案的。
几乎每一套手写评测集都是 100% 可完成的,这意味着它探测不到代价最高的那种生产失败:一个干不了这活、却报告说干完了的智能体。那就是失败隐瞒,而在一套「每个任务都能完成」的集合里,它是不可见的。
所以要明确地为「做不成的活」给生成器下任务书,并把它定成配额而不是「有就更好」。一套成熟集合里大约五分之一到四分之一,应当是「诚实答案是一次拒绝或一个问题」的用例:
- 权限缺失——任务需要一个智能体凭据并不携带的范围。
- 指称对象缺失——请求中点名的那条记录、文件或账户并不存在。
- 自相矛盾——请求里的两条约束无法同时成立。
- 超出政策——做得到,但智能体应当拒绝。
- 欠定——缺了一个只有用户才有的事实;正确动作是反问一个澄清问题,而一个自信的回答即便恰好对了也算失败。
给它们的计分方式和其余用例一样:正确拒绝给满分,编造式完成给零分——并且绝不要在任何被测系统看得见的地方给它们打标签。一个在这件事上很擅长的生成器,比在任何别的事上擅长的生成器都更有价值,因为这一类正是你的人类同事系统性写不出来的。
按用例记来源,否则这套集合会无声腐烂。
一套生成出来的集合是一份带供应链的数据集,而它的失败模式不是某个用例坏掉——而是这套集合照样能跑、照样报出数字,却已经什么都不衡量了。从用例被创建的那一刻起,就给每一个用例带上元数据:
case_id: rfnd-0412
situation: { goal, conversation_prefix, tool_state, injected }
oracle: { class: state_assertion | rubric_judge | human, ref }
satisfiable: false
shape: "order id belongs to another account"
source_trace: trace_8e21c4 (2026-09-12)
generator: model=<id> prompt_version=7
reviewer: alice (2026-09-14)
frozen: true # excluded from any prompt or training corpus
discriminates: [v3.1 > v2.8] # last pair of systems this case separated
四项政策挂在这些字段上:
- 冻结一个私有切片,并且永远不要把它发到任何地方去。生成的用例是文本,而文本会渗进提示词、微调语料与少样本示例里。污染不是公开基准才有的问题;它就发生在某人为了调试而把一条失败的评测用例粘进提示词的那一刻。
- 按漂移重新生成,而不是按日历。触发条件是你的链路聚类在移动——出现了一个新形态,或某个旧形态不再发生。在一个安静的产品上按月重新生成只是折腾;参见评测集维护。
- 给集合打版本,并把每次运行钉到某个版本上。没有版本的分数是没有意义的;而一套在两次运行之间长大了的集合会让这次比较变成非配对的——按评测方差与统计效力所述,大多数幻影式改进正是从这里来的。
- 把不再有区分力的用例退役。一个所有系统都能过的用例,花着钱却什么也没告诉你。把它挪进一套便宜的冒烟集,并从头条数字里拿掉。
那道闸:生成出来的集合,分得开你本就知道有差别的两个系统吗?
这个评测用例撰写智能体需要它自己的验收测试,而那测试不是「它写了多少条用例」。拿两个你对其相对质量有把握的版本——最好其中一个是你故意弄差的——然后问:这些新用例把它们排对了吗?一个两个版本都能过、或都过不了的用例,不管看着多聪明,都没有区分力。
- 区分率——已接受用例中,能把一个已知更好的系统与一个已知更差的系统分开的比例。这是主要指标,也是那个没人汇报的指标。
- 判定稳定性——每个用例对着一个未改动的系统跑三遍;判定会翻转的用例衡量的是采样噪声。把单次尝试成功率与「全部尝试均成功」并列报告:两者的差距很大,而且随重复次数拉开——如在 τ²-Bench 上,某个被报告的配置在零售域的「全部 k 次均成功」从 k=1 时的 81.6% 掉到 k=4 时的 56.1%。
- 每条被接受用例的人工分钟数——真正的单位成本。如果评审比手写这个用例还花时间,这个生成器就是净负的,而修法在上游,在 STEP 2 的那些拒绝规则里。
- 接受率——已接受比已生成。低到大约五分之一以下就停下来别再生成,去把形态清单修好;生成器缺的不是流畅,缺的是接地。
就从这里开始,按这个顺序,一周之内你会有点能用的东西:把上个月那些糟糕的运行手工聚成被命名的形态;挑出最痛的三个形态;让智能体为每个形态生成二十个场景,并套上一道硬性的「用一句话说出正确结果」过滤;把能转的全部转成状态断言,并像评审代码那样评审它们;再要求集合中有五分之一是做不成的、且拒绝有分。然后把这整套东西只对着一条标准来卡——一个用例要挣到自己的位置,只能靠分开两个你本就知道有差别的系统。这份手册里其余的一切,都是这条标准的展开。
延伸:模拟用户讲如何生成一个场景里的对话那一侧,评测完整性与评分器套利讲评分器一旦成了靶子会怎样,而评测驱动开发讲如何把得到的集合接成一道闸。