第 09 篇 评测工程:把「好不好」变成可测的数字
第 09 篇 评测工程:把「好不好」变成可测的数字
本篇属于「工程质量」模块。02 篇搭过三层评测结构的概览,这一篇把它做成完整操典:如何建一个可信的 golden set、如何从失败模式反推指标、如何让 LLM 当裁判而不被它骗、如何把评测焊进 CI 与线上监控。读完应能独立搭出一套可运行的评测体系。
引言:为什么评测是 PM 最大的分水岭
本系列第一篇对 654 份在招产品经理 JD 的分析显示,85% 的岗位描述提到 AI/ML,其中 32% 明确要求候选人具备 evals(评测)能力。换句话说,约三分之一的岗位把"能不能定义并运行评测"当硬门槛。
为什么是评测,而不是别的?因为 AI 系统的输出是概率性的。传统软件"跑通测试"约等于"功能正确";AI 系统"跑通一次"什么都不证明——同样的输入换一次运行可能就错。没有评测,你不知道一次 prompt 改动是变好还是变坏;没有评测,你不知道上线后是不是在悄悄退化;没有评测,团队的所有讨论都停留在"我觉得"。
结论先行:评测是 AI PM 唯一的客观话语权。它把"好不好"从主观感受翻译成可对比的数字,让迭代有方向、让争论有依据、让上线有底线。
一、评测的三种类型与分工
很多人把"评测"当成一件事,于是要么只在上线前跑一次,要么只盯线上曲线。实际上评测分三种,职责、频率、负责人都不同,缺任何一种都会出现盲区。
| 类型 | 目的 | 何时跑 | 谁负责 | 成本 | 失败的后果 |
|---|---|---|---|---|---|
| 能力评测(离线) | 测"这个系统当下能做到什么水平" | 每次改动(prompt/检索/模型/知识库)后,接入 CI | PM 定义集与指标,工程接入 | 中(全量跑固定集) | 不知道改动是涨是跌,迭代靠猜 |
| 回归评测(离线) | 测"改动有没有破坏已有能力" | 同上,与能力评测同一次运行 | 同上 | 低(复用 golden set) | 旧能力悄悄退化,用户先发现 |
| 在线评测(生产) | 测"真实环境下表现如何、是否在漂移" | 持续,按采样比例回流 | PM 看指标,算法/SRE 接监控 | 高(依赖 trace 与标注) | 线上退化数周后才被投诉暴露 |
核心判断:
- 离线评测保"底线":每次合并前必须全绿,红灯不合并。它回答"这次改动有没有把事情搞砸"。
- 在线评测保"现实":离线分数好不代表线上好,因为真实输入分布、用户问法、知识库状态都在变。它回答"系统在真实世界里还站不站得住"。
两者不可互相替代。离线集是冻结的、可控的;在线是开放的、噪声大的。只看离线会过度自信,只看在线会反应滞后。
二、Golden Set 的构建方法
这是整篇最该花时间的一章。一个糟糕的 golden set 会让整个评测体系变成精密的摆设——它给你漂亮的数字,却对你真正的失败视而不见。
2.1 规模:50–200 条起步
经验上,一个能用的 golden set 从 50 条开始,到 200 条进入稳定区。这个量级基于两个考量:
- 统计意义:少于 50 条时,单条失败会让总分波动 2 分以上,你分不清是真退化还是噪声。100 条以上,多数核心失败模式才能各分到足够样本。
- 维护成本:golden set 要人工标注、长期维护。超过 200 条后,标注与复核的人力成本上升很快,而边际信息增益递减。
扩充的时机:当出现新的、稳定的失败模式,而现有集合里该类样本不足 5 条时,针对性补到能支撑趋势判断为止。不要为了"凑大"而堆量。
2.2 来源优先级:真实生产 > 专家手写 > 合成
| 来源 | 可信度 | 适用 | 局限 |
|---|---|---|---|
| 真实生产数据(已脱敏) | 最高 | 覆盖真实分布与长尾 | 可能含敏感信息,需脱敏;早期没有 |
| 领域专家手写 | 高 | 冷启动期、定义"什么叫对" | 规模有限,专家时间贵 |
| 合成数据 | 中–低 | 扩充表达多样性、格式变体 | 无法发明领域知识,会放大模型自身盲区 |
为什么合成数据只能补充、不能当主力?模型生成的数据来自模型已有的认知。它能把"已知"说成"另一种说法",但不能产生模型不知道的知识,也不能创造它没见过的失败形态。用合成数据撑起 golden set,等于让系统在自己熟悉的舒适区里考自己,分数虚高却不代表真实能力。合成数据正确的位置是:在真实/专家样本定标后,做表达层面的扩充。
2.3 覆盖原则:按失败模式分层,而非随机抽样
最常见的错误是"从生产日志里随机抽 100 条"。随机抽到的几乎全是正常 case,因为失败本来就是少数。你的 golden set 于是成了"漂亮案例集",对真正的 bug 毫无覆盖。
正确做法:先列失败模式清单(参考《第 03 篇:LLM 能力边界与失败模式图鉴》),用失败模式作为第一维来构造。一个覆盖矩阵示例:
| 失败模式 | 简单场景 | 复杂/多跳场景 | 对抗/边界场景 | 小计 |
|---|---|---|---|---|
| 幻觉(编造事实) | 15 | 20 | 15 | 50 |
| 答非所问(相关性差) | 15 | 15 | 10 | 40 |
| 检索遗漏(该召不回) | 10 | 20 | 10 | 40 |
| 工具调用错误 | 10 | 15 | 5 | 30 |
| 格式崩溃 | 5 | 5 | 5 | 15 |
| 合计 | 55 | 75 | 45 | 175 |
构造顺序:先保证每个已知失败模式都能分到 5–15 条;再用"场景难度"拉开分布,逼出长尾;最后补少量"正常 case"防止集子全是负样本导致指标失真。
2.4 冻结原则:主集冻结,新失败进"新失败集"
golden set 一旦建立,主集必须冻结——不增、不改、不删。原因:指标要跨版本可比。如果每次都往主集里加新题,你看到的分数变化里混进了"题目变难了"的因素,分不清是系统变好还是题目变简单。
新发现的失败案例,先进独立的"新失败集"。观察它是否稳定复现、是否代表一类而非个例,稳定后再合并进主集并提升版本号(如 golden-v3)。每次合并都是一次有记录的版本演进。
2.5 污染问题:绝不能用测试集调 prompt
用 golden set 调 prompt,等于用答案反推考题。你会得到一组在这个集上异常好看的数字,但它在真实分布上几乎一定失效——因为模型只是"记住"了这几十条题。这叫测试集污染(data leakage 的一种)。
纪律:golden set 是"考试卷",不是"练习册"。任何为了抬高主集分数而做的针对性改动,都必须在另一个独立集上验证才作数。
2.6 标注规范:判分标准写到可执行
模糊的标注指令(“判断回答是否忠实”)会让两个标注员给出完全不同的分,指标因此不可信。规范必须写到"看到什么算什么"。
下面是一份"忠实度"可执行分级定义(0/1/2 分):
忠实度评分标准(Faithfulness)
判断对象:回答中的每一个事实性论断,是否都能在给定检索内容中找到依据。
2 分(完全忠实):
- 所有事实性论断(人名、数字、时间、因果、结论)都能在检索内容中找到原文或等价表述;
- 没有引入检索内容之外的任何事实;
- 推理步骤(若有)可由检索内容直接推出。
1 分(部分忠实):
- 核心结论有依据,但存在一处次要事实无法溯源(如多出一个未提及的时间点、一个模糊的"通常");
- 或对检索内容做了轻微过度概括,但不改变结论方向。
0 分(不忠实):
- 出现检索内容中不存在的具体事实(编造的数字、来源、事件);
- 或结论与检索内容相悖;
- 或把 A 的信息安到 B 身上(张冠李戴)。
判分铁律:拿不准时,凡检索内容里找不到原文支撑的事实性论断,一律记 0。
注意最后一条"拿不准记 0"——它把主观判断的歧义推到最严格一侧,保证不同标注员的分差可控。
2.7 测试用例记录模板
每条用例建议落库为一条结构化记录,而非散落的文本文件。模板如下(可直接套用):
# 测试用例记录(单条)
id: RAG-042
所属失败模式: 幻觉-编造数字
场景难度: 复杂/多跳
输入(query): 我们去年 Q3 的华东区退货率是多少?对比 Q2 变化多少?
期望输出: 给出具体百分比与环比,并引用来源段落
检索内容(ref): [段落A: ...][段落B: ...] # 与 query 对应的真实上下文
参考回答: ...(可选,专家手写的标准答案)
标注维度:
faithfulness: 2
answer_relevancy: 2
context_recall: 1
format_valid: 1
关键判定点: "退货率"必须是检索内容里出现的真实数字,不得估算
标签: regression(回归必须保持), p0(高优先)
版本引入: golden-v1
备注: Q2 段落缺失时本应触发降级而非编造
这套字段让每条用例都可被程序读取、可跨版本比对、可按失败模式聚合——它是你评测体系的"最小数据单元"。
三、指标设计:从失败模式反推指标
指标不是凭空定的。先有失败模式,才有指标;指标必须能追溯到具体失败模式,否则就是虚荣指标(vanity metric)——看着涨了,问题还在。
下面这张对照大表把常见失败模式映射到可测指标,并标出每个指标"能抓到什么、抓不到什么"。
| 失败模式 | 对应指标 | 建议阈值 | 能抓到什么 | 抓不到什么 |
|---|---|---|---|---|
| 编造事实 | 忠实度 Faithfulness | ≥ 0.90 | 回答超出检索依据 | 回答"对但没用" |
| 答非所问 | 答案相关性 Answer Relevancy | ≥ 0.85 | 偏题、答错方向 | 事实是否准确 |
| 召不回关键信息 | 上下文召回率 Context Recall | ≥ 0.85 | 该检索的没检索到 | 检索内容是否相关 |
| 召回到垃圾 | 上下文精确率 Context Precision | ≥ 0.80 | 检索结果不相关 | 生成质量 |
| 任务没完成 | 任务完成率 Task Success | ≥ 0.80 | 多步目标未达成 | 单步质量细节 |
| 调错工具 | 工具选择正确率 Tool Selection Acc. | ≥ 0.95 | 选错/漏选工具 | 参数对错 |
| 违反约束 | 约束违反率 Constraint Violation | ≤ 0.05 | 越权/超范围/违规 | 完成质量高低 |
| 成本失控 | 每正确答案成本 Cost / Correct | ≤ 预算 | 花了很多钱才对 | 答案本身对不对 |
| 该答不答 | 拒答率 Refusal Rate | ≤ 0.05 | 过度拒答 | 答了之后的质量 |
| 格式崩 | 格式合规率 Format Compliance | ≥ 0.98 | 多了前言/占位符 | 语义正确性 |
| 长尾慢 | P95 延迟 | ≤ 2s | 长尾体验差 | 平均体验 |
| 结果飘 | 一致性 Consistency(同输入多次方差) | 方差 ≤ 阈值 | 同问不同答 | 绝对对错 |
RAG 四指标(忠实度/相关性/上下文精确率/上下文召回率)的计算思路简述:
- 忠实度:把回答拆成论断,逐条判定有无检索依据,比值即分。可 LLM-as-judge 自动算,但需人工校准。
- 答案相关性:判断回答是否回应了 query 的意图,与事实无关。
- 上下文召回/精确率:以"检索到的内容"相对"与问题相关的理想内容"的覆盖与纯度来算,需要标注"哪些段落是相关的"。
Agent 类指标特别强调"成本与约束":因为 Agent 会多步调用、会自己选工具,光看"最后对不对"掩盖了两件事——它是否绕了远路(成本)、它是否干了不该干的(约束违反)。任务完成率 ÷ 成本 才是 Agent 的真实效率。
通用指标里最容易被忽略的是一致性:同一输入跑 5 次,答案一会儿对一会儿错,说明系统不可信。一个平均 90% 但对同一问题方差极大的系统,不如稳定 85% 的系统。
四、LLM-as-judge 的正确用法与三个偏差
人工标注贵且慢,全量评测几乎必须上 LLM-as-judge(用模型当裁判自动打分)。但它有三个已知偏差,不处理就会系统性虚高或虚低。
| 偏差 | 机制 | 表现 | 缓解手段 |
|---|---|---|---|
| 循环论证 | 用会幻觉的模型判另一个模型 | 判官自己也编,给错分 | 换不同厂商模型做集成评判;冻结 golden set;5% 人工校准 |
| 位置偏差 | 成对比较时偏好特定位置 | 总判第一个或第二个"赢" | 成对比较时随机交换 A/B 顺序,各跑一次取平均 |
| 长度/风格偏差 | 偏好更长、更"像样"的回答 | 冗长但空洞的回答得分高 | 在判官 prompt 里明确要求"只看事实正确性,忽略长度与文风";必要时做长度归一 |
缓解手段落地清单
- 换厂商集成评判:主裁判用 A 厂模型,副裁判用 B 厂模型,分歧超阈值才升级人工。两个会幻觉的模型来自不同训练分布,同时犯同一个错的概率显著低于单一模型。
- 成对比较随机交换位置:任何 A vs B 的胜负判断,都随机决定哪个放前面,跑两次,消除位置偏置。
- 抽 5% 人工标注定期校准:每周抽 5% 的 trace 人工打分,计算判官与人工的一致性(如 Cohen’s kappa 或简单一致率)。一致率低于某阈值就说明判官已漂移,需重新调 prompt 或换模型。
- 定期验证判官与人工一致性:不是跑一次就完。判官本身也是个"模型",它也会随你改它的 prompt 而变。把它当成一个需要被评测的对象。
核心原则:LLM-as-judge 是"放大器",不是"真理"。它能把人工定好的标准规模化,但标准本身必须来自人。
五、把评测接进工程流程:CI 门禁
评测最大的敌人是"忘了跑"。解决方法是把它焊进工程流程——不跑评测,就不许合并。
5.1 哪些变更必须触发评测
任何可能影响输出的改动都要触发全量评测:
- prompt 改动(哪怕是改一个词)
- 检索参数改动(top-k、chunk 大小、相似度阈值)
- 模型版本替换(升级或降级)
- 知识库更新(新增/删除文档、重新建索引)
这几类改动里,prompt 和知识库更新最容易"以为没事"——结果上线才发现忠实度掉了。所以门禁对它们一视同仁:先红后绿,不许跳过。
5.2 红灯规则伪代码
门禁不是"跑一下看分数",而是带硬阈值的断言。一个包含质量、延迟、成本三道闸的写法:
def gate_before_merge(eval_result, budget):
# ---- 质量下限(任何一项低于阈值,红灯)----
assert eval_result.faithfulness >= 0.90, "忠实度低于 0.90"
assert eval_result.answer_relevancy >= 0.85, "答案相关性低于 0.85"
assert eval_result.context_recall >= 0.85, "上下文召回率低于 0.85"
assert eval_result.format_compliance >= 0.98, "格式合规率低于 0.98"
assert eval_result.refusal_rate <= 0.05, "拒答率超过 0.05"
# ---- 延迟上限(P95 单点不能超)----
assert eval_result.p95_latency_ms <= budget.max_latency_ms, "P95 延迟超限"
# ---- 成本上限(单次与每正确答案成本)----
assert eval_result.avg_cost_per_call <= budget.max_cost, "单次成本超限"
assert eval_result.cost_per_correct <= budget.max_cost_correct, "每正确答案成本超限"
# ---- 回归保护:相比上一版本,核心指标不得明显退化 ----
assert eval_result.faithfulness >= baseline.faithfulness - 0.02, "相对基线退化超 0.02"
return "GREEN" # 全过才放行
注意最后一条"回归保护":它不仅守绝对下限,还守"相对上版本不退化"。这能拦住那种"分数没破线、但比上周差了一截"的隐性劣化。
5.3 例外流程:紧急修复怎么办
门禁不是铁板。生产事故时要能绕,但要留痕:
- 紧急修复可走 hotfix 通道,附"已绕过评测门禁"标签与理由,但必须在 24–48 小时内补跑评测并回填结果。
- 任何绕过都要有 owner 签字(哪怕是即时通信里的一句确认),避免"临时"变成"永久"。
- 补跑若红灯,立即回滚或进入修复流程,不得带病上线。
原则:没有绿灯的 eval,不许合并。例外是例外,不是常态。
六、在线评测与漂移监控
离线绿灯不等于线上安全。真实输入分布、用户问法、知识库状态都在变,系统会"漂移"。
6.1 采样比例
| 环境 | 采样比例 | 说明 |
|---|---|---|
| 开发/预发 | 100% | 每条 trace 全留,便于定位 |
| 生产 | 5%–20% | 全量成本过高,按流量抽样 |
| 错误/异常 | 高采样(接近 100%) | 失败日志多采,才有足够失败样本 |
6.2 监控什么
- 输入分布:用户真实问法的分布是否变了(新意图出现、老意图消失)。
- 指标趋势:在线忠实度、相关性、拒答率、格式合规率的周环比。
- 工具错误率:Agent 场景下,工具调用失败/超时/参数错误的比例。
- 成本与延迟:单次成本、P95 的实际分布,是否随流量上升而劣化。
6.3 告警阈值怎么定
阈值要分"观察"与"行动"两级:
- 观察线:指标偏离基线 1 个标准差 → 进周报,不告警。
- 行动线:连续两次采样(或单周跌幅超 3%)→ 触发告警,PM 必须响应。
- 硬性红线:忠实度周跌幅超 5%、工具错误率翻倍 → 立即回滚或降级。
6.4 漂移的三种来源
| 来源 | 机制 | 例子 |
|---|---|---|
| 知识库变了 | 文档更新后,旧答案依据失效 | 价格改了,模型还在引用旧价 |
| 用户问法变了 | 真实意图分布迁移 | 上新功能后,大量新问题无对应知识 |
| 模型版本变了 | 底层模型升级/降级,行为偏移 | 同 prompt 换模型后语气或边界变化 |
每周节奏:周一采样、周二标注、周三归集、周四并入测试集、周五重跑评测(与《第 10 篇:数据飞轮与冷启动》的飞轮节奏对齐)。
七、评测报告怎么写
评测的价值在于被消费。一份没人读的报告等于没跑。一页纸模板,结论先行:
# 评测报告:[功能名] [版本号] [日期]
## 结论(一句话)
本次 [prompt 改动 / 模型升级] 后,忠实度 0.91→0.93(达标),但 P95 延迟 1.4s→2.1s(逼近上限),建议上线前优化检索。
## 指标对比
| 指标 | 上版本 | 本版本 | 阈值 | 判定 |
|------|--------|--------|------|------|
| 忠实度 | 0.91 | 0.93 | ≥0.90 | ✅ |
| 相关性 | 0.88 | 0.87 | ≥0.85 | ✅ |
| P95延迟 | 1.4s | 2.1s | ≤2.0s | ⚠️ |
| 单次成本 | 0.002 | 0.0021 | ≤0.003 | ✅ |
## 失败归因
- 延迟上涨主因:检索 top-k 从 5 调到 8,召回更全但更慢。
- 2 条忠实度失败:均属多跳推理,模型跳过中间步骤。
## 下一步动作
1. 检索 top-k 回调到 6,平衡召回与延迟(owner:工程,本周)。
2. 新增 8 条多跳用例进 golden-v4(owner:PM)。
## 附:测试集版本
golden-v3,共 175 条;标注规范 v2。
记住:报告第一行就该让人知道"能不能上"。细节是给想知道为什么的人看的,不是给所有人看的。
一页速查
评测体系搭建清单
├─ 先建 golden set
│ ├─ 规模 50–200 条,按失败模式分层,不随机抽
│ ├─ 来源:真实生产 > 专家手写 > 合成(合成只补表达)
│ ├─ 主集冻结,新失败进"新失败集",稳定后升版本合并
│ └─ 绝不用测试集调 prompt(防污染)
├─ 指标从失败模式反推(抓不到失败的指标是虚荣指标)
│ RAG:忠实度/相关性/上下文精确率/召回率
│ Agent:完成率/工具正确率/约束违反率/每正确答案成本
│ 通用:拒答率/格式合规/P95/单次成本/一致性
├─ LLM-as-judge 三偏差:循环论证/位置偏差/长度偏差
│ 缓解:换厂商标判 + 随机交换位置 + 5% 人工校准
├─ 焊进 CI:prompt/检索/模型/知识库改动必跑
│ 红灯规则:质量下限 + 延迟上限 + 成本上限 + 回归保护
│ 原则:没绿灯不许合并;紧急可绕但 48h 内补跑
└─ 线上监控:开发 100% / 生产 5–20% / 错误多采
漂移三源:知识库变 / 用户问法变 / 模型变;每周重跑
常见坑
- 用测试集调 prompt:分数虚高,线上翻车。golden set 是考卷不是练习册。
- 随机抽 case 当测试集:抽到的全是正常样本,失败模式零覆盖,等于没测。
- 指标凭空定:没有对应失败模式的指标只是虚荣数字,涨了也发现不了真问题。
- 只用单一模型当裁判:循环论证 + 位置/长度偏差叠加,系统性虚高。
- 忘了位置偏差:成对比较不交换顺序,判官永远偏向某一个位置。
- golden set 从不冻结:每次加题导致分数变化混进"题变难",无法判断系统涨跌。
- 只看离线不顾线上:离线全绿,但知识库/问法/模型已漂移,真实表现早崩了。
- CI 门禁没有回归保护:守了绝对下限却放过"比上周差一截"的隐性退化。
- 告警只有一条线:要么不响要么狂响,PM 对波动麻木,真事故被淹没。
- 评测报告写成长文:结论埋在倒数第二段,没人看,跑评测变成走过场。
结语
没有评测的 AI 项目,迭代全靠感觉,上线只能靠运气。评测不是上线前的一道手续,而是 AI PM 贯穿产品全生命周期的底层操作系统——它定义"好",守住"好",并证明"还好吗"。
本文为「AI 产品经理入门与进阶」系列第 09 篇。数据来源:本系列第 01 篇对 654 份产品经理 JD 的分析(32% 岗位要求 evals 能力)、公开 LLM 评测框架技术文档(Ragas / DeepEval / Arize Phoenix / LangSmith)、LLM-as-judge 偏差相关研究。数据用于说明趋势与方法,具体数值随技术迭代变化,请以最新数据为准。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)