olmo-eval:模型开发循环中的评估工作台
olmo-eval: An evaluation workbench for the model development loop
Allen AI 发布 olmo-eval,一个基于 OLMES 标准构建的 LLM 评估工作台,用于活跃模型开发。它将 benchmark 逻辑与运行时策略解耦,支持 agent 和多轮评估,提供沙盒路由层、标准化实验 schema 及成对模型比较结果查看器。通过 Task/Suite/Harness 抽象,用户可快速添加 benchmark、跨 checkpoint 运行并分析逐题差异,判断干预是否带来真实改进。代码已在 GitHub 开源。
](https://huggingface.co/undfined)
💻 代码:https://github.com/allenai/olmo-eval
在构建 LLM 的过程中,你会在多次干预中反复评估它。对数据、架构或超参数的每一次调整——以及每一次规模上的提升——都会让你回到同一个循环:添加或重新配置 benchmark,在每个新的模型 checkpoint 上重新运行它们,记录结果,并检查在小规模实验中有效的方法是否在完整训练中仍然成立。
大多数评估工具并非为此而设计——它们要么是为了在已完成的模型上运行既定 benchmark,要么是在沙盒中通过多步骤、使用工具的问题来运行模型。它们跟不上一个不断变化的模型,也无法反映模型在特定真实世界条件下的行为。
我们上一个应对这一评估挑战的项目是 OLMES,即开放语言模型评估标准。它于 2024 年推出,旨在让 LLM benchmark 分数在不同版本之间更易于比较。相同的模型在相同的 benchmark 上以不同的方式评分——诸如 prompt 格式和任务表述等方面往往因论文而异——因此关于哪个模型表现最佳的声明往往无法复现。OLMES 将 benchmark 选择固定在一个开放、有文档记录的标准中,并成为我们从 Olmo 到 Tulu 评估开放模型的基础。
但模型的最终分数只是评估过程的一部分——这就是我们发布 olmo-eval 的原因,这是一个新的工作台,它建立在 OLMES 之上,并将其扩展到 LLM 开发的其余部分。与 OLMES 相比,olmo-eval 减少了实现新评估的工作量,在定义评估运行位置和方式方面提供了更多灵活性,并使将单个组件组合成更大工作流变得更加容易。Agent 和多轮评估作为一级用例得到支持,更强大的分析工具可帮助你判断一次干预是否确实比基线有所改进,或者差异是否只是噪声。
olmo-eval 与现有工具有何不同
性能变化 2.4 个百分点是否足以做出判断?
olmo-eval 在某些方面与 Harbor 重叠,Harbor 是一个用于在容器化、沙盒化环境中评估 AI agent 的开放框架。但这两个工具的范围不同。Harbor 主要旨在运行和发布 agent benchmark;olmo-eval 则是为日常的模型开发工作而构建——添加和配置 benchmark,跨 checkpoint 运行它们,并逐个 prompt 分析结果,而不是只看一个整体分数。
Harbor 以相同的方式运行所有内容——在密封、可复现的容器内。由于容器可能消耗大量资源,olmo-eval 允许你选择每个 benchmark 的运行方式。一个只需要模型回答问题的 benchmark 可以直接运行,这样更快、成本更低;一个需要锁定环境——例如,运行模型编写的代码——的 benchmark 则会获得一个隔离的容器设置。轻量级路径是默认选项,olmo-eval 仅在 benchmark 实际需要时才选择重量级设置。
Harbor 添加 benchmark 的流程是为你计划发布和公开分享的评估而构建的,并包含额外的验证步骤。olmo-eval 则是为在开发过程中快速推进而构建的,添加 benchmark 的方式取决于 benchmark 的需求:对于基本评估,只需一个简短的定义,并允许模型在处理 benchmark 时使用工具;或者,对于已有自己代码和流程的 benchmark,只需一个薄包装器,以便 olmo-eval 可以原样运行它,并以相同格式将结果与其他 benchmark 分数一起报告。
Harbor 和 olmo-eval 都将 benchmark 与运行时策略(模型如何运行以生成答案)分开,这样你可以在不重写另一个的情况下更改其中一个,但 olmo-eval 的设计更具模块化。在 olmo-eval 中,被评估的模型、它可以使用的工具、容器化环境以及任何辅助模型——例如 LLM-as-a-judge——都是可替换的组件。你可以在多个 harness 中重用同一个工具,或者将一个评分模型插入一个 benchmark 而不影响其他 benchmark,并且无需大量工作即可调整小设置(例如,prompt 的确切措辞)。
Harbor 为每个模型报告一个整体分数。olmo-eval 也报告这些分数,每个分数都带有标准误差和最小可检测效应(可以可靠地与噪声区分开的最小差异)。但更有用的视图是将两个模型 checkpoint 的相同问题逐题对齐并进行比较,同时保持其他所有条件不变。这有助于你判断整体平均值中的微小变化是否表明真正的改进,或者仅仅是噪声。
| 如果你在寻找... | olmo-eval 提供 |
|---|---|
| 编写一个多示例 benchmark | 带有 DataSource、指标和评分表面的 Task 子类 |
| 包装一个已有自己运行器的现有 agent 风格 benchmark | ExternalEval 或 SandboxedExternalEval;benchmark 保留其循环和评分,结果落入 olmo-eval 的 schema |
| 在固定 benchmark 下交换运行时 | --harness 和 harness 预设;harness 携带 provider、工具、scaffold、沙盒和辅助 provider |
| 并行容器执行 | 用于并行执行器的沙盒实例,具有基于能力的路由、Docker 或 Modal 模式 |
| 可在任务和 harness 间重用的工具定义 | @tool 装饰器,带有可选全局注册表 |
| 多轮执行循环 | Scaffold,例如 openai_agents,按 harness 选择,而非嵌入任务定义 |
一个集成的评估栈
olmo-eval 由四个组件组成,它们各自有用,但设计为协同工作,以收紧实验性 LLM 开发循环:
一个将 benchmark 逻辑与运行时策略解耦的任务/套件/harness 抽象。 任务是你如何在 olmo-eval 中定义 benchmark——即评估什么。套件将任务分组为你一起运行的一组任务,而 harness 控制每个任务如何运行。这种分离允许同一个任务作为标准基线运行,或使用工具和 scaffolding 运行,而无需更改其测量内容。
一个沙盒和基于能力的路由层,包括一个异步沙盒规划器。 这支持模型响应取决于其使用工具所采取行动的评估,例如编写和运行代码或浏览网页。关键在于评估模型的真实工具使用:当 benchmark 需要工具时,olmo-eval 会运行这些工具并将结果反馈给模型。
一个标准化的实验 schema,以相同的结构化格式记录每次运行、其配置和结果。 这使得可以分组相关实验、随时间比较 checkpoint,并避免在长期运行的模型开发工作流中经常积累的不一致性。
一个用于成对模型比较的结果查看器: 将两个模型或 checkpoint 逐题对齐,可以揭示整体平均值可能掩盖的微小但真实的性能变化。
在大多数模型评估设置中,添加一个 benchmark 是一个相当大的集成项目。在 olmo-eval 中,只需要一个任务——任务定义 benchmark 数据集、如何构建评估请求以及如何对模型答案进行评分(所有代码均为 Python):
from olmo_eval.common.formatters import ChatFormatter
from olmo_eval.common.metrics import AccuracyMetric
from olmo_eval.common.scorers import ExactMatchScorer
from olmo_eval.common.types import Instance, SamplingParams
from olmo_eval.data import DataLoader, DataSource
from olmo_eval.evals.tasks.common import Task, register, register_variant
@register("internal_freshqa")
class InternalFreshQA(Task):
data_source = DataSource(path="s3://evals/internal/freshqa.jsonl", split="test")
formatter = ChatFormatter()
sampling_params = SamplingParams(temperature=0.0)
metrics = (AccuracyMetric(scorer=ExactMatchScorer),)
@property
def instances(self):
loader = DataLoader()
for idx, doc in enumerate(loader.load(self.config.get_data_source())):
yield Instance(
question=doc["question"],
gold_answer=doc["answer"],
metadata={"id": doc.get("id", f"freshqa_{idx}")},
)
变体表达了评估策略的变化,而无需复制 benchmark:
register_variant("internal_freshqa", "3shot", num_fewshot=3, fewshot_seed=1234)
register_variant("internal_freshqa", "zero", num_fewshot=0)
套件将 benchmark 分组为你一起运行的标准集合:
from olmo_eval.evals.suites import Suite, register
register(Suite(
name="base_qa_few_shot",
tasks=(
"sciq:mc:3shot",
"arc_challenge:mc:3shot",
"internal_freshqa:mc:3shot",
),
))
由于运行时策略存在于 harness 而非任务定义中,因此同一个 benchmark 可以轻松地在不同执行方式下重新运行,而不是依赖于生成的分数点轨迹是否看起来合理。
# 基线
olmo-eval run -m my-instruct-checkpoint -t internal_freshqa:zero
# 相同任务,相同评分,启用搜索/工具运行时
olmo-eval run -m my-instruct-checkpoint -t internal_freshqa:zero --harness search_agent
开放的可复现评估
当评估是持续模型开发的一部分,而非一次性运行时——当你需要在可复现条件下跨 checkpoint 重复运行相同的 benchmark,并在聚合和逐题级别比较干预时——请使用 olmo-eval。
如果你反复问的问题是“这个 checkpoint 与上一个有何不同,它在哪些方面确切地改进或退步了?”,那么这就是 olmo-eval 为之构建的工作流。
可复现的评估应与模型的构建方式保持同步——而不仅仅是模型完成后如何评分。olmo-eval 将 OLMES 标准带入活跃的模型开发中,我们将其开放发布,以便社区可以在此基础上继续构建。

