返回

07-Eval自动化与回归测试.md

12.4 KB · MD · 2026-06-14 11:17

Eval 自动化与回归测试

Eval 是 evaluation 的简称,意思是评估。对提示词工程来说,Eval 不是“让 AI 自己夸自己好不好”,而是把 AI 输出质量变成可重复测试、可比较、可回归检查的工程流程。

没有 Eval,提示词优化很容易变成凭感觉改来改去:这次看起来更好,下一次换一批输入又坏了。Eval 的目标是让你能回答三个问题:

  1. 这个 prompt、RAG 或 Agent 到底好不好?
  2. 新版本是否比旧版本更好?
  3. 哪些失败样例必须进入长期回归测试?

截至 2026-06-14,OpenAI 官方文档提示旧 Evals 平台有退场时间:现有内容会保留过渡期,平台计划在 2026-10-31 对现有用户变为只读,并在 2026-11-30 关闭。因此,本讲重点不绑定某个平台,而是讲稳定的工程方法:评估集、评分器、运行器、报告、阈值、失败样例和持续回归。

本讲常见术语先按下面理解,详细定义和更多例子见 00.5-术语词典与最小用例

术语 直觉解释 最小例子
Eval 可重复评估 AI 输出质量的流程 50 个样例每次改 prompt 后都跑一遍
Evaluation set 固定测试样例集合 普通、长文档、缺失信息、对抗样例
Rubric 评分标准 忠实性 0-5 分,格式 0-2 分
LLM-as-judge 用另一个模型按标准评分 让评分模型判断回答是否引用充分
Gold set 人工确认过的高质量标准答案集 法务确认过的 30 个合格摘要
Regression test 防止旧错误复发的测试 曾经漏掉金额的案例永久加入测试集

一、直觉

传统代码测试像这样:

输入 -> 函数 -> 输出 -> 断言是否等于预期

LLM 评估像这样:

输入样例 -> AI 系统 -> AI 输出
-> 评分器检查输出是否满足标准
-> 汇总分数、失败原因、成本、延迟
-> 决定是否接受新版本

区别在于:AI 输出经常不是唯一正确答案。所以 Eval 不总是检查“是否完全相等”,更多时候检查“是否满足任务标准”。

例如总结任务不应该只问:

输出是否等于参考答案?

更应该问:

是否忠实于原文?
是否覆盖关键事实?
是否遗漏重要数字?
是否把不确定信息说成确定?
是否符合输出格式?

Eval 的本质是:把“好不好”拆成可检查的维度。

二、Eval 系统的基本结构

一个成熟 Eval 系统通常包括:

组件 作用
评估目标 说明要验证什么能力
评估集 一批固定测试样例
被测系统 prompt、RAG、Agent、模型版本或完整应用
运行器 批量执行测试样例
评分器 判断输出质量
指标 pass rate、平均分、严重错误数、成本、延迟
报告 比较版本、列出失败样例和原因
阈值 决定是否允许上线
回归集 从历史失败中沉淀的长期测试集

可以用一条链路表示:

目标 -> 数据集 -> 运行 -> 评分 -> 报告 -> 错误分析 -> 修改 -> 回归

这条链路比某一个工具更重要。工具会变,但链路应该长期保留。

三、评估集怎么建

评估集不是随便找几条样例。它要代表真实任务。

最小结构:

{
  "id": "case_001",
  "task": "summarize_document",
  "input": "...",
  "expected": {
    "must_include": ["关键事实A", "金额B"],
    "must_not_include": ["原文未出现的结论"],
    "format": "markdown_sections"
  },
  "rubric": "按忠实性、完整性、精确性、格式评分",
  "tags": ["normal", "long_document"]
}

评估集至少要覆盖:

  • 普通样例:最常见输入。
  • 长输入样例:测试上下文管理。
  • 信息缺失样例:测试拒答和不确定性。
  • 边界样例:测试规则边界。
  • 格式混乱样例:测试鲁棒性。
  • 对抗样例:测试提示注入和越权请求。
  • 历史失败样例:防止同样错误再次出现。

评估集不要只包含“模型容易答对”的样例。真正有价值的是能暴露失败的样例。

四、评分器的层级

评分器越简单、越确定,越应该优先使用。

1. 程序评分

最可靠,适合明确格式和确定答案。

例子:

  • JSON 是否可解析。
  • 必填字段是否存在。
  • 分类结果是否等于标准答案。
  • 输出是否包含指定引用编号。
  • 数字、日期、ID 是否匹配。
  • 工具调用参数是否符合 schema。

优点:快、便宜、稳定。

缺点:不擅长判断语义质量。

2. 规则评分

适合半结构化任务。

例子:

  • 输出必须少于 300 字。
  • 每个结论必须包含来源标注。
  • 不允许出现“根据常识可知”。
  • 不能包含外部资料中的提示注入指令。

优点:清楚、可解释。

缺点:规则写不全时会漏判。

3. LLM-as-judge

让另一个模型按评分标准评价输出。

适合:

  • 总结质量。
  • 语气风格。
  • 复杂推理是否合理。
  • 回答是否真正解决用户问题。
  • 多个答案之间哪个更好。

使用 LLM judge 时要注意:

  • 给明确 rubrics,不要只说“评估好坏”。
  • 让它输出结构化分数和失败原因。
  • 尽量使用二分类、三档或 1-5 分,不要只要长篇评论。
  • 用人工标注的小样本校准 judge。
  • 对重要任务保留人工复核。
  • 不要让 judge 看到候选版本名称,避免偏见。

4. 人工评分

最贵、最慢,但在高风险任务里不可替代。

适合:

  • 建立第一版 gold set。
  • 校准 LLM judge。
  • 复核严重失败。
  • 判断业务上真正能不能上线。

五、普通 Prompt 的 Eval

普通 prompt 的评估重点是输出质量和稳定性。

常见指标:

  • 忠实性:是否只基于输入材料。
  • 完整性:是否覆盖关键要求。
  • 精确性:数字、日期、名称是否正确。
  • 格式:是否符合结构。
  • 拒答:信息不足时是否不编造。
  • 风格:语气、长度、专业度是否符合要求。
  • 稳定性:多次运行是否大体一致。

最小评估表:

case_id 输入类型 预期 实际输出 分数 严重错误 是否通过
p001 普通 覆盖 A/B/C
p002 信息缺失 应标注不足
p003 对抗输入 不执行注入指令

Prompt 改版时,不要只看平均分。必须单独看严重错误数。一个版本平均分提高,但新增了高风险幻觉,仍然不能上线。

六、RAG 的 Eval

RAG 评估要分两层:

检索是否找到了正确资料?
生成是否忠实使用了正确资料?

检索层指标:

  • context recall:该找出的关键资料是否被找出。
  • context precision:检索结果中噪声多不多。
  • rank quality:正确资料是否排在前面。
  • metadata filtering:权限、日期、版本过滤是否正确。

生成层指标:

  • groundedness:回答是否有资料支持。
  • citation accuracy:引用是否真的支持结论。
  • answer completeness:是否答全。
  • abstention:资料不足时是否拒答。
  • conflict handling:来源冲突时是否说明冲突。

RAG 失败分析要先问:

  1. 正确资料有没有进入检索结果?
  2. 正确资料有没有进入模型上下文?
  3. 模型有没有使用正确资料?
  4. 引用是否支持结论?
  5. 如果资料不足,模型是否承认不足?

不要一看到答案错就立刻改 prompt。RAG 的错误常常出在 chunk、metadata、召回、重排或上下文打包。

七、工具调用和 Agent 的 Eval

Agent 不能只评最终答案,因为它可能中途做错事。

Agent Eval 要看 trace:

用户目标
-> Agent 计划
-> 工具选择
-> 参数
-> 工具结果
-> 下一步决策
-> 停止条件
-> 最终输出

关键指标:

  • 工具选择是否正确。
  • 参数是否完整、合法、来自可信上下文。
  • 是否优先使用只读工具。
  • 高风险操作前是否请求确认。
  • 工具失败时是否降级或停止。
  • 是否把工具结果忠实解释给用户。
  • 是否执行了外部内容中的恶意指令。
  • 是否在完成后停止。

Agent 评估样例一定要包含:

  • 工具返回空结果。
  • 工具报错。
  • 用户信息不足。
  • 用户要求高风险写操作。
  • 外部内容包含提示注入。
  • 两个工具名称相似,容易误选。
  • 已完成任务但模型可能继续调用工具的场景。

八、回归测试

回归测试的意思是:过去出过的错,以后不能再犯。

每次发现失败,都要判断是否加入回归集:

失败样例 -> 归因 -> 修复 -> 加入回归集 -> 后续每次改动都跑

应该加入回归集的样例:

  • 严重幻觉。
  • 金额、日期、权限、工具参数错误。
  • 格式破坏导致程序无法消费。
  • 安全边界被绕过。
  • RAG 引用错误。
  • Agent 未确认就执行高风险操作。
  • 用户明确指出的错误。

回归集不是越大越好。它应该代表真实风险,并保持可维护。

九、自动化运行

一个平台无关的 Eval 自动化流程可以这样设计:

eval_cases.jsonl
-> run_candidate.py
-> outputs.jsonl
-> grade_outputs.py
-> report.md
-> fail / pass

触发时机:

  • 修改 prompt。
  • 更换模型。
  • 调整温度、输出长度、reasoning effort 等参数。
  • 修改 RAG chunk、embedding、重排或上下文打包。
  • 修改工具定义、参数 schema 或权限。
  • 修改 Agent 工作流。
  • 上线前。
  • 定期从生产日志抽样。

报告至少包含:

  • 总通过率。
  • 各维度平均分。
  • 严重失败数。
  • 与上一版本相比的提升和下降。
  • 新增失败样例。
  • 成本和延迟变化。
  • 是否达到上线阈值。

十、上线阈值

不要用“总体 80 分”这种模糊标准上线。应该按风险拆分阈值。

示例:

上线要求:
1. 严重安全失败 = 0
2. JSON 格式通过率 >= 99%
3. 忠实性平均分 >= 4.5 / 5
4. 关键字段准确率 >= 98%
5. RAG 引用准确率 >= 95%
6. P95 延迟 <= 3 秒
7. 单次平均成本不超过旧版本 120%

注意:平均分不能掩盖严重错误。高风险任务中,一次严重失败可能比 100 次小瑕疵更重要。

十一、错误分析

Eval 的价值不只是给分,而是帮助你决定下一步该改哪里。

常见归因:

失败类型 优先改哪里
输出格式不稳定 结构化输出、schema、少量 prompt
原文没依据却编造 资料边界、拒答规则、RAG 引用
检索不到资料 chunk、embedding、关键词、metadata、重排
有资料但没用对 上下文打包、回答规则、引用规则
工具选错 工具名、描述、schema、工具数量
参数填错 参数 schema、输入校验、澄清问题
高风险操作失控 权限、确认节点、审批、工具分层
成本延迟过高 模型选择、上下文长度、缓存、批处理

这就是 Eval 驱动开发:不是“分数低就继续加提示词”,而是根据失败原因选择正确工程手段。

十二、常见误区

误区 1:人工看几个样例就够了

不够。人工检查可以发现问题,但不能保证每次改动后没有回归。

误区 2:平均分高就能上线

不一定。平均分会掩盖严重失败。高风险任务要单独统计严重错误。

误区 3:LLM judge 一定客观

不对。LLM judge 也会偏、会漏、会受提示词影响。必须用人工标注样例校准。

误区 4:Eval 只评最终答案

不对。RAG 要评检索,Agent 要评工具调用轨迹,结构化输出要评 schema。

误区 5:评估集建好后就不用管

不对。生产中的新失败、新输入分布、新模型行为都要不断进入评估集。

十三、理解检查

请你试着回答:

  1. 为什么 LLM 评估不能只用“输出是否等于参考答案”?
  2. 程序评分、LLM judge、人工评分分别适合什么场景?
  3. RAG 评估为什么要分成检索层和生成层?
  4. Agent Eval 为什么必须看工具调用 trace?
  5. 一个 prompt 改版上线前,至少应该看哪些指标?

十四、下一步

下一步可以继续补两个方向:

  1. 多智能体协作:什么时候需要 subagents、handoff、并行评审和任务分派。
  2. 成本与延迟优化:Prompt caching、上下文裁剪、批处理、模型分层和监控。