浮动真实值:大语言模型评估工具中的数据集版本锁定
对lm-evaluation-harness任务配置的统计显示,几乎没有任何配置指定了数据集版本。了解这对分数比较意味着什么,以及如何审核自己的评估结果。
当大型语言模型在两次测试中的基准分数发生变化时,你需要判断是模型本身发生了改变,还是用于评分的数据发生了变化。在大多数公开评估体系中,并没有机制来记录第二种可能性。最近对开放模型评分系统中使用最广泛的工具之一 lm-evaluation-harness 中的任务目录进行的审计显示,841 个配置中仅有一个是设置了数据集版本字段的,而该字段的值实际上根本不是版本标识。本文将详细介绍这一数字是如何得出的、为何分母与分子同样重要、另一套工具为何做出了相反的取舍,以及如何对自己的评估进行同样的检查。
核心数值与被弃用的数值
这项测量结果值得研究,部分原因在于它最初出错的方式。早期版本的统计数据显示,13,986个配置中有1个锁定了其数据,这一数字要惊人得多。该数据在几小时内就被废弃了。在这13,986个文件中,10,391个文件本身并未指定数据集名称,而是通过include:从父文件继承数据集;另有2,966个是根本未指定数据集名称的群组文件。这两类文件都没有需要锁定的内容,因此将它们计入会夸大分母数值,使得研究结果看起来比实际更显著。分析人员指出,这已是同一周内第二次因为未能检查分母包含的内容而得出看似惊人的数据,这对任何自行生成指标的人而言都是一则重要的警示。
修正后的结论如下:在 lm-evaluation-harness 中,有 841 个任务配置直接指定了数据集名称,其中仅有一个是设置了修订字段。该字段的值为 refs/convert/parquet,这是一个用于选择存储格式而非特定数据版本的引用。实际上,并没有哪个配置被固定下来——每次运行都会根据执行当天上游数据集的实际状态来进行评分。
主要发现概览
- 在 13,986 个任务配置中,有 841 个直接指定了数据集名称。其余的 13,145 个配置中,10,391 个通过
include:语句继承了某个数据集,另外 2,966 个则是没有自身数据集的归类文件。 - 在这 841 个配置中,只有一个是设置了修订号或 SHA 密钥,而它所指定的
refs/convert/parquet只是用于选择文件格式,并非固定数据版本。
load_dataset函数,而这其中只有2个指定了revision=参数。openai/evals采取了相反的处理方式:其463个评估任务中有455个会读取仓库中的samples_jsonl文件,而这些文件又依赖于存储在仓库中的722个数据文件。该系统的真实值不会发生变化,但可能会过时。简而言之
评估套件实际上就是一个依赖图,软件团队会固定这些依赖是有充分理由的。我逐一检查了lm-evaluation-harness中的所有任务配置,提取出每个任务用于评分的数据集,并查找被固定的版本,最终找到了一个候选方案,但它其实并非真正的固定版本。通过统计这些配置多久未被修改一次,发现大多数数据集对应的配置大约有18个月未曾被编辑过。这些情况并不能说明任何已公布的基准测试数值是错误的,只是表明如果因为数据变化导致某个数值出错,该评估套件本身不会发出任何提示。
为何基准测试需要固定的数据集版本
正在测试的模型并非唯一可能发生变化的对象。每个任务配置都对应一个数据集,例如 alexandrainst/m_truthfulqa、OALL/ACVA 或 CogComp/mc_taco,而托管在公共平台上的数据集其实是一种动态发展的产物。它有维护者,会不断收到修正、许可证变更、数据重新划分、新的配置,偶尔还会对已知有误的标签进行无声修正。这类活动很正常,且大多有益处。
问题在于它对比较结果的影响。分数只有相对于稳定的参考标准才有意义。当新模型版本产生不同的分数时,你就获得了关于该模型的信息;而当数据发生变化时,你看到的只是类似发现结果的测量误差。如果没有记录版本变更,无论事后回顾还是在进行评估时,都无法将两者区分开来。
未标记的分数是一种其测量标准从未被记录下来的数值。
这与JavaScript项目中的锁文件原理相同:package.json中如^4.2.0这样的版本范围允许构建过程自动采用新代码,而锁文件则将最终确定的精确版本记录下来。评估数据也应得到同样的处理。
计数方式的产生过程
最有趣的决策大多体现在方法论上,尤其是与分母相关的部分。
- 代码仓库:
EleutherAI/lm-evaluation-harness,使用--filter=blob:none --unshallow命令克隆并保留完整历史记录。该仓库包含从2020-08-27到2026-09-10的4,115次提交记录,测量工作于2026年9月12日进行。由于目录内容会不断变化,后续的测量结果可能会有所不同。 - 配置文件遍历: 查看
lm_eval/tasks目录下的所有.yaml和.yml文件。脚本会从每个文件中提取dataset_path或hf_path,查找是否存在dataset_revision、revision、dataset_sha或sha这类字段,并记录该文件是否使用了include:选项。
git log来获取每个文件的添加日期和最后修改日期,这些日期是相对于HEAD提交时间而非当前日期来计算的,因此随着时间推移数值保持不变。经过筛选后,共有841个合格配置指向273个不同的数据集。
这些配置的过时程度如何?
过时程度的计算需要采用两种方式,因为最初的简单计算结果具有误导性,这一情况只有通过手动检查才能发现。
按配置项统计,上次修改后的中位数时间为729.8天。在841个配置项中,有691个(占比82.2%)已超过一年未被修改,另有551个(占比65.5%)自添加以来从未被编辑过。
这些数据夸大了实际情况。仅有5次提交就贡献了841个配置项中的50.9%,其中单次提交decc533d就在一天之内新增了272个配置项。因此,按配置项单独统计的结果并不能反映841个独立配置项各自按不同时间表演变的状况,而只是反映了少数批量修改以及少量零星修改的情况。
若按数据集而非文件进行分组,就能消除这种聚集现象:
- 对于处于中位数的数据集,其关联配置项上次被修改至今已有547.9天。
- 273个数据集中有196个(占比71.8%)已超过一年未修改。
- 273个数据中有245个(占比89.7%)已超过180天未修改。
每个数据集的具体数值才是值得引用的,因为它能够克服聚类带来的问题。中位数仍约为18个月,而十分之九的数据集持续时间超过6个月。
支持固定版本,但很少使用
如果该工具套件完全无法实现固定版本的功能,那批评它就有失公平,但实际上它并非如此。其底层使用的仍是标准的Hugging Face datasets库,且load_dataset函数支持传入版本参数。在任务目录的Python文件中,15个调用load_dataset的文件中有2个指定了revision=参数,而该目录下共有673个Python文件,其中仅有1个文件的版本是固定为某个拉取请求的引用地址。
虽然有固定功能可用,但几乎没人使用它,工作流程中也没有任何机制引导贡献者去使用它。由于默认设置为浮动模式,因此会有841种配置以浮动形式存在,因为大型目录实际上都是基于默认设置运行的。
如果你负责维护评估系统,最简单的做法就是今天就在自己的任务定义中查找修订字段,看看能找到多少结果。
另一种权衡:openai/evals中的预置数据
openai/evals从另一个角度回答了同样的问题,其方法显然并不逊色。在463种评估配置中,有455种会读取存储在仓库中的samples_jsonl文件,而这些文件又包含722个数据文件为它们提供支持。真实值是预置的,这意味着从设计上就已被固定:这些数据会与其他所有内容一起通过Git进行版本控制。
其优势在于能够实现完美复现:2024年进行的评估可以在完全相同的输入数据上重复进行。代价则是金钱。商业版本永远无法获得上游的修正,因此虽然该评估体系不会偏离标准,但会逐渐变成“博物馆”般的存在,用多年前就已修正错误的旧版本来评估新模型。
这两种体系都没有选择第三条路径:即锁定特定版本并刻意推动其发展。一种是无记录地随时间变化,另一种则是停止更新而一成不变。在这两种情况下,选择都是默认发生的,而非经过刻意决策。
评估无法展现的内容
分析的局限性与其结果同样重要。
- 未观察到数据集有任何变化。审计环境的网络策略禁止与
huggingface.co建立连接,两台测试机器发起的CONNECT请求均被代理返回403错误,因此无法查询到解析信息及最后修改时间。此处讨论的只是是否能够检测到变化,而非变化是否确实发生。 - 未被标记并不代表有误。这些数据集很可能从未发生过变化。该问题反映的是控制机制的缺失,而非现有的错误。
- 数据过时并不代表被忽视。一个700天未被任何人编辑的配置文件仍可能完整且准确。过时仅表示没人再查看过它,这与缺陷是不同的概念。
promptfoo、deepeval和ragas这类工具属于库而非注册表,没有可比较的YAML任务目录,因此相关结果无法反映它们的实际表现。include:文件属于主观判断。更严格的解读可能会考虑父配置是否代表子配置进行绑定。经检查,它们并未如此操作。常见问题
那么已公布的基准测试分数不可靠吗?
并非如此,这种观点应当被摒弃。只是缺少了特定的控制项。只有当底层数据发生变化时,分数才会受到影响;审计结果显示,即便出现这种情况,该测试套件也不会留下任何可用于事后检测的记录。
为何不直接检查数据集是否发生了变化?
这需要访问huggingface.co来确认数据集的版本信息,但审计的网络策略在云环境和本地机器上均通过403错误阻止了此类连接。因此,人们不再试图从较弱的信号中推断数据漂移,而是将范围限定在仅能通过代码仓库验证的内容上,这也是该发现关注“固定版本”而非“变化”的原因。
固定版本总是正确的选择吗?
并非如此。固定的评估方式无法检测到错误标签的真实修正,而这正是openai/evals能够实现完美复现却又逐渐出现误差的原因。更为合理的策略是“固定并逐步调整”:先锁定某个版本,再有意图地将其向前推进,并记录每一次调整,但实际上几乎没人这么做。
如何检查自己的测试套件?
遍历任务定义,提取数据集所包含的字段名,然后在这些文件中查找任何版本信息或SHA密钥。此处讨论的指标就是第二次统计结果与第一次的比值。审计报告显示每处理一千个文件大约需要三十秒的计算时间,因此将此检查加入持续集成流程成本很低。
总结
- 将评估数据集视为依赖项:在每组要比较的得分旁记录确切的版本信息。
- 在未查看分母内容之前,要对异常的比值保持警惕;继承的和聚合的配置几乎让本不严重的问题变成了具有误导性的结果。
- 浮动数据与冻结数据的问题方向相反:前者会悄然偏离,后者则会逐渐过时而未被修正。通过固定版本并配合变更日志,可以避免这两种问题。
对于在持续集成环境中进行评估的任何团队而言,一个关键问题在于:当不同运行次数的得分出现变化时,你的设置中有哪些依据能判断是模型还是数据发生了变动?如果答案是没有,那么在任务定义中添加修订字段是最简单的解决方式。你可以直接查看lm-evaluation-harness任务目录和openai/evals注册表,以比较这两种方法。
相关阅读
- AI工程概念的分级图及应用场景 — 了解哪些AI工程概念决定了系统是否能够正常运行,哪些在投入生产后至关重要,哪些则可以暂缓处理。
- 将LLM作为评判系统进行管理 — 了解Netflix采用的四阶段生命周期——真实数据、基于评分标准的训练、安全部署以及持续监控——如何确保大规模应用中LLM评判系统的准确性。