如果你关注过大模型榜单,又亲手在本地复现过某个开源模型的效果,多半会遇到一个困惑:为什么官方的榜单分数能到 70 分,自己跑出来却只有 50 分?是显卡不行,还是写错了命令?
最近一篇关于 LLM 评测可靠性的论文给出了一种很有意思的解释:同一个模型,在不同的评测配置下,分数差异可能非常大。论文里被测模型写作 gemma4-31b,最高分与最低分之间可以从约 31% 一直波动到约 89%。也就是说,排行榜上的名次差异,未必代表模型真实能力差异,反而像是对“评测配置”的敏感度测试。
本文会围绕这个结论展开,不堆实验数据,而是把“评测配置到底包含什么”“哪些参数对分数影响最大”“如何用开源工具亲手做一次可控的评测”“怎么避免在论文和大模型选型中被榜单误导”这件事拆清楚。无论你是要做开源模型对比、准备论文实验,还是给业务挑基座模型,都值得花几分钟读完。
1. 从论文结论看:LLM 评测不只是“跑个准确率”
1.1 一个反直觉的现象
很多人对模型评测的理解是这样的:
找一份 benchmark 数据集,把模型放上去,跑出来的准确率高,模型就强。
事实上,这个“跑”的过程里包含了大量可调因素。不同评测框架对解码的超参数设置不同,提示词模板写法不同,少样本示例采样方式不同,甚至同一个数据集在不同版本下给出的答案格式不同,都会影响最后的分数。
论文把一个能反映该问题的现象摆在了明面上:对于同一个模型,在传统固定答案类测试集上,只要调整评测配置,得分区间可以从 31% 移动到 89%。这两个数字在排名表上分别位于垫底和中上位置。
这说明,很多时候大家争论“模型 A 是否比模型 B 强”,争论的基础本身就不牢靠。如果把配置换一换,A 和 B 的顺序完全可能反转。
1.2 评测配置到底是什么
“评测配置”不是一个单独参数,而是整条评测管线的组合。按影响程度从粗到细可以分为几类:
- 解码层:温度、top-p、top-k、do_sample、max_new_tokens、频率惩罚等;
- 提示词层:问题模板、选项拼接格式、有无“Let's think step by step”、分隔符使用等;
- 少样本层:few-shot 数量、示例来源、示例顺序、随机采样种子等;
- 模型加载层:全精度、半精度、int8、int4、AWQ/GPTQ 量化等;
- 评估指标层:是否用 token 概率比较、是否只接受单个选项字母、是否有后处理规范;
- 框架版本层:不同版本的评测工具对生成结果解析逻辑不同,可能带来系统性偏差。
这些变量原本应该属于“评测说明”里必须交代的内容,但在实际排行榜和论文中往往被简化成一行字,甚至完全不写。缺少信息的分数,很难被复现。
1.3 为什么容易忽略这个问题
原因是评测工具默认了参数。大多数主流评测框架默认使用 greedy decoding,也就是温度等于 0,每次生成结果尽量确定。这本身是合理的,但问题是:
- 不是所有跑分人都知道默认参数存在;
- 不是所有框架都强迫用户显式设置解码参数;
- 一旦有人使用带采样配置的推理服务接入评测,结果就会出现偏差。
于是,同一个模型权重被下载后,在不同人手里可能跑出不同分数。跑分人以为自己是在测模型能力,实际是在测配置组合。
2. 为什么同一模型分数能出现 31% 到 89% 的巨大波动
这一节我们把评测配置拆开来看。理解每个环节的放大效应,比背答案更重要。
2.1 解码参数:从确定性到随机性
如果你的评测任务是对“单选题”做输出,并且直接用模型生成文本,那么解码参数的影响会非常明显。
| 配置 | 模型行为 | 对分数影响 |
|---|---|---|
| temperature=0 | 每次选择概率最大的令牌,输出稳定 | 波动小,相对可复现 |
| temperature=0.3 | 偏保守,但仍有一定随机性 | 可能出现少量答案变化 |
| temperature=0.7~1.0 | 随机性增强 | 对复杂推理题可能更容易答错 |
| do_sample 开启且未设种子 | 每次运行结果不同 | 分数可能在不同运行间跳动 |
对于选择题,如果评测逻辑要求模型直接输出某个选项字母,那么在采样开启后,模型一旦在概率边界附近“摇骰子”,就会影响最终正确率。多测几次,分数方差会变得非常大。
很多评测框架默认关闭采样,但当你通过 vLLM、TGI 等推理服务接入评测时,服务本身可能有独立的 sampling 参数,评测框架未必能完全覆盖。一个粗心配置,就会让结果变得不可控。
2.2 提示词模板:同一个模型,两套“人设”
提示词的变化对 LLM 输出的影响,已经是老话题,但在评测中容易被忽略。
同样一道数学题:
问题:小明有 3 个苹果,给了小红 1 个,还剩几个? 答案:2另一种写法:
Q: 小明有 3 个苹果,给了小红 1 个,还剩几个? A:模型对两种格式的敏感程度不同。对某些模型来说,中英文提示词差异、是否带“A:”、是否换行,都会影响生成 token 的分布。
在论文对应的现象中,如果测试方使用了和模型训练分布不一致的提示词格式,模型可能完全不理解任务意图,导致分数跌到接近随机水平。反之,如果提示词接近模型训练时的指令风格,分数就会回暖。这就是同一个模型分数可以从 31% 提到 89% 的重要原因之一。
在实际评测中,我建议采用下面策略:
- 固定一套提示词模板,不要中途修改;
- 如果要跑横向对比,必须保证所有被测评模型使用完全相同的模板;
- 不能因为某个模型在某个模板下表现好,就认为它一定比另一个模型强。
2.3 少样本示例:样例顺序也能改变结果
少样本(few-shot)评测中,常见操作是从训练集里抽出几个示例拼在提示词前面。这里的问题在于:
- 抽哪些示例;
- 示例之间顺序如何;
- 抽样的随机种子是否固定。
模型本质上是在做模式匹配,如果给出的示例恰好覆盖了某种题型,接下来遇到类似题型时表现就会更好。不同评测复现时,如果采样种子不一致,结果会有几个百分点的天然波动。
论文里提到的案例,并不仅仅是一个配置的简单开关,而是多个因素叠加后的效果。当所有“不利配置”叠加在一起,模型就可能跌到 31%;当所有“有利配置”对齐之后,它又能接近 89%。因此,单项差异可能没有想象中夸张,但累计效应十分惊人。
2.4 量化与推理精度
另一个容易被忽略的点是权重精度。
同一个模型,在 A100 上用 BF16 跑和在消费级显卡上用 int4 量化跑,输出概率分布会发生变化。量化会损失一部分精度,但在某些任务上,因为量化带来的隐式正则化,分数并不一定下降,甚至可能略有上升。
如果不记录量化方式,只写一句“我们评测了 Qwen2.5-7B 的 MMLU 结果”,这个结果其实很难被其他人直接复现。
2.5 评价指标与答案解析
最后,很多评测工具对生成的答案要做解析。比如多选题中,模型可能输出:
这道题的答案是 B,因为……如果解析逻辑只判断第一个字母是否为 B,结果正确;如果判断是否以“B”开头但模型先输出了语气词,可能被误判为错误。解析规则的不同,造成几分的波动并不奇怪。
评测工具越“死板”,越容易出现误伤。但换个角度看,如果榜单作者没有公开解析规则,你便无法判断分数差来自模型能力还是解析逻辑。
3. 对实际选型论文和工程落地的影响
3.1 别把排行榜当作选型唯一标准
对于做模型选型的人而言,这个现象的最直接提醒是:不要只依赖公开榜单的绝对值。
选型时应做到:
- 确认榜单方是否公开了完整评测配置;
- 在目标业务场景抽取 200~500 条真实数据,做小规模评测;
- 让相同问题分别用模型和现有规则系统跑一遍,人工抽检回答质量;
- 观察模型在边界情况下的表现,而不是只算及格率;
- 对分数结果增加 3~5 次运行,看波动区间。
一个排行榜分数高 5 个百分点的模型,在实际业务中可能只是因为它的提示词模板恰好和榜单一致。到了你的业务中,这个优势未必能延续。
3.2 复现他人实验结果时,需要核对哪些信息
复现开源模型分数时,如果分数对不上,优先核对:
- 评测框架是否为同一版本;
- temperature 和 top_p 是否一致;
- few-shot 样例是否固定;
- 是否开启同一种量化;
- 数据集的提示词模板是否完全一致;
- max_new_tokens 是否足够生成完整答案;
- 是否使用相同的答案解析策略。
这些信息在论文里通常不会全部出现,但作者如果提供了评测仓库或配置文件,就能极大减少复现时间。如果论文没有注明,可以直接在回复中要求作者补充配置,这是学术界越来越常见的要求。
3.3 公开榜单的分数也不一定可靠
不少第三方榜单会滚动收录不同时间提交的分数。每份提交使用的硬件、量化、解码参数可能不同。把这些分数放在一起排名,必然会出现失真。
一个理性的榜单阅读方式是:判断结果是否来自同一套评测流程,只比较同一流程内部的分差。跨流程的绝对分数没有太大意义。
4. 用开源工具做一次可控的 LLM 评测
下面我们实际操作一次。这里以评测框架 lm-evaluation-harness 为例。它由 EleutherAI 开源,支持多种模型加载方式和数据集,是目前比较流行的大模型评测工具之一。
注意,不同版本的 lm-evaluation-harness 在安装命令和参数细节上可能略有差异。本文展示的是常见方式,具体环境请以官方文档为准。
4.1 准备环境
建议使用 Python 3.10 或更高版本,创建独立虚拟环境。
python -m venv .venv source .venv/bin/activate pip install lm_eval如果你希望用 vLLM 后端加速评测,需要额外安装:
pip install vllm如果下载模型不方便,也可以使用已有的本地模型目录。下面的示例中,会把模型路径写成/data/models/your-model,实际使用时要替换成你的真实路径。
4.2 验证基础评测命令
下面命令会加载一个 Hugging Face 格式的开源模型,并执行 MMLU 数据集的 5-shot 测试。
python -m lm_eval \ --model hf \ --model_args "pretrained=/data/models/your-model,tokenizer=/data/models/your-model" \ --tasks mmlu \ --num_fewshot 5 \ --batch_size 16 \ --output_path ./results/greedy关键参数含义:
--model hf:使用 Hugging Face transformers 直接加载模型;--model_args:传递模型路径和 tokenizer 路径;--tasks mmlu:指定评测数据集;--num_fewshot:少样本数量,MMLU 常设置为 5;--batch_size:批次大小,需要根据显存调整;--output_path:结果保存目录。
如果不额外设置解码参数,lm-evaluation-harness 默认使用确定性解码,这对复现实验结果更友好。跑完命令后,终端会输出类似下面的结果:
| Tasks |Version|Filter|n-shot| Metric | |Value| |Stderr| |--------------|-------|------|-----|-----------|---|---|---|------| |mmlu | |none |5 |acc |↑ |0.712|± |0.012 |4.3 故意开启采样配置
接下来我们故意把 temperature 调高,模拟不同评测配置的影响:
python -m lm_eval \ --model hf \ --model_args "pretrained=/data/models/your-model,tokenizer=/data/models/your-model" \ --tasks mmlu \ --num_fewshot 5 \ --batch_size 16 \ --gen_kwargs "temperature=0.8,top_p=0.9,do_sample=true" \ --output_path ./results/sample由于开启采样,每次运行生成的答案可能不同。对于 MMLU 这类“固定答案”任务,只要输出解析方式不变,适当采样不至于让分数从 70 分掉到 30 分。但如果你把自己评测中的提示词模板也换掉,差异就会明显放大。
我们可以做一个更完整的实验:
- 分别记录温度 0.0 和 0.8 的结果;
- 固定提示词模板时,看两个温度之间的分差;
- 再自定义一套不合适的提示词,看是否出现大幅度下降;
这个实验可以帮助团队理解:模型评分到底受哪些变量控制。
4.4 用脚本多次运行并统计波动
手动运行多次会比较麻烦,可以用一个简单脚本批量执行。
下面是一个核心思路示例,不绑定具体框架版本:
#!/usr/bin/env bash for seed in 42 43 44; do python -m lm_eval \ --model hf \ --model_args "pretrained=/data/models/your-model,tokenizer=/data/models/your-model" \ --tasks mmlu \ --num_fewshot 5 \ --batch_size 16 \ --seed $seed \ --output_path ./results/ours_${seed} done注意这里--seed参数不是所有版本都叫这个名字,可能需要换成--seed_everything或直接在配置里指定随机种子。
脚本本身不重要,核心是:重复运行,把结果记录下来。最终报告分数时,不要只抛出一个最高值,而应给出多次运行的均值与波动区间。
4.5 记录评测配置
一次可复现的评测报告,至少应包含一个类似下面的配置快照:
model_name: your-model-name model_path: /data/models/your-model tokenizer_path: /data/models/your-model quantization: none inference_backend: hf decode: do_sample: false temperature: 0.0 top_p: 1.0 top_k: -1 max_new_tokens: 256 task: name: mmlu version: standalone fewshot: 5 fewshot_seed: 42 repeat_times: 3 hardware: 8*A100-80G framework_version: lm-evaluation-harness-0.4.x score: acc_mean: 0.712 acc_min: 0.707 acc_max: 0.716如果你在团队内部复现某个模型,这份 YAML 能让所有人少走很多弯路。
5. 常见问题与排查思路
在跑 LLM 评测时,下面几种情况比较常见。我把它们整理成一个速查表。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 本地复现分数和榜单分数不一致 | 解码参数、提示词模板或少样本种子不同 | 核对所有评测配置,用统一框架重跑 |
| 每次运行分数忽高忽低 | 开启了采样但没有固定随机种子 | temperature 调成 0 或固定 seed,多次运行取均值 |
| 某个模型 MMLU 分数低于公开值 10 分以上 | 评测框架版本不同,或解析逻辑不同 | 先查框架版本,再查是否使用官方的 prompt 模板 |
| 量化模型分数异常低 | 量化精度损坏或任务格式不适配 | 先用全精度模型跑一遍,再对比量化模型 |
| 显存不够导致评测中断 | batch_size 过大或 max_new_tokens 过长 | 降低 batch_size,减少生成长度,换更强后端 |
| 单选题输出“A”却判定错误 | 输出中包含多余格式内容 | 检查解析逻辑,允许模型先输出解释 |
| 不同任务分数趋势矛盾 | 任务难度和模型能力分布不均衡 | 综合多个数据集结果,不要只依赖一个任务 |
如果遇到分数无故偏低,我建议从下面排查清单开始逐项核对。
5.1 排查清单:分数对不上的时候
- 是否已经重新加载模型权重,而不是使用了缓存中的旧结果?
- 是否在同一个 GPU 上运行了多个任务,导致显存不足?
- 是否设置了 do_sample=true 且 temperature=1.0?
- 是否在 prompt 里加入了与数据集不匹配的额外指令?
- 是否修改过数据集的默认模板?
- 是否使用了和模型 tokenizer 不一致的 tokenizer?
- 是否在并行推理时使用了不稳定的随机采样?
多数情况下,排查到前三步就能发现问题。
5.2 如何避免分数波动问题
最稳的方案是:把评测流程固化到仓库中。不管是论文实验还是业务选型,统一使用同一个评测配置,任何人都可以一键复现。
如果有能力,可以把多组配置写入脚本,然后把日志和配置快照一起输出。这样就算结果异常,也能快速追溯是哪个环节引入的偏差。
6. 评测实验设计与工程建议
6.1 明确评测目标:测的是能力还是兼容性
不同的评测目标应该采用不同配置:
- 思考模型上限:用尽量公平的模板、默认确定性解码,多个数据集综合对比。
- 模拟线上业务:需要在模型部署服务上直接评测,temperature 等参数必须与线上正式配置一致。
- 验证模型对提示词的敏感度:在固定模型条件下,刻意变化模板、few-shot、采样参数,观察分数范围。
不要把这三类目标混在一起。否则你得到的分差并不能说明任何问题。
6.2 报告评测配置的黄金指标
在写论文、技术报告或者团队内部汇报时,下面信息必须出现:
- 模型权重来源与 commit 版本;
- 模型加载精度;
- 解码参数;
- 抽样种子;
- few-shot 示例如何选择;
- 提示词模板结构;
- 评测数据集名称和版本;
- 答案解析方式;
- 重复运行次数;
- 运行硬件。
不要嫌内容多。正是因为缺少这些,才导致大量模型分数不可复现。
6.3 用区间代替点估计
排行榜总喜欢给一个精确到小数点后一位的数字。但在了解了评测配置的敏感性之后,我们应该学会用区间表示结果:
模型 A:0.71 ± 0.01 模型 B:0.73 ± 0.02两个模型如果差异小于波动区间,就不应判定为显著差异。这一判断标准在学术论文中尤为重要。
另外,在选择基座模型时,最好测试目标模型在“低配置”和“高配置”下的分数区间。如果区间过大,说明该模型对提示词和采样参数敏感。部署到生产环境前,需要额外设计好提示词和温度参数。
6.4 评测只是手段,不是终点
大模型评测里没有“唯一正确分数”。评测配置相当于一个放大镜:放大镜的倍数不同,看到细节不同,但不代表物体本身在改变。
如果你要评估模型在业务中的价值,最靠谱的不是看它能在某个榜单上排第几,而是用业务真实数据构造一套内部评测集,并把评测配置固定下来。之后每次升级模型、调整提示词,都在同一配置下对比。这样得到的纵向趋势,比公开排行榜上的名次更有可信度。
回到最开始那篇论文的启示:gemma4-31b 在 31% 到 89% 之间的波动,本质上不是模型“能高能低”,而是评测配置这个变量被放大了。未来的大模型评测,应当像传统机器学习实验一样,把数据划分、随机种子、预处理流程全部公开。当所有人都能复现同一个分数时,排行榜上的名次才有真正的参考价值。