干了这么多年Agent开发,最常被新手问爆的问题就是:“我搭的智能体为什么测评分数这么难看?”说实话,测评成绩差这件事,十有八九不是模型本身不行,而是你压根还没把Agent当成一个“系统”来调。你把它当成了一个会聊天的接口,那它自然只能给你交出一份不及格的答卷。
这篇东西就是写给被测评分数按在地上摩擦的新手看的。我先把话放这儿:只要你还在地球上做Agent开发,无论你是用某商业大模型的API、开源底座模型,还是自研的垂域小模型,下面这套改进方法论都适用。我会把整个“分数差→定位根因→逐层修复→回归验证”的闭环流程掰开揉碎讲清楚,每一板斧都给到可以直接抄的实操方案。
1. 先别急着怀疑模型:搞清楚测评到底在打什么分
1.1 一张测评成绩单告诉你的三件事
很多人拿到测评报告,只看一个总分,然后就开始焦虑。这是最大的误区。测评报告本质上是一张“体检单”,它至少包含三个维度的信息:任务完成率、过程合规性和资源消耗。
以我手头一个虚构的“客户服务工单Agent”为例,它在某内部基准集上的表现是:任务完成率62%,工具调用准确率71%,平均每任务触发的模型调用次数高达9.4次。总分61.5,看着就很惨。但你拆开看会发现——工具调用准确率71%意味着每三次调用就有一次是瞎猜的意图,而调用次数9.4次则说明Agent在反复兜圈子,一次性能解决的事它拆成了十步。这两个数字一叠加,任务完成率低就是必然结果。
所以拿到测评报告,先别盯着总分,要盯着三个数字:成功率、工具调用准确率、平均步数。这三个数字基本框定了问题边界。成功率低可能是规划能力弱,工具调用准确率低大概率是工具描述和参数Schema有毛病,平均步数过高则指向状态管理混乱或Prompt里没有给清晰的终止条件。
1.2 分数低只是表象,要区分“病在prompt”还是“病在工程”
我见过太多人一看到分数低就冲去换更大的模型。那个“客户服务工单Agent”起初就是,换了某头部商业大模型API后,分数确实从61分涨到了68分,但多花的token成本翻了三倍。而且一换回轻量底座模型,分数立刻打回原形。这说明问题根本不在模型智力,而在系统设计。
模板右移,思路左移,核心还是箱体设计
这里有个简单的判断口诀:如果Agent在简单的单步任务上频繁翻车,那大概率是Prompt和工具定义的问题;如果单步任务没问题、复合任务老是断线,那才是规划与状态管理的问题。 前者的修复成本很低,改几段文案就能见效;后者则需要动工程架构,不是换个模型能糊弄过去的。
很多人分不清这两类问题,结果就是在一个错误的层面反复折腾。改Prompt没用就去调参数,调参数没用就去换模型,换模型没用就怀疑数据集,最后陷入玄学调参的怪圈。
1.3 快速定位:先跑一遍人工走查,再决定往哪个方向改
在动任何代码之前,我强烈建议做一次人工走查。具体操作是:从测评集里随机抽20个失败case,把Agent的完整对话轨迹(包括每一步工具调用的输入输出)打印出来,自己扮作一个评审员,逐个标注“它是在哪一步开始走偏的”。
这一步花不了多少时间,但价值极大。举个例子,那个工单Agent的失败case里,有接近一半是在“查询客户历史订单”这个动作上报错。人工一看就明白了——工具接口本身没问题,但Agent在调用时传参格式经常错,而且是那种把日期字符传成数字对象的低级错误。这种case喂给任何大模型都救不回来,因为根因不在推理,在工具Schema设计和参数校验上。
人工走查的产出是一张简单的表格:case编号、失败步骤、失败类型(意图识别错误/参数构建错误/流程中断/过度调用)、可能根因。这张表就是后续所有改进的作战地图。没有这张图,一切调优都是盲人摸象。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 立竿见影的第一板斧:把System Prompt变成“操作手册”
2.1 指令模糊是Agent翻车的第一大原因
我看了很多团队写的System Prompt,风格出奇一致:充满情怀、目标远大、细节匮乏。 比如“你是一名专业的客服助手,请尽力帮助用户解决他们的问题,提供准确、周到的服务”……这话说给任何模型听,模型都只会回你一句“好的,我明白了”,然后开始自由发挥。自由发挥就意味着不可控,不可控就意味着测评分数飘忽不定。
同样的行业,国内Agent赛道有人死在Demo环节,多半是prompt没有操作感。你要把System Prompt从一段“角色介绍”改写成一本“操作手册”。操作手册的定义是:明确输入是什么、处理流程分几步、每一步输出什么格式、什么情况下终止、什么情况下上报异常。不需要文采,需要的是可执行的确定性。
我曾经把工单Agent的System Prompt从160字扩写到1400字,没有用任何花哨技巧,只是把处理流程拆成了五个明确步骤,并给每一步定义了输入前置条件和输出格式。分数当场涨了9个百分点。这不是什么魔法,而是把模型的决策空间从“开放式问答”压缩到了“流程填空”。
2.2 给Agent写“流程脚本”而不是“目标宣言”
这里给一个可以直接参考的Prompt结构模板,按顺序写就行:
code复制你是[角色],负责[任务边界]。
处理流程:
1. 收到[触发信号]时,先执行[动作A],判断条件X是否满足。
2. 若条件X满足,进入[流程B],并调用[工具/接口]获取数据。
3. 若条件X不满足,输出[兜底话术],不得尝试[动作C]。
4. 每个步骤完成后,用[格式]输出中间结果,供后续步骤使用。
终止条件:
- 当[目标状态]达成时,输出最终答复并停止调用工具。
- 当[步骤]连续失败超过N次时,输出[降级话术]并转人工。
硬性约束:
- 禁止在未调用[工具Z]的情况下直接生成[结论类内容]。
- 禁止猜测用户未提供的[必要参数],参数缺失时发起追问。
你会发现核心是写“条件分支”和“终止条件”。模型最怕的是没有退路的任务——它不知道什么时候该停,就会一路瞎编下去。终止条件写清楚了,平均步数立刻往下掉,成本也会跟着省。
2.3 少样本示例怎么给才不喧宾夺主
Prompt里加few-shot示例是有效手段,但示例选不好会起反作用。我见过的典型错误是:示例内容和实际业务场景南辕北辙,或者示例过于复杂、包含了太多边界情况,导致模型学会了“在简单输入上做复杂输出”。
正确做法是给“典型路径”的示例。每个示例必须覆盖:一个完整的输入、Agent内部的思考摘要、每一步的工具调用(含参数)、最终输出。并且示例数量控制在3到5个之间,不要贪多。我试过给8个示例,测评分数反而下降了1.5个百分点——因为示例之间的冲突开始干扰模型的判断。
这里有个细节很多人忽略:示例中的工具调用参数必须是“正确格式”,不能有笔误或用幻觉写出的字段。 模型会把你示例里的格式当作模板去模仿,一旦模板错了,它会一直错下去。我曾经排查一个诡异问题——Agent频繁把一个文本参数的格式从正确的JSON字符串改成纯文本,后来发现是我few-shot示例里不小心写了一个未加引号的字符串,模型还以为那才是正确格式。
2.4 关键参数调整:temperature不只是调“创造性”
说到参数,先把结论放这里:跑Agent测评,temperature绝大多数场景应该设在0到0.2之间。 很多人把temperature当成控制“创意”的旋钮,把0.7当默认值,于是Agent每次调用的输出都在随机游走,工具参数生成错了第一次、重试又错第二次,因为每次返回的字段名都不一样。
一次测试中,我把某客服Agent的temperature从0.6降到0.1,同时在tool调用参数里打开“结构化输出”强制约束,工具调用准确率从71%直接拉到89%,而且token消耗降低了22%。原因很简单:低temperature让模型不再“换着花样犯错”,而是稳定遵循一种最优格式。稳定是一切工程化的前提,创意在这个场景里一文不值。
另外,很多平台的API支持response format参数,能指定JSON模式,这玩意儿能开就开。开了之后,模型输出的解析失败率基本归零,这可比事后用正则去补漏高到不知道哪里去了。
3. 第二板斧:工具描述写不好,Agent就是在盲人摸象
3.1 工具描述不是给用户看的,是给模型看的
很多人写工具描述,写的是“面向人类的产品说明书”——功能齐全、措辞精炼,就是模型看不懂。工具描述的核心读者是LLM,它唯一需要搞清楚的是三件事:这个工具什么时候用、怎么用、用了之后会得到什么。其他全是噪音。
还是拿工单Agent说,它的“查询客户历史订单”工具最初描述是:“根据客户信息查询其在系统中的历史订单记录,返回订单列表。”看着没毛病吧?但模型经常不知道该传什么参数、不知道返回结构长什么样、不知道什么时候不该调它。问题就出在描述信息根本不够。
我的改法是,把工具描述拆成四个模块:工具用途与适用场景、参数说明(含格式和量纲)、返回结构说明、典型调用示例。 尤其是“适用场景”这一条,要写明白“什么时候用”,更得写明白“什么时候不用”。比如补上一句:“若用户提及'最近订单'但未提供客户ID,先通过'客户搜索'工具获取ID,再调用本工具。”就这一句,意图识别错误率肉眼可见地下降。
3.2 参数Schema里的每个字段都要“逼供”自己
工具参数Schema是Agent最容易翻车的地方,而且翻车方式千奇百怪。我自己总结了一条铁律:每一次工具调用失败,先怀疑Schema,再怀疑模型,这个顺序反了就会白忙一场。
给你看一个典型的错误Schema(简化版):
json复制{
"name": "query_orders",
"parameters": {
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "客户编号"
},
"start_date": {
"type": "string",
"description": "开始日期"
}
},
"required": ["customer_id", "start_date"]
}
}
看起来挺干净对吧?实际上模型在这里踩了无数坑:start_date到底什么格式?“YYYY-MM-DD”还是“YYYY/MM/DD”还是时间戳?description里没说。customer_id的用途也没说。模型只能靠猜,猜错就是参数构建失败。
改进后的版本是这样的:
json复制{
"name": "query_orders",
"description": "查询客户历史订单列表。适用于用户要求查看购买记录、订单状态、物流信息等场景。必须先通过search_customer获取customer_id。",
"parameters": {
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "客户唯一标识,由search_customer接口返回,形如CUST-2024-0001。必须完整保留前缀和分段符,不要拆分或拼接。"
},
"start_date": {
"type": "string",
"description": "查询起始日期,格式为YYYY-MM-DD,如2024-03-01。若用户未指定,默认为180天前。"
}
},
"required": ["customer_id", "start_date"]
}
}
看到了吗?我在每个字段描述里都写清楚了格式、示例、默认值和来源链。 模型需要的不是抽象定义,而是这种近乎“啰嗦”的约束信息。参数描述写得越具体,模型构建参数的准确率越高。这不是玄学,是信息论——你给模型的信息熵越低,它的选择空间越小,结果就越稳定。
此外还有一个极其容易被忽略的点:不要混用类型。某些平台的函数调用支持integer,但老有人图省事统一用string,然后在描述里写“数字字符串”。模型确实能输出数字字符串,但一旦遇到“号码前导零”这类情况就容易翻车。能用int就用int,能用enum就写死enum,能用const就写死const。每多一条硬约束,模型就少一次自由发挥的机会。
3.3 用“工具调用记录”反推描述缺陷
实操里有个非常好用的debug技巧:不要光看工具调用是否成功,要看工具调用前模型生成的“思考痕迹”。很多Agent框架会记录模型在调用工具前的思考文案,那种“我需要查询客户订单,因此调用query_orders工具,customer_id来自之前的搜索结果”就是健康调用。
而如果思考痕迹里出现“用户似乎想知道订单状态,我尝试调用order_status工具,但参数不足……”这类犹豫表述,说明工具定义和当前输入之间存在缺口——模型判断自己缺少必要信息,又不知道该不该追问。这时候应该去补工具的“触发条件”和“参数缺失时的处理策略”,而不是盲目加大模型。
我调试工单Agent的时候,把30条失败的工具调用记录打印出来逐条过了一遍,发现在“退款申请”这个场景下,模型竟然有27%的概率去调用“创建售后单”工具而不是“退款申请”工具。两个工具的功能描述有重叠,边界不清晰。后来我把两个工具的description里各加了一段“是否适用”的判断逻辑,并互相点名排除,意图错误率立刻降了6个百分点。工具描述之间的“边界感”是真的重要。
4. 第三板斧:给Agent装上“安全网”:验证、重试与降级
4.1 让Agent学会“先验证再回答”
有些Agent翻车不怪构思,而在于“流程粗壮”。比如让Agent直接根据用户描述生成一个工单并提交,从不校验数据是否存在。用户描述的信息可能是错的、不完整的、甚至是幻觉出来的,Agent要是直接把话当命令执行,那就等着测评集里一片红。
正确的做法是给Agent加入一道“验证闸门”。在关键动作执行之前,强制Agent回头确认三个问题:必要参数是否齐全、参数值是否符合范围约束、执行这个动作与用户原始意图是否一致。 这不是什么高深技术,就是在Prompt里加一段“执行前自检清单”,或者在代码里加一个拦截器,不让Agent直接调用敏感工具,而是先走一遍参数校验函数再放行。
我常跟别人开玩笑:给Agent装安全带,比给Agent配更强的引擎更优先。 因为Agent一旦高速跑偏,毁的不仅是测评分数,还有生产环境的信用。具体到实现上,如果平台支持“工具前置钩子”,就把参数校验写成独立函数;如果不支持,就在Prompt里明确要求“先输出一段JSON格式的预检结果,再决定是否执行”。实测下来这种二次确认会让成功率上浮不少,虽然多消耗一次调用,但远比重试反复折腾划算。
4.2 重试不是简单重复调用,要改变调用策略
新手最常犯的错误是:调用失败就让Agent原样重试。原样重试的本质是赌概率——如果模型是有随机性的,那么低temperature下重试结果几乎一样,不低temperature的话重试会越来越离谱。这不是重试,是掷骰子。
真正的重试策略要包含三个要素:错误原因回传、策略调整、目标收敛。 也就是说,当一次工具调用失败时,要把失败的错误信息(比如“参数校验失败:date格式应为YYYY-MM-DD,实际收到时间戳”)作为文本回传给模型,让模型看到自己刚才错在哪,然后基于错误信息重新构建参数。这就形成了一次“纠错循环”。
我在工单Agent上实测,加入“错误回传+重新生成参数”后,工具调用成功率从81%提到94%,而且没有增加太多额外调用。本质上这利用了模型的文本推理能力——你直接把错误抛给它,让它自己分析并纠偏,这比抽象地在外面套一层if-else管用得多。
4.3 多步任务的状态管理:别让Agent“失忆”
Agent做多步任务时,“失忆”是头号杀手。比如客服Agent先查了用户订单,然后用户随口问了一句“那这个订单能退吗?”,Agent可能会直接把上一轮的订单号丢掉,重新去“找订单”,然后因为没找到而报错。这就是典型的上下文闪断。
解决方案有两种主流做法。一种是显式状态注入:每一步工具调用结束后,把关键信息(比如订单号、客户ID)存进一个“工作内存”变量,下一步继续组装进Prompt。另一种是结构化推理摘要:模型每完成一步,要用固定格式输出“当前状态摘要”,后续步骤基于这个摘要继续。前者要动代码逻辑,后者纯靠Prompt也能实现,门槛相对低。
我第一次给Agent加“状态记忆”功能的时候,是简单粗暴地在每次调用前把前两步的JSON结果原样拼接进用户消息。效果立竿见影,但因为context里塞了太多冗余信息,token消耗暴增,响应也变慢了。后来改成了“摘要式记忆”——只把上一步提取到的“实体-属性-值”三元组塞进去,效果差不多,但token开销降低近一半。有做多轮任务的朋友,强烈建议在这块多花点心思。
4.4 兜底降级设计:Agent承认不会,比硬编一个答案强
测评集里总有一些Agent能力边界之外的query,比如用户问“你们公司股票代号是多少”,客服Agent既没有工具查询,也不该瞎编。如果它硬答一个错误代码,测评直接扣分。正确做法是给它一条明确的“我不知道”路径。
我给工单Agent设计的兜底是:当工具集整体不可满足用户请求时,输出固定的“转人工请求”话术,并主动收集用户联系电话和问题描述,调用“创建转人工工单”工具。这个兜底逻辑写在System Prompt的最后一条硬性约束里:“如果你判断当前工具集无法满足用户请求,禁止猜测,必须转人工。”就这么一句,不仅提升了测评合规性,更重要的是降低了幻觉率。测评数据的“幻觉扣分项”从12%直接降到4%以下。
5. 第四板斧:用评测数据说话,而不是靠感觉调优
5.1 错误聚类:把失败case按模式归类
凭感觉修Agent是新手村最大的陷阱。你觉得是Prompt不够好,改了半天分数没动;其实是工具Schema偏了,你压根没改到点子上。正确的打开方式是:对测评集里的失败case做错误聚类,把所有失败原因归并成几类,然后逐类分析。
我常用的错误分类标签包括这几类:意图识别错误、参数构建错误、工具选择错误、流程状态丢失、过度调用、幻觉生成、终止条件缺失、候选无兜底。每一个失败case贴一个标签,然后统计频次。频次最高的两三类,就是你要优先干掉的“主要矛盾”。
拿那个工单Agent为例,我第一次聚类后的分布是:参数构建错误占31%,流程状态丢失占24%,意图识别错误占19%,过度调用占14%,其余杂项占12%。这个分布告诉我:模型本身不是主要瓶颈,工程和Prompt设计才是。所以我把80%的精力投在工具Schema和状态管理上,只花20%的精力微调Prompt,一个迭代周期下来分数涨了15个百分点。
5.2 回归测试集:比测试分数更有用的一个习惯
很多团队拿一份公开基准确当“圣旨”,每次迭代只盯着那份分数。但公开基准的题目是静态的,Agent很容易“背题”——它记住了题目的模式,到了真实场景还是瞎。我强烈建议你构建一个自己的回归测试集:从历史用户真实问题里抽80到100条,覆盖正常路径、边界路径、异常路径三种类型,每轮代码改动后都跑一遍这个集子。
回归测试集的核心价值不是衡量“绝对水平”,而是衡量“有没有改坏”。你有一次改了工具描述,主基准分数涨了2分,但回归集里“中文口语提问”这一类case全部崩掉。如果没有回归集盯着,这个“坏改动”根本没人发现,直到上线被用户教育。
我的做法是给每个case标注了难易等级和期望行为。简单case要求完全正确;中等case允许一次追问后正确;困难case要求至少给出合理的兜底路径。每一轮跑完,对比上一轮的表现矩阵,任何类别的回退都一票否决,哪怕总分是涨的。这个习惯帮我避开了很多次“看起来涨分、实际上变蠢”的假象。
5.3 一页纸的Agent诊断清单
最后分享一份我每次接一个“测评分数差”的Agent时,都会先跑一遍的排查清单。按顺序执行,剩下的就只是执行问题。
| 序号 | 排查项 | 操作方式 | 期望结果 |
|---|---|---|---|
| 1 | 人工抽看20个失败case | 打印完整对话轨迹并标注失败步骤 | 圈定主要失败模式 |
| 2 | 检查工具参数Schema | 逐个字段检查类型、格式、示例、默认值 | 无歧义、无缺省、无错误示例 |
| 3 | 检查System Prompt终止条件 | 搜索有无“何时停止”的说明 | 每个任务都有明确终止路径 |
| 4 | 检查few-shot示例格式 | 核对每个示例中的工具调用参数是否规范 | 示例即标准,不能有错 |
| 5 | 检查重试策略 | 确认失败后有无错误回传与策略调整 | 不做无脑重复调用 |
| 6 | 检查关键链路状态管理 | 观察多步任务是否丢失关键实体 | 关键信息在步骤间保持 |
| 7 | 跑回归集对比 | 对比上一版表现矩阵 | 无类别回退 |
| 8 | 检查温度与解析参数 | 确认temperature <= 0.2、开启结构化输出 | 低随机性、高可解析度 |
这个清单看起来平淡无奇,但每一条都是我用一次次翻车换回来的。拿这个清单去对照手头那个“分数差的Agent”,你会发现至少有三四条的答案是否定的——而这几条,就是你翻盘的杠杆点。
6. 常见问题速查:那些我踩过的坑
问:我换了一个更贵的模型,分数涨了,但这算解决问题吗?
先看涨分的原因是什么。如果是因为大模型弥补了工具Schema的歧义,那本质上还是在替代码背锅;一旦换回原模型,分数又会掉回去,而且推理成本会压垮利润。我见过一个 AI 助手项目,靠换大模型把分数从58分拉到72分,但单次对话成本从0.03元涨到0.14元,业务算不过账。你在换模型前,先想想Prompt和工具定义是不是真的优化到头了。
问:Agent在个别case上反复失败,但聚类后看不出规律,怎么办?
这种“散点型失败”多半跟评测问题本身的表达歧义有关,不是Agent一个环节的问题。你可以尝试在few-shot示例里显式增加一个与这个case最接近的实例,或者用“改写用户输入”的预处理方式把问题标准化后再喂给Agent。我试过在入口加一个轻量的意图归一化步骤,散点失败率降了不少。
问:多轮对话场景下,Agent把上一轮的信息忘了,怎么处理?
优先检查每一轮结束后,关键实体有没有被结构化提取并注入下一轮的System或上下文。只要跨轮状态是显式传递的,模型失忆概率会大幅降低。“记忆”这块不要指望模型自觉,工程约束比模型自觉可靠一万倍。
问:重试次数设多少合适?
没有固定答案,但我的经验是不要超过3次。超过3次重试,大概率是任务设计有问题而不是模型随机失误。与其让Agent反复给同一堵墙撞头,不如让它早点转兜底流程。这个“3次上限”同时约束token成本,避免了一场对话烧掉几十步调用。
问:temperature已经在0了,为什么工具调用还是会不稳定?
temperature为0不代表完全随机性,因为采样还有top_p、频率惩罚等参数在起作用。另外,如果启用了流式输出,部分平台在不同流式策略下返回的JSON会有差异。最稳妥的方式是启用结构化输出或JSON Mode,让模型在格式约束下生成,而不是指望纯靠temperature压死随机性。
问:加了很多few-shot示例,分数反而降了,这是为什么?
大概率是示例之间互相冲突,或者示例与真实业务间距太大。模型在有限上下文里会从多个示例中“求同存异”,但如果你给的示例在工具调用路径上各不相同,它就会“融合”出一个不伦不类的调用序列。减少示例数量到3个,并且确保这3个示例都在同一条调用路径上,很多莫名其妙的下跌会自己消失。
最后再分享一个我反复用的小技巧
上面讲了那么多方法论,最后说一个我在实际项目里反复用到的小技巧:每次改完Prompt或工具描述后,把改动记录写进一个“调试日志”,并且跑回归集的时候,保留上一轮的模型输出。 不要只记分数,要把Agent说过的话、调用过的工具、参数内容全部存档。很多问题在当时看是“分数波动”,隔一个版本再看,能直接定位到是哪次改动引入的。
这个习惯帮我省了太多排查时间。有一次我发现Agent突然爱在前面加“好的!”,怎么调都去不掉,后来翻日志才发现是一次Prompt示例里不小心带了个语气词。没有日志的话,这种问题可能要被折磨一整天。
另外,不要迷信“提示词工程师”那个神乎其神的职业光环。Agent调优的本质还是工程:结构化、可观测、可回归、有兜底。把这四条做到了,哪怕你用的是一个小参数模型,测评分数也能拉到能看的水平;做不到,你就算烧钱上满血版大模型,测评报告照样教你做人。
把这套方法用起来,分数从“差”到“能看”,一般两到三个迭代周期就够了。
