我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

自制LLM基准测试集:从题目构建到可复现跑分全指南

自制LLM基准测试集:从题目构建到可复现跑分全指南 最近连续跟几波朋友聊到同一个话题——大家手上都攒了不少自建的评测任务集但聊起来普遍感觉缺一套像样的评估流程跑出来的数字要么没法横向比要么换个环境就忽高忽低。这篇把我自己搭评测集的过程、选型思路和踩过的坑整理了一遍不整学科式的大理论就讲实际怎么把一套可复现的基准跑起来。1. 为什么自制基准测试集值得投入先说结论没有自己的结构化评估体系模型优化基本就是盲人摸象。今天调个采样参数好像变好了明天换个测试集又感觉退步了心里完全没底。自制基准测试集解决的不只是能不能跑而是让你真正拥有可重复、可比较、可回归的观察体系。举个例子我一直在跟进某个开源对话模型的迭代。社区里大家都在报分数但用的评测集各不相同有的测中文问答有的测代码生成有的只测逻辑推理。结果就是A 说这个模型好B 说不行其实两边都对只是测的东西根本不是一回事。自己搭一套基准集本质上是在建立一套我关心的能力维度的测量协议。这套协议要包含三个要素要素作用题目集决定测什么以及覆盖哪些能力边界评分规则决定怎么打分人工还是自动口径统一跑分流程决定结果是否可复现环境、参数、日志都得锁定那是不是意味着必须从零开始造题不一定。我当时的做法是搭积木从公开数据集里筛选一批适合自己场景的题目再补一批自制的、贴近真实业务的题目混成一个封闭集。关键在于一旦定下来这个集合就固定住只允许按版本号递增不允许临时改题。提示封闭集很重要。评测集一旦开放给模型训练阶段接触过数据泄露问题就会让所有数字失去意义。2. 题目集构建覆盖度与封闭性的平衡术题目集是基准测试的灵魂。我的经验是构建题目集的核心矛盾在于覆盖度和封闭性之间的平衡。覆盖度决定评测有没有代表性封闭性决定数值是否可信。2.1 能力维度的拆解方式如果只是随手收集几百条问答跑一圈看个总分这个基准基本没什么参考价值。我当时把评测拆成了六个维度每个维度单独出题、单独出分事实准确性验证模型输出内容是否符合客观事实逻辑推理考察多步推理、条件判断、排除法指令遵循测试模型对约束条件、格式要求的遵从程度上下文理解给定长文本后提取信息、归纳总结代码能力算法题、API 调用、Bug 定位安全与拒答敏感问题是否拒答、是否不产生有害内容每个能力维度下我又设置了不同的难度等级。比如逻辑推理一级是单步条件判断二级是双条件叠加三级就需要结合常识做排除性推导了。这样做的好处是跑分结果出来后不光有个总分还能看出来模型哪个维度强、哪个维度弱后续优化方向一目了然。2.2 题目的来源组合策略题目全原创真的不现实纯粹堆公开题目又容易踩数据泄露的问题。我用的策略是混合配比公开数据筛选比如从通用知识问答库里筛出一批答案确定、无争议的题目约 40%半开放改造把公开题改条件、换数字、反转提问角度约 30%完全自创围绕真实业务场景设计约 30%这里有个很容易被忽略的细节题目格式要同构也就是所有题目必须用统一的套话和结构组织。我的题目模板长这样{[任务类型标签]} 问题{具体问题描述} 要求{约束条件如用不超过50个字概括} 参考答案{用于评分对照的标准答案}你会发现模板统一的好处不仅仅是好看。它最大价值在于后期所有自动评分脚本都可以基于同一个结构化格式进行解析和处理。我见过不少评测集题目本身质量不错但格式五花八门最后光清洗数据就耗了两周。2.3 关于题目数量我的建议题目太少统计波动太大跑分没有意义。题目太多人工评审不现实跑一轮分成本太高。我当时定了一个原则每个维度至少 50 题总量 300 题起步如果打算做回归测试用子集。子集的做法也分享一下总集做深度评估子集做回归测试。子集大概 100 题每个维度抽 15~20 题分布保持和总集一致。每当模型更新一版先跑子集指标不低于上一版就继续走完整评估。这个做法帮我省了很多时间。3. 评分设计自动评估与人工评估的分工题目建好之后很多人的第一反应是直接扔给模型跑然后看答案对不对。但对不对这个判断本身就需要一套规则。3.1 选择题与填空题的自动判分如果题目是有标准答案的选择题或填空可以用自动判分但有一些细节需要注意答案归一化模型可能输出42.0 元、答案是 42、42元整直接字符串匹配必然误杀。我写了一个归一化脚本把数字、单位、标点、量词统一格式再比对。同义替换尤其是填空题模型可能用同义词或不同句式表达相同意思。我的处理方式是限定填空题的评分标准尽可能收敛同时给自动判分器内置一个关键词白名单和否定词检查。多选题陷阱多选题如果模型多选了或少选都算错误。不要网开一面因为线上使用时这种输出就是不可用。3.2 开放题的评分如何做得靠谱开放题是最难评的。纯靠人看几十条还好几百条要评死人而且标准容易漂移——上午和下午给的分数可能都不一样。我最终采用的方案是自动预筛 人工核验两层结构自动预筛用规则先粗略分三档——明显正确、明显错误、边界情况人工核验只处理边界情况和明显错误中疑似误伤的样例这样一来人工负荷直接降了一个量级。为了让人工评分的标准尽量一致我还写了一份简单的评分细则表档次定义示例满分信息完全正确无冗余错误直接给出正确答案并做了必要解释半分关键信息正确有部分冗余或表述偏差答案对但解释有一处不准确零分关键信息错误或拒绝作答给错答案或者回避问题3.3 对抗刷分式输出我在实际评测中还发现一个问题模型可能会把答案藏在一大段废话里。你说它错吧里面有正确内容你说它对吧用户根本提取不出来。所以评分规则里一定要包含冗余惩罚条款例如答案超过参考长度两倍自动降档处理。注意基准测试的评分标准不能太宽松。宽松的评分只会让分数全面虚高最后自己骗自己。4. 跑分工程化环境锁定与日志规范跑分流程的工程化水平直接决定评测结果的可信度。跑分不是把题目喂给模型然后把输出记下来那么简单。4.1 环境的可复现性第一个要锁定的是模型版本。这里特别强调一下模型版本号必须精确到 commit 或者权重文件的哈希值。我在实际测试中遇到过自己隔了一周觉得代码没改任何地方重新跑评测分数掉了不少。后来一查发现拉取的最新权重已经悄悄更新过了——评测结果记录里写的版本号还停留在最新版完全没法定位。第二个要锁定的是推理参数。温度、top_p、max_tokens、带不带 system prompt都会影响结果。我的做法是给每个跑分任务记录一份环境清单包括模型版本标识哈希或 commit推理参数字典随机种子解码器版本运行环境信息框架版本、硬件型号等4.2 输出日志的数据结构设计跑分过程中往往会出现各种意外某天模型崩了每个 task 超时某天日志里 token 数异常输出全为空。如果没有规范日志排查起来真的很痛苦。我设计的日志结构包含以下字段{ task_id: fact_0012, model_version: 7b_alpha_20250115, prompt: 问题原文, raw_output: 模型原始输出, inference_params: { temperature: 0.7, top_p: 0.9, max_tokens: 2048 }, latency_ms: 1523, tokens_used: 356, created_at: 2025-01-15T14:22:31.208Z, status: success }有了这个结构后续无论是做异常排查还是统计不同维度的 token 消耗都有据可查。4.3 并行跑分与串行跑分的选择评测集几百条题逐条串行跑太慢了。我当时把整个评测集拆成多个分片并行跑最后合并结果。需要注意一点并行任务一定要保证每个任务独立、无状态不要共享内存缓存也不要共享输出文件句柄否则很容易出现日志交错。实际跑分的时候我会先用 20 道题的 smoke test 验证整个流程确认没有报错后再开全量任务。这个习惯帮我避免了很多次全量跑完才发现某个维度漏掉的尴尬。5. 一次完整跑分复盘选一个具体案例来复盘完整的跑分过程。这是一个大致模拟某问答模型的能力评测我的目标是评估它是否适合内部知识助手场景。5.1 第一轮跑分暴露基础问题第一轮跑完后我进行了完整的日志汇总。结果如下能力维度得分率主要问题事实准确性76%部分回答存在过时信息逻辑推理62%多步推理容易中途断掉指令遵循88%基本格式能够遵守上下文理解71%长文本提取关键信息能力偏弱代码能力53%复杂 API 调用经常出错安全与拒答96%基本能拒答偶尔会啰嗦这个结果其实挺有价值。总得分率看似还行但拆开一看看出明显的短板代码能力只有 53%作为内部知识助手虽然影响不大但如果将来打算扩展到辅助开发场景这块就是个瓶颈。5.2 针对性调优后的第二轮根据第一轮结果我做了几个针对性调整在提示词里增加分步思考要求优化了 system prompt 的约束描述。在第二轮评测中逻辑推理得分从 62% 提升到 74%代码能力从 53% 提升到 61%。但意外的是指令遵循从 88% 降到了 84%。原因在于加了分步思考要求后模型输出长度明显增加产生了更多冗余内容被冗余惩罚规则扣了分。这个现象值得单独说一说评测分数不是越高越好每个改动都有代价要结合目标场景来判断哪个维度的优先级更高。对我来说逻辑推理比输出简明性更接近我的核心业务需求所以 4 个百分点的损失可以接受。5.3 排查异常输出的效率法则跑分日志里有些 task 输出完全为空。通过查看日志发现我在并行跑分时对某些分片设置的超时时间过短长文本任务直接被强杀。定位方式很简单统计 status 字段为失败的 task_id 列表再看 latency_ms如果大量集中在超时阈值附近那基本就能判断是超时配置问题了。这里也分享一下超时设计的经验分开设置短任务和长任务的超时阈值短任务 30 秒长任务 120 秒。宁可单任务多等一会儿也不要为了赶总耗时把超时卡得太死逼出各种假阳性失败。6. 回归测试与迭代节奏评测体系搭了不跑是摆设跑了不回归也很快就失效。我在迭代过程中逐渐形成了自己的固定节奏。每次模型更新后先跑 100 题子集半天内出结果快速判断本次改动是大步前进还是原地踏步。如果回归结果掉了就直接终止不让改动波及后续流程。只有子集分数稳定或提升才跑全量 300 题。全量跑完得到完整的能力画像更新评测记录表写简短的结论存档。这套流程必须靠工具支撑。我搭了一个简易评测结果归档表按日期记录每个模型的各维度分数。只要回看表格就能直观看到模型从哪个版本开始某项能力突然提升或者是在哪个版本出现了明显的退化。7. 两个最容易踩的坑最后聊两个我确实踩过、又花了不少时间才填上的坑希望各位绕开走。第一个坑是模型版本号的管理。当时我的跑分输出里模型版本字段填的是latest。某个深夜我更新了一版模型权重第二天直接跑全量评测发现分数反而下降。第一反应是评测流程出了问题排查了半天最后发现是权重更新带来的真实退化。从那以后我要求任何跑分任务必须使用包含版本哈希的标识禁止用latest这种不明确的标签。第二个坑是随机采样种子数没有固定。当时我的推理配置里没有固定种子导致同一个模型、同样参数、两轮跑分出分有正常波动。单个维度看起来波动不大顶多一两个百分点但累计到总分上就容易出现哪个改动都有效果的幻觉。固定随机种子并不能完全消除生成结果的随机性不可控因素总是有的但至少能够让大部分概率可控评测回归的置信度才上得去。8. 最后的建议让评测服务于决策经历这套流程后最大的体会是自制 benchmark 的核心价值不在分数本身而在它驱动的决策过程。没有基准你的每一次调整都是盲选有了基准你能明确每次改动到底动了哪块能力。我先在这里交个底这套体系远谈不上完美。题目集覆盖度还有局限自动评分的准确率也没高到可以完全替代人工的程度但对一个需要持续迭代、频繁跑分、定期复盘的项目来说这套方案已经带来了足够的复现能力与参考价值。如果你也正好在规划自建评测集我建议你把核心精力放在两件事上把题目结构规范好把跑分日志记录好。剩下的边界和细调都可以在后面几轮迭代里慢慢补。先跑起来再谈优化。
返回列表