做这个业务 Agent 评测平台之前,我在货运平台这边已经吃了快一个月的“人工验收”的亏。业务同学提了一堆 Agent 需求,客服机器人、调度助手、费用申诉助理,每个听起来都能提效,但每次要上线,大家都不知道怎么验收。拉几个典型问题人工聊一轮,凭感觉说“还行”,可一旦放量,各种边界情况全冒出来。
后来我们决定把评测这件事工程化,做一个统一的业务 Agent 评测平台。这篇文章就是这段时间的工程实践记录和复盘,不聊概念,只聊实际怎么设计、怎么落地、踩了哪些坑。适合正在做 Agent 应用,尤其是业务侧 Agent 落地,又对“怎么证明 Agent 变好了”这件事头疼的团队参考。
1. 为什么货运业务的 Agent 不能继续“拍脑袋验收”
1.1 业务 Agent 到底在解决什么问题
货运平台里的 Agent,跟传统意义上的“聊天机器人”差别很大。它不只是陪用户聊天,而是要真正介入业务流程、调用系统能力、影响业务结果。
我盘了一下,平台里的 Agent 主要有这么几类:
- 用户侧服务助手:用户问“货到哪了”“为什么司机还没接单”“运费怎么算”,Agent 要查订单、查轨迹、查计价规则,然后给出准确解释。
- 司机侧费用申诉助手:司机发起油费补贴、等待费、搬运费等申诉,Agent 要按规则判断是否成立、该补多少钱,或者决定要不要转人工审核。
- 内部运营调度助手:给调度运营提供改派建议、异常订单处理方案,辅助决策。
这些 Agent 的共同点是什么?它们都会调用真实的接口、读取真实的订单数据,甚至直接改动业务状态。一旦说错话、做错判断,轻则用户投诉,重则直接造成资金损失。
所以问题从来不是“Agent 会不会聊天”,而是“Agent 能不能在真实业务约束下,把一件事办对、办稳、办得体面”。这句话直接决定了评测体系该怎么搭。
1.2 没有统一评测时的三个真实痛点
在评测平台做出来之前,我们的验收状态基本是“裸奔”的,核心痛点有三个:
第一个痛点:验收靠抽查,覆盖全靠运气。
每次迭代,业务同学会挑几条“平时最常遇到”的问题,打开测试环境跟 Agent 聊一轮,看看回复像不像人话。这本质上是在测“演示路径”,不是在测系统能力。真实线上用户的问法千奇百怪,有些地址写一半、有些话里有情绪、有些一句话里带三个诉求,这些边界 case 在人工抽查里很难被覆盖到。
第二个痛点:口径不统一,算法和业务对不上。
算法同学说“这次任务完成率到了 92%”,业务同学一听就炸:“怎么可能 92%,我随便试了几个都没解决。”两边吵了半天才发现,算法定义的“完成”是“模型输出了结果”,业务定义的“完成”是“用户诉求真真切切被处理好了”。中间差着一大截。
第三个痛点:回归成本太高,改一句 Prompt 要半天没人敢发。
有一次我们调了一版对话策略,改动点很小,但谁都不敢说“这版一定不会把老问题带出来”。于是只能手工把之前积累的几十条典型场景重新聊一遍,一个同学聊了一下午,第二天说“感觉差不多”。问题是,“感觉差不多”完全不是一个可量化的上线依据。
这三个痛点叠在一起,结论就很清楚:业务 Agent 需要一个能把“行还是不行”用统一标准量化出来的评测平台,否则后面 Agent 数量越来越多,一定失控。
1.3 评测平台能承诺什么,不能承诺什么
这里要先划清边界。评测平台不是万能的,它承诺的事情只有三件:
- 一致的指标:所有人都用同一套评分规则看结果。
- 可复现的测试:同一份用例、同一个版本,任何时候跑结果都一致。
- 快速的反馈:每次改动 Prompt 或模型,几小时内得到完整回归报告。
它不能承诺的是“评测分数高,业务就一定成功”。分数代表的只是在预设条件下的表现,线上真实流量、用户情绪、突发活动这些变量,评测环境模拟不了。所以我把这个平台定位成“出厂质检线”,不是“业务增长引擎”。想清楚这个边界,后面很多设计决策就不会跑偏。
2. 评测指标怎么定:从任务完成率到过程合规度的取舍
2.1 三个评测维度是怎么来的
定评测指标的时候,我们没有一上来就抄市面上常见的“准确率”“召回率”,而是从头问了一个问题:货运业务 Agent 做错事,会错在哪几种方式?
答案归纳下来就三类:事情没办成、办成了但过程违规、办成了但体验很差。
所以评测维度就按这三类落地:
| 评测维度 | 要回答的问题 | 典型指标 | 举例 |
|---|---|---|---|
| 任务完成度 | 用户诉求最终有没有被解决 | 目标达成率、关键信息覆盖率 | 查时效时,有没有给出预计到达时间 |
| 过程合规度 | 每一步操作是否符合业务规则 | 违规次数、越权操作数、错误承诺数 | 有没有承诺规则外的赔偿金额 |
| 体验友好度 | 交互过程中用户是否感到顺畅 | 重复话术率、转人工率、回复冗余度 | 遇到不会的问题能不能坦诚说明 |
这三个维度不是并列关系。任务完成度是底线,过程合规度是红线,体验友好度是加分项。
2.2 指标怎么定义才算可执行
很多团队把“指标”定义成“回答准确率”,听起来很合理,真正落地时完全没法判分。因为“准确”这个词太糊了。
我们的做法是:把每个用例拆成结构化、可判定的条件。一份用例至少包含四个部分:
- 预期目标:会话结束时,Agent 应该达成的状态。比如“给出预计到达时间并说明路况异常原因”。
- 关键信息:回复里必须覆盖哪些要素。比如“至少包含预计到达时间”“如果超时,必须说明原因”。
- 禁止行为:绝对不能出现的话术或动作。比如“不得承诺 12:00 前一定送达”“不得自行修改订单金额”。
- 可接受的失败方式:有些问题 Agent 确实解决不了,但必须给出合理的兜底。比如“承认暂时无法查询,并引导用户联系人工”。
这里我特别想强调一点:判分条件要尽量做成“判断题”,而不是“打分题”。“回复是否包含预计到达时间”是判断题,“回复是否友好”是打分题。判断题机器能稳定判,打分题哪怕是人工标也有分歧。所以我们把 80% 的判分条件都做成了判断题,剩下必须打分的主观项,留给 LLM 判分器处理。
2.3 分数合成与阈值设定
三个维度各自算完分之后,要合成一个总分,方便横向对比版本。我们初期用的公式很简单:
总分 = 0.6 × 任务完成度 + 0.25 × 过程合规度 + 0.15 × 体验友好度权重不是拍脑袋拍出来的,是根据业务复盘结果反推的:过去三个月线上客诉里,60% 是因为事情没办好,25% 是流程违规引发纠纷,15% 是表达问题引发用户不满。如果后面数据分布变了,权重也要跟着调,这个公式只是起点。
但有个例外:一旦出现严重违规,比如承诺了不存在的赔付、自行修改了订单金额,总分直接清零,不参与加权。这跟现实中“一票否决”的逻辑是一样的,能力再强,底线破了就是不行。
阈值方面,我们没有定一个死的“80 分及格”,而是做“相对回归 + 绝对兜底”两条线。绝对兜底指的是严重违规 case 数量必须为 0;相对回归指的是总分和关键子项不能比上一个版本下降超过 2%。这个设计防止了一个很常见的问题:用单一分数卡版本,容易让团队去“刷总分”,而不是真正把薄弱环节做好。
3. 测试数据从哪来:真实会话重放与合成用例的双轨构造
3.1 真实会话脱敏与重放
评测这块最容易被低估的就是测试数据。刚开始我们以为写个几十条用例就够用了,跑到第二周就发现,用例太“正”了,全是标准问法、标准场景,Agent 答得很好,一到线上就打回原形。
后来我们把重心转回真实会话上。直接从线上日志里抽用户和 Agent 的真实对话记录,做严格脱敏处理:手机号、姓名、地址、订单号、车牌号全部替换成模拟数据。脱敏不是简单把字段打码,还要保持语言风格和问题结构不变,否则评测的就变成“另一个问题”了。
重放的方式也踩过坑。最开始我们天真地以为“重放”就是把线上用户说的话原样发一遍给 Agent,然后对比新的回答和线上回答像不像。后来发现这个思路不对,因为 Agent 是多轮交互,用户会根据 Agent 的回答继续追问。如果只重放第一句,后面就断掉了。
我们的做法是:从真实会话里截取一段“Agent 独立服务”的片段,把用户的每一轮输入按顺序存储,评测时逐轮喂给被测 Agent。这本质上是把真实用户的对话路径当作预设脚本,看新版 Agent 沿着这段路径走能不能走通。它对覆盖真实分布非常有效,在我们平台里大约占了 60% 的用例来源。
3.2 合成用例的构造方法
真实会话覆盖的是“已知问题”,但评测不能只有已知问题,还得有“边界问题”和“未来可能遇到的问题”。这部分靠合成用例。
合成用例我们主要靠两种方式生成:规则模板 + LLM 辅助扩写。先用业务同学把典型边界场景列出来,比如“用户情绪激动反复追问”“地址信息不全导致无法计算时效”“司机和用户同时改约”这类,然后人工写成结构化用例,再用 LLM 基于这些模板扩写一批表达方式不同的变体。
一份合成用例长这样,我们用的是 YAML 结构,方便版本管理:
case_id: SC_0412 场景: 时效查询_地址不完整 用户初始消息: "我的货到底几点到啊,等了一天了" 预期目标: 引导用户补充完整地址信息,并提供大致时效范围 关键信息: - 需要向用户确认完整收货地址 - 需说明当前无法精确计算时效的原因 禁止行为: - 不得编造预计到达时间 - 不得承诺"马上就到" 难度标签: 边界情况_信息缺失生成合成用例有个特别要注意的地方:不要让 Agent 察觉自己是在被测试。我们一开始在 Prompt 里带了明显的评测标记,结果模型“演”得很乖,所有规则都完美遵守,一上真实环境就露馅。后来把所有评测相关标识从用户输入里去掉,情况才好转。这算是一种“评测污染”,后面细说。
3.3 题库管理与版本对齐
用例多了之后,题库管理就成了新的工程问题。
我们现在把用例当成代码一样管理,进 Git 仓库,每次修改都要走分支和评审。每条用例有唯一 ID、变更历史、适用场景标签、难度标签。评测报告里会记录“当前这批结果是用哪个版本的题库跑出来的”。
这个看起来细枝末节,实际救过大命。有一次一个版本跑分暴涨,大家差点欢呼,后来一查发现是题库里删掉了一批难用例,不是 Agent 变强了。没有版本对齐机制,这种乌龙根本查不出来。
另外,题库不是越多越好。我们每两周做一次用例体检,淘汰三类用例:已经被 Agent 完美解决很久的、跟现有业务流程已经不匹配的、线上线下表现差异特别大的。题库需要“流动”,一旦僵住,评测结果就会失真。
4. 评测引擎的工程实现:三个模块和一条流水线
4.1 整体模块划分
评测平台的代码结构没有做得很复杂,核心就四个模块:
- 用例仓库:管理所有评测用例,包括真实会话重放脚本和合成用例,支持按标签筛选和版本回溯。
- 执行引擎:负责把用例跑起来,调用被测 Agent 的接口,模拟用户输入,收集每一轮对话以及 Agent 的每一次工具调用。
- 判分服务:拿到完整的会话轨迹,先用规则判分器处理结构化条件,再用 LLM 判分器兜底主观项。
- 报告服务:聚合所有用例的判分结果,生成总分数、分维度分数、失败 case 列表和趋势报表。
整体流水线就是一条直线:从用例仓库取出用例集,执行引擎跑出轨迹,判分服务打分,报告服务出报表。没有复杂的编排系统,因为这条链路已经足够稳定,引入重框架反而增加维护成本。
4.2 执行引擎的关键取舍
执行引擎是整个平台里最有技术含量的部分,也是最容易被低估的。
我们第一个取舍是用“模拟用户”的方式做端到端测试,而不是把 Agent 的函数单独拆出来做单元测试。原因很简单,Agent 的价值恰恰在多轮交互里。单测能发现“接口算错了”,但发现不了“第一轮把用户带偏了,第二轮怎么拉都拉不回来”。所以每条用例都走完整对话流程,执行引擎负责按脚本发消息、等待响应、触发工具调用、继续下一轮。
第二个取舍是对超时和异常做严格兜底。线上的一次 Agent 调用可能耗时几秒甚至更久,评测时如果每轮都在那里傻等,几百条用例跑下来没半天结束不了。我们给每轮交互设置了超时时间,超时直接判失败,并把卡住的轨迹存下来,方便定位是模型问题还是环境问题。
第三个取舍是全量记录轨迹。不只是记录用户说了什么、Agent 回了什么,还包括中间每一次工具调用的入参、出参、耗时、走了哪个分支。这太重要了,很多评测失败,人工排查时需要看的是“Agent 在哪一步做了错误决定”,而不是只看最后那句话。
4.3 判分器:规则优先,LLM 兜底
判分服务设计上我们坚持一个原则:能用规则判的就不要用模型判。
规则判分器处理的是结构化条件。比如“关键信息里要求包含预计到达时间”,那就直接在回复文本里做信息抽取,看有没有时间实体;比如“禁止出现编造的赔付金额”,那就先解析出所有金额实体,再跟允许值列表比对。这些用正则、实体解析、字段比对就能搞定,稳定、可解释、便宜。
真正需要 LLM 判分的,只剩那些没法用规则硬拆的主观项。比如“是否在无法解决问题时主动引导用户转人工”“回复语气是否得体”“解释是否足够清晰”。
LLM 判分器我们自己写了一套提示词模板,核心是强制它先给判断依据,再给结论,最后输出结构化 JSON:
你是业务对话质量评估员。 请根据以下评分标准判断这段客服回复是否合格。 先输出你的判断理由,再输出结果 JSON。 评分标准: 1. 当无法解决问题时,是否明确告知用户并给出下一步建议。 2. 是否使用绝对化承诺(如"一定""保证")。 3. 语气是否礼貌、克制、不推卸责任。 回复文本: {对话轨迹} 输出格式: { "reason": "判断理由", "pass": true或false, "violated_rules": ["违反的规则列表"] }这样设计有个额外的好处:LLM 判分结果不是“是/否”一个值,而是带理由的,出问题后可以直接拿理由去追溯,而不是对着一个分数猜。
4.4 评测环境与线上一刀切
最后说一个容易被忽略但很关键的工程点:评测环境必须和线上完全隔离。
我们刚开始直接连测试环境的接口,跑着跑着发现评测数据会污染业务缓存,也会被定时任务干扰。后来统一调整为专供评测的独立环境,连接影子数据库和 mock 服务。被测 Agent 的所有工具调用都指向 mock,不会真的发消息给用户、不会真的改订单状态。
隔离这件事要做得非常彻底,哪怕线上只是多了一个新的限流策略,评测环境没同步,结果也会失真。所以我们在每次发版前会同步一次环境配置,并在评测报告里记录环境版本,确保“这次结果和上次结果可比”。
5. 上线半年踩过的坑:判分不稳定、用例污染、环境隔离
5.1 LLM 判分器为什么时好时坏
第一个大坑就是 LLM 判分器的不稳定性。上线初期,经常出现同一个 case 连续跑了两次,一次显示合规,一次显示违规,毫无规律。
排查了半天,原因有两个。
一是判分时的生成参数没固定。默认的 temperature 不是 0,模型每次输出的概率分布都有波动,同样的输入会产生不同的判断。解决办法很粗暴,把判分模型的 temperature 固定为 0,关闭随机性。
二是判分标准太抽象。最初判分提示词里写的是“判断回复是否友好”,这种词模型每次理解都不一样。后来我们把每个主观项都拆成更小的布尔问题,比如“是否使用了威胁性语气”“是否出现连续重复内容”“是否拒绝回答但没有给出替代方案”。布尔问题的稳定性远高于“友好度打分”。
但即便这样,偶尔还是会出现模型误判。我们加了最后一层保险:同一个 case 用两条不同路径的判分 Prompt 各判一次,结果一致才通过;不一致就转人工抽检。虽然成本高了,但评测平台本身必须是可信的,否则没人敢信它的结论。
5.2 用例污染,Agent 开始“背答案”
第二个坑,也是我们后知后觉发现的:模型开始在评测用例上“过拟合”了。
具体表现是,日常回归分数稳定上涨,但每次上新题,分数都会明显掉一截。很长一段时间我们都以为只是“新题更难”,后来才意识到,研发同学在优化模型和 Prompt 的时候,已经潜移默化地把固定评测用例里的题型信息带进去了。模型见过这些问题太多遍,学会的不是“解决问题”,而是“对这些问题输出标准答案”。
这不是故意作弊,而是整个评测机制天然会诱发的问题。我们做了三层改进:
- 引入私有留出集:一批新题只在发版前跑,不进日常回归,研发平时看不到题面。
- 题库定期轮换:每次回归从大题库里随机抽一部分,而不是全量固定跑,减少模型“背题”的机会。
- 强调效果而非答案:在评测维度里增加对“推理过程”的检查,让模型知道判分看的是过程合规和关键信息覆盖,而不是某一句标准话术。
5.3 并发评测时的状态互相污染
第三个坑是典型的工程细节问题。平台上并发跑几百条用例,经常出现“单独跑一条能过,并发跑就挂掉”的诡异现象。
查到最后发现是状态污染。Agent 的工具调用会读写一些共享缓存和会话状态,并发场景下,case A 的上下文串到了 case B 里,导致 Agent 以为自己已经查过订单了,实际上根本没有。
解决办法是强制隔离一切可变状态:
| 隔离项 | 风险 | 处理方案 |
|---|---|---|
| 会话状态 | Case 之间上下文串线 | 每条用例独立 session,按 case_id 隔离 |
| Mock 数据 | 共享 mock 导致数据覆盖 | 每条用例创建独立的 mock 数据副本 |
| 缓存 | Agent 读取到其他用例写入的缓存 | 评测环境禁用共享缓存,或按 trace_id 隔离 |
| 中间件状态 | 限流、熔断误伤 | 评测流量走独立队列,不触发线上防护策略 |
这个坑告诉我们,评测平台自身的稳定性也是一项治标治本的工作。评测结果里的“失败”必须是 Agent 真实能力的失败,而不能是基础设施串线造成的假失败。
6. 关于 Agent 评测的几点后续思考
6.1 评测平台守的是“下限”,不是“上限”
做了这么久,我最大的体会是:评测平台本质上是个“守下限的系统”,它没办法帮你做出一个惊艳用户的 Agent,但能防止你带着明显瑕疵上线。
这就像工厂里的出厂质检线。质检不能保证产品一定大卖,但能防止把一批次品发到客户手里。没有质检线,产品偶尔超常发挥,偶尔完全翻车,业务没法稳定运转;有了质检线,也许产品不会每次惊艳,但至少表现是稳定的、烂也是烂在明处,团队知道改哪里。
所以如果你想靠评测平台来回答“这个 Agent 到底能带来多少业务增量”,大概率会失望。它更适合回答“这次改动有没有把老问题搞坏”“这个新场景能不能撑住底线”。
6.2 评测得从“结果判断”走向“过程判断”
当前评测体系里,我们对“结果”的判断已经比较完善,但对“过程”的判断还非常粗糙。而这个缺口正在变得越来越关键。
很多线上问题并不是最终结果错了,而是过程出了问题。比如 Agent 在合规底线边缘反复试探,跟用户说“我可以试着申请,但不保证成功”,看起来没问题,但话术里隐含了不该有的承诺;再比如 Agent 绕了很多弯,调用了一堆不必要的工具,最终结果是对的,但效率极低,用户等得很不耐烦。
后续我想把评测的重心从“最后那句话对不对”往“中间每一步该不该这么做”迁移。具体来说,把会话轨迹拆成行为标签序列,比如“查询订单”“解释原因”“主动承诺”“请求确认”,再拿这个序列跟专家标注的“最优行为路径”做比较。这个方向工程量不小,但我觉得是 Agent 评测绕不开的一站。
6.3 评测平台自身也要有演进闭环
最后一个思考是关于平台自身的。评测平台很容易做成一个一次性的工具,但 Agent 在持续进化,评测平台也必须跟着进化。
我们现在已经在做的,一是把线上用户的负面反馈自动回流到评测用例池里。线上出现一例投诉,沉淀成一个新的评测用例,下个版本重点盯。这样评测题库会跟着业务痛点一起长。二是判分器自身的纠错机制,每次人工抽检发现的误判,都会回到判分提示词或规则库里,逐步减小判分盲区。
如果让我重新做一次这个平台,我会更早动手。业务 Agent 的评测这事,永远没有“等数据攒够了再开始”的说法,从第一条用例开始沉淀,结果自然会慢慢长出来。