ARTICLE DETAIL

资讯详情

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

Agent评测体系实战:Harness、Rubric与LLM-Judge全解析

Agent评测体系实战:Harness、Rubric与LLM-Judge全解析 1. Agent 评测体系到底在解决什么问题1.1 从“跑起来”到“跑得对”的鸿沟做 Agent 开发的人大概都有过这种体验demo 阶段一切丝滑工具调用准确、多轮对话连贯、任务完成率看着也不错。可一旦把同一套 Agent 放到真实业务流量里问题就像雨后春笋一样冒出来——昨天还能正确查天气的 Agent今天面对“帮我看看明天适不适合洗车”这种带推理的请求就彻底懵了。更让人头疼的是你根本说不清它到底是退步了还是只是这次运气不好。这就是 Agent 评测体系要解决的核心矛盾。传统的软件测试有明确的输入输出断言单元测试跑一遍绿灯就代表没问题。但 Agent 的输出是自然语言、是工具调用序列、是多步推理链你没法用assert result expected来判定对错。一个 Agent 回答“北京明天晴适合洗车”和“明天北京天气不错可以洗车”语义上等价字符串比对却完全不同。我见过太多团队在 Agent 上线后靠“用户反馈”来发现问题这本质上是一种被动的、滞后的质量监控。等用户投诉来了坏影响已经产生了。评测体系的价值就在于把这种被动变成主动——在 Agent 进入生产环境之前用一套可重复、可量化、可对比的流程把它的能力边界摸清楚。1.2 评测体系的三层结构Harness、Rubric、LLM-Judge一套完整的 Agent 评测体系拆开来看是三个相互咬合的模块。Harness评测执行框架是骨架。它负责把测试用例喂给 Agent、捕获 Agent 的完整执行轨迹包括思考过程、工具调用、中间结果、最终输出、然后交给评判模块。你可以把它理解成一个专门为 Agent 设计的“测试跑道”——没有它你连 Agent 每一步做了什么都不知道更别提评测了。Rubric评分标准是尺子。它定义了“什么叫好”。比如对于“订机票”这个任务Rubric 可能包含是否正确识别了出发地和目的地、是否选择了用户偏好的时间段、是否在价格超出预算时主动提醒、最终是否成功完成预订。每一条都是一个可判定的维度。LLM-Judge大模型裁判是裁判。它用另一个大模型来根据 Rubric 对 Agent 的表现打分。为什么不用规则匹配因为 Agent 的输出太灵活了规则覆盖不全。LLM-Judge 能理解语义等价、能判断推理链是否合理这是传统断言做不到的。这三者的关系可以这样理解Harness 负责“跑”Rubric 负责“量”LLM-Judge 负责“判”。缺了任何一个评测都跑不通。1.3 谁需要这套体系如果你只是自己玩一玩 Agent做个玩具项目那确实不需要这么重的评测。但只要你面临以下任一场景评测体系就是刚需Agent 要上线给真实用户用你需要知道它到底靠不靠谱你在迭代 Agent 的 prompt 或工具集需要判断新版本是不是真的比旧版本好你在多个模型之间做选型需要客观对比它们在具体任务上的表现你的 Agent 涉及多步工具调用你需要定位失败到底发生在哪一步我个人的经验是Agent 开发到一定复杂度后没有评测体系就像蒙着眼睛开车——你感觉在前进但不知道方向对不对也不知道什么时候会撞墙。2. 核心组件拆解Harness、Rubric、LLM-Judge 各自怎么落地2.1 Harness 工程评测执行框架的设计要点Harness 这个词在 Agent 圈子里最近热度很高但很多人对它的理解还停留在“一个跑测试的脚本”。实际上一个合格的 Harness 需要处理的问题远比想象中复杂。第一它要能捕获完整的执行轨迹。Agent 执行一个任务中间可能调用了三次搜索、两次计算器、一次代码执行。如果 Harness 只记录最终输出那评测就只能看到结果对不对看不到过程合不合理。而 Agent 的很多问题恰恰出在过程里——比如它绕了一大圈才找到答案或者调用了不该调用的工具。第二它要能处理非确定性。同一个 Agent 跑同一个任务两次结果可能不同。Harness 需要支持多次运行取统计结果而不是跑一次就下结论。我一般会设置至少 3 次重复运行对于关键任务会跑到 5 次然后看通过率而不是单次结果。第三它要能隔离环境。Agent 在执行过程中可能会修改文件、调用外部 API、产生副作用。Harness 需要为每个测试用例提供干净的沙盒环境避免用例之间相互污染。这一点在涉及代码执行的 Agent 上尤其重要。一个典型的 Harness 执行流程是这样的# 伪代码示意展示 Harness 的核心逻辑 class AgentHarness: def __init__(self, agent, test_cases, rubric, judge): self.agent agent self.test_cases test_cases self.rubric rubric self.judge judge def run_single_case(self, case, repeat3): results [] for i in range(repeat): # 每次运行前重置环境 env self.setup_sandbox() # 捕获完整执行轨迹 trace self.agent.execute( taskcase.input, envenv, capture_traceTrue ) # 用 LLM-Judge 按 Rubric 打分 score self.judge.evaluate( tracetrace, rubricself.rubric, expectedcase.expected ) results.append(score) return self.aggregate(results) def run_all(self): report {} for case in self.test_cases: report[case.id] self.run_single_case(case) return report这段代码的关键点在于capture_traceTrue和setup_sandbox()。前者保证你能看到 Agent 的每一步后者保证用例之间不互相干扰。实操心得Harness 的日志格式一定要统一。我踩过的坑是早期用不同格式记录不同 Agent 的轨迹结果后面想对比两个版本时发现数据对不齐白白浪费了两天做数据清洗。建议从一开始就定义好 trace 的 schema包含时间戳、步骤序号、动作类型、输入、输出、耗时这几个字段。2.2 Rubric 设计把“好”拆成可判定的维度Rubric 是评测体系里最需要人工投入的部分也是最容易被低估的部分。很多人随便写几条“回答准确”“格式正确”就完事了结果 LLM-Judge 打分时模棱两可评测结果毫无区分度。好的 Rubric 应该满足三个条件可判定、有区分度、覆盖关键维度。可判定意味着每一条标准都能明确回答“是”或“否”或者至少能落到一个明确的分数档位上。比如“回答准确”就不可判定但“回答中提到的天气状况与工具返回结果一致”就可判定。有区分度意味着这条标准能区分好的 Agent 和差的 Agent。如果所有 Agent 在某个维度上都拿满分那这个维度就没有存在的意义。覆盖关键维度意味着 Rubric 要覆盖任务完成度、过程合理性、输出质量这几个层面。我通常会把 Rubric 分成三组维度组具体条目示例权重建议任务完成度是否完成了用户请求的核心目标40%过程合理性工具调用是否必要且顺序合理30%输出质量语言是否自然、格式是否规范、有无幻觉30%权重的分配取决于你的业务场景。如果是客服 Agent输出质量的权重可能更高如果是自动化任务 Agent任务完成度的权重应该占大头。Rubric 的每一条最好配上正例和反例。比如“工具调用是否必要”这一条正例是“用户问天气Agent 调用了天气 API”反例是“用户问天气Agent 先调用了计算器再调用天气 API”。有了正反例LLM-Judge 的判断会稳定很多。2.3 LLM-Judge 实战怎么让裁判靠谱用大模型当裁判最大的风险是裁判本身不稳定。同一个回答今天打 8 分明天打 6 分那评测结果就没有意义了。让 LLM-Judge 靠谱有几个关键技巧。第一给裁判明确的评分锚点。不要只说“1-10 分打分”要给出每个分数段的具体描述。比如9-10 分完全满足所有 Rubric 条目无任何可改进之处7-8 分满足核心条目有轻微瑕疵但不影响使用5-6 分部分满足存在明显问题但仍有参考价值3-4 分大部分不满足输出基本不可用1-2 分完全偏离任务目标第二让裁判输出推理过程。不要只让 LLM-Judge 给一个分数要求它先逐条分析 Rubric 的满足情况再给出总分。这样一方面提高了打分的可解释性另一方面也迫使裁判更认真地思考。第三用多个裁判取共识。如果条件允许用两个不同的大模型分别打分然后取平均或取一致结果。这能有效降低单个模型的偏见。我实测下来双裁判的一致性通常在 80% 左右比单裁判的稳定性好很多。第四定期校准裁判。每隔一段时间人工抽一批样本打分和 LLM-Judge 的结果对比。如果发现偏差较大就需要调整 Rubric 的描述或裁判的 prompt。# LLM-Judge 的 prompt 模板示例 JUDGE_PROMPT 你是一个 Agent 评测裁判。请根据以下评分标准对 Agent 的执行轨迹进行打分。 ## 评分标准 {rubric} ## 任务输入 {task_input} ## Agent 执行轨迹 {trace} ## 期望输出 {expected_output} ## 评分要求 1. 逐条分析每个评分标准的满足情况给出你的判断理由 2. 基于逐条分析给出总分1-10 分 3. 输出格式 逐条分析 - 标准1[满足/部分满足/不满足]理由... - 标准2... 总分X 总评... 注意事项LLM-Judge 对长轨迹的处理能力有限。如果 Agent 的执行轨迹超过裁判模型的上下文窗口就需要做摘要或分段评判。我的做法是先用一个轻量模型对轨迹做结构化摘要再把摘要交给裁判。这样既控制了 token 消耗又保留了关键信息。3. 从零搭建一套可用的 Agent 评测流程3.1 测试用例的设计与组织测试用例是评测的基石。用例设计得好不好直接决定了评测结果有没有参考价值。我一般把测试用例分成四个层次基础功能用例覆盖 Agent 的核心能力比如“查询天气”“预订会议室”“发送邮件”。这些用例的输入明确、期望输出清晰主要用来验证 Agent 的基本功能是否正常。边界用例测试 Agent 在极端情况下的表现比如“查询一个不存在的城市天气”“预订一个已经满员的会议室”。这些用例用来验证 Agent 的错误处理能力。推理用例需要 Agent 进行多步推理比如“帮我找一个明天下午三点后有空、且离我办公室步行 10 分钟以内的会议室”。这类用例最能区分 Agent 的智能程度。对抗用例故意给 Agent 制造陷阱比如输入中包含误导信息、或者要求 Agent 做它不应该做的事。这类用例用来验证 Agent 的安全性和鲁棒性。用例的组织建议用 YAML 或 JSON 格式方便版本管理和批量加载# test_cases.yaml - id: weather_001 category: basic input: 北京明天天气怎么样 expected: must_contain: [北京, 明天] tool_calls: [weather_api] rubric_overrides: - 必须调用天气工具获取数据不能凭记忆回答 - id: meeting_003 category: reasoning input: 帮我找一个明天下午三点后有空、离我办公室步行10分钟以内的会议室 expected: must_contain: [会议室, 时间] tool_calls: [calendar_api, map_api] rubric_overrides: - 必须同时考虑时间可用性和距离约束rubric_overrides字段允许你为特定用例追加评分标准这在处理特殊场景时非常有用。3.2 评测执行与结果分析有了 Harness、Rubric 和测试用例就可以跑评测了。但跑完评测只是开始真正的价值在于结果分析。我一般会从三个角度看评测结果通过率视角整体通过率是多少哪些类别的用例通过率最低这能帮你快速定位 Agent 的薄弱环节。趋势视角和上一个版本相比通过率是升了还是降了如果某个维度的分数下降了说明这次改动可能引入了回归。失败模式视角失败的用例有没有共同的模式比如是不是都在多步推理上出错是不是都在某个特定工具上失败找到失败模式才能有针对性地改进。下面是一个评测报告的示例结构用例类别用例数通过率平均分主要失败模式基础功能2095%8.7无边界情况1573%6.2错误处理不完善多步推理1060%5.8中间步骤遗漏对抗测试540%4.1被误导信息带偏这张表一眼就能看出Agent 在基础功能上没问题但推理和对抗能力是短板。接下来的优化方向就很明确了。3.3 持续评测把评测融入开发流程评测体系建好之后最重要的是让它持续运转起来。我见过太多团队花大力气搭了评测结果只跑了一次就放在那里吃灰。持续评测的关键是自动化。每次 Agent 的 prompt、工具集或模型版本有变更就自动触发一轮评测。评测结果和上一次对比如果有明显退步就告警。# CI 中集成评测的示例 #!/bin/bash # 在 Agent 代码变更后自动运行评测 # 1. 启动 Agent 服务 docker-compose up -d agent-service # 2. 运行评测 python run_evaluation.py \ --test-cases ./test_cases/ \ --rubric ./rubric.yaml \ --output ./reports/latest.json # 3. 对比历史结果 python compare_reports.py \ --current ./reports/latest.json \ --baseline ./reports/baseline.json \ --threshold 0.05 # 4. 如果退步超过阈值退出码非零CI 会标记失败这个流程跑通之后每次代码提交都会自动评测团队能第一时间发现回归。我自己的项目里这套流程帮我在一次 prompt 调整中发现了多步推理通过率从 60% 掉到了 45%及时回滚避免了上线事故。实操心得评测用例不要一次性写太多。我一开始贪多写了 200 个用例结果每次评测要跑半小时开发迭代时根本等不及。后来精简到 50 个核心用例评测时间控制在 5 分钟以内大家才愿意频繁跑。用例的质量比数量重要得多。4. 常见问题与排查技巧实录4.1 LLM-Judge 打分不稳定怎么办这是被问得最多的问题。同一个回答裁判模型今天打 8 分明天打 6 分评测结果完全不可信。排查思路分三步走。第一步检查 Rubric 是否足够具体。如果 Rubric 里写的是“回答质量高”那裁判只能凭感觉打分当然不稳定。改成“回答中不包含与工具返回结果矛盾的信息”就具体多了。第二步检查裁判的 prompt 是否给了足够的上下文。裁判需要知道任务是什么、期望是什么、评分标准是什么。如果只给它一个回答让它打分它只能瞎猜。第三步检查温度参数。裁判模型的 temperature 应该设为 0 或接近 0减少随机性。我一般用 0.1既能保持一定的灵活性又不会太随机。如果以上都做了还是不稳定那就上多裁判共识机制。两个裁判分别打分如果分差超过 2 分就引入第三个裁判做仲裁。4.2 Agent 执行轨迹太长导致裁判看不全这个问题在复杂任务上特别常见。Agent 执行了 20 步轨迹有上万 token裁判模型的上下文窗口装不下。我的解决方案是分层摘要。先用一个轻量模型把轨迹压缩成结构化摘要保留关键决策点和工具调用结果去掉冗余的中间文本。然后把摘要交给裁判。摘要的 prompt 可以这样写SUMMARIZE_PROMPT 请将以下 Agent 执行轨迹压缩为结构化摘要保留以下信息 1. 每一步的工具调用名称和关键参数 2. 每一步的关键返回结果如果结果很长只保留与任务相关的部分 3. Agent 的关键决策点比如为什么选择这个工具而不是另一个 4. 最终输出 去掉以下内容 - 重复的思考过程 - 与任务无关的工具返回细节 - 格式化的冗余文本 轨迹 {trace} 请输出摘要 这样处理之后摘要通常能压缩到原轨迹的 20%-30%裁判就能看全了。4.3 评测通过但线上效果差这是最让人沮丧的情况——评测全绿上线后用户投诉不断。根本原因通常是评测用例和真实流量分布不一致。排查方法从线上随机抽取一批真实请求人工标注期望输出然后把这些请求加入评测集。跑一遍评测看看通过率是多少。如果明显低于原有评测集的通过率说明你的评测集偏离了真实场景。我自己的做法是每个月做一次“评测集刷新”从线上流量中采样 20-30 条新用例补充进去同时淘汰一些已经不再有代表性的旧用例。这样评测集始终跟真实场景保持同步。4.4 常见问题速查表问题现象可能原因排查动作解决方案裁判打分波动大Rubric 不具体 / 温度过高检查 Rubric 描述和 temperature细化 Rubrictemperature 设为 0.1轨迹超长裁判看不全任务步骤过多统计轨迹 token 数引入分层摘要评测通过但线上差用例分布偏离真实流量对比评测集和线上请求分布定期从线上采样补充用例评测跑得太慢用例太多 / 重复次数太多统计单次评测耗时精简用例关键用例才做多次重复不同版本无法对比评测集变更 / 评分标准变更检查评测集和 Rubric 版本评测集和 Rubric 都做版本管理Agent 工具调用失败沙盒环境配置问题检查工具依赖是否安装在 Harness 中预装所有工具依赖4.5 几个容易踩的坑坑一用同一个模型既做 Agent 又做裁判。这会导致“自己评自己”的偏见Agent 的输出风格和裁判的偏好高度一致评分虚高。尽量用不同的模型做裁判至少用不同版本的模型。坑二忽略工具调用的评测。很多人只评测最终输出不评测工具调用过程。结果 Agent 可能用错误的方式得到了正确答案这次对了下次就错了。工具调用的必要性、顺序、参数正确性都应该纳入评测。坑三评测集一成不变。Agent 在迭代用户需求在变化评测集如果一直不变很快就会失去参考价值。建议至少每季度更新一次评测集。坑四只看总分不看细分。总分 7.5 分看起来不错但如果任务完成度是 9 分而过程合理性只有 5 分说明 Agent 虽然能完成任务但过程很笨拙。细分维度的分数才能指导优化方向。5. 工具选型与规模化实践5.1 自建还是用现成方案Agent 评测这个领域现成的开源方案还不多而且大多偏向研究用途工程化程度不够。我的建议是核心的 Harness 和 Rubric 自己搭LLM-Judge 可以用现成的 API。自建 Harness 的好处是灵活能适配你自己的 Agent 架构和工具集。现成的评测框架往往假设了特定的 Agent 接口接入成本可能比自己写还高。Rubric 必须自己设计因为只有你最清楚你的业务场景里什么叫“好”。LLM-Judge 可以直接调用大模型 API不需要自己训练裁判模型。现在主流的大模型在语义理解和推理判断上已经足够好了。5.2 规模化评测的工程挑战当评测用例从几十个增长到几百个评测就从“跑个脚本”变成了“跑一个系统”。这时候会遇到几个工程挑战。并发控制同时跑太多用例会打爆 API 限流。需要实现一个带速率限制的并发调度器控制同时执行的用例数量。失败重试网络抖动、API 超时这些临时故障会导致用例假失败。需要实现重试机制但要注意区分“Agent 真的失败了”和“评测基础设施故障”。结果存储评测结果需要持久化存储方便历史对比。我一般用 SQLite 存结构化结果用对象存储存原始轨迹。成本控制LLM-Judge 的 API 调用是有成本的。几百个用例乘以多次重复乘以多个裁判token 消耗很快。需要做成本估算和预算控制。# 带并发控制和重试的评测调度示例 import asyncio from asyncio import Semaphore class EvaluationScheduler: def __init__(self, max_concurrent5, max_retries3): self.semaphore Semaphore(max_concurrent) self.max_retries max_retries async def run_case_with_retry(self, case): async with self.semaphore: for attempt in range(self.max_retries): try: result await self.run_single_case(case) return result except InfrastructureError as e: if attempt self.max_retries - 1: raise await asyncio.sleep(2 ** attempt) # 指数退避 except AgentError as e: # Agent 本身的错误不重试直接记录 return {status: agent_error, error: str(e)}这段代码的关键是区分了InfrastructureError和AgentError。前者是评测系统的问题需要重试后者是 Agent 本身的问题重试没有意义直接记录即可。5.3 评测体系的演进方向一套评测体系建起来之后不是一成不变的。随着 Agent 能力的提升和业务场景的变化评测体系也需要演进。从静态评测到动态评测早期的评测用例是固定的后来可以引入基于模板的用例生成自动产生变体。比如同一个“订机票”任务可以自动生成不同的出发地、目的地、时间组合。从单轮评测到多轮评测很多 Agent 的实际使用场景是多轮对话但评测往往只测单轮。多轮评测需要模拟用户的后续追问这对 Harness 的设计提出了更高要求。从结果评测到过程评测不仅看最终输出对不对还要看 Agent 的推理过程是否合理、工具调用是否高效。这需要更精细的轨迹分析和更复杂的 Rubric。从离线评测到在线评测离线评测跑得再好也不能完全代表线上表现。可以在线上做 A/B 测试用真实用户的行为数据来补充评测结果。我个人在实际操作中的体会是评测体系的价值不在于一开始就建得多完美而在于持续运转和迭代。哪怕一开始只有 10 个用例、3 条 Rubric只要坚持每次变更都跑一遍就能比没有评测的团队少踩很多坑。先跑起来再慢慢完善这是最务实的路径。最后分享一个小技巧把评测结果做成一个简单的看板每次评测后自动更新。团队所有人随时能看到当前 Agent 的健康度这比在群里发评测报告有效得多。可视化带来的透明度会让整个团队对 Agent 的质量有共同的认知基础。
返回列表