没有评估,提示词调优就是玄学;有了评估,你才知道一次修改是进步、退步,还是只是换了个错误。
四个评估层级
确定性测试
1. 单元评估
不需要模型的部分用普通测试:
- 工具参数校验;
- 文档解析正确性;
- 输出 Schema;
- 权限过滤;
- 幂等与重试。
这些应该 100% 通过,且跑得很快。
2. 轨迹评估
多步任务里,最终答案对可能是蒙的。轨迹评估看:
- 是否选了正确的工具;
- 参数是否正确;
- 步数是否合理(有没有绕路);
- 是否调用了不该调用的工具;
- 失败后是否恢复;
- 是否越权。
一个简单的轨迹评分卡:
工具选择正确 0/1
参数完整正确 0/1
无多余步骤 0/1
无越权动作 0/1
错误可恢复 0/13. 端到端评估
给一个任务,看最终产物是否满足标准。评分方式:
- 精确匹配:分类、抽取、计算;
- 包含关键事实:报告、回答;
- 规则校验:格式、引用、金额;
- 评分量表:写作质量、完整性;
- 成对比较:A/B 哪个更好。
4. 线上评估
线上没有标准答案,看行为指标:
- 任务完成率(用户是否接受结果);
- 人工接管率;
- 重试/重新生成率;
- 投诉率;
- 平均步数、P95 延迟、单任务成本;
- 工具错误率;
- 安全拦截率。
构建黄金集
一个可用的起步规模是 50–200 条,覆盖:
| 类型 | 占比 | 例子 |
|---|---|---|
| 常见顺利路径 | 40% | 标准退款、常规查询 |
| 边界情况 | 20% | 金额刚好等于上限、日期最后一天 |
| 信息不足 | 15% | 缺订单号、文档没有答案 |
| 对抗/注入 | 10% | 网页里的恶意指令、越权请求 |
| 历史失败 | 15% | 线上真实出过的问题 |
每条样本至少包含:
{
"id": "refund-014",
"input": "订单 A1024 签收 9 天了,还能退吗?",
"context": { "user_id": "u_1", "now": "2026-10-29" },
"expected": {
"answer_contains": ["超过 7 天", "无法自动退款"],
"must_call": ["search_policy"],
"must_not_call": ["create_refund"],
"citations": ["refund_policy#p2"]
},
"tags": ["refund", "boundary", "policy"]
}不要只存「标准答案文本」。多步任务要存必须调用的工具、禁止的动作、关键事实、引用来源。
数据来源:
- 真实用户请求(脱敏后);
- 客服/运营整理的高频问题;
- 线上失败案例;
- 人工构造的边界与对抗样本。
模型生成的样本往往过于顺滑,缺少真实世界的噪声。黄金集必须有人工确认的部分。
指标怎么选
| 任务 | 主指标 | 辅助指标 |
|---|---|---|
| 分类 | 准确率、混淆矩阵 | 置信度校准 |
| 抽取 | 字段级 F1 | 格式通过率 |
| 工具调用 | 工具选择准确率、参数正确率 | 平均步数 |
| 问答 | 事实正确率、引用准确率 | 拒答率 |
| 报告 | 评分量表、事实覆盖 | 长度、可读性 |
| 代码 | 测试通过率 | 补丁大小、回归率 |
| 端到端 | 任务成功率 | P95 延迟、成本 |
不要用一个模糊的「总分」掩盖具体问题。分类错和引用错需要完全不同的修复。
LLM-as-a-Judge:能用,但要校准
适用场景:主观质量、开放式回答、成对比较。
最佳实践:
- 明确评分标准:每个分数对应什么行为;
- 成对比较:A/B 哪个更好,比绝对打分稳定;
- 随机顺序:消除位置偏见;
- 控制长度:评委容易偏爱更长的回答;
- 多次采样:取多数或平均;
- 人工校准:抽 50 条,对比人工与评委的一致性;
- 记录理由:让评委先给证据再给分。
一个可用的评分提示:
你是严格的评审。根据以下标准比较 A 与 B:
- 事实准确性(0-3):每个事实是否有来源支持
- 完整性(0-2):是否覆盖问题的所有部分
- 简洁性(0-1):是否有重复或无关内容
先列出各自的证据与问题,再给出胜者。不要因为更长就给更高分。评委与被评模型最好不同家族,减少共同偏见。
统计:别被小样本骗了
50 条样本、80% 通过率,95% 置信区间大约是 66%–90%。也就是说,两个版本 78% vs 82% 的差异可能只是噪声。
实践建议:
- 关键决策至少 100–200 条;
- 用 Wilson 区间或 bootstrap 估算置信区间;
- 同一版本跑 2–3 次,观察方差;
- 比较「失败类型分布」,而不只是总分;
- 不要针对测试集反复调参(过拟合)。
一个评估脚本
import json
from statistics import mean
def run_eval(agent, dataset):
results = []
for case in dataset:
trace = agent.run(case["input"], context=case.get("context"))
checks = {
"answer": check_answer(trace.answer, case["expected"]),
"tools": check_tools(trace.tool_calls, case["expected"]),
"citations": check_citations(trace.citations, case["expected"]),
"steps": len(trace.steps) <= case["expected"].get("max_steps", 8),
}
results.append({
"id": case["id"],
"tags": case["tags"],
"passed": all(checks.values()),
"checks": checks,
"steps": len(trace.steps),
"tokens": trace.tokens,
"latency_ms": trace.latency_ms,
})
by_tag = {}
for r in results:
for tag in r["tags"]:
by_tag.setdefault(tag, []).append(r["passed"])
return {
"pass_rate": mean(r["passed"] for r in results),
"by_tag": {k: mean(v) for k, v in by_tag.items()},
"avg_steps": mean(r["steps"] for r in results),
"p95_latency": percentile([r["latency_ms"] for r in results], 95),
"total_tokens": sum(r["tokens"] for r in results),
"failures": [r for r in results if not r["passed"]],
}输出要能回答三个问题:
- 整体通过率是多少?
- 哪一类失败最多?
- 成本与延迟是否可接受?
接进 CI
每次改提示、工具、模型,自动跑:
- name: agent-eval
run: python evals/run.py --dataset evals/golden.jsonl --fail-under 0.85CI 里用固定模型版本、固定温度、固定工具 mock。真实模型调用可能慢且贵,可以:
- 小规模冒烟(10 条)每次跑;
- 全量(100+)每天或发版前跑;
- 记录基线,低于基线就失败。
线上评估
线上最重要的是可归因:
- 每个任务有 trace_id;
- 用户反馈能关联到具体轨迹;
- 失败能分类(检索、工具、推理、权限、超时);
- 抽样人工复核。
不要只看「点赞率」。用户可能因为界面好看而点赞,也可能因为不知道正确答案而无法判断。
评估集污染
- 训练数据可能包含公开评测题;
- 提示里可能泄漏测试样本;
- 长期记忆可能记住了答案;
- 团队反复针对测试集调参。
对策:保留一个从未看过的留出集,只在发版前跑;定期更换样本;用新构造的边界案例。
常见失败
过程错了但答案蒙对,线上迟早出问题。多步任务必须看轨迹。
10 条样本的 90% 和 80% 没有统计意义。至少几十条,关键场景上百条。
共同偏见会让评估虚高。尽量换家族,或加入人工校准。
只报一个通过率,不知道从哪修。按标签、失败类型、工具维度拆开看。
测试用 mock 工具、生产用真实 API,行为差异大。关键路径要有端到端测试。
检查清单
- 有 50+ 条人工确认的黄金集
- 覆盖顺利路径、边界、信息不足、对抗、历史失败
- 多步任务评估轨迹,不只评估答案
- 指标按标签/失败类型拆分
- LLM 评委经过人工校准,顺序随机
- 有置信区间与方差意识
- 评估接进 CI,有基线
- 线上有 trace、反馈关联、失败分类
- 保留未公开留出集
- 评估成本与延迟可接受
小结
- 评估分单元、轨迹、端到端、线上四层。
- 黄金集要覆盖边界、拒答、对抗和历史失败。
- 多步任务必须看工具选择与步骤,而不只是最终答案。
- LLM 评委需要标准、随机化、校准和人工抽检。
- 小样本差异可能只是噪声,关注失败分布与置信区间。
下一篇讲怎么在线上看见 Agent 内部发生了什么:可观测性。