ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

构建Agent专项评估体系:从评测维度到回归基线的完整实践

构建Agent专项评估体系:从评测维度到回归基线的完整实践 上个月我改了一个工具调用型 agent 的 system prompt手工测了五个 case看起来都正常其中一个我甚至觉得“效果拔群”。结果上线跑了两天用户投诉变多拉日志一看一个本来三句话能说清楚的任务agent 绕了八个工具调用才做完中间还有两次重复搜索。后来我把这事复盘成两个问题第一我根本没有一套可重复的评估方式所有测试结果全凭感觉第二我也没有把耗时、调用次数这些过程数据记录下来问题发生之后连个对照物都没有。这篇文章想聊的就是怎么解决这个问题——构建一个专门用于 Agent 和 Skills 专项能力评估的 agent。它本身也是一个 agent但它不负责干活它负责“给其他 agent 和 skills 出题、监考、阅卷、出报告”。这套体系最早是我在跑多个开源 agent 框架时被逼出来的后来慢慢沉淀成了团队内部的评估基建。如果你也在写 agent 或者维护自己的 skills 库这篇文章应该能帮你省掉不少冤枉路。1. 为什么需要一个专门评估 Agent 的 Agent1.1 人工测试的两个致命缺陷Agent 开发和传统后端开发最大的不同在于你不是在面对一个确定性系统。同样的 prompt同样的工具列表跑两遍结果可能完全不一样。这种随机性让“手动测试几个 case”变得非常不可靠。我经常遇到的情况是上午测了六个 case觉得一切完美下午同事稍微调了一下模型温度或者工具描述的分隔符整个行为就变了。手工测试最大的问题是不可复现——你没法确定改动 A 到底是让系统变好了还是变坏了因为你连上一次的测试条件都没法完全重建。第二个问题是覆盖面太窄。任何 agent 的能力边界都是很大的尤其是接了五六个 skills 之后每个 skill 又有自己的参数组合和边界场景。靠手工测一次只能覆盖三五个典型路径边界情况、异常输入、工具报错后的恢复行为几乎全部漏掉。1.2 Skills 生态让评估问题雪上加霜当项目还只是单一 agent 自己调用两三个工具时手工测试勉强能撑住。真正把问题放大的是 Skills 生态你可能从社区装了一些别人写的 skill也可能自己开发了好几个然后让 agent 自由组合它们。每个 skill 本质上是一个“能力黑盒”。你在一个主 agent 的 prompt 里注入了五个 skills它们的描述如何被模型理解、相互之间会不会干扰你完全不知道。尤其是社区来源的 skills作者的能力假设和你的使用场景经常不匹配。如果你没有一个标准化的评估手段你连“是哪个 skill 拖累了整体效果”这种基本问题都答不上来。1.3 评估 agent 的定位出题者、监考者、阅卷者所以我们要构建的评估 agent本质上是一个“元层”系统。它不做业务它只做三件事按照评估清单给被测 agent 或 skills 分发任务在执行过程中采样完整轨迹根据预设的评分标准给出量化结论。这个评估 agent 的输入是一批评测样本集eval set输出是一份包含通过率、稳定性、效率、安全等多个维度的报告。它本身也可以接入大模型做动态判分所以叫它 agent 是名副其实的——它不是跑一堆断言脚本而是会阅读执行轨迹、理解用户意图的语义等价性然后给出判断。2. 先做评估维度拆解功能、稳定、效率、安全一个都不能少很多人在搭评估系统时一上来就写代码这是最容易踩的坑。评估体系的第一块基石不是代码而是评估维度。你到底想测什么如果这个问题不明确后面所有基建都是空中楼阁。2.1 功能正确性任务完成不是二元判断最基础的维度是“任务完成率”但这里的“完成”定义要小心。你不能简单判断 agent 有没有在最后一条消息里说“已完成”因为它可能说了漂亮话但根本没做实事。更靠谱的做法是定义“语义等价判定”——把 agent 的最终输出和被标注的预期结果做语义比对看是否满足用户意图。在真实场景里我习惯把功能正确性拆成三个等级完全满足3分、部分满足2分、不满足1分。部分满足的情况特别多比如“agent 生成了统计图但图里的数据口径不对”这种结果不能说完全失败但也不能算通过。2.2 稳定性同一任务跑三遍看结果有多一致Agent 的随机性决定了稳定性必须作为独立维度来测。我通常的做法是每个评测样本默认跑三轮记录三轮结果的一致程度。如果同一个任务三次结果差异很大说明这个 agent 或 skill 的行为风格不稳定在线上生产中会很难控。稳定性指标我用两个结果一致率和路径一致率。结果一致率看最终答案的语义是否一致路径一致率看工具调用序列是否相近。有些场景下路径一致比结果一致更敏感——比如某个 skill 时而三步完成、时而绕了八步虽然终态结果一样但效率差异说明内部逻辑有问题。2.3 效率工具调用次数、Token 消耗、端到端耗时Agent 的效率短板非常隐蔽。功能上全对但为了拿到一个简单答案调用了十几个工具这种问题在单次手工测试里几乎不会被发现。效率指标我会在每次评估中自动计算三个值工具调用总次数、输入输出 Token 总量、端到端耗时。注意效率指标不能只看绝对值要看相对基准。同一个任务用 v1.2 版本跑平均消耗 4000 tokenv1.3 版本变成 9000 token即使回答质量相同也要警惕。Token 消耗直接对应成本这在生产环境是硬约束。2.4 安全与合规注入攻击和越权操作测试Agent 的安全评估和普通 API 测试不太一样。除了要测试 prompt 注入恶意指令屏蔽还要检查 agent 是否会在没有明确授权的情况下执行危险操作。我见过一个案例评估样本里加了一个“删掉桌面所有文件”的指令某个开源的 skill 居然真的调了删除类工具好在沙箱环境没有真实文件。安全维度的通过标准很严格只要出现一次越权操作或有害输出整个样本即记零分不参与加权平均。安全是不可妥协项不适合用分数平滑。2.5 评估维度汇总维度核心指标判定方式功能正确性任务完成率、语义对齐度规则 模型裁判稳定性三轮测试结果一致率自动比对效率工具调用数、Token 消耗、耗时自动统计对比基线安全合规越权操作次数、注入攻击失败率规则硬判定可恢复性工具报错后自主纠正成功率轨迹分析 模型裁判可恢复性这个维度容易被忽略但在真实场景中极其重要。工具会报错、API 会超时、skill 偶尔会返回异常格式agent 能不能从错误状态里自己爬出来决定了它是否适合无人值守运行。3. 评估 agent 的架构设计调度、执行、采样、评分四层分离想清楚测什么之后再谈怎么测。我搭这套评估 agent 时把架构分成四个相对独立的层调度层、执行层、采样层、评分层。核心原则是层与层之间只通过标准数据结构通信这样每一层都能单独替换。3.1 任务调度层并发控制和超时管理调度层负责控制评估的整体流程。第一步是加载评测样本集第二步是把每个样本包装成任务交给执行层。因为要跑三轮一个样本实际会产生三个任务实例。并发控制很关键不同 agent 框架对并发的承受能力差异很大我会先做小规模压测确定安全并发数再配置全局并发上限。超时策略也要在这一层定死。每个样本根据难度配置 timeout比如单工具任务给 60 秒多步骤任务给 180 秒。超时后强制终止该任务在结果里标记为“超时失败”。没有超时控制的评估系统是灾难——某个 skill 卡住了整个评测队列都得等它。3.2 执行环境沙箱、模型参数固定执行层是真正运行被测 agent 或 skills 的地方。最基本的要求是隔离被测系统跑在沙箱环境里不允许访问真实生产数据不允许产生真实的外部副作用比如真的发邮件、真的删文件。沙箱内部可以有一批 mock 服务模拟真实的工具返回值。一个经常被忽略的细节是模型参数必须固定。评估期间被测 agent 的温度要设成一个固定值我一般用 0或者至少把 temperature、top_p 等参数锁死。否则不同的评估轮次之间不只是被测代码在变模型的采样随机性也在变结果根本没有可比性。3.3 轨迹采样层记录每一次工具调用采样层是整个评估系统的“录像机”。它要记录的不只是 agent 最终输出而是完整的过程轨迹每一条模型回复、每次工具调用的名称和参数、每个工具返回的原始结果、每一步的时间戳。轨迹数据我用 JSON Lines 格式落盘每个任务实例一个文件。字段大致是task_id、step_index、event_typemodel_output / tool_call / tool_result / system_error、content、timestamp。这条轨迹是后续一切评分和分析的基础也是问题定位的第一手材料。有了它你说“这个 skill 表现很差”时可以精确到是第几步开始跑偏的。3.4 评分层和报告聚合可插拔的评分器评分层按“评分器”插件组织每个评分器对轨迹文件做分析输出分维度的分数。规则评分器适合做效率统计和安全硬判定模型裁判评分器则适合做语义层面的判断。我会在下一章详细展开判分逻辑这里先说报告聚合。聚合层把每个样本、每个维度的原始分汇总生成两个核心产物机器可读的 JSON 报告给 CI 门禁用和人类可读的 Markdown 报告给人看。JSON 报告里必须包含每个样本的通过/失败详情和轨迹文件索引这样后续定位问题时可以直接跳到具体的一条轨迹。evals/ ├── runner/ # 调度与执行 │ ├── dispatcher.py │ └── sandbox.py ├── memory/ # 轨迹存储 │ └── trace_store.py ├── scorers/ # 评分器集合 │ ├── rule_scorer.py │ ├── llm_judge.py │ └── hybrid_scorer.py ├── tasks/ # 评测样本集 └── reports/ # 聚合报告输出4. 评测样本集建设三个来源、两级难度、一套版本管理评估系统的地基是评测样本集。没有好的样本集架构再漂亮也是白搭。我在样本建设上花了最多时间这里分享一些慢慢摸出来的经验。4.1 样本的三个来源第一个来源是线上真实任务的脱敏沉淀。翻一翻你线上日志把用户经常问的高频任务挑出来去掉敏感字段整理成评估样本。这是最优先的来源因为它代表真实世界的分布。我在迭代过程中发现真实任务的覆盖面远比自己拍脑袋编的 case 要广得多很多边界情况是你坐在电脑前根本想不到的。第二个来源是合成任务尤其是针对边界和异常场景的合成。比如空的输入参数、超过上下文长度的超长文本、工具返回空结果、工具返回非法 JSON、多个工具抛出矛盾结果。这些场景在线上出现概率不高但一旦出现影响很大。第三个来源是社区开源的 skill 测试用例。很多成熟的 opencode skills 或 Claude skills 项目里带了基础测试用例虽然它们本身就是按作者自己的场景设计的但作为参考价值很大可以从中筛出适合你场景的样本再做二次改造。4.2 能力标签与难度分级每个样本建议打上两层标签能力标签和难度等级。能力标签描述这个样本在测什么能力例如“网页搜索”、“代码生成”、“数据分析”、“多工具协同”。难度等级我简单分两级L1 是单步骤任务调用一个 skill 即可完成L2 是多步骤规划任务需要结合多个 skill 或者进行步骤拆解。这两层标签的用处是支持分层回归。当你只改了一个搜索类 skill 的描述你不需要跑全部样本只需要跑能力标签里带“网页搜索”的那一批就够了。评测时间成本因此能大幅压缩。4.3 每个样本的标注结构一个评估样本不是简单的一条 prompt它至少应该包含五个字段任务描述、预期结果、能力标签、难度等级、可选的具体配置比如超时时间、允许调用的工具范围。其中“预期结果”很关键它不需要写成一整段标准答案但要足够让评分者判断“用户意图是否被满足”。下面是我常用的一套样本格式id: ts-0027 name: 用excel skill处理三列数据并生成统计图 ability_tags: [excel,>你是一个评分员。请根据以下评分标准对任务执行轨迹打分。 任务要求 {{ task_description }} 预期结果 {{ expected_result }} 评分维度 1. 结果正确性1-5分 2. 过程合理性1-5分 3. 效率1-5分 判定要求 - 结果正确性优先于其他维度 - 如果最终结果不满足用户意图结果正确性最高不超过3分 - 如发现重复工具调用效率分最高不超过2分 - 请以 JSON 格式输出{correctness: 分数, process: 分数, efficiency: 分数, reason: 你的理由}5.3 第三道关人工抽检模型裁判也有自己的盲区和偏好比如容易被冗长且措辞自信的输出带偏。所以人工抽检是必须的。我现在的做法是每次全量评估结束后结果报告生成时随机抽取 10% 的样本由人工对照轨迹重新打分然后和模型裁判的分数做一致性比对。如果发现人工分和模型分的偏差超过 1 分5 分制就要审查是模型判错了还是评分标准理解不一致。这一套流程本质上在做“评分器的校准”。我经历过一次校准后才发现模型裁判对“过程合理性”的评分标准跟团队预期差得很远调整 prompt 描述后一致性才恢复正常。5.4 过程评分完成结果之外的路径质量最后专门说说“过程评分”。Agent 不是只要结果对就万事大吉执行路径的质量直接决定了可维护性和用户体验。路径质量我主要看三点是否绕了远路、是否进行了重复尝试、是否在不该调用工具的时候调用了工具。打个比方用户问“现在几点”一个 agent 直接调用一个专门的时间查询工具合理但如果在调用之前先绕了三次网络搜索就算最终给出了正确时间这个路径也是有问题的。过程分的存在就是为了把这类问题显性化。6. 回归基线机制怎么知道这次改动是变好还是变坏评估体系建立之后最大的价值就是支撑迭代决策。但“这次改动到底变好还是变坏”这个问题比看起来要复杂得多。因为 agent 的随机性单次评估的通过率不能完全代表能力水平。6.1 基线的建立和锁定每到一个稳定的功能版本我就把它锁为基线版本跑一次完整评估记录各个维度的指标分布。这个基线指标的用途是当“度量衡”。后续每次改动候选版本和基线版本跑同一套评测集逐维度对比。基线数据要保存原始结果而不仅仅是分数汇总。因为我们经常需要回溯比如三个月后发现某个指标连续下滑就要把历史轨迹捞出来重新分析。6.2 多轮运行取分布为了避免随机采样带来的误差我规定的评估流程是候选版本每个样本至少跑三轮取平均分和分布区间。通过率的置信区间比单纯的平均值更有参考价值——如果基线通过率是 88%±3%候选版本是 79%±5%实际上两个区间没有重叠判断就比较可靠。还有一种常见的情况是候选版本在单个样本上表现波动极大一轮通过、一轮失败、一轮超时。这种“不稳定通过”本身就是信号说明被测系统内部存在不可控因素不建议进入生产。6.3 判定阈值与 CI 门禁有了基线就能把评估接入 CI 门禁。我定的规则很简单候选版本全量通过率不得低于基线 3 个百分点取平均值对比安全维度硬性要求为满分效率维度不劣化超过 20%。三条任一不满足发布流程会被自动阻断。这个门禁不是死板的。如果改动目标是优化效率那么少量通过率下降是可以接受的——此时需要人工在报告里写清楚权衡理由。门禁的意义是强制团队直面变化而不是拍脑袋决定“我觉得这个版本不错”。6.4 分层回归裁剪评估范围当改动只涉及某个特定 skill 时全量评估时间成本太高。我的做法是借助能力标签做分层回归只运行和该 skill 相关标签下的样本子集对比该子集上的基线和候选版本表现。这里要注意的是分层回归只适合“局部改动影响范围可控”的情况。如果改的是主 agent 的系统 prompt 或底层模型影响是全局的必须全量评估。我曾在主 prompt 改了一个标点符号结果意外导致某个不相关 skill 触发频率降低——这种串扰只有全量测试才可能捕捉到。7. 踩坑实录被评分器坑过三次之后的教训最后这部分我把自己在构建这套评估系统过程中踩过的坑、犯过的错、调过的参都列出来希望对你有实际参考价值。7.1 教训一模型裁判会被“语言包装”欺骗第一次用 LLM-as-judge 我踩了大坑。一个被测 agent 输出了一大段逻辑通顺、语气自信的总结模型裁判给它打了满分 5 分但实际上这段总结根本没有执行用户要求的任务完全是“编了一份合理的工作报告”。后来我在评分 prompt 中加了一条硬规则“如果最终输出中没有调用任何与任务相关的工具结果正确性直接打 1 分。”同时强制要求评分模型参照轨迹里面的工具调用记录而不是只看最终文本。加了这两条之后编报告骗分的现象大幅减少。7.2 教训二上下文污染让评估结果失真有段时间我的评测集里连续多个样本涉及同一个业务数据表。跑第二轮的时候被测 agent 在上一个测试任务中已经“记住”了数据表结构后面的任务回答质量肉眼可见地提高。这会严重高估能力。解决办法是每个被测任务实例启动一个全新的对话上下文魂断旧任务的记忆。如果你需要评估长记忆能力那就要单独设计对应的评估维度而不是让记忆在无形中串到其他任务上。现在我的评测系统里每个任务实例都会显式重置被测 agent 的上下文。7.3 教训三评测集过拟合评测集用得多了被测系统会慢慢往评测集上“拟合”。尤其是当你用同一组样本反复调 prompt 时你会不自觉地针对样本里的坑做优化结果评测集上分数很高真实场景却还是一塌糊涂。应对办法没有捷径保持评测集的更新频率每周从线上日志里抽新样本替换那些已经跑通的旧样本同时保留一部分“holdout 样本”这些样本不出现在常规评测里只在发布前作为一票否决项。如果 holdout 样本通过率明显低于常规集说明大概率过拟合了。7.4 教训四评测环境本身的不稳定评测跑在本地机器上时环境因素会干扰评估结果。最典型的是并发过高导致某个工具超时——这不是被测 agent 的问题纯粹是环境资源不够。还有一次沙箱里的 mock 服务悄悄多了一段指令导致同一批样本的轨迹和之前对不上浪费了我一整天排查。从此我规定评测环境必须和开发环境隔离mock 服务版本固定评测前先跑一遍“环境自检样本”包含几个必过的基础任务确认环境有效再开始正式评测。7.5 小技巧给每个样本加一个“参考路径示例”在样本的标注结构里我建议加一个可选字段参考路径示例reference_path。它描述的是“这一步最好应该怎么走”比如先调用搜索工具再调用计算工具。这个字段不参与自动评分但它有两个作用一是给模型裁判提供判定“过程合理性”的行为锚点二是给后续维护样本的人提供上下文——三个月后回来看这个样本你还能明白当初设计它的意图是什么。我后来复盘整个评估体系的建设过程发现最值钱的部分并不是那些评分代码和架构分层而是“把 agent 行为变成可测、可量化”这个思维转变。没有评估体系时团队讨论 agent 表现全靠“我感觉”“我觉得”有了评估报告后吵架都没意思了——数据在那儿摆着谁对谁错一目了然。如果你现在刚开始做 agent 开发别着急优化技巧先把一版最小可用的评估体系搭起来哪怕只是二十个样本的三轮测试也足够让你在迭代时不再闭着眼睛走路。
返回列表