设计题 04:给一个 LLM 应用搭评测体系
权重:★★★ 形式:45 分钟系统设计轮
素材来源:Own — HKGAI LLM(HKMMLU 的构建、标注质量与污染控制、人工标注的真实代价)、QueWI(意图识别「23% 提升」的口径问题、分桶评测)
相关知识点:05-agent-evaluation/llm-as-judge.md、benchmarks.md、rag-eval.md、agent-eval.md、06-agent-infra/observability.md
1. 题干#
「我们这个 LLM 产品下周就要上线了。老板问我两件事:第一,我们怎么知道它做得好不好?第二,接下来我们每次改 prompt、换模型、加功能,怎么知道是变好了还是变差了?你帮我们搭一套评测出来。」
注意这个题干有多模糊:没说产品形态(开放式生成?分类抽取?agent?)、没说答错会怎样、没说有多少标注人力、没说改版频率、没说什么叫「好」。这不是题干写得差,这是刻意的。 面试官在看你什么时候发现「评测什么」这件事还没定义。
2. 第一步:澄清(这一轮最重要的动作)#
绝对不要听完就开始列指标。开场第一句应该是:
「搭评测之前我想先确认几件事 —— 因为这几个答案会决定评测集长什么样、要不要上 LLM judge、以及要花多少标注人力。」
必问清单(按对方案的影响排序)#
| # | 问题 | 为什么它会改变方案 |
|---|---|---|
| 1 | 这个产品是哪种形态? | 分类 / 结构化抽取 / 有标准答案的问答 → 大部分维度可以用确定性校验(schema、字段值、集合匹配),根本不需要 judge;开放式生成 → 才需要 judge。先想清楚能不能不用 judge |
| 2 | 哪一类错误最不能接受? | 决定门禁维度。内部写作助手的事实错误只是尴尬;面向客户的合规问答的事实错误是事故 —— 后者需要 faithfulness 硬门禁 + 拒答维度,前者只需趋势监控 |
| 3 | 谁来标注、有多少人力? | 有标注团队 → 可以建较大的 golden set;没有人 → 只能小校准集 + judge 覆盖广度。这是最硬的资源约束,它决定整个方案的上限 |
| 4 | 改动频率和决策时限? | 每天迭代 → 需要小到能在 CI 里分钟级跑完的核心回归集;一季一次 → 可以跑大集 + 人工评审 |
| 5 | 评测数据能放真实用户内容吗? | 有合规限制 → 评测集必须脱敏或合成;无限制 → 可以直接从线上 trace 回流,分布最真实 |
| 6 | 现在有没有 baseline? | 没有 baseline,任何分数都不可解读。必须先把「上线前的那一版」固化成可重跑的快照 |
| 7 | 要跨版本 / 跨时间比较吗,还是只卡一个绝对阈值? | 要比较 → pairwise 或固定评测集 + 配对统计;只卡阈值 → pointwise + rubric(但要定期重校准) |
| 8 | 语言与本地语境? | 香港产品常是粤语口语 + 繁简混用 + 中英夹杂 → 评测集的语言分布必须和真实流量一致,否则指标虚高(HKMMLU 的存在就是这个道理) |
面试技巧:不要机械地把 8 个问题念完 —— 那像在念清单。挑影响最大的 2–3 个先问(通常是 1、2、3),拿到答案再往下问。追问本身也是考点。
3. 参考架构#
假设澄清后得到:开放式生成、有合规要求、有少量标注人力、迭代频繁、没有 baseline。
┌─ L0 口径与 baseline ──────────────────────────────────┐
│ 固化一版可重跑的快照 + 指标定义 + 分桶方案 │
│ (没有这一步,后面所有分数都不可解读) │
└───────────────────────────────────────────────────────┘
↓
┌─ L1 离线 golden set(评测集)─────────────────────────┐
│ 分桶:任务类型 / 难度 / 语言 / 风险等级 │
│ 每条:input + 期望(答案/证据/终态断言)+ 类型标签 │
│ 来源:真实流量采样 + 反向合成 + 线上失败回流 │
└───────────────────────────────────────────────────────┘
↓
┌─ L2 回归集(CI 门禁)─────────────────────────────────┐
│ L1 的核心子集,几十条量级,每次改动自动跑; │
│ 不达阈值不放行,全集留到发版前跑 │
└───────────────────────────────────────────────────────┘
↓
┌─ L3 自动打分:规则优先 → judge(必须校准)─────────────┐
│ judge:rubric + 打分锚点 + 换序 + 跨家族 + 一致性报告 │
└───────────────────────────────────────────────────────┘
↓
┌─ L4 线上:A/B + 持续信号 → 回流闭环 ──────────────────┐
│ 灰度分流 · 版本 tag · 点赞点踩 / 追问率 / 转人工率 │
│ 采样 trace 挂 judge 分数 → 持续质量监控(非只测一次) │
│ 线上失败 → 人工归因 → 评测集 / 训练数据 → 回归评测 │
└───────────────────────────────────────────────────────┘画图时要讲的三个点(这是把架构和「背指标」区分开的地方):
- L1 和 L2 不是两套评测集,是同一套数据的两个子集。 很多人会建两套,结果是两套都要维护、两套都会过期。正确做法是一个评测集带难度与优先级标签,核心子集进 CI,全集发版前跑。
- L3 的顺序是先规则后 judge,不是先 judge。 能确定性判定的(有 gold answer、schema、可执行验证、环境终态)一律不用 judge —— judge 的每个偏置都要靠校准去压,能不引入就不引入。L4 同理不是可选项:离线指标好但线上反馈差,通常意味着评测集分布和真实流量不一致,而这个信号只有线上能给。
4. 关键决策与权衡#
4.1 第一原则:能用确定性判定就不要用 judge#
按可靠性排序(前面的优先):
| 手段 | 适用 | 代价 |
|---|---|---|
| 环境终态断言 | agent 类任务:检查数据库那行改对了没、文件生成了没 | 要为每个任务搭可重置的沙箱 |
| gold answer 匹配 | 有标准答案的抽取 / 分类 / 事实题 | 只能覆盖有唯一答案的部分 |
| 规则与 schema 校验 | 格式、字段、引用是否存在、拒答是否触发 | 需要为每个任务写判定逻辑 |
| LLM-as-a-Judge | 语气、有用性、有害性、过程合理性、开放式质量 | 引入全部偏置,必须校准 |
说这句话很加分:「judge 不是评测的起点,是确定性校验覆盖不到时的补位。」把 judge 当第一手段,等于给自己造了一个需要长期维护的不可靠指标。
4.2 judge 怎么校准(这一节必须讲透)#
裁判的合法性只能来自与人工标注的一致性。五步:
- 建校准集:人工标注一批样本,覆盖你关心的难度与类别分布 —— 不要只抽简单样本,难样本上的一致性才是真信号。
- 选一致性指标:pairwise 用原始一致率 + Cohen's kappa(扣掉瞎猜的部分);分级评分用 Spearman / Kendall 秩相关。
- 把标注者之间的一致性当作实用上限。如果人和人之间也只有七成一致,要求 judge 九成一致是没有意义的 —— 这个参照点一定要主动说出来。
- 迭代 judge prompt:加 rubric、给打分锚点范例、要求先写推理再给结论(CoT-then-verdict)、明确允许「平局」。每改一版重跑一致性。
- 报告数字:把「judge vs 人工一致性」写进评测报告。一致性不达标,judge 分就不允许用来卡门禁。 阈值要按校准结果定,不要拍脑袋。
加分补充:judge 模型换版本、被测模型分布漂移、任务换类型,都要重新校准 —— judge 的有效性是任务特定的,校准过一次不等于永久有效。
4.3 judge 和人工不一致时,改什么(最能区分深浅的一节)#
关键立场:不要一律去改 judge。 分层处理:
- 先看是系统性分歧还是随机分歧。 随机分歧为主 → 多半是样本量与标注噪声问题;分歧集中落在某一类样本上 → 是判定标准问题,不是 judge 能力问题。
- 不要默认人工是对的。 人工标注本身有噪声(标注者之间也不一致)。分歧样本要复核,有一部分是标注错了 —— 直接照着错的标注去调 judge 会把 judge 调坏。
- 最常见的原因是 rubric 没定义清楚。 这时候要修的是判定标准,不是 judge 的措辞:把分歧案例写成 rubric 里的锚点例子,明确边界(「答对了但引用了错误来源,算不算通过」这种问题必须被判分标准回答)。
- 某个子类一致性持续很低 → 把该子类移出 judge 的判定范围,改用人工或确定性校验,并在报告里标明覆盖边界。承认 judge 覆盖不到的地方,比强行让 judge 覆盖更专业。
- 分歧样本回流进校准集,让下一次校准更靠近边界。
- 最后一道:judge 不得单独决定上线;高风险维度保留人工门禁。
4.4 pointwise vs pairwise#
- 要绝对阈值卡门禁(如「faithfulness ≥ 阈值才允许上线」)→ pointwise,但必须带 rubric,且要定期重校准 —— 它有分数标尺漂移的问题。
- 要版本对比、排行榜、构造偏好数据 → pairwise。它不需要绝对标尺,跨批次可比性好得多;代价是 O(n²) 的调用量、需要聚合(Elo / Bradley-Terry 之类),且对 position bias 敏感,必须换序各评一次再聚合。
- 绝对不要用 pointwise 的绝对分跨批次比较版本 —— 标尺漂移会让这个比较失去意义。
4.5 benchmark 污染#
- 公开 benchmark 的分数不能当产品指标。 除了污染,还有格式敏感、饱和、Goodhart 效应(团队会不自觉地向题型优化)。它测的也是窄能力 —— 多选题测不出生成、指令遵循、多轮对话。
- 自建评测集的防污染做法:私有留出(原题不公开发布,只发布形态说明)、时间切分(题目晚于模型训练截止)、去重检测(n-gram / 子串能抓逐字泄漏,改写抓不到)、性能异常模式检查(冷门子集反而特别高分往往是见过的信号)。
- 检测是不完美的 —— 在训练数据不透明的前提下无法完全排除污染。所以在报告里写清做了哪些检查;声称「绝对没有污染」不可信,坦诚反而是加分。
- 一个容易被忽略的自污染来源:你的评测集是从自己系统的输出或线上流量构造的,而 prompt、工具描述、few-shot 在迭代中会把「答案」泄漏进上下文。所以评测集和优化对象之间要有隔离 —— 用来调 prompt 的样本,不能再用来当这一轮的门禁样本。
4.6 什么不该做(资深信号)#
- 不要一上来就建评测平台。 先用一个 CSV + 一个脚本跑起来,验证评测集本身有区分度,再投入工程。平台化是把成熟的流程固化,不是用来发现流程的。
- 不要追求单一总分。 总分是给老板看的,分桶才是给工程师看的 —— 总体持平常常掩盖某一桶的严重退化。
- 不要全量人工标注。 人工只用于校准集 + 高风险门禁子集,广度交给 judge。
- 不要让被测模型给自己当 judge(self-preference 会让模型对比结论失真)。
- 不要在还没有 baseline 的情况下开始调优(不知道自己在变好还是变差);也不要拿用户点赞率当质量指标 —— 反馈稀疏、滞后、有严重选择偏置,且不能用于上线前门禁。
4.7 门禁阈值与统计显著性#
- 样本量小的时候,两个版本的差异很容易落在噪声里。几十条样本只能分辨很大的差异(十几个百分点量级);要检出几个百分点的差异通常需要几百条量级的配对样本,而且要看方差 —— 具体样本量必须按你的方差算,不能拍一个数。→ 这句话背后的公式与算法见
01-fundamentals/05-agent-evaluation/05-statistical-significance.md:、误差减半需 4 倍样本、McNemar 与 paired bootstrap 的口径。被追问「那你说怎么算」时,这里要能当场推一遍。 - agent 类评测方差更大(同一输入多次运行路径不同),必须多次采样,报 pass@k(能力上限)和 pass^k(可靠性)并给置信区间;单次结果没有意义。
- 门禁不要只看均值:同时看最差桶(守住高风险场景)与最差 case 的类型分布。阈值要从校准结果推出来,不要拍脑袋。
4.8 怎么让评测集活下去#
这是最容易被忽略、也最体现工程成熟度的一段:
- 版本 tag 齐全:评测集版本、judge 版本、被测模型/prompt 版本都要记录。少任何一个,跨时间比较都不成立。
- 分布漂移:定期从线上采样补新 case,覆盖新出现的意图、语言、输入形态。评测集不更新,半年后它测的就不是你的产品。
- 饱和与过时:指标到顶后失去区分度 → 保留私有的难例子集,或产品加新能力时同步加题;产品下线某功能,对应 case 要删。
- 人工抽检:按固定比例复核 judge 的输出,防止它悄悄漂走(漂移是静默的错误)。
5. 容量与成本直觉#
面试官常问「这套东西要多少成本」。不要求精算,但要有量级感觉:
- 一次评测的调用量 ≈ 样本数 ×(生成 + 打分)次调用。judge 调用通常比被测生成便宜,但如果 judge 的输入里要塞长上下文(比如整篇文档做 faithfulness 判定),它就会变成成本主项 —— 所以只给裁判必要的上下文,这同时也是降 distractibility 偏置的手段。
- pairwise 要换序跑两次,调用量直接翻倍,这是它的隐性代价。
- 人工标注是真正的瓶颈:按条计费、有周期、有不一致性。所以人工只覆盖校准集和高风险门禁子集。
- 回归集要小、要快:它在每次改动的关键路径上,目标是分钟级出结论;全集可以慢(小时级,发版前跑)。线上 A/B 的成本不是钱,是流量 —— 达不到足够流量就一直不显著,这时宁可先用离线评测 + 灰度覆盖代替。
- 一句面试话术:「评测体系自身的成本,要能被它防住的回退抵消。所以先搭最小可用的一套,验证它真的拦住过一次回退,再扩。」
6. 面试官会怎么往下挖#
第一层:澄清与动机#
- Q:你会先问我什么? ← 见第 2 节,这是开场题
- Q:为什么不直接看用户反馈? ← 稀疏、滞后、有选择偏置,而且上线前根本没有
- Q:为什么不用 BLEU / ROUGE? ← 基于 n-gram 重叠、需要参考答案,开放式生成里「都对但措辞不同」的重叠度可能很低,与人类偏好相关性不足以支撑决策
第二层:技术细节#
- Q:你怎么证明你的 judge 可信? ← 校准集 + 一致性指标 + 以标注者之间的一致性为上限 + 报告数字
- Q:judge 和人工不一致,你改什么? ← 见 4.3:先分系统性/随机,先怀疑 rubric,必要时缩小 judge 的适用范围
- Q:pointwise 还是 pairwise?为什么? ← 见 4.4
- Q:评测集多大才够? ← 取决于要分辨多小的差异和数据的方差,不能给绝对数字;要报置信区间
- Q:一个模型在公开 benchmark 上分很高,能说明什么? ← 只能说窄能力;测不出生成、指令遵循、多轮、安全,而且有污染、饱和与 Goodhart 问题
第三层:工程与生产#
- Q:怎么接进 CI? ← 小核心集 + 自动跑 + 门禁;大集发版前跑;失败要能定位到具体 case 而不是只报一个数字
- Q:评测集自己会过期吗? ← 会,见 4.8
- Q:线上出现一类新失败,怎么进到评测集里? ← 从 trace 筛失败 case → 人工标注与归因 → 补进评测集并打桶标签
第四层:反思与边界#
- Q:这套体系什么时候会失效? ← 分布漂移(评测集不再代表真实流量)、rubric 跟不上产品变化、judge 静默漂移、指标饱和、以及评测集被当成优化目标(Goodhart)
- Q:客户说「我就要一个质量分数,一个数就行」,你怎么回? ← 可以给总分,但必须同时给分桶,并把高风险桶单列成门禁。一个数会掩盖局部退化,而局部退化恰恰是上线事故的来源
- Q:只有两周和一个人,你砍掉什么? ← 砍平台化、砍大评测集、砍在线 A/B。保留:baseline 快照 + 几十条覆盖高风险场景的回归集 + 一条最可靠的确定性校验 + 一个校准过的小 judge。先保证「改坏了能立刻发现」。
7. 自测#
1. 为什么说「能用确定性校验就不要用 judge」?举三类可以用确定性校验的评测。
答案要点
因为 judge 引入的全部偏置(position、verbosity、self-preference……)都要靠人工校准和长期维护去压,它是代理指标不是 ground truth。确定性校验不需要校准、结果可复现、能直接当门禁。三类:① agent 任务的环境终态断言(检查数据库那行改对了没);② 有 gold answer 的抽取/分类/事实题匹配;③ 规则与 schema 校验(格式、字段、引用是否存在、拒答是否触发、可执行验证如跑测试)。judge 只用于这些覆盖不到的维度:语气、有用性、过程合理性、开放式质量。
2. 你的 judge 和人工一致性只有 60%,但人工标注者之间的一致性也只有 65%。你怎么处理?
答案要点
先看参照系:标注者之间也只有 65%,说明任务判定标准本身模糊,人工一致率就是这套任务的实用上限,「judge 60%」未必是 judge 的问题。处理顺序:① 复核分歧样本,分系统性还是随机 —— 系统性 → rubric 没定义清楚,修判定标准并补锚点例子;随机为主 → 样本量不足或标注噪声;② 有一部分分歧是人工标错了,不能默认人工是对的;③ 某子类怎么调都低,就把该子类移出 judge 的覆盖范围,改用人工或确定性校验,并在报告里标明边界;④ 分歧样本回流校准集。核心立场:不能拿未达一致性的 judge 卡门禁,但也不该假装人类标注是完美基准。
3. 为什么不能用 pointwise 的绝对分跨批次比较模型版本?
答案要点
pointwise 的分数依赖绝对标尺,而标尺会漂移:judge 对量表锚点的理解会随批次、随 prompt 微小改动、随 judge 模型版本变化而移动(还会出现分数聚集,都打中间档)。所以「上周 4.2 分、这周 4.5 分」不能推出变好了。要做版本比较应该用 pairwise(只做局部比较,不需要绝对标尺),或者保证同一批次、同一 judge 版本、同一 rubric 下做配对比较;门禁用的绝对阈值则必须定期重校准。
4. 客户说「我就要一个质量分数」。你怎么回应?
答案要点
先给:可以有一个总分,但要说清它是多个维度的聚合,且必须同时给分桶结果(任务类型、难度、风险等级)。理由:总体持平或微升常常掩盖某一桶的严重退化,而上线事故通常就出在某个高风险桶上。所以正确交付是「一个总分 + 分桶视图 + 高风险桶的单列门禁」,并明确总分不能被单独用来做上线决策。如果客户坚持只要一个数,就把这个数的口径和它的失效条件写进报告 —— FDE 的价值是让客户知道自己在拿什么做决策。
5. 只有两周和一个人,你砍掉什么、保留什么?
答案要点
砍掉:评测平台化(用 CSV + 脚本)、大评测集、在线 A/B、复杂的 judge 体系与多裁判投票。保留:① baseline 快照(上线前那一版可重跑)——没有它后面所有比较都不成立;② 几十条覆盖高频与高风险场景的核心回归集;③ 一条最可靠的确定性校验(比如 schema + 引用存在性 + 拒答触发),这条能自动跑、零维护;④ 一个校准过的小 judge,只覆盖一两个最关键的主观维度,并报告其与人工的一致性。判断标准是:先保证「改坏了能立刻发现」,而不是「度量得多全面」。