Files
my-vault/01_Projects/Personal-Tech/LLM_Evaluation/04-Reference/evaluation-guidebook/04-Troubleshooting.md
T
windyboy 63add96a09 dedupe LLM_Evaluation zone: single-source tables, fix nav orphans, compress guidebook 2025
- Why Guide: remove duplicated 20-case/rubric/test-definition tables, link to
  authoritative Roadmap/Worksheet instead; 10-min action points to entries
- Concept Map / What-Is: cross-link narrative vs quick-reference roles
- Worksheet: annotate sections with authoritative sources
- 04-Reference 01-04 <-> archive/01: bidirectional resource links
- archive/00-Material-List: shrink guidebook listing, now reachable from READMEs
- guidebook: compress 06-Yearly-Dives 2025 section (-> 08-2025-Edition §3),
  add old/new version nav banners to 01-05, reverse links in 08
- README/Start-Here: link Learning Board (was orphaned)
2026-08-21 17:25:12 +08:00

28 KiB
Raw Blame History

type, tags, status, created, source
type tags status created source
reference
llm-evaluation
evaluation-guidebook
troubleshooting
active 2026-08-21 https://github.com/huggingface/evaluation-guidebook

Troubleshooting(排错)

本页提炼自 HuggingFace LLM Evaluation GuidebookTroubleshooting 章节(共三小节:推理排错、LaTeX 数学解析、可复现性排错)。这是整本指南中最实操的部分——当评测跑不起来、跑得慢、分数对不上时,先查这里。文内 标记为作者特别推荐的资源。

⚠️ 旧版内容2024 GitHub 仓库)。新版仅保留「可复现性排错」章节(与旧版基本一致,见 08-2025-Edition §7 的复现提示与 §5.6 Normalization / Math-Verify);推理排错与 LaTeX 解析独立页已从新版删除,本节作为旧版独有实操细节保留。

本节速览(TL;DR

症状 / 诉求 第一反应 详见
评测跑得太慢 增大 batch size → 数据并行 → 换推理库 → 降精度 §1.1
模型太大放不进 GPU 量化 → 模型并行(pipeline / tensor)→ CPU offloading §1.2
装得下却 OOM 怀疑 context size,用 dummy 数据测试 §1.3
数学评测分数异常偏低 检查 LaTeX 解析器(sympy 自洽只有 0.94) §2
复现不出论文分数 逐项对齐:代码库 / seed / 指标 / normalization / prompt / 生成参数 / 加载方式 §3

贯穿全章的三条核心心法:① 评测工具链本身也是被测对象——解析器、normalization、指标实现都会系统性改变分数;② 评测不只是"模型回答问题",而是"在特定环境里跑特定管道"——环境细节决定一切;③ 想对比两个分数,先确认它们是不是用同一套管道算出来的。

1 推理排错(Troubleshooting Inference

评测中跑模型推理会遇到三类典型问题:(内存装不下)、以及装得下却 OOM。本节逐一给出排查思路。先给一张按症状定位的速查表:

症状 直接原因 对策 代价 / 注意
推理慢 batch size 太小 增大 batch size 破坏绝对可复现性
推理慢 只用了单张 GPU 数据并行(多 GPU 需同节点,避免节点间瓶颈
推理慢 推理库实现不够优化 换更快推理库 / 参考优化清单 需要实测
推理慢 精度过高 降到 bfloat16/float16,或 8bit/4bit 量化 精度损失,部分量化库本身偏慢
模型太大 精度过高 量化 中规模模型建议停在 float16/8bit
模型太大 单卡放不下 模型并行 / CPU offloading 并行较难编码;offloading 显著更慢
装得下却 OOM context size 过大 dummy 测试 + 降 batch + 逆序呈现样本 让失败尽早暴露

1.1 模型太慢怎么办

① 修改 batch size

  • 如果你追求绝对可复现(给定特定硬件与特定评测 prompt),通常只能用 batch size = 1。
  • 但只要内存放得下,调大 batch size 几乎必然显著加速评测——这是最简单的提速手段。

② 数据并行(data parallelism

  • 思路:把模型复制到多张 GPU 上(而不是只加载到一张卡),把数据切成子集分给每张卡的副本,各自计算后再聚合结果
  • 效果:多条数据流同时被处理,总执行时间约除以 GPU 数量
  • 注意:尽量让所有 GPU 在**同一个节点(node)**上,避免节点间通信成为瓶颈(inter-node bottleneck)。

③ 更换推理代码

  • 不是所有推理库速度都一样,有些实现优化得更好,需要针对你的用例实测对比
  • 如果使用 PyTorch,作者推荐参考 PyTorch 模型推理性能优化清单

④ 降低精度(precision

  • float32 每个数占 32 bit,计算精确但内存与算力开销都大
  • 降到 bfloat16 / float16(一半精度),速度约翻倍,精度损失几乎可以忽略。
  • 想进一步提速可量化到 8 bit 或 4 bit(例如用 gptqbitsandbytes),n-bit 矩阵计算更快、模型占内存更少。
  • ⚠️ 某些量化库本身可能偏慢,需要针对你的场景实测。

贯穿 1.1 的原则:以上手段不是二选一的单选题,而是可以叠加的组合拳(如"大 batch + 数据并行 + bfloat16"),且提速效果必须在你的硬件与任务上实测确认——作者多次强调"test things out for your use cases"。

1.2 模型太大(GPU 装不下)怎么办

估算内存需求

用如下公式估算加载模型所需的最小理论内存

<memory (in GB)> = <number of parameters (in G)> × <precision factor>

原理:1 Byte = 8 bit,总内存 ≈ 参数量 × 每个参数占用的 Byte 数。precision factor 取值:

精度 precision factor
float32 4
float16 / bfloat16 2
8 bit 量化 1
4 bit 量化 0.5

更稳妥的推荐公式(留出推理时的 batch 等额外开销):

<memory (in GB)> = <number of parameters (in G)> × (<precision factor> × 110%)

示例估算(用推荐公式 参数(G) × factor × 110%,取 7B 与 70B 两个常见规模):

模型规模 float32 float16/bfloat16 8 bit 4 bit
7B 7×4×1.1 ≈ 30.8 GB 7×2×1.1 ≈ 15.4 GB 7×1×1.1 ≈ 7.7 GB 7×0.5×1.1 ≈ 3.9 GB
70B 70×4×1.1 ≈ 308 GB 70×2×1.1 ≈ 154 GB 70×1×1.1 ≈ 77 GB 70×0.5×1.1 ≈ 38.5 GB

由此可快速判断硬件选型:单张 80GB 的 GPU 要跑 70B 模型,float16154GB)不行,需要 8bit(77GB,一张卡勉强)或 4bit 量化 / 模型并行;而 7B 模型在 float16 下单张 16–24GB 的消费级卡即可胜任。

① 量化(quantization

  • 最直接的手段:调小上面的 precision factor。从 float324 bit,内存需求直接缩小 8 倍
  • ⚠️ 精度过低会损害评测结果。对中规模模型建议保守停在 float16 或 8 bit。
  • 经验观察:量化对超大模型的性能影响反而较小(可能因为存在信息冗余)。

② 模型并行(model parallelism

把模型切成小块,分别加载/运行在不同的 GPU 上;因为从不一次性加载完整模型,所以省内存,但可能更慢。两种主要类型:

类型 切分粒度 机制 代价 / 特点
Pipeline parallelism(流水线并行) 整层(layer)级别 按层分派到不同 GPU,层 1 输出是层 2 输入 GPU 会空转等待,产生所谓 "bubble";把输入拆成更小的 batch 可缓解 bubble;需要 GPU 间传输数据
Tensor parallelism(张量并行) 矩阵计算级别 把矩阵按行/列切开,各 GPU 算完再聚合 只要 GPU 都在同一节点就极其高效(避免节点间网络瓶颈),但难以编码
  • Pipeline parallelism 正被原生加入 PyTorch 的 PiPPy 库,也是 accelerate 底层使用的并行方式。
  • Tensor parallelism 在 vllm 库中有很好的实现,作者形容其带来 "insane speedups"(惊人的加速)
  • 各类并行(含用于提速的 data parallelism)的最佳参考文档:Transformers 官方并行文档

③ CPU offloading

  • 把部分计算和模型参数挪到 CPU,以降低 GPU 显存占用。
  • ⚠️ 比上面任何方法都慢得多——因为要持续在设备之间搬运数据。
  • 典型实现:DeepSpeed 的 ZeRO-Offload(在 ZeRO-2 优化之上):优化阶段的梯度、optimizer states、fp32 参数计算放 CPUGPU 上保留 fp16 参数与前向/反向传播,以"用 CPU 内存 + GPU 算力、最小化通信"为设计目标。

1.3 模型装得下,但还是 OOM

大概率是 context size(上下文长度) 的问题——显存峰值往往由"batch size × 序列长度"决定,模型权重本身反而放得下。作者建议:

  1. 先用虚拟推理数据(dummy inference data)测试模型是否真的放得下;虚拟数据要使用足够大、能代表你任务的 context size。
  2. 降低 batch size;如果你开了 auto-batch size search(自动搜索 batch size),考虑关掉——它可能导致意外的 OOM。
  3. 一般性原则:让样本按 context size 逆序(从大到小)呈现给模型——这样如果 context 太大,会一开始就立刻失败,而不是跑了几小时后才崩。

2 数学能力评测中的 LaTeX 解析问题(MATH & sympy

📌 新版(2025 Space)更新:新版指南把 LaTeX 解析问题并入「Designing your automatic evaluation」的 Normalization 小节,并推荐使用专门的数学解析库 Math-Verify(替代 sympy 手工解析/字符串比较,见 08-2025-Edition §5)。下方记录的是旧版(sympy)的探索过程与教训,仍有参考价值。

2.1 问题背景

  • 解析 LaTeX 非常困难。当评测任务期望模型输出 LaTeX 时(典型如 MATH benchmark,它用 LaTeX 表示数学计算与符号),问题就来了。
  • 评测这类任务本应只是"解析并比较 ground truth 与模型输出",但实际上不存在"正确"的 LaTeX 解析方式sympy 文档自己也这么说)。

2.2 sympy 的局限:0.94 的自洽准确率

  • lm-evaluation-harness 使用 sympy(Python 符号数学库)解析 LaTeX 并比较表达式。
  • 残酷的事实:即使用 ground truth 去解析 ground truth 本身(自己和自己比),sympy 也只有约 0.94 的准确率
  • 原因:sympy 无法解析一部分本身正确的 LaTeX 表达式。
  • 这个"用 ground truth 自比"的测试本质是一个解析器健全性检查(round-trip test:它排除了模型因素,单独测量解析管道的上限。0.94 意味着即使模型 100% 输出正确答案,评测系统也会因解析失败丢掉约 6% 的分数——解析器成了评测误差的主要来源之一。

2.3 典型报错示例

以下三个示例中,sympy 都因语法问题拒绝了正确的 LaTeX:

例 1:半开区间 [0,1)interval

couldn't parse one of [0,1) or [0,1), I expected one of these: ']'
[0,1)
~~^

例 2:并集 \cup 与无穷 \infty(此处写作 \iny

couldn't parse one of (-\iny,-5]\cup[5,\iny) or (-\iny,-5]\cup[5,\iny), I expected something else here
(-\iny,-5]\cup[5,\iny)
~~~~~~^

例 3:分数中的空分组 \frac{1}{{}2x}

couldn't parse one of -\frac{1}{{}2x} or -\frac{1}{{}2x}, I don't understand this
-\frac{1}{{}2x}
~~~~~~~~~~~^

小结:把上述失败归纳成三类典型盲区——

失败类别 报错示例 原因
区间表示(interval [0,1) 半开区间 [/) 混用,sympy 期待 ] 之类的闭合符号
集合运算与特殊符号 (-\iny,-5]\cup[5,\iny) \cup(并集)等集合运算符、\infty(示例中写作 \iny)不被支持
多余分组 -\frac{1}{{}2x} 分子/分母里的空分组 {} 导致语法不识别

三类都是合法、正确的 LaTeX,却会被解析器拒绝——这正是"解析器不是标准答案"的实证。

2.4 怎么绕过

两条路:

  1. 重写 LaTeX grammar:向 sympy 的 LaTeX 语法文件 latex.lark 添加所需特性(为解析器增加新规则)。
  2. 在代码里加手动检查:为模型输出增加字符串比较等后处理兜底。

作者的选择:在几乎掉进"重写 grammar"这个深坑之后,决定只给代码加上字符串比较(string comparison)检查就足够了——即对 lm-evaluation-harness 打一个修复补丁(见原文附图中的 LM Eval Harness fix)。

为什么选"字符串比较"而不是"重写 grammar"?重写 parser grammar 是个无底洞:LaTeX 语法变体无穷无尽(区间、集合、特殊符号、各种分组写法),每补一个规则都可能引入新冲突,维护成本高。而字符串比较实现简单、可立刻生效——解析失败时退而求其次做规范化后的字符串比对,足以覆盖评测场景中大多数"模型其实答对了"的情况。对评测工程而言,够用、可维护,比理论上完美更重要。

2.5 修复效果:MATH 上旧/新解析器对比

修复后对 MATH benchmark 前 25 个模型的分数(原始解析器 vs 修复后解析器)对比如下(分数列为 0–100;"提升"为两列差值):

模型 原始 修复后 提升 排名变化
rombodawg/Rombos-LLM-V2.5-Qwen-72b 47.58 50.68 +3.10 1 → 1
MaziyarPanahi/calme-2.2-qwen2-72b 41.16 43.43 +2.27 2 → 2
arcee-ai/Arcee-Nova 40.48 42.90 +2.42 3 → 3
fblgit/TheBeagle-v2beta-32B-MGS 39.43 42.52 +3.09 4 → 4
rombodawg/Rombos-LLM-V2.5-Qwen-32b 39.12 41.99 +2.87 5 → 5
dnhkng/RYS-XLarge 38.97 41.24 +2.27 6 → 6
dfurman/CalmeRys-78B-Orpo-v0.1 37.92 40.71 +2.79 8 → 7
MaziyarPanahi/calme-2.2-rys-78b 37.92 39.95 +2.03 8 → 9
MaziyarPanahi/calme-2.4-rys-78b 37.69 40.41 +2.72 9 → 8
MaziyarPanahi/calme-2.3-rys-78b 36.56 38.97 +2.41 10 → 10
MaziyarPanahi/calme-2.1-rys-78b 36.40 38.90 +2.50 11 → 11
Qwen/Qwen2.5-72B 36.10 38.67 +2.57 12 → 12
MaziyarPanahi/calme-2.1-qwen2-72b 36.03 38.07 +2.04 13 → 15
Qwen/Qwen2-Math-72B-Instruct 35.95 38.14 +2.19 14 → 14
dfurman/Qwen2-72B-Orpo-v0.1 35.42 38.14 +2.72 15 → 13
abacusai/Smaug-Qwen2-72B-Instruct 35.35 37.46 +2.11 16 → 19
anthracite-org/magnum-v1-72b 35.27 37.69 +2.42 18 → 16
alpindale/magnum-72b-v1 35.27 37.69 +2.42 18 → 16
Qwen/Qwen2-72B-Instruct 35.12 37.69 +2.57 19 → 18
dnhkng/RYS-XLarge-base 34.67 37.16 +2.49 20 → 20
Undi95/MG-FinalMix-72B 33.61 36.10 +2.49 22 → 21
abacusai/Dracarys-72B-Instruct 33.61 35.65 +2.04 22 → 22
Qwen/Qwen2.5-32B 32.85 35.50 +2.65 23 → 23
anthracite-org/magnum-v2-72b 31.65 34.06 +2.41 24 → 24
dnhkng/RYS-Huge-bnb-4bit 31.57 33.84 +2.27 25 → 25

关键观察

  • 所有模型的分数都提升了约 23 分(最低 +2.03,最高 +3.10)——这个量级的差距足以改变一个模型的"好不好"结论,说明解析器(而非模型)曾经拖累了大量分数。
  • 排名大体稳定,但个别模型有 ±1~3 位的变化(如 Smaug-Qwen2-72B-Instruct 从 16 掉到 19Qwen2-72B-Orpo-v0.1 从 15 升到 13)——若按排名做基准对比,解析差异会改变排行榜序

为什么分数整体平移、排名却会变? 解析器对每个模型的"扣分"并不均匀:模型 A 输出的 LaTeX 恰好多是 sympy 的盲区(区间、集合、多余分组),被多扣;模型 B 的输出风格恰好全被解析,少扣。所以修复解析器后,被多扣的模型分数抬升更多,相对位置就动了。结论:解析器不只是"对所有人一视同仁的常量误差",它还可能掩盖模型之间的真实差距。

引申教训:评测指标管道(metric pipeline)本身也是被测对象的一部分。解析器、normalization、后处理的实现差异会系统性抬高/压低某些模型的分数。

3 可复现性排错(Troubleshooting Reproducibility

场景:你读了某篇最新技术报告,想在本地复现它的分数,却复现不出来?以下是作者拆解的原因清单。

3.1 不同的代码库(code base

  • 要复现到小数点,第一步是使用与论文完全相同的代码库
  • 通常意味着:用作者提供的评测默认代码,或用参考库中的标准实现——如 Eleuther AI 的 lm_eval、HuggingFace 的 lighteval。这两个库是社区事实上的"标准管道":lm_eval(EleutherAI)是使用最广的评测框架,lightevalHuggingFace)由 Open LLM Leaderboard 团队维护——用它们,等于和其他人共用同一套任务定义与指标实现,这是复现的前提。
  • 如果论文没提供评测代码:几乎不可能精确复现,只能放弃精确比对。
  • 想直观理解不同实现带来的差异,读作者团队写的这篇博客:MMLU 在不同评测实现下的差异——它研究了 MMLU 在 lm_evalhelm 与原始作者实现三种版本下的分数差异。
  • 背景:正因为如此,HuggingFace 团队才发起 Open LLM Leaderboard,用统一、同质的评测来做模型间的横向比较。

3.2 同一代码库内也容易踩的坑

即使代码库相同,以下细节也容易出错:

① 不同的随机种子(random seed

  • 推理受 seed 影响通常比训练小,但仍可能影响:
    • 部分 CUDA 操作(参考 PyTorch 可复现性文档);
    • 非 greedy 生成策略下的预测结果;
    • 使用 few-shot 时的 prompt 内容(抽样选出哪些示例);
    • 某些前处理 / 后处理函数
  • 一个小 seed 差异就可能带来几分之差

② 同名但实际不同的指标(metric)

指标名相同 ≠ 计算方式相同,例如:

  • log likelihood 版 exact match(计算不同候选答案的对数概率) vs 生成式 exact match(只把 greedy 生成与参考答案比较)——两者分数完全不同。
  • 代码库里不少任务名叫 exact match,实际却是:
    • prefix exact match(只比生成的开头与参考);
    • suffix exact match(反过来,只比结尾);
    • quasi exact match(带 normalization 的 exact match)。
  • 结论:不能只靠指标名判断评测做了什么,必须看代码。

③ 不同的 normalization

  • 回到上面生成式 exact match 的例子:lm_eval v1 中不少任务只叫 generative exact match,你会以为预测是"原样与参考比较";但看代码会发现预测先经过 normalization(去标点、数字同质化等)再比较——这会大幅改变结果
  • lm_eval v2 已把 normalization 的名字写进大多数指标名
  • 这是最容易被搞砸的点,尤其对需要大量 normalization / 答案后处理的任务,比如数学评测(需要从模型生成的解释里抽取最终答案再比较)。

3.3 不同的 prompt

prompt 变化有三个来源。

① prompt 本身(格式)

prompt 格式对分数的影响巨大。以多选题为例,仅呈现选项的格式就有多种"语义等价"的变体:

Question: <text of the question>
Choices:
| A. <Choice A> | (A) <Choice A> | <Choice A> | 
| B. <Choice B> | (B) <Choice B> | <Choice B> | 
| C. <Choice C> | (C) <Choice C> | <Choice C> | 
| D. <Choice D> | (D) <Choice D> | <Choice D> | 
Answer: 

并要求模型预测 A/B/C/D,或直接输出 <Choice A/B/C/D> 的完整文本。

  • 这些 prompt 语义等价(内容完全相同),但对同一模型仍可能差好几分
    • 作者团队实验(原帖)观察到同一模型最高差 7 分
    • 相关论文也观察到了类似结果。
  • 有些任务还会带任务前缀 prompt(如 The following questions are about <topic>),其有无也会影响分数。
  • 这篇论文还揭示一个副作用:不少模型被训练成"过拟合基准的 prompt 与答案格式",代价是在评测时对其他 prompt 的适应能力下降。
  • 实例(Open LLM Leaderboard 2 上的 Llama3.1):这些模型在 MATH-Hard 评测中能预测出正确答案,分数却很低——因为它们过拟合了 GSM8K(另一个数学评测)的 prompt 与答案格式,无法适配 few-shot 中提供的模板。

② system prompt 与 chat template

  • Chat 模型通常经过指令/偏好训练(instruction/preference training 或 fine-tuning),这个阶段它们学会了遵循特定模板推理。
  • 常见模板要素:
    • 每轮对话以system prompt 开头(通常以特定 token 前缀,如 System: ),用于给模型高层指令(人设、回答风格等);
    • 对话轮次给文本加前缀关键词,如 User(提问)与 Assistant(回答)。
  • 使用 few-shot 时还要决定:示例按多轮(multi-turn,模拟 user/assistant 轮次)提供,还是一次性放在单条 user prompt 里
  • ⚠️ 不遵循模型期望的 chat template,会严重损害性能——因为它把模型输出推向其已收敛的概率空间之外。

③ few-shot 样本

  • 显然要用与参考任务相同的 few-shot 数量
  • 还要用完全相同的样本——不同样本会改变结果(这不太意外:有些样本更能表达任务)。
  • 更反直觉的一点:样本完全相同还不够,顺序也必须完全相同。作者团队观察到:同样的样本仅改变顺序,在 MMLU 的某些子集上最多差 3 分结果见这里,第三个 colorgrid)。
  • 因此这里同样要注意随机种子

3.4 不同的生成参数(generation parameters

对生成式评测,需要对齐:

  • 使用相同的 end of sentence tokenEOS token
  • 允许模型生成相同数量的 token
  • 如果使用 sampling,确保相同的 seed / temperature 参数

3.5 不同的模型加载(model loading

已观察到的差异来源:

来源 说明
不同硬件 PyTorch 不保证非确定性操作在不同硬件上可复现
不同推理库 例如用 transformers 还是 vllm 作为推理后端,矩阵计算的实现方式并不完全相同
不同 batch size 多个评测库与模型后端都有文档记录:batch size 不同会改变推理结果;要完全可复现就固定 batch size(虽然内存受限时不一定总能做到)
不同加载精度 用更低精度加载权重可省内存与推理成本,但用的是不同版本的权重,数值结果必然改变

排查复现问题时的总思路:从"最可能、最容易改"的项开始逐项对齐——先核对 prompt 与 few-shot(改动最频繁、影响最直接),再查指标与 normalization(需要看代码确认),最后核对生成参数与加载方式(涉及硬件环境)。每锁定一项就重跑一次对比,通常很快能找到分差来源。

3.6 可复现性检查清单(速查)

综合 3.1–3.5,复现一份评测分数前逐项核对(任一项不满足,分数就可能对不上):

  • 使用与参考完全相同的代码库/评测框架lm_eval / lighteval / 作者实现)
  • 相同随机种子(尤其非 greedy 生成、few-shot 抽样)
  • 相同的指标定义log-likelihood vs generative、prefix/suffix/quasi exact match,看代码确认)
  • 相同的 normalization / 后处理(数学评测尤其注意答案抽取)
  • 相同的 prompt 格式、system prompt、chat template(多轮 vs 单次 few-shot
  • 相同的 few-shot 数量、样本与顺序
  • 相同的生成参数EOS token、max tokens、seed / temperature
  • 相同的硬件、推理库、batch size、加载精度

核心要点(一句话版)

  1. 提速四杠杆(按性价比排序):调大 batch size → 数据并行 → 换更快推理库 → 降精度(bfloat16/float16 → 8bit/4bit 量化)。
  2. 内存估算memory(GB) = 参数(G) × precision factor × 110%factor 为 float32=4、float16/bfloat16=2、8bit=1、4bit=0.5。
  3. 放不下时:先量化(最多省 8 倍内存),再模型并行(pipeline 慢在 bubble、tensor 慢在难编码但同节点极快),CPU offloading 是最后手段(显著更慢)。
  4. 装得下却 OOM:八成是 context size 问题——用大 context 的 dummy 数据先测、降 batch、样本按 context 逆序呈现让失败提前暴露。
  5. 数学评测的 LaTeX 解析没有标准答案lm-evaluation-harness 用的 sympy 连 ground truth 自比都只有约 0.94 准确率;别去重写 grammar,加字符串比较兜底就够(修复后 25 个模型 MATH 分数全部 +2~3 分)。
  6. 复现不出分数 = 某个环境细节没对齐:代码库、随机种子、指标真实定义(prefix/suffix/quasi exact match)、normalization、prompt 格式与 chat template、few-shot 的数量/样本/顺序(顺序变化最多差 3 分)、生成参数(EOS、max tokens、seed/temperature)、硬件/推理库/batch size/加载精度——每一项都可能差几分。
  7. 最容易被低估的两处:① 同名指标的实现差异(必须看代码,别信名字);② prompt 格式的微小变化——语义等价也能差 7 分,还有模型专门过拟合基准 prompt 格式,换格式分数暴跌。
  8. 工具取向:优先使用维护中的标准框架(lm_eval v2、lighteval),因为它们把 normalization 等细节暴露在指标名里,减少"实现悄悄不同"的踩坑概率;升级框架版本时,也要顺手核对指标定义是否变化。

参考资料

原文(GitHub 仓库)

文中引用的外部链接