发布时间:2026-07-12
标签:AI Agent|LLM|Benchmark|质量评测|工程实践
系列导航
上一篇:AI Agent 工程实践(17):Agent 为什么需要可观测性(Observability)
下一篇: AI Agent 工程实践(19):从 Demo 到生产环境——AI Agent 的工程 Checklist
本文是 [AI Agent 工程实践] 系列的第 18 篇(第二季 · 工程实现)。
上周我改了一行 Prompt——把"请详细回答"改成了"请简洁回答"。
感觉上,Agent 回答变快了。"优化成功",我在 commit message 里写道。
三天后我发现,这行改动让代码审查任务的漏检率从 12% 涨到了 28%——Agent 变"简洁"了,但也跳过了关键检查项。"感觉好了"和"真的好了",差了一个 Benchmark。
我说的是 Benchmark Agent,不是 Benchmark 模型。前者回答"改完之后 Agent 变好了吗",后者回答"哪个模型分高"。你改了一行 Prompt,Agent 变好了还是变差了——没有 Benchmark,你永远不知道。
本文你将学到
✓ Benchmark Agent 和 Benchmark 模型的本质区别——前者是持续交付,后者是选型
✓ Agent Benchmark 的核心链路:Task → Expected → Result → Score
✓ 四个关键指标:Success Rate / Cost / Time / Tool Calls
✓ 如何把 Benchmark 做成 CI/CD——每次改动自动跑、自动对比
适合阅读
✓ 经常调 Prompt / Rule / Tool、但靠"感觉"判断效果的人
✓ 想让 Agent 的质量像代码一样可回归测试的人
✓ 不知道"Agent 改完是变好还是变坏"的人
问题背景
99% 的 Benchmark 文章在讲同一件事:哪个模型更好。MMLU 几分、HumanEval 几分、这个榜那个榜。
但 Agent 开发者真正需要的不是"选模型时的决策依据"——模型选完之后,问题才刚开始。你每天在做的操作是:
- 改了
core/00-must.md的一条规则 - 加了一个新的 heavy 文件
- 调整了 Router 的 priority 配置
- 换了一个 Tool 的实现
每次改动后,Agent 是变好了还是变坏了?这个问题,MMLU 回答不了,HumanEval 也回答不了。因为它们在测"裸模型",不是在测"你的 Agent 这个具体系统"。
Benchmark Agent 不是做一次,是每次改动后都做——这才是真正的 CI/CD for Agent。它回答的不是"GPT-5 比 GPT-4 好多少",而是"你今天的 commit 让 Agent 的质量涨了还是跌了"。
错误尝试
第一次:靠"感觉"判断质量
改完 Prompt,自己跑几个 case,觉得"好像不错"就上线。
结果:很多退化是统计意义上才可见的——成功率从 92% 降到 88%,跑 5 个 case 根本看不出来,跑 50 个才能发现。感觉是 Benchmark 的敌人——感觉好的时候,往往指标在变差。
第二次:只测最终输出对错
搭了一套自动评测:给 Agent 一个任务,比对输出是否和预期一致。对就是对,错就是错。
结果:Agent 的输出"对了",但多了 3 次不必要的 Tool 调用,延迟从 5 秒变成了 18 秒,token 消耗翻了一倍。用户不会告诉你"答案对了但太慢了"——他们直接不用了。只看 Success Rate 的 Benchmark,和只看血压的心脏检查一样——漏了一半的指标。
两次尝试指向同一个教训:Benchmark 需要多维度 + 回归对比 + 统计显著。不是"跑 5 个 case 看看",而是"每次改动后对同一组标准任务跑分、和历史版本对比、多维指标综合判断"。
关键观察
我把"Agent 上线后退化的 case"做了根因追溯:
| 退化类型 | 改动操作 | 单看 Success Rate 能发现吗 | 占比 |
|---|---|---|---|
| 成功率下降 | 改了一条 Rule | ✅ 能 | 30% |
| 延迟暴涨 | 加了一个 Tool 调用 | ❌ 不能(Success 反升) | 25% |
| 成本翻倍 | 改了 Router 配置 | ❌ 不能 | 25% |
| Tool 调用冗余 | 改了 Planner | ❌ 不能 | 20% |
pie title Agent 退化的可检测性(只看 Success Rate) "Success Rate 能发现" : 30 "延迟暴涨(Success Rate 看不出)" : 25 "成本翻倍(Success Rate 看不出)" : 25 "Tool 冗余(Success Rate 看不出)" : 20你改了一行 Prompt,Agent 变好了还是变差了——没有 Benchmark,你永远不知道。
70% 的质量退化,Success Rate 看不出来。你需要四维指标同时跑——少一维就有一个盲区。
最终方案:Agent Benchmark 四维体系
核心链路:Task → Expected → Result → Score
Benchmark 的本质就是"标准任务 + 预期输出 + 多维评分 + 回归对比"。少任何一环,就是盲测。
四个指标的全部含义
| 指标 | 测什么 | 为什么不能只看它 | 怎么算 |
|---|---|---|---|
| Success Rate | 输出是否正确 | 覆盖不了效率和成本退化 | 正确数 / 总任务数 |
| Cost | Token 消耗 | 单独看没意义——便宜的废品还是废品 | input_tokens × 单价 + output_tokens × 单价 |
| Time | 端到端延迟 | 快没用的答案也是没用 | 从 Task 进入到 Result 输出的总耗时 |
| Tool Calls | 调用效率 | "答案对了但调了 10 次 Tool"是浪费 | 任务完成用的 Tool 调用次数 |
四维不是四个独立的分数,是综合评判。我的产出公式是:
综合分 = Success Rate × 0.5 + (1 - Cost/预算) × 0.2 + (1 - Time/阈值) × 0.2 + (1 - ToolCalls/上限) × 0.1Success Rate 占 50% 权重(答案对不对最重要),但 Cost / Time / Tool Calls 各占其余 50%——一个慢到不可接受的 Agent,和答错的 Agent 一样不能用。
Benchmark 作为 CI/CD
真正的价值不在"测一次",在"每次改动都测、每次和历史对比":
def benchmark_regression(agent_v2, test_suite, baseline): """每次 commit 后自动跑,和历史版本对比""" v2_scores = run_benchmark(agent_v2, test_suite) report = { "success_rate": (v2_scores.sr, baseline.sr, v2_scores.sr - baseline.sr), "cost": (v2_scores.cost, baseline.cost, v2_scores.cost - baseline.cost), "time": (v2_scores.time, baseline.time, v2_scores.time - baseline.time), "tool_calls": (v2_scores.tc, baseline.tc, v2_scores.tc - baseline.tc), } # 如果任一指标退化超过阈值,CI 报红 degraded = any(delta < -THRESHOLD for _, _, delta in report.values()) return "FAIL" if degraded else "PASS"Agent 的 CI/CD 不是"代码能跑就行",是"质量没跌就行"。
架构图 / 流程图
Benchmark 驱动的 Agent 迭代闭环
关键:不是"上线前手动测一下"——是每次 commit 自动跑、自动对比、退化自动阻止。这和第 04 篇 Review 闭环、第 15 篇 RAG Evaluate 闭环是同一种思想:反馈系统必须自动化,靠人做不了。
代码或配置示例
标准 Benchmark 任务集定义
# benchmark/suite.yaml tasks: - id: code_review_01 task: "审查这段 Python 代码的安全性" expected: must_contain: ["SQL 注入风险", "建议使用参数化查询"] must_not_contain: ["看起来不错", "没有明显问题"] - id: db_query_01 task: "查询 user_id=42 的订单状态" expected: must_return: "shipped" max_tool_calls: 2 - id: report_gen_01 task: "根据过去 10 条订单生成周报" expected: must_contain: ["总订单数", "完成率"] max_time_ms: 8000Benchmark 执行引擎
def run_benchmark(agent, suite: list) -> BenchmarkScore: results = [] for test in suite: start = now() result = agent.run(test.task) # Trace 自动记录(17 篇) elapsed = (now() - start).ms # 四维评分 sr = 1.0 if evaluate(result, test.expected) else 0.0 cost = result.total_tokens * TOKEN_PRICE tc = result.tool_calls_count results.append({"sr": sr, "cost": cost, "time": elapsed, "tc": tc}) # 汇总:所有任务的各维度取平均值 return BenchmarkScore( sr=np.mean([r["sr"] for r in results]), cost=np.mean([r["cost"] for r in results]), time=np.mean([r["time"] for r in results]), tc=np.mean([r["tc"] for r in results]), )和 17 篇的 Trace 无缝衔接:每跑一次 Benchmark 都是一次完整的 Trace 记录。Benchmark 不只产出一个分数,还产出了每次运行的完整调用链——分数跌了,Trace 告诉你哪个 Span 出了变化。
设计权衡
| 候选方案 | 优点 | 缺点 | 为什么不选 |
|---|---|---|---|
| 靠感觉评测 | 零成本 | 完全不可靠 | 感觉骗人 |
| 只看 Success Rate | 简单直观 | 漏 70% 的退化 | 效率/成本退化看不见 |
| 人工评测(每次手测) | 最准 | 不可持续 | 规模一大人就崩 |
| 自动 Benchmark + CI 回归 | 持续可对比、多维覆盖 | 需维护标准任务集 | 选择理由:唯一把质量变成可量化、可自动化的工程实践的方案 |
Benchmark 的任务集需要持续维护。标准任务集不是"写完一次永远不变"——新功能上线要加新 case,过时的 case 要淘汰。这本身也是一个治理问题,和第 15 篇 RAG 知识治理同源:测试集本身也有生命周期。
总结
✅ Benchmark Agent ≠ Benchmark 模型——前者是持续交付的 CI/CD,后者是选型依据。
✅ 核心链路:Task → Expected → Result → Score → 和历史 baseline 回归对比。
✅ 四维指标缺一不可——Success Rate / Cost / Time / Tool Calls。只看 SR 会漏掉 70% 的退化。
✅ Benchmark 必须做成 CI/CD——每次 commit 自动跑、自动对比、退化自动阻止合并。
✅ 测试集本身也需要治理——新 case 持续加、旧 case 淘汰更新。
参考资料
- 第 17 篇:Agent Observability→ Trace 是 Benchmark 的数据源,每次 Run 生成完整 Trace
- 第 15 篇:RAG 知识治理→ 测试集的治理与知识治理同构
- 第 04 篇:Review 闭环→ Benchmark 是 Review 的量化工具
- RAGAS / LangSmith Evaluation→ Agent 自动评测的工程参考实现
- ML CI/CD (MLOps)→ 模型回归测试的最佳实践,Agent Benchmark CI 的思想来源
系列导航
上一篇:AI Agent 工程实践(17):Agent 为什么需要可观测性(Observability)
下一篇: AI Agent 工程实践(19):从 Demo 到生产环境——AI Agent 的工程 Checklist
本文是 [AI Agent 工程实践] 系列的第 18 篇(第二季 · 工程实现)。