
做Agent开发这一年多我最大的感受是写Prompt已经不难了难的是改Prompt。一段几百字的Agent指令改掉三行你根本不知道它是让Agent变聪明了还是埋了一颗雷。很多团队的迭代模式还停在“改Prompt靠猜上线靠反馈”的原始阶段——发一个版本上去等几天用户来骂再连夜复盘。这个循环又慢、噪音又大、还经常归因错误。这篇东西想聊的是AI Agent评估这套工具链。它解决的问题很直接把“感觉这个版本变好了”变成“数据证明这个版本确实变好了”。通过离线测试集、量化指标、自动化回归和一个反馈回流机制让每一次Prompt改动都有依据、有对照、有后悔药。如果你正在做Agent应用开发尤其是涉及多轮对话、工具调用、状态流转这类复杂逻辑的项目这篇文章应该能帮你省掉不少冤枉路。我不打算给你一套学院派的理论框架而是把我实际踩过、试过、最后沉淀下来的方法拆开来讲。1. 为什么Agent迭代总像在掷骰子1.1 一个改动引发的“连带翻车”我之前参与过一个客服Agent项目最初的时候大家改Prompt主要靠直觉。有一次为了降低Agent乱猜价格的频率开发者在系统指令里加了一句“请直接使用工具查询不要根据历史信息推测”。直觉上这句话没毛病。实际跑下来涉及“价格查询”的会话确实变好了工具调用率上去了。但同期我们发现凡是用户问“你们最近有什么活动”这类偏开放的问题时Agent反而变得很死板——它接了一句“请提供商品ID”而不是主动调用活动查询工具来帮忙找。这个问题如果放线上可能要等两三天等用户通过“转人工”按钮表达不满客服再逐条翻聊天记录才能定位到是这句Prompt改坏了。这个案例说明了Agent迭代的核心窘境你改的是一个局部行为但它影响的可能是整条链路。没有回归机制你根本不知道一个改动到底让哪些场景变好、哪些场景变差。所谓的“靠猜”本质上就是缺少一套可量化的对照工具。1.2 线上反馈为什么救不了火“上线靠反馈”这个模式最大的问题已经不是慢而是不可归因。反馈从用户端传到开发端中间要经过好几道关卡每一道都在丢信息。第一道关卡是“沉默的大多数”。用户遇到Agent答得不好很多时候不会主动骂而是直接关掉页面、换个人工入口或者干脆放弃。你在后台看到的“满意度低”其实是一个严重被稀释的信号——那些最不满意的用户往往没有留下任何结构化反馈。第二道关卡是“反馈的混淆性”。就算用户点了“不满意”你也很难分清到底是Prompt写得不清楚、工具调用失败、模型本身理解错还是某个分支逻辑压根没覆盖。一条会话轨迹里有十几轮对话和七八次工具调用归因难度非常高。第三道关卡是“时间差”。从改动上线到用户反馈平均已经过去几天甚至几周。这期间如果又改了其他Prompt、换了模型版本那新反馈到底对应哪次改动基本只能靠猜。所以我一直跟团队说线上反馈不是不能看而是它只能作为“长远方向的信号”不能作为“每一次改动好坏的判断器”。你需要一套能在改动后几分钟内给出答案的机制这就是离线评估体系。1.3 评估驱动开发到底改变了什么所谓评估驱动开发就是让每一次Prompt或代码改动都跑一遍固定的测试集用固定的指标算出一份对比报告再决定能不能上。这套逻辑和传统软件工程里的单测、回归测试非常像。区别在于Agent的行为不像普通函数那样确定——同一个Prompt同一段输入模型输出可能每次都不一样。所以Agent评估要考虑概率分布要看统计结果而不是孤立的对错。把评估嵌进开发流程之后整个迭代节奏会变成这样你从线上日志里沉淀一批代表性测试用例组成黄金测试集。改动前先跑一遍当前版本得到基线指标。改完Prompt或代码后再跑同一批测试集得到新指标。对比两份报告看哪些指标涨了、哪些指标跌了、哪些具体用例从“通过”变成“失败”。如果整体变好且没有关键场景回退就上线否则继续调整。这套循环本身并不复杂但它需要解决三个前置问题用什么指标、用什么测试集、用什么方式跑评估。这也是我后面要讲的重点。2. 评估体系搭建第一步把“好”的标准定义到可测量2.1 指标到底怎么选从“准不准”到“值不值”很多第一次搭评估体系的团队上来就把“正确率”当成唯一指标。但Agent任务和普通分类任务不一样一个多轮会话很难用“对”或“错”来一刀切。我常用的做法是把指标分成四个层次指标类型具体示例关注点使用场景任务完成指标任务成功率、流程完整率、目标达成率结果对不对所有面向最终目标的任务过程质量指标工具调用正确率、无效轮数、是否跑偏过程顺不顺多工具、多分支的复杂链路资源消耗指标token消耗、平均调用轮数、端到端延迟成本高不高需要控制线上成本的项目用户感知指标最终回复规范率、满意度打分、转人工率用户体验好不好偏客服、助手类场景每个指标都不是独立存在的。我举个常见的冲突如果你追求“任务成功率”Agent可能会倾向于多调用工具、多追问、多尝试几次这会让平均轮数上升成本也跟着涨。反过来如果你把“轮数”卡得太死Agent遇到边界情况可能草草收场成功率就掉了。所以选指标的原则是先确定你最核心的一两个目标再辅助加两三个约束型指标。比如说客服Agent的核心指标是“问题解决率”约束指标是“平均轮数不超过X轮”和“工具调用错误率低于Y%”。指标不是越多越好多了反而没法决策。2.2 黄金测试集从线上日志到“固定考题”指标定义完之后最重要的资产就是测试集。我把它叫“黄金测试集”因为它一旦建立就是你所有迭代的锚点。测试集的来源有三个第一线上真实日志。这是最宝贵的来源。你只需要在Agent的日志系统里加一个随机采样任务每天抽取一定比例的真实会话按月汇总。注意抽取时不要只抽成功样本那些转人工、差评、超长会话更要抽——这些才是问题的富矿。第二历史问题清单。把过去几个月里用户明确表达不满、或客服介入处理过的会话整理出来做成“红队样本”。这类样本体量不大但每一个背后都可能藏着一个系统性的缺陷。第三合成样本。有些边缘场景线上极少出现比如用户用特殊格式输入、同时问两个问题、或要求Agent做超出能力范围的事。这时候可以人工编写一批典型指令模拟这种输入。不过合成样本要控制比例不要超过测试集总量的两成。在搭建测试集的时候我会给每条用例打上多层标签意图类型、流程长度、是否涉及工具调用、历史反馈状态、预期结果说明。标签的意义不只是方便管理更重要的是以后做指标分析时可以按标签切片查看。不然你只知道“整体成功率跌了”却不知道跌在哪个场景那排查效率还是不高。体量方面我的实践经验是每个核心场景至少保留40到60条用例。场景越多样本总量越大。测试集少于100条统计波动会非常大哪怕你没做任何改动同一版本跑两遍都可能差好几个百分点。那时候你收到的“评估结果”基本都是噪声完全没有决策价值。2.3 基线与阈值没有比较就没有伤害有了测试集第一件事不是定阈值而是跑基线。我见过不少团队测试集刚建好就开始追求“准确率95%”结果发现怎么调都到不了然后怀疑测试集本身有问题。正确的做法是先用当前线上版本把整批测试集跑一遍记录每项指标的原始数值。这个数值就是基线。之后所有改动的评价都建立在“相对基线的变化”上。这里有一个很容易被忽略的坑同一版本跑两遍指标也可能有波动。因为大模型输出本身有随机性哪怕温度设成0在多轮场景下也可能因为中间分支选择的细微差异产生不同结果。所以在定基线那天我建议同一个版本连续跑三遍记录下来指标的波动范围。比如某场景成功率基线是86%到91%之间那么下次评估如果新版本只做到90%并不算真正提升——它可能只是随机波动。阈值怎么定我的习惯是分三层红线指标不允许低于基线比如核心场景的任务成功率。一旦跌破直接拦截上线。观察指标可以有3到5个百分点的浮动态势但连续两次下跌就要警觉。参考指标比如token成本、延迟不设硬性门槛但记录趋势供后续优化参考。阈值不要拍脑袋。如果定得太高你会为了过拟合测试集而反复调整“措辞”最后Agent在测试集上好看线上照样翻车。如果定得太低评估就失去了拦截意义。3. 评估执行层LLM裁判、规则校验与自动化流水线3.1 LLM裁判怎么调才靠谱有了测试集和指标接下来面临一个现实问题谁来判定一个会话算“成功”还是“失败”特别是客服Agent这类开放域任务用户问法千奇百怪Agent只要最终帮用户解决了问题过程稍微绕一点算成功还是失败一种做法是人工抽检但抽检无法规模化。现在主流方案是让一个更“聪明”的大模型来当裁判也就是所谓的LLM-as-Judge。它读一遍Agent的完整会话轨迹对照预期目标输出一个结构化评分。但直接让模型“凭感觉打分”是不行的。我踩过不少坑总结下来有五个关键配置第一打分标准必须可操作。不要写“请评估回答质量”而是写“如果Agent在用户未提供订单号时主动询问了订单号并且没有编造订单信息则判定为通过”。标准越具体打分的一致性越高。第二强制模型先推理再打分。通过Prompt要求裁判“先列出证据再给出结论”可以明显降低模型凭印象打分的概率。我一般让裁判输出一个JSON内容包括判断依据、证据列表、最终分数。第三防止位置偏见。如果让裁判比较两个版本的输出它可能更偏好先出现的那个。对策是把要比较的两段输出顺序随机交换跑两轮如果结论不一致就标记为“存疑样本”交给人工复核。第四防止自我偏好。裁判大模型往往会对自己生成的内容偏心。所以在打分指令里不要强调“这是参考回答”而要把参考回答描述成“来自另一个系统的常规输出”让裁判基于客观标准而不是风格相似度来评价。第五校准裁判的“手劲”。有些模型打分偏保守动不动给低分有些模型偏宽松什么都能给满分。做法是让裁判先在20条人工标注过的样本上打分把它的评分分布和人工分布对齐一下如果偏差大就调整Prompt里的语气词或使用few-shot示例。下面是一个我实际用过的打分指令模板精简版你是一个评估专家。请阅读下面的Agent会话记录判断Agent是否成功解决了用户的目标。 评估标准 1. Agent是否从用户输入中正确识别了意图 2. Agent是否按需调用了正确的工具 3. Agent的最终回复是否准确且不包含编造信息 4. 如果信息不足Agent是否主动追问而不是猜测。 输出格式JSON {passed: true/false, evidence: 一句话理由, score: 0-100} 注意先阅读完整会话再下结论。用这个模板之后裁判打分的稳定性会有明显提升。但要注意LLM裁判不是万能的它只能帮你“区分好坏”不能帮你发现“规则漏洞”。所以在评估体系里规则校验器必须占有一席之地。3.2 规则校验器确定性那部分不能靠模型LLM裁判擅长做开放性的质量判断但它不擅长做确定性的格式校验。比如Agent调用工具后返回了一串JSON它是否包含了必要的字段最终回复里是否包含了订单号这些用大模型来判断不仅慢而且可能出错。我一直建议把评估拆成两层底层用确定性规则上层用LLM裁判。规则层处理“结构性问题”LLM层处理“语义质量问题”。举个例子我处理过的Agent里经常需要校验这样一些规则工具调用参数是否符合接口Schema比如订单查询工具要求“订单号必须是数字”如果Agent传了一个字符串订单号直接判失败。状态流转是否合法比如用户还没确认身份时Agent不能直接调取“修改订单”的接口。最终回复是否包含关键要素比如客服场景里Agent回答完问题必须附带上一次工单编号否则算不完整。这些规则用一个简单的配置文件就能管理类似这样rules: - name: order_query_param_check type: schema tool: query_order expect: order_id: number - name: final_reply_contains_ticket type: regex target: final_answer match: 工单号[:]?[A-Z0-9]{8,} - name: no_hallucinated_price type: tool_result_match target: final_answer source_tool: query_price规则层和LLM裁判的组合方式我是这样处理的先跑规则层如果规则层发现明确错误直接判失败不再浪费钱去调用大模型裁判。只有当会话通过了所有规则校验才交给LLM裁判做质量打分。这么做的好处很多。最直接的是成本下降因为大部分明显不合格的案例在规则层就被拦截了。其次是可解释性好规则层给出的失败原因非常具体开发者一眼就能知道要改哪里。3.3 评估自动化把“跑一次评估”变成一条命令测试集和评估逻辑都有了之后剩下的工作就是让它跑起来足够快、足够方便。如果每次评估都要手工拉数据、手工调脚本、手工看结果人很快就懒得跑了评估体系最终会沦为摆设。我搭的评估流水线一般包含四个步骤全部可以用一条命令触发第一步拉取当前代码和Prompt配置固定版本号。 第二步在测试集上批量执行Agent逻辑保存完整的会话轨迹。 第三步先跑规则校验再用LLM裁判对通过规则层的会话打分。 第四步生成对比报告输出到本地文件或者 CI 的产物目录。报告的重点不是总通过率而是对比视图和上一个版本相比哪些场景的通过率上升哪些下降哪些具体的用例从“通过”变成“失败”。这部分的输出我会控制在“一眼能看出问题”的范围而不是丢出一张几千行的表格。在自动化流水线里我还会加一个“回归门禁”的概念。也就是说在合并代码或发布新版之前必须跑一遍评估脚本如果红线指标跌破基线流水线直接给出失败状态。这样就把“评估”从可选项变成了必选项——很多团队坚持不下来就是因为评估没有卡在发布流程中可有可无。4. 一次完整的实战某客服Agent的评估改造全流程4.1 项目背景一个靠人工抽检的售前客服Agent我用一个实际经历来把这套方法串起来。某工具类App接了一个客服Agent负责处理售前咨询查价格、查库存、查优惠活动、引导下单。Agent会调用工具但Prompt写得比较“厚”各种规则堆在一起逻辑分支很多。项目当时的迭代方式是这样的每个版本上线前团队抽几十条历史会话人工看一遍感觉差不多就发。结果没人敢改Prompt因为你动一个分支可能影响另外三个分支。大家宁可在大版本边界上挤牙膏式地微调也不敢来一次大重构。整个项目最痛的场景是“价格问题”。Agent面对“这个多少钱”之类的提问有时会引用过一个时间点的历史价格或者在工具返回多个结果时选错SKU库存量单位。用户一旦收到错误价格信任度就会明显下降。4.2 落地过程200条黄金样本和5个核心指标我和团队第一步是做数据沉淀。从线上日志里随机抽了150条真实会话再从过去三个月转人工和低评分会话里挑出了50条“问题样本”合并成200条测试集。接下来打标签按意图分成“价格查询、活动咨询、库存查询、物流催办、售后申请”五个场景每个场景大概40条。指标方面我们最后只定了5个核心指标价格提示正确率最终回复价格是否来自最新工具查询结果工具调用正确率Session中所有工具调用的参数和时机是否正确场景任务成功率每个场景是否达成用户目标平均会话轮数超过8轮视为异常关键信息完整率最终回复是否包含适用的免责提示或单号先跑基线。当时代价并不低200条会话全部用真实模型跑了一遍加上LLM裁判花了几十块钱的token费用。但换来一份完整的基线报告整体任务成功率76%价格提示正确率只有68%活动咨询场景的成功率是62%。这两个数据直接印证了开发者的感觉——价格确实是重灾区。4.3 一次迭代的全过程从“改一行Prompt”到“看完整diff”拿到基线之后我们做了一次典型迭代。开发者想解决“Agent猜价格”的问题。第一次改动很简单在系统指令里加了一行“禁止根据历史会话或常识推测价格价格信息必须来自实时工具查询结果。”改完后跑同一批测试集结果很有意思整体成功率涨到了80%价格提示正确率涨到了77%。看起来是成功了对吧但点开“活动咨询”场景的分项成功率从62%掉到了55%。查看失败用例后发现问题出在措辞的歧义上。Agent碰到“你们最近有什么优惠”这类开放问题时不知道应该调用哪一个工具因为它既不是纯粹的价格查询也不是库存查询。新Prompt里那句“价格必须来自实时工具查询”并没有给它指明方向反而让它过度保守起来——它开始反问用户“您是指哪个商品的价格”而不是主动先调用活动列表接口。第二次改动我们调整了Prompt结构不再是一味地“禁止推测”而是增加了条件分支如果用户问的是具体商品价格走价格查询工具如果问的是活动或优惠先调活动查询工具再结合返回结果回答。跑完评估整体成功率落在85%活动咨询场景恢复到了60%价格提示正确率到了80%。更关键的是原来那些“历史价格误导”的翻车用例全部从失败列表里消失了。整个过程花了两天实际每次跑评估只需要十几分钟。如果没有这套评估流程第一次改动上线后大概率会变成“线上价格类问题变少了但活动类问题变多了”——而我们直到用户投诉才会发现。4.4 线上反馈怎么回流到测试集评估体系运行一段时间后一定要形成一个持续更新的闭环。我们的做法是每周五做一次“日志挖掘”从本周线上会话里随机抽取50条再加上人工标记了“转人工”或“情绪负面”的全部会话合并成一个待审队列。然后由运营或产品同学快速看一遍把其中真正体现新问题的会话挑出来补充到测试集里同时更新标签。这个操作听起来挺轻量但坚持下来效果很明显。我们管这个机制叫“红队集”。每次Prompt改动上线之后当周新增的“红队样本”会在下周一自动被标记并合入测试集。一个月之后我们发现线上转人工率下降了约三成而测试集本身也从200条长到了400条左右覆盖面比之前宽了很多。值得提醒的是红队集会引入一些极端、冷门的样本。如果全部合入而没有任何筛选测试集会很快变得“过于严苛”导致正常迭代很难通过。所以每次合入前我会对新增样本按“问题共性”做去重。比如这个星期有20个用户都因为“查不到发票”转人工那么只需要挑出2到3条典型会话入集即可不需要把20条全部塞进去。5. 常见问题与排查技巧实录5.1 为什么评估分数涨了线上反而更差这是评估体系建设中最容易遇到的“信任危机”。明明离线评估数据显示新版本更强上到线上一跑用户的反馈却更糟了。我复盘过几次原因大致有这么三类。第一类是测试集分布偏离线上。测试集里的场景比例是从某个时间段采样的但线上用户行为一直在变。比如你评估时“订单查询”占大头上线后实际涌进来一半“售后纠纷”请求而测试集里售后样本却很少那评估结果自然不能代表线上。解决办法是定期重采线上日志更新测试集比例同时保留一部分“历史保留集”防止过度拟合到最新分布。第二类是数据泄漏。测试集里的某些样本在模型训练语料或检索库里出现过Agent的评测表现可能有一部分来自“记住了答案”而不是真正理解。你改动Prompt后这种“记忆优势”可能被放大或破坏和线上真实表现脱节。这个比较难避免只能多从私有日志里抽取样本减少公共语料成分。第三类是单案例过拟合。我见过一个现象开发者为了把某条失败case跑通反复调整Prompt的措辞最终那条case过了但它的过法非常“巧合”——比如刚好绕开了某个通用逻辑结果同一版本里另外五条相似case全挂了。对策是每次评估时要同时关注“测试级通过率”和“跨场景稳定性”。如果总分涨了但某个关键场景的通过率掉得离谱那就要警惕是“局部好、整体差”。5.2 用户评分能不能直接当评估指标很多团队喜欢把线上满意度评分直接当成评估指标。我不是反对但你要意识到它有三个天然缺陷。第一是滞后性。评分数据通常要等用户会话结束之后才产生而且很多用户压根不评数据量不够每天都够做决策。第二是偏置性。敢给低分的用户往往是情绪最强的那一批而满意的用户可能直接走了不会顺手点个赞。所以平均分往往会被低估。第三是不可归因。评分只能告诉你“这单砸了”不能告诉你“为什么砸了”。用户可能在纠结第五轮的问题结果只在最后点了“不满意”你根本看不出是哪次工具调用出的错。我的建议是用户评分不要作为主评估指标它是“作业帮”而不是“考试卷”。你可以把评分低、转人工的会话提炼成红队样本补充进测试集用离线指标去追踪它的修复状态。这样既利用了线上反馈信号又明确了归因路径。5.3 评估成本太高怎么办评估费用是很多团队放弃的最后一根稻草。200条测试集每条都调用一次大模型执行再调用一次LLM裁判打分确实不是一笔小钱。我优化成本的方法是三层漏斗。第一层用规则层拦截确定性错误。这些case不需要LLM参与直接判失败成本和速度都可控。第二层用小参数模型做预筛。对于通过规则层的case先让一个便宜的小模型给出“疑似失败”和“疑似通过”的初判。只有那些“疑似失败”到一定置信区间的case才交给大模型裁判复核。第三层LLM裁判只做争议样本和核心场景。非核心、低风险场景可以用抽样的方式评估不必每一条都跑全量。实践下来这套漏斗让我们的评估成本降到了原来的六成左右而评估结论的可用性没有明显下降。如果你的测试集很大还可以在代码层面加上“结果缓存”同一版本同一case的评估结果直接复用不需要重复计算。5.4 关键习惯把Prompt、测试集和模型版本绑在一起我最后单独说一个经验这可能是整个评估体系里最容易被忽略、但对历史回溯最有帮助的动作——版本绑定。每次跑评估的时候我会在产出报告顶部记录三条信息Prompt版本、测试集版本、模型版本。这三者缺一个这份报告就失去了回溯价值。很多团队跑评估的时候随便改了一点Prompt就重新跑测试集结果不理想却说不清到底是“测试集变了”还是“Prompt变了”导致的。版本绑定可以帮你快速锁定变因。我习惯在每条Prompt改动的描述里加上一句“本次评估对应测试集版本vX”。这样过一个月再回看你能从历史评估报告中清楚地看到哪一次改动、在哪一个测试集版本上、让哪个场景的指标发生了变化。这套“审计线索”看起来不起眼但在你遇到线上事故、需要快速回滚时它的价值会无限放大。只要定位到“当前线上版本对应的是哪一次评估报告”你就能立刻判断它是正常的迭代波动还是隐藏的系统性问题。做了这半年评估体系改造我个人最大的体会是它不会让你成为一个更“会写Prompt”的人但能让你成为一个更“敢改Prompt”的人。以前每次改动都像赌博现在每次改动都像做实验——你手里有数据心里有底。而且这套机制一旦转起来越到后面越值钱因为你的测试集会越来越贴合真实用户你的迭代速度也会越来越快。