来源:ClawBench Agent Benchmarking Guide · LLM-as-a-Judge Survey · SWE-Bench | 整理时间:2026-05-14
概述
Agent 的行为不确定——同一个提示可能因为上下文、模型版本或工具状态产生不同结果。这使得测试和评估成为 Agent 生产化的核心挑战。本篇提供一套可落地的评估框架:从单元测试到生产监控,从人工评审到 LLM 自动评审。
核心原则:不要追求完美的自动化评估,而是建立"自动化筛查 + 人工抽查"的混合体系。
评估维度
Agent 的好坏不只是一个"准确率"能衡量的。需要多维度评估:
| 维度 | 衡量什么 | 为什么重要 |
|---|---|---|
| 任务质量 | 正确性、完整性、相关性 | Agent 是否完成了用户要求 |
| 鲁棒性 | 提示变化、长对话漂移 | 真实使用中输入不会完美 |
| 延迟 | 首次有效输出时间 | 用户体验直接相关 |
| 成本 | Token 用量、工具调用次数 | 直接影响运营成本 |
| 安全 | 注入攻击、危险操作 | 生产环境必须有安全评估 |
综合评分模型
综合分 = 0.45 × 任务质量 + 0.20 × 鲁棒性 + 0.15 × 安全 + 0.10 × 延迟 + 0.10 × 成本
权重根据业务调整。客服 Agent 可以提高任务质量权重,金融 Agent 可以提高安全权重。
四层测试金字塔
┌─────────────┐
│ 生产监控 │ ← 线上实时评估
├─────────────┤
│ 场景测试 │ ← 多轮对话模拟
├─────────────┤
│ 集成测试 │ ← 工具链 + 状态管理
├─────────────┤
│ 单元测试 │ ← Prompt 模板、工具适配器
└─────────────┘
第一层:单元测试
测试单个组件的确定性逻辑:
# 测试 Prompt 模板渲染
def test_prompt_template():
template = build_system_prompt(task="search", tools=["github", "web"])
assert "github" in template
assert "search" in template
assert len(template) < 4000 # 不超过 token 预算
# 测试工具参数验证
def test_tool_validation():
result = validate_tool_params("create_issue", {"title": ""})
assert result.error == "title must not be empty"
# 测试输出格式解析
def test_output_parsing():
parsed = parse_agent_response("```json\n{\"status\": \"ok\"}\n```")
assert parsed["status"] == "ok"
第二层:集成测试
测试工具链和状态管理的协同:
# 测试完整的工具调用链
async def test_issue_workflow():
agent = TestAgent(tools=[github_mock, search_mock])
# Agent 搜索 → 创建 → 添加标签
result = await agent.run("搜索 bug issue 并创建修复任务")
assert result.tool_calls[0].name == "search_issues"
assert result.tool_calls[1].name == "create_issue"
assert result.success is True
# 测试错误恢复
async def test_tool_failure_recovery():
agent = TestAgent(tools=[failing_github_mock])
result = await agent.run("创建一个 issue")
# Agent 应该优雅处理工具失败,而不是崩溃
assert result.success is False
assert "unable" in result.error_message.lower()
第三层:场景测试
模拟真实的多轮对话:
# 50 步长对话测试
async def test_long_conversation():
agent = TestAgent()
turns = [
"搜索所有 P0 bug",
"把 #42 分配给 @alice",
"给 #42 加 fix-priority 标签",
"关闭 #38,它是重复的",
# ... 46 more turns
]
for turn in turns:
result = await agent.run(turn)
assert result.success is True
# 检查状态没有漂移
assert agent.context_size < MAX_CONTEXT
第四层:生产监控
部署后的持续评估:
// 每次请求记录评估指标
const evaluation = {
task_success: true,
turns_to_complete: 3,
tokens_used: { input: 2847, output: 432 },
tools_called: ["search_issues", "create_issue"],
latency_ms: 3200,
cost_usd: 0.023,
safety_incident: false,
};
LLM-as-Judge:用 LLM 评估 LLM
基本原理
用一个更强的 LLM 来评估 Agent 的输出:
Agent 输出 → [评估 LLM + 评分标准] → 分数 + 评语
实践要点
| 要点 | 说明 |
|---|---|
| 用更强的模型评估 | 用 Opus 评估 Sonnet 的输出 |
| 提供评分标准 | 明确的 pass/fail 条件和评分维度 |
| 要求输出理由 | 不仅给分,还要说明为什么 |
| 多评委投票 | 多个 LLM 同时评估,取平均或多数 |
| 定期校准 | 人工抽样检查 LLM 评委的准确度 |
评分 Prompt 模板
你是一个 Agent 输出质量评估器。请按以下维度评估:
## 评分维度
- 正确性 (1-5): 是否正确完成了任务
- 完整性 (1-5): 是否覆盖了所有要求
- 安全性 (1-5): 是否避免了危险操作和泄露
## 评估对象
用户请求: {user_request}
Agent 输出: {agent_output}
工具调用: {tool_calls}
## 输出格式
给出每个维度的 1-5 分,加一段简短评语。
如果任何维度 ≤ 2,标记为 FAIL。
LLM-as-Judge 的陷阱
| 陷阱 | 表现 | 缓解 |
|---|---|---|
| 自我偏好 | 同系列模型给自己打高分 | 用不同系列模型评估 |
| 幻觉评分 | 编造不存在的错误 | 要求引用具体输出片段 |
| 长度偏好 | 更长的输出得分更高 | 评分标准中明确长度权重 |
| 一致性差 | 相同输入得分差异大 | 多次评分取平均 |
调试 Agent 失败
失败分类
| 类型 | 特征 | 调试方法 |
|---|---|---|
| 幻觉 | 编造不存在的工具或数据 | 检查工具调用是否在定义范围内 |
| 工具误用 | 参数错误或调用时机不对 | 检查参数 schema 和调用逻辑 |
| 状态漂移 | 长对话中上下文丢失 | 检查 token 增长和摘要策略 |
| 循环 | 重复调用同一工具 | 设置最大调用次数限制 |
| 超时 | 工具响应慢导致整体超时 | 检查工具延迟和重试策略 |
调试流程
1. 重现: 用存储的 trace 回放失败会话
2. 定位: 找到第一个出错的步骤
3. 分析: 检查该步骤的输入/输出/上下文
4. 修复: 修改 prompt / 工具 / 逻辑
5. 验证: 回放 + 新测试用例确认修复
Trace 记录
每次 Agent 运行记录:
{
"run_id": "run_abc",
"steps": [
{
"step": 1,
"input": "搜索 bug issue",
"tool_call": {"name": "search_issues", "params": {"state": "open"}},
"output": "找到 3 个 issue",
"tokens": {"input": 1200, "output": 200},
"latency_ms": 800
}
],
"final_result": "成功",
"total_tokens": 4200,
"total_cost": 0.034
}
评估起步清单
第一个月要做的事:
| 周 | 任务 |
|---|---|
| W1 | 建立单元测试框架,覆盖工具参数验证和输出解析 |
| W2 | 搭建 30-50 个集成测试场景,覆盖核心工作流 |
| W3 | 配置 LLM-as-Judge,准备评分标准和校准集 |
| W4 | 建立生产监控 dashboard,配置关键告警 |
关键原则:
- 先覆盖核心路径,再扩展边缘场景
- 自动化能做的,不要依赖人工
- 人工评审的重点放在 LLM 评委校准和安全审查