ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LLM评测配置如何影响排行榜分数?从原理到lm-eval实践

LLM评测配置如何影响排行榜分数?从原理到lm-eval实践 如果你关注过开源 LLM 排行榜应该会发现一个让人困惑的现象某个模型今天排在榜单前几过两周却跌出第一梯队同一个模型在不同榜单上的分数能差十几个百分点。最近一篇论文把这个现象推向了一个更极端的结论LLM 排行榜的名次很大程度由评测配置决定而不是只由模型真实能力决定。论文标题里特别提到gemma4-31b 这个量级的模型在改变评测配置后得分可以在 31% 到 89% 之间大幅波动。这个结论听起来很夸张但它并不是在说模型突然变强了或变弱了而是在提醒我们评测配置本身会影响模型被观测到的能力。换句话说当一份榜单把某模型排到第一时我们要问的不仅是“它真的更强吗”还要问“用什么数据集、什么 prompt、什么解码方式评测出来的”。本文会围绕 LLM 评测配置这条主线展开适合正在做模型选型的算法工程师、需要搭建评测流程的后端开发者以及关注大模型基准测试的学生开发者。读完你会理解LLM 排行榜的评测流程由哪些环节构成哪些“不起眼”的配置能让同一模型的分数发生巨大漂移论文中提到的评测敏感性问题在现代评测框架中如何体现如何用 lm-evaluation-harness 这类工具搭建可复现评测记录足够的评测元信息面对 LLM 排行榜时怎么判断分数差是否可信。1. 背景与核心概念为什么评测配置会“决定”排行榜名次1.1 什么是 LLM 排行榜与评测配置LLM 排行榜本质上是“用统一评测脚本在同一批任务上比较不同模型”。常见的排行榜包括 Hugging Face Open LLM Leaderboard、LMSYS Chatbot Arena、SuperCLUE、C-Eval 等。它们通常选择一批公开数据集如 MMLU、ARC、HellaSwag、TruthfulQA、GSM8K再通过推理、算分、汇总得到每个模型的总分或单项分。评测配置就是“模型在评测过程中被如何调用、结果如何打分”的全部参数总和。它不只是“跑一下脚本”这么简单至少包括配置维度示例任务选择MMLU、ARC、GSM8K、BBH提示词模板“请选择正确的答案” 或 “Answer the following question.”few-shot 示例0-shot、5-shot、示例怎么选、按什么顺序排解码参数temperature、top_p、max_new_tokens、是否 greedy答案提取方式正则提取 A/B/C/D或计算选项 token 的 logprob评分指标exact match、normalized accuracy、passk上下文长度prompt 是否被截断、截断哪一端这些配置在论文或榜单说明中通常只有一行比如“MMLU 5-shot”。但正是这些配置叠加起来可以让一个中等规模的模型从“不及格”变成“优秀”。1.2 论文的核心结论评测不是中性测量工具论文标题中的例子——gemma4-31b 得分在 31% 到 89% 间波动——是评测敏感性的一种极端表现。从作者的角度看他们并不是随机挑一个弱模型去改温度而是系统性地改变评测协议中的若干项例如切换 few-shot 的示例集改变任务指令的语言风格从“让模型生成完整答案”换成“比较每个选项的 logprob”调整输出截断长度更换数据集中某些样本的题干顺序。每一项改动都可能带来 1 到 10 个百分点的变化。如果把这几个因素叠加模型的分数上限和下限之间自然会出现极其夸张的鸿沟。论文所呼吁的是评测社区要建立“配置透明、可复现”的评测规范否则榜单会被无意或有意的配置选择所操纵。论文本身并不是在否定 LLM 的能力评估而是在给“评测”这一动作做元研究你如何评测决定了你看到什么结果。2. 评测链路拆解从模型加载到最终分数经历了什么要理解为什么评测配置的影响如此之大先把一次模型评测拆成几个阶段会很有帮助。2.1 任务定义层任务定义层决定“模型要完成什么”。LLM 评测通常不会让模型像人在考试一样自由答题而是封装成自动可判分的形式。常见任务类型有多项选择如 MMLU给一个题干和 A/B/C/D 选项要求模型给出正确项文本生成后匹配如生成一个数字再和标准答案比较复杂推理如 GSM8K需要中间步骤文本相似度或信息检索如需要比较生成文本与参考答案的语义相似度。不同任务天然对评测配置的敏感度不同。选择题比较容易受 prompt 模板影响因为模型可能对“选项序号是否带括号”“题目开头是否加 category 描述”非常敏感而生成题更容易受解码参数影响比如温度升高可能让结果更发散。2.2 模型运行层模型运行层是配置最密集的区域加载模型时使用什么精度fp16、bf16、int8、int4推理时是否使用 vLLM、TensorRT-LLM 等加速引擎解码策略greedy、beam search、sample温度与 top_p是否允许模型输出很长的 CoT 内容上下文窗口长度超出后是截断还是报错模型是否支持 system prompt评测框架有没有预设 system prompt。同一模型在这些参数下会表现出不同的行为。例如 temperature0.7 时模型会在多个候选词之间随机采样。如果一个评测只跑一次那么分数就带有随机性如果跑 5 次取平均分数会稳定一些但也可能因为采样空间太大而下降。很多排行榜为了稳定性使用 greedy decoding也就是温度设为 0 或关闭 sampling但它也会低估模型在“真实开放问答”中的表现。2.3 答案提取与打分层评测不像人改卷那样智能它需要用代码把模型输出变成可见分。这一层包括是否用正则从模型输出中找 “A/B/C/D”是否要求模型输出严格 JSON 或只输出答案是否对选项 token 计算概率总和而不是让模型生成下一 token是否使用 flexible-extract例如去掉标点、小写化后再匹配如果模型在答案后追加解释判分器是取第一个字母还是最后一个答案。学术界现在更推荐“logprob 打分”。做法是把题干和四个选项拼接成四段文本分别计算每个选项 token 的对数概率之和取最高的一项作为预测答案。这种方式能避免“模型明明知道答案却因为输出格式不对被判 0 分”的尴尬同时也会显著改变分数大小。当任务定义、模型运行、答案提取三个阶段的选择发生变化最终分数自然会有巨大差异。3. 为什么这些配置足以让排行榜“洗牌”下面重点分析几个影响幅度大、且实际评测时容易被忽视的配置项。3.1 few-shot 示例数量与顺序MMLU 等数据集默认是 5-shot也就是在正式问题前放 5 道带答案的示例。示例的作用是帮模型理解任务格式。0-shot 时模型可能不知道输出格式5-shot 时格式信息被示例强化分数通常更好。但这里有个隐藏问题示例并不一定是“等价的”。从同一个题库中随机抽取 5 道示例跑出的分数可能差 3~5 个百分点。示例的顺序也有影响比如把最难的一道放最后模型可能被带偏。如果某些示例恰好和待测问题来自同一学科模型更容易“照猫画虎”。部分评测工具为了公平会固定使用某个 offset 或某个固定的随机种子。所以同一模型在不同工具里跑 MMLU 会得到不同分数这是常见原因之一。3.2 Prompt 模板与答案格式这里先看一个极简例子。同样是 MMLU 风格的问题下面三种模板可能让同一模型给出不同结果模板A Question: What is the capital of France? A. Berlin B. Madrid C. Paris D. Rome Answer:模板B The following is a geography question. Please answer with the correct option letter. Q: What is the capital of France? Options: A. Berlin B. Madrid C. Paris D. Rome Correct option:模板C |system| You are a helpful assistant./|system| |user| What is the capital of France? Choose from A-D./|user| |assistant|不同指令微调模型对格式的偏好不一样。有的模型在模板 A 下已经学会“直接输出选项字母”有的模型只有在模板 B 的显式指令下才输出正确答案还有的模型会因为 system prompt 的不同而改变回答风格。评测如果只使用其中某一套模板相当于在暗中惩罚那些“不擅长该模板”的模型。在实际复现论文结果时可能出现同型号的两个模型权重几乎一样只因使用了不同的 prompt 模板最终在某个任务上相差 10 个百分点以上。3.3 解码策略与随机性排行榜通常使用 greedy decoding保证相同输入得到相同输出。但它有两个问题对某些模型来说贪婪搜索容易陷入重复如果模型的真实能力需要采样才能发挥那么 greedy 会低估它。如果评测脚本改成 temperature0.7、top_p0.9 并做一次采样结果会受随机种子影响。同一个 40B 模型同一道题第一次采样可能对了第二次采样可能错了。如果评测任务只有几百道题随机波动可能带来 2~5 个百分点的差距。如果做多次采样再投票例如生成 5 次取最常见答案模型分数通常会上涨。这种改进更多来自自一致性而不是模型权重发生变化。因此我们不能把不同采样策略下的分数直接对比。3.4 答案提取与 logprob 计算答案提取是分数变化最隐蔽的来源之一。下面是一个常见情况。模型实际输出The correct answer is C. Paris is the capital of France.如果评测脚本使用正则[A-D]去匹配可能匹配到 C判定正确。但如果脚本要求“严格只输出一个字母”这段输出会被判为格式错误。如果脚本把最后一个 A/B/C/D 作为答案并且模型在解释里又提到了 A那么即使本来选 C也可能被误判。为了避免解析问题很多库会采用 logprob 法。它对四个选项分别计算概率不依赖自由生成。但 logprob 法也有配置差异是否考虑 token 级加和、是否归一化 token 数量、是否加入空格前缀。举例来说选项C可能被 tokenizer 拆成带空格或不带空格的 token导致logprobs计算出现偏差。3.5 输入截断、tokenizer 与数据污染当评测任务上下文很长时评测框架会截断输入。截断策略不同可能丢掉开头特征或末尾指令。模型看到的内容发生变化分数也会发生变化。另外不同模型使用不同 tokenizer。同一个英文词可以被拆成 1 个 token 或 3 个 token这会直接影响 logprob 计算时的长度归一化。如果两个模型词表差异大直接用原始 token 概率比较会存在不公平。数据污染问题更严重。某些模型的训练语料中已经包含 MMLU 等评测集题目。当示例、题目被模型记忆后分数会虚高。论文中之所以强调“排行榜很大程度上由评测配置决定”其中一个潜在因素就是评测集污染很难被完全识别污染程度不同会让成绩失真。4. 复现实验用同一模型在不同评测配置下测试 MMLU前面讲的都是理论下面用开源评测工具 lm-evaluation-harness 做一组简要实验观察同一模型在不同配置下的分数变化。为了控制时间和资源我们选择一个小模型例如 Qwen2.5-0.5B-Instruct。这个模型不足以复现 31% 到 89% 的极端差异但可以清楚展示 few-shot、模板和解码参数对分数的影响。4.1 环境准备建议在 Linux 环境Python 3.10 以上。安装 lm-evaluation-harness。pip install lm-eval验证安装python -c import lm_eval; print(lm_eval.__version__)不同版本的 lm-eval 参数会有差异。如果输出报错请参考官方仓库最新文档调整参数名。4.2 实验 A固定模板下改变 few-shot 数量先跑 0-shot MMLU。命令如下lm_eval --model hf \ --model_args pretrainedQwen/Qwen2.5-0.5B-Instruct,trust_remote_codeTrue \ --tasks mmlu \ --num_fewshot 0 \ --batch_size auto \ --output_path results/mmlu_0shot再跑 5-shotlm_eval --model hf \ --model_args pretrainedQwen/Qwen2.5-0.5B-Instruct,trust_remote_codeTrue \ --tasks mmlu \ --num_fewshot 5 \ --batch_size auto \ --output_path results/mmlu_5shot在这个阶段你会看到同一个 checkpoint 的 MMLU 分数发生变化。对一个 0.5B 模型来说5-shot 通常会比 0-shot 高 3~8 个百分点。原因不是模型在 5-shot 时“学到”了知识而是示例帮助模型稳定了输出格式。4.3 实验 B固定 few-shot 下改变 prompt 模板lm-evaluation-harness 中任务自带的 prompt 模板通常由 YAML 文件定义。要自定义模板可以写一个 task YAML然后通过--tasks指向它。下面是最小示例重点是示意不一定适用所有版本# 文件路径tasks/my_mmlu.yaml task: my_mmlu tag: - my_benchmark dataset_path: cais/mmlu dataset_name: all output_type: multiple_choice training_split: auxiliary_train validation_split: validation doc_to_text: Question: {{question}}\n\nOptions:\nA. {{choices[0]}}\nB. {{choices[1]}}\nC. {{choices[2]}}\nD. {{choices[3]}}\n\nAnswer: doc_to_target: {{answer}} metric_list: - metric: acc运行lm_eval --model hf \ --model_args pretrainedQwen/Qwen2.5-0.5B-Instruct \ --tasks my_mmlu \ --num_fewshot 5 \ --batch_size auto \ --output_path results/my_mmlu_template把doc_to_text改成doc_to_text: 你是一个善于回答选择题的助手。请根据题目选择一个正确选项只输出A、B、C或D。\n\n问题{{question}}\nA. {{choices[0]}}\nB. {{choices[1]}}\nC. {{choices[2]}}\nD. {{choices[3]}}。\n答案再跑一次观察分数变化。对中文指令模板和英文指令模板模型可能表现出明显差异。这里要特别解释lm-eval 的 YAML 需要遵循特定格式。不同版本字段略有不同建议先跑示例任务再逐步改成自己的模板。4.4 实验 C采样参数与多数投票使用 Python API 可以更方便地控制采样参数。核心思路如下# 文件路径eval_with_sampling.py from lm_eval import simple_evaluate from lm_eval.models.huggingface import HFLM from lm_eval.tasks import get_task_dict model HFLM( pretrainedQwen/Qwen2.5-0.5B-Instruct, batch_sizeauto, ) # 第一次采样 results_1 simple_evaluate( modelmodel, tasksget_task_dict(mmlu), num_fewshot5, gen_kwargs{ do_sample: True, temperature: 0.7, top_p: 0.9, max_new_tokens: 32, }, ) # 第二次采样 results_2 simple_evaluate( modelmodel, tasksget_task_dict(mmlu), num_fewshot5, gen_kwargs{ do_sample: True, temperature: 0.7, top_p: 0.9, max_new_tokens: 32, }, ) for key in [mmlu]: acc_1 results_1[results][key][acc,none] acc_2 results_2[results][key][acc,none] print(fsample 1: {acc_1:.4f}) print(fsample 2: {acc_2:.4f})由于采样随机性两次跑出的结果可能不同。这说明如果评测报告没有记录随机种子和温度那么得到的数字并不可靠。实际生产评测中更推荐先生成多次再做多数投票。多数投票会稳定提升一些模型的分数但它属于后处理技术不属于模型原始能力需要在报告中注明。4.5 记录评测元数据一个完整的评测记录至少应包含以下字段评测时间 评测模型 模型版本/权重 commit 评测工具与版本 任务列表 few-shot 数量 few-shot 固定种子 prompt 模板文件 解码策略 temperature/top_p 随机种子 输出结果文件每次跑完评测把这些信息写入一个eval_meta.json然后和评测结果一起保存。当相同测试在不同日期出现 10 个百分点差时先对比eval_meta.json而不是怀疑模型。5. 当我们对比两个模型时分数差多少才可信论文揭示的核心风险是如果评测配置不同模型 A 对模型 B 的优势可能被放大或缩小。即使配置相同也存在随机误差。一种常用的判断方法是计算多个任务上分数的置信区间。以多选任务为例如果模型 A 准确率 60%模型 B 准确率 58%测试样本约 400 题那么两个模型差异可能并不显著如果样本量是 14000 题这个差异可能显著。只看单个 benchmark 榜单的冠军意义有限应该看跨数据集、跨模板的表现稳定性。在业务选型中更合理的做法是固定一份内部评测集固定一个评测脚本版本固定 prompt、few-shot、解码参数在相同硬件条件上运行每个模型至少跑 3 次随机种子报告均值和标准差用 bootstrap 或粗略的区间估计判断差距是否可信。当你发现“某模型为什么在别人的榜单上比我这里高很多”时大概率是因为评测配置不同需要先把各自的配置对齐到同一 yaml 文件再比较分数。6. 常见问题与排查思路6.1 问题现象与解决方向下面用表格汇总几个高频问题。问题现象常见原因解决思路同一模型两次评测分数差 5 个百分点以上解码启用了采样或评测脚本版本变化固定随机种子使用 greedy 作为基准升级工具后重新生成基线某模型 MMLU 得分和官方报告差异较大prompt 模板不同few-shot 示例选取不同找到官方评测脚本逐项对齐 YAML 配置生成式任务得分忽高忽低答案提取逻辑不稳定优先用 logprob 打分若用正则提取检查大小写、空格和多余文本长上下文任务启动后得分异常低输入被左截断指令或示例丢失设置更大的 max_length或改成保留开头和结尾的拼接策略量化模型分数低于原模型动态量化精度损失tokenizer 不一致需要确认评测时是否使用 bf16/fp16对量化模型单独做校准某任务只有 30% 准确率怀疑写错没有设置正确的 system prompt对照任务原始配置查看文档中的 doc_to_text 和 target 定义6.2 如何避免“自欺欺人”的评测很多时候团队内部评测出现问题不是恶意刷榜而是缺少评测规范。可以从三个角度规范流程。第一建立单一数据源。所有评测数据集、提示词模板、few-shot 示例、评测工具版本都放进 Git 仓库避免每个成员本地一份配置。第二先跑基准线再调参。当你想测试“温度对模型效果的影响”时先固定其他所有条件再修改目标参数而不是一次性改三个变量。第三记录版本号。模型权重、tokenizer、评测工具都可能有更新不记录 commit 就没法复盘。如果为了发布模型声称达到某个分数务必保留 cfg 文件和输出文件。这样即使评审质疑也能快速复现。公开发布评测配置不是额外负担而是团队技术可信度的基础设施。7. 评测工程化的最佳实践如果你所在团队需要长期维护一个内部 LLM 评测体系下面这些实践值得参考。7.1 评测脚本当作产品代码管理评测脚本不是一次性脚本。它的 YAML 配置、数据集选择、提示词模板都会随着模型迭代而变化。建议像管理服务代码一样管理评测代码每次评测前锁定依赖版本使用requirements.txt或 poetry 锁文件记录 lm-eval 及相关库版本模型权重和 tokenizer 使用明确的 commit idprompt 模板文件与调用脚本分离评测结果输出到带时间戳的目录例如results/20250218_qwen25_5shot/。7.2 设计多配置交叉评测单个配置的分数容易产生偏差。如果资源充足可以建立交叉评测矩阵任务 x prompt 模板 x few-shot 数量 x 采样策略对每个模型在同一矩阵上跑分然后报告最好配置最差配置跨配置均值跨配置标准差。这个矩阵能揭示模型的鲁棒性问题。比如模型 A 在默认模板下 85 分但换一个 neutral 模板降到 70 分模型 B 虽然没有 85 分但横跨多种模板都稳定在 75 分左右。实际业务中模型 B 往往更可靠。7.3 区分“内部评测”和“公开排行榜”公开排行榜是一种营销与社区比较工具内部评测才是模型选型依据。如果只看公开榜你可能无法知道某模型的分数是用 0-shot 还是 5-shot无法知道生成时是否开了采样甚至无法排除数据污染。内部评测应更关注领域数据来自你业务场景的真实样本人工评估小规模、高质量标注回归测试当 prompt、客服流程、RAG 检索链路变化时模型是否出现明显下降安全评测在禁止输出有害内容的场景配置与准确率之外还需要规则和审核。7.4 建立评测 CI 门禁在比较两个模型版本时可以写一个简单的评测脚本自动跑几个小规模任务并把结果记录到本地或 CI 报告中。下面是示例流程# 1. 生成评测配置文件 python scripts/build_eval_config.py \ --model $MODEL_NAME \ --tasks arc:0,mmlu:5 \ --template configs/template_default.yaml # 2. 执行评测 python scripts/run_eval.py --config eval_config.yaml # 3. 对比基线 python scripts/compare_result.py \ --base results/base.json \ --new results/new.json \ --threshold 0.02当新模型相对基线的整体分数下降超过阈值时CI 就报警提醒团队查看是否是 prompt 或解码配置变化导致。这个流程避免了很多“上线后效果变差”的返工。8. 写在最后把评测配置当作模型的一部分回到开头论文里的那组数据gemma4-31b 在一种评测配置下只有 31%换一种评测配置却能到 89%。我们不必把这个例子解读成“模型分数是假的”更要紧的是意识到如今的大模型评测仍然对被评测对象高度敏感任何单一数字都无法完整描述模型能力。对普通开发者来说最实用的态度是当你在排行榜上看到一个高分模型时先去查看它的评测配置当你要选型时跑一个与业务场景一致的评测脚本当你自己发布评测结果时把配置写清楚让分数可以被复现。评测配置不应该在论文附录里一笔带过而应该成为模型发布、榜单对比和版本迭代中的一等公民。下一次如果你发现两个模型明明差不多分数却差了一大截别再怀疑自己的模型出问题了。先把评测 yaml、few-shot 示例和随机种子拉出来对齐你会发现很多“能力鸿沟”其实是评测配置造成的影子。
返回列表