27届大模型面试准备(二十):评测体系全攻略------Benchmark、数据污染、LLM-as-Judge 与 Arena 对战
上一篇《模型量化全攻略》结尾留了个问题:量化之后"到底掉了多少点",靠什么来回答?答案就是评测体系。这一篇是本系列第二十篇,也是把前面所有技术串起来的一篇------无论是 RAG、长上下文、后训练还是量化,最终都要面对同一个拷问:"你怎么证明它变好了?"评测看起来是最"没技术含量"的环节,实际上是大厂面试里区分度最高的题目之一,因为它直接暴露一个人有没有真正把模型送上过线。本文按"评测的三层结构 → 静态 Benchmark 与它的崩塌 → 数据污染 → LLM-as-Judge → Arena 与 Elo → 业务评测体系搭建"展开,结尾给面试速答和高频追问清单。
一、先建立框架:评测的三层结构
面试被问"你怎么评测大模型",最忌讳上来就报菜名(MMLU、GSM8K、C-Eval)。正确姿势是先给结构:
大模型评测的三层结构
第三层 业务评测 端到端指标、A/B 实验、人工标注、线上反馈
(决策层) 回答"这次迭代能不能上线"
▲
│ 真实分布,成本高,样本少
第二层 能力评测 MMLU / GSM8K / HumanEval / 长文本 / 指令遵循
(诊断层) 回答"模型在哪类能力上强、哪类弱"
▲
│ 标准化,可比,但易污染
第一层 基础指标 PPL、Loss、token 级准确率
(冒烟层) 回答"模型有没有训崩/量化崩"
三层的关系是逐层放大、逐层可信度提升、逐层成本上升 。第一层几分钟出结果但只能判死活;第三层要几天但直接决定上线。大部分候选人只会讲第二层,讲不出第一层的用途和第三层的设计,这就是差距。
一个必须说清楚的原则:评测指标的选择要匹配决策场景。选基座模型看第二层,判断训练是否正常看第一层,决定要不要发版看第三层。用第二层的分数去决定发版,是最常见的工程错误。
二、静态 Benchmark:还剩多少价值
2.1 主流 Benchmark 分类图谱
知识类 MMLU / MMLU-Pro / C-Eval / CMMLU / GPQA
└─ 多选题为主,考"记得住多少"
推理类 GSM8K(小学数学) / MATH(竞赛数学) / BBH / DROP
└─ 考多步推理,对 CoT 敏感
代码类 HumanEval / MBPP / LiveCodeBench / SWE-bench
└─ 用单测通过率(pass@k)判分,客观性最强
长文本 LongBench / RULER / 大海捞针(NIAH) / InfiniteBench
└─ 考上下文利用率,见第十三篇
指令遵循 IFEval / MT-Bench / AlpacaEval
└─ 考"听不听话"、格式约束能否满足
Agent ToolBench / BFCL(函数调用) / AgentBench / WebArena
└─ 考工具调用与多步任务,见第十八篇
安全 AdvBench / HarmBench / TruthfulQA
└─ 考越狱抵抗与幻觉,见第十六篇(B系列)
2.2 pass@k:唯一真正客观的指标
代码类评测之所以最可信,是因为有编译器和单测这个"绝对裁判"。pass@k 的无偏估计公式要会写:
对每题采样 n 个候选(n ≥ k),其中 c 个通过单测:
⎡ C(n-c, k) ⎤
pass@k = E ⎢ 1 - ───────── ⎥
⎣ C(n, k) ⎦
直觉:C(n-c,k)/C(n,k) 是"抽 k 个全是错的"概率
python
import numpy as np
def pass_at_k(n: int, c: int, k: int) -> float:
"""n: 总采样数, c: 通过数, k: 目标 k。无偏估计,避免直接用 1-(1-p)^k 的偏差。"""
if n - c < k:
return 1.0
# 用连乘避免大数阶乘溢出
return 1.0 - np.prod(1.0 - k / np.arange(n - c + 1, n + 1))
# 用法:每题采样 n=20,统计通过数,再对全体题目求平均
scores = [pass_at_k(20, c, k=1) for c in per_task_correct_counts]
print("pass@1 =", np.mean(scores))
注意面试陷阱:直接用 1-(1-c/n)^k 是有偏的,样本量小的时候偏差明显,必须用上面的组合数形式。
2.3 Benchmark 正在失效的四个原因
这部分是高分回答区。
原因一:数据污染。 测试集大量出现在预训练语料里,模型是"背过答案"而非"会做题"。下一节详述。
原因二:饱和。 GSM8K 上顶尖模型都在 95% 以上,剩下的 5% 大部分是标注错误,指标已经无法区分模型。这叫天花板效应。应对是升级到更难的版本(MATH、AIME、GPQA-Diamond)。
原因三:格式敏感性。 同一个模型,选项顺序打乱、prompt 模板换一个,MMLU 分数能波动好几个点。这说明测的是"对特定格式的适应性"而非真实能力。
同一模型在 MMLU 上的分数波动来源
┌────────────────────┬──────────────┐
│ 选项顺序 (ABCD 轮换) │ ±2 ~ 4 点 │
│ few-shot 数量 0/5 │ ±3 ~ 6 点 │
│ 答案提取正则 │ ±1 ~ 5 点 │
│ 是否允许 CoT │ ±5 ~ 15 点 │
└────────────────────┴──────────────┘
→ 所以跨论文比较分数几乎没有意义,
必须自己在统一 harness 下重跑
原因四:能力与体验脱节。 MMLU 高不代表用户觉得好用。用户体验取决于回答的组织、语气、拒答边界、追问处理,这些多选题一点都测不到。
面试可以这样收尾:"静态 benchmark 现在的定位更像回归测试而不是能力度量------用来确保这次改动没把已有能力搞坏,而不是用来证明模型有多强。真正证明能力要靠 Arena 和业务评测。"
三、数据污染:怎么检测、怎么防
3.1 污染的三种形态
形态 描述 严重度
─────────────────────────────────────────────────────
输入污染 测试集的题目出现在训练语料 中
标签污染 题目 + 标准答案成对出现 高
改写污染 语义相同但表述不同(翻译/同义改写) 高且难检测
改写污染最麻烦:字符串匹配查不出来,但模型确实见过等价内容。
3.2 四种检测方法
方法一:N-gram 重叠。 最基础,也是 GPT-3/PaLM 等论文的标准做法。
python
def ngram_contamination(test_text: str, train_corpus_index, n: int = 13) -> bool:
"""13-gram 是业界常用阈值(GPT-3 用 13-gram,Llama 用 8-gram)。
train_corpus_index 是预建的 n-gram 哈希集合(布隆过滤器更省内存)。"""
toks = test_text.split()
grams = [" ".join(toks[i:i + n]) for i in range(len(toks) - n + 1)]
if not grams:
return False
hit = sum(1 for g in grams if g in train_corpus_index)
return hit / len(grams) > 0.05 # 超过 5% 的 n-gram 命中即判污染
局限:只能查字面重叠,对翻译和改写无效;而且需要能访问训练语料------评测闭源模型时根本做不到。
方法二:困惑度对比法。 如果模型在测试集上的 PPL 显著低于同分布的"新鲜"数据,说明可能背过。
取测试集 D_test 与同来源但发布时间晚于模型截止日期的 D_fresh
若 PPL(D_test) << PPL(D_fresh),且难度相当 → 疑似污染
方法三:选项顺序扰动(顺序敏感性检验)。 一个巧妙的思路:如果模型是真理解,把正确答案从 A 挪到 D 不该有影响;如果是背下了"答案是 A",打乱后准确率会暴跌。
python
def order_sensitivity_probe(model, question, options, gold_idx):
"""把选项做多种轮换,看准确率方差。方差极大 → 疑似记忆而非推理。"""
import itertools, random
accs = []
for _ in range(8):
perm = list(range(len(options)))
random.shuffle(perm)
shuffled = [options[i] for i in perm]
new_gold = perm.index(gold_idx)
pred = model.choose(question, shuffled)
accs.append(int(pred == new_gold))
return sum(accs) / len(accs) # 与原始准确率差距过大即为红旗
方法四:时间切分(最可靠)。 用模型训练截止日期之后发布的题目做评测。LiveCodeBench、AIME 当年真题、LiveBench 都是这个思路。这是目前公认最干净的做法,也是面试的加分答案。
3.3 工程上怎么防
- 训练前做去污:把所有已知评测集的 n-gram 建索引,从训练语料中剔除命中样本。
- 自建私有测试集且永不上网:这是最实在的一条。业务侧自己标 500~2000 条,只在内网使用,不发布、不进任何语料。
- 金丝雀字符串(canary):在测试集文件里嵌入一段随机 UUID,之后就可以直接问模型"你见过这串字符吗"来探测是否被训练进去。BIG-bench 就用了这个技巧。
- 定期换血:私有测试集每季度替换 20~30%,防止长期使用被间接泄漏(比如通过 API 日志)。
四、LLM-as-Judge:便宜但危险
开放式生成任务没有标准答案,人工评又太贵,于是用强模型当裁判成为主流。但它的坑非常多,面试官最爱问的就是"你怎么保证裁判是公正的"。
4.1 三种裁判范式
单点打分 (Pointwise) 给一个回答打 1-10 分
优点:可扩展,能算绝对分 缺点:分数漂移严重,裁判倾向给 7-8 分
两两对比 (Pairwise) A 和 B 哪个更好
优点:判断更稳,人类一致性最高 缺点:O(n²) 次比较
参考答案打分 (Reference-based) 给定标准答案再判
优点:最准 缺点:需要标准答案,成本高
工程上的共识:能用 pairwise 就别用 pointwise。人类和模型在"二选一"上都远比"打绝对分"稳定。
4.2 五种已知偏差与对应校正
这是本节的核心,也是面试的高分点。
| 偏差 | 表现 | 校正方法 |
|---|---|---|
| 位置偏差 | 系统性偏好排在前面(或后面)的回答 | 交换 A/B 各判一次,只有两次判断一致才计数,不一致记平局 |
| 长度偏差 | 偏好更长的回答,哪怕废话多 | 控制长度分布;或用 AlpacaEval 2.0 的长度校正回归 |
| 自我偏好 | GPT-4 偏爱 GPT-4 生成的文本 | 用第三方模型做裁判;或多裁判投票 |
| 格式偏差 | 偏好带 markdown 列表、加粗的回答 | 评分标准里显式声明"不因排版加分" |
| 权威偏差 | 回答里出现引用、数字就更信 | 要求裁判逐条核实事实,而非整体印象 |
位置偏差的校正代码:
python
def pairwise_judge_debiased(judge, question, ans_a, ans_b):
"""双向判定消除位置偏差:两次结论一致才算数,否则判平局。"""
v1 = judge(question, first=ans_a, second=ans_b) # -> 'first'|'second'|'tie'
v2 = judge(question, first=ans_b, second=ans_a) # 顺序交换
# 把第二次的结论映射回 A/B 语义
map2 = {"first": "B", "second": "A", "tie": "tie"}
r1 = {"first": "A", "second": "B", "tie": "tie"}[v1]
r2 = map2[v2]
if r1 == r2:
return r1
return "tie" # 不一致 = 裁判不可靠,保守判平局
4.3 裁判 Prompt 的设计要点
一个能用的裁判 prompt 至少要有五个部分:
1. 角色与任务 "你是严格的评审,判断哪个回答更好"
2. 明确的评分维度 正确性 > 完整性 > 相关性 > 表达(给出优先级!)
3. 反偏差声明 "不要因为回答更长或排版更好而加分"
4. 强制先分析后结论 要求逐维度对比,最后一行才给结论(CoT 提升一致性)
5. 结构化输出格式 固定 JSON,便于解析
python
JUDGE_PROMPT = """你是严格公正的评审专家。请判断以下两个回答哪个更好。
[用户问题]
{question}
[回答 A]
{ans_a}
[回答 B]
{ans_b}
评分维度(按优先级从高到低):
1. 事实正确性 ------ 有无事实错误、编造内容
2. 完整性 ------ 是否覆盖问题的所有子问题
3. 相关性 ------ 有无答非所问、无关铺陈
4. 表达清晰度 ------ 逻辑是否连贯
严格遵守:
- 不得因回答更长而给更高评价,冗长啰嗦应扣分
- 不得因使用 markdown 排版而加分
- 不得因回答风格与你自身相似而偏袒
- 必须先逐维度分析,再给结论
输出严格遵循以下 JSON,不要有其他内容:
{{"analysis": {{"correctness": "...", "completeness": "...",
"relevance": "...", "clarity": "..."}},
"verdict": "A" 或 "B" 或 "tie"}}"""
4.4 怎么验证"裁判本身可信"
这是面试最容易被追问、也最容易答不上来的一步。答案是:用人工标注做校准,算一致性。
1) 抽 200~500 条样本,让 3 位标注员独立标注
2) 先算人类之间的一致性(Fleiss' Kappa),这是天花板
3) 再算 LLM 裁判与人类多数意见的一致率 / Cohen's Kappa
4) 判定标准:
LLM-人类一致率 ≥ 人类-人类一致率 - 5% → 裁判可用
否则改 prompt / 换裁判模型 / 改用 pairwise
python
from sklearn.metrics import cohen_kappa_score
# human_major: 人工多数投票结果; llm_votes: LLM 裁判结果
kappa = cohen_kappa_score(human_major, llm_votes)
# Kappa 参考:>0.8 极好, 0.6~0.8 可用, 0.4~0.6 勉强, <0.4 不可用
print(f"Judge-Human Kappa = {kappa:.3f}")
关键认知:LLM 裁判的上限是人类标注的一致性水平。如果一个任务连人类标注员之间都只有 60% 一致(比如"这个文案更有创意吗"),那就不该指望 LLM 裁判给出可信结论,这类任务应该走 A/B 实验用行为数据说话。
五、Arena 与 Elo:用群体对战排名
5.1 为什么需要 Arena
静态 benchmark 测的是固定题目,Arena(如 LMSYS Chatbot Arena)让真实用户提任意问题、盲评两个模型的回答。它的优势是题目分布贴近真实使用、无法被针对性优化、天然抗污染。
5.2 Elo 与 Bradley-Terry
Elo 的更新公式要会写:
期望胜率: E_A = 1 / (1 + 10^((R_B - R_A)/400))
分数更新: R_A ← R_A + K × (S_A - E_A) S_A ∈ {1, 0.5, 0}
K 通常取 4~32:K 大则收敛快但抖动大
python
def elo_update(ra: float, rb: float, score_a: float, k: float = 16.0):
"""score_a: A 胜=1, 平=0.5, 负=0。返回更新后的 (ra, rb)。"""
ea = 1.0 / (1.0 + 10 ** ((rb - ra) / 400.0))
eb = 1.0 - ea
return ra + k * (score_a - ea), rb + k * ((1 - score_a) - eb)
但在线 Elo 有个致命问题:结果依赖对战顺序 。同一批对战记录,换个顺序喂进去,排名可能不同。所以 LMSYS 实际用的是 Bradley-Terry 模型做最大似然估计------它是顺序无关的,且能给置信区间。
BT 模型: P(i 胜 j) = exp(β_i) / (exp(β_i) + exp(β_j))
用逻辑回归拟合全部对战记录求 β,再线性映射到 Elo 尺度
再用 bootstrap 重采样得到 95% 置信区间
python
import numpy as np
from sklearn.linear_model import LogisticRegression
def bt_ratings(battles, models):
"""battles: [(winner_idx, loser_idx), ...],返回 Elo 尺度分数。"""
n = len(models)
X = np.zeros((len(battles), n))
y = np.ones(len(battles))
for r, (w, l) in enumerate(battles):
X[r, w], X[r, l] = 1.0, -1.0
lr = LogisticRegression(fit_intercept=False, C=1.0, max_iter=1000)
lr.fit(X, y)
# 映射到 Elo 尺度:400/ln(10) ≈ 173.72,基准 1000
return dict(zip(models, lr.coef_[0] * 173.72 + 1000))
5.3 Arena 的局限
面试要能辩证地说:
-
偏好 ≠ 正确 。用户投票会偏好自信、详尽、排版好的回答,即使有事实错误。Arena 高分模型不一定更准确。
-
题目分布偏娱乐化 。真实 Arena 里大量是闲聊、写诗、脑筋急转弯,专业领域覆盖不足。
-
可被刷榜 。通过风格微调(更长、更多列表、更热情)能显著提升 Arena 名次而实际能力不变。这也是为什么 LMSYS 后来引入了风格控制(style control)后的榜单。
-
长尾能力测不到。Arena 测不出 128K 长文本、复杂工具调用这类低频但关键的能力。
六、搭一套业务评测体系
前面都是"通用能力怎么测",面试真正想听的是"你们自己的系统怎么测"。给一套可直接照搬的方案。
6.1 整体架构
┌─────────────────────────────────────────────────┐
│ 离线评测流水线(CI 触发) │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ 回归集 │ │ 能力集 │ │ 安全/红队集 │ │
│ │ 300 条 │ │ 500 条 │ │ 200 条 │ │
│ │ 必须全过 │ │ 看趋势 │ │ 拦截率≥阈值 │ │
│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
│ └────────────┼───────────────┘ │
│ 规则判分 + LLM 裁判 │
└──────────────────┬──────────────────────────────┘
│ 通过
▼
┌─────────────────────────────────────────────────┐
│ 灰度 / A-B 实验(线上 1%~10% 流量) │
│ 行为指标: 采纳率、重问率、会话轮次、人工转接率 │
│ 质量指标: 抽样人工标注 200 条/天 │
│ 成本指标: 单会话 token 成本、P95 延迟 │
└─────────────────────────────────────────────────┘
6.2 三类测试集的分工
| 集合 | 规模 | 来源 | 判分方式 | 卡点规则 |
|---|---|---|---|---|
| 回归集 | 300 | 历史 badcase 修复后沉淀 | 规则/精确匹配为主 | 一条都不能挂,挂了直接阻断发布 |
| 能力集 | 500 | 真实流量分层采样 | LLM 裁判 pairwise | 相对上版胜率 ≥ 50%(含平局) |
| 安全集 | 200 | 红队 + 公开越狱库 | 规则 + 分类器 | 拦截率不得低于上版 |
回归集是最有价值的资产。每修一个线上 badcase,就把它连同期望行为固化成一条用例。半年下来这套集合的业务针对性远超任何公开 benchmark。
6.3 落地代码骨架
python
from dataclasses import dataclass
from typing import Callable, Literal
import json, statistics
@dataclass
class TestCase:
id: str
kind: Literal["regression", "capability", "safety"]
query: str
context: dict | None = None
expect: dict | None = None # 规则判分用:关键词、正则、JSON schema
baseline_answer: str | None = None # pairwise 判分用:上一版答案
def rule_score(case: TestCase, answer: str) -> bool:
"""规则判分:覆盖必含关键词、禁词、JSON 合法性三类硬约束。"""
exp = case.expect or {}
if "must_include" in exp:
if not all(k in answer for k in exp["must_include"]):
return False
if "must_not_include" in exp:
if any(k in answer for k in exp["must_not_include"]):
return False
if exp.get("json_schema"):
try:
json.loads(answer)
except Exception:
return False
return True
def run_suite(cases: list[TestCase], model: Callable, judge: Callable) -> dict:
report = {"regression": [], "capability": [], "safety": []}
for c in cases:
ans = model(c.query, c.context)
if c.kind in ("regression", "safety"):
report[c.kind].append({"id": c.id, "pass": rule_score(c, ans)})
else:
v = pairwise_judge_debiased(judge, c.query, ans, c.baseline_answer)
report["capability"].append({"id": c.id, "verdict": v})
reg_pass = all(x["pass"] for x in report["regression"])
saf_rate = statistics.mean([x["pass"] for x in report["safety"]])
wins = sum(x["verdict"] == "A" for x in report["capability"])
ties = sum(x["verdict"] == "tie" for x in report["capability"])
n = max(len(report["capability"]), 1)
return {
"regression_all_pass": reg_pass, # 硬卡点
"safety_pass_rate": round(saf_rate, 4), # 硬卡点
"capability_winrate": round((wins + 0.5 * ties) / n, 4),
"gate": reg_pass and saf_rate >= 0.98 and (wins + 0.5 * ties) / n >= 0.5,
}
6.4 统计显著性别忘了
500 条样本上胜率 52% 和 48% 有区别吗?必须算显著性,否则就是在噪声里做决策。
python
from scipy import stats
def winrate_significance(wins: int, losses: int, ties: int):
"""去掉平局做二项检验(sign test)。p<0.05 才认为有真实差异。"""
n = wins + losses
if n == 0:
return 1.0, 0.5
p = stats.binomtest(wins, n, 0.5, alternative="two-sided").pvalue
return p, wins / n
# 经验:想检出 5 个点的胜率差异,大约需要 400~800 条有效对比样本
一个实用经验值要记住:要稳定检出 5 个百分点的胜率差异,大约需要 400~800 条有效样本。这个数字在面试里说出来会很加分,因为它说明你真的做过。
七、面试速答
Q:你会怎么评测一个大模型?
A:分三层。第一层基础指标(PPL/Loss)只用来判断训练或量化有没有崩,几分钟出结果。第二层能力评测用标准 benchmark 做能力画像和回归防护,覆盖知识、推理、代码、长文本、指令遵循、Agent、安全七个维度。第三层业务评测才是发版决策依据,包括自建回归集、能力集、安全集三套离线数据,加上线上 A/B 实验的行为指标。关键原则是指标选择要匹配决策场景------用 MMLU 分数决定要不要发版是典型的工程错误。
Q:为什么现在大家都说 benchmark 不可信了?
A:四个原因。一是数据污染,测试集大量泄漏进预训练语料,模型是背过而非会做。二是饱和,GSM8K 这类已经普遍 95% 以上,剩余误差主要是标注噪声,失去区分度。三是格式敏感,换个 prompt 模板、打乱选项顺序,分数能波动好几个点,说明测的是格式适应性而非真实能力。四是能力与体验脱节,多选题测不出回答组织、拒答边界、追问处理这些真正影响用户感受的东西。所以 benchmark 现在更适合当回归测试用,而不是能力度量。
Q:怎么检测数据污染?
A:四种手段。N-gram 重叠(13-gram 命中率超 5% 判污染)是基础做法,但只能查字面重叠且需要访问训练语料。困惑度对比法看模型在测试集和同分布新鲜数据上的 PPL 差异。选项顺序扰动是个巧妙的黑盒方法------真理解的模型不该对答案位置敏感,打乱后准确率暴跌说明是记忆。最可靠的是时间切分,只用模型训练截止日期之后发布的题目,LiveCodeBench、LiveBench 都是这个思路。工程上防污染靠训练前 n-gram 去污、自建永不上网的私有测试集、埋 canary 字符串、以及定期换血。
Q:LLM-as-Judge 有哪些偏差?怎么校正?
A:五种主要偏差。位置偏差(偏好特定位置的回答),校正方法是 A/B 交换各判一次,两次一致才计数,不一致记平局。长度偏差(偏好更长回答),靠控制长度分布或做长度校正回归。自我偏好(偏爱同源模型生成的文本),用第三方裁判或多裁判投票。格式偏差(偏好 markdown 排版),在 prompt 里显式声明不因排版加分。权威偏差(见到数字引用就更信),要求逐条核实而非整体印象。另外能用 pairwise 就别用 pointwise,因为绝对打分的漂移远大于二选一。
Q:怎么知道你的 LLM 裁判本身是可靠的?
A:必须用人工标注做校准。抽 200~500 条让三位标注员独立标注,先算人类之间的 Fleiss' Kappa 作为天花板,再算 LLM 裁判与人类多数意见的 Cohen's Kappa。判定标准是 LLM 与人类的一致率不低于人类之间一致率减 5 个点。Kappa 大于 0.6 才算可用。核心认知是 LLM 裁判的上限就是人类标注的一致性水平------如果连人类都只有 60% 一致,这类主观任务就不该用 LLM 裁判,应该走 A/B 实验用真实行为数据说话。
Q:Arena 的 Elo 是怎么算的?有什么问题?
A:Elo 用期望胜率 E_A = 1/(1+10^((R_B-R_A)/400)) 和更新式 R ← R + K(S-E)。但在线 Elo 的结果依赖对战顺序,同样的数据换个顺序排名可能变。所以 LMSYS 实际用 Bradley-Terry 模型做最大似然估计,它顺序无关,再用 bootstrap 给置信区间。Arena 的局限是:用户偏好不等于正确性,会偏好自信详尽的回答哪怕有错;题目分布偏娱乐化,专业领域覆盖不足;可以通过风格微调刷榜,所以后来引入了风格控制榜单;长文本、复杂工具调用这类低频关键能力完全测不到。
Q:模型量化后怎么验证效果?
A:三层递进。第一层 PPL 冒烟,只判有没有崩。第二层跑标准 benchmark,重点关注对量化最敏感的推理和代码任务------PPL 只掉 0.1,GSM8K 可能掉 5 到 10 个点。第三层是业务数据端到端评测,如果是 Agent 场景必须专门统计 JSON 结构化输出合法率和工具调用参数准确率,量化后这两个指标劣化往往比 PPL 明显得多,而它们直接决定线上能不能用。评测时还要控制变量,用同一套 harness、同样的采样参数,否则对比没有意义。
Q:500 条测试样本上新版胜率 52%,能发版吗?
A:不能直接下结论,要先算统计显著性。去掉平局做二项检验,如果 p 值大于 0.05,52% 和 50% 在统计上无差异,这就是在噪声里做决策。经验值是要稳定检出 5 个百分点的胜率差异大约需要 400 到 800 条有效对比样本。如果确实要发,正确做法是先看回归集和安全集这两个硬卡点是否全过,然后走小流量灰度,用线上行为指标(采纳率、重问率、人工转接率)来做最终判断,这些指标的样本量足够大,结论更可信。
八、高频追问清单
- pass@k 为什么不能直接用
1-(1-p)^k?无偏估计的推导思路是什么? - 如果 MMLU 涨了 3 点但线上用户满意度下降,你怎么排查?
- 自建评测集时如何做分层采样,才能代表线上真实分布?
- LLM 裁判用同一个模型既当选手又当裁判,会有什么后果?
- Bradley-Terry 相比在线 Elo 的优势具体在哪?置信区间怎么算?
- 长文本能力(128K)该怎么设计评测?大海捞针为什么不够?
- Agent 类任务的评测和普通问答有什么本质区别?中间步骤要不要评?
- 如何评测 RAG 系统?检索和生成的问题怎么归因区分?(下一篇 B19 详述)
- 幻觉率该怎么量化?有哪些自动化方法,各自的假阳性问题是什么?
- 多模态模型的评测和纯文本相比多了哪些挑战?
- 评测成本太高怎么办?有哪些用小样本估计大样本结论的方法?
- 如果 CI 里的评测流水线跑一次要 6 小时,你会怎么优化?
至此 A 系列前二十篇覆盖了从架构、训练、对齐到推理、量化、评测的完整链路。下一阶段会转向更前沿的主题:MoE 架构细节、推理时扩展(test-time scaling)、强化学习新范式(GRPO 等)。B 系列今天的两篇(B19 RAG 评估、B20 智能体可观测性)刚好和本篇形成呼应------本篇讲"怎么评模型",那两篇讲"怎么评系统"。