Skip to main content
Benchmark 通过 MetricContract 声明 attempt 观测,将观测写入 RunResult.metrics,并由 aggregate_metrics() 返回经过校验的 MetricReport。执行状态与指标观测是两套独立契约。

声明 Metric Contract

标准的二元或标量结构可使用 make_metric_contract():
每个 Contract 必须且只能包含一个主观测: 辅助观测可以是二元值或标量。未声明的观测、非布尔的二元值以及非有限标量都会校验失败。标量主观测不能使用 pass 策略。

写入评测观测

使用 dataclasses.replace() 保留 Harness 已生成的结果,并且只把 Benchmark 观测写入 metrics:
合法的错误答案携带有效的零分观测。评分时保留输入中的 issues、轨迹、产物和用量;ERROR 和 WARNING 可以与有效得分共存,完整诊断保存在 artifacts.execution_diagnostics。 在实际调用边界分类异常。exception_issue() 接收明确的 severity、phase 和 code,生成脱敏摘要并保留已有的 StageFailure.issue;failed_result() 接收已分类的 issue,保留部分结果与 traceback。不要通过 source 字符串让外层推断原因。同一 run 阶段中,模型超时为 ERROR,模型鉴权、配额和服务端故障为 FATAL;模型 API 适配器可复用 runtime.llm.errors.model_exception_issue()。Judge 调用失败在评分边界显式标为 FATAL,清理失败在释放边界显式标为 WARNING。 详情序列化器不会读取或写入旧的顶层 correct 和 score 字段。它始终保留 status、metrics、final_answer、trajectory、issues、artifacts、analysis_result 以及 benchmark、harness 两个 meta 命名空间,确保任务详情结构一致。

组织评分逻辑

Benchmark 负责声明指标,并在 evaluate() 中组织评测、将观测写入 RunResult。具体判分逻辑可按评测方式组织:
  • 答案型评测:简单判分可直接写在 evaluate() 中,也可按需将提示词、答案解析和判分规则封装为独立 scorer,例如 BrowseComp。scorer 只是可选的内部代码组织方式,不是需要单独注册的组件。
  • 测试或 verifier 型评测:如 SWE-bench、TerminalBench,可直接执行测试或调用 verifier,并将结果转换为已声明的指标,无需额外封装 scorer。

理解两级聚合

聚合分为两个相互独立的阶段:
  1. runtime 按选定的 attempt strategy 和 metric reducer,合并同一任务的 k 次观测。k=1 生成 native@1;k>1 时,avg 要求所有 attempt 完整,pass 可以在第一次二元成功后停止。
  2. Benchmark.aggregate_metrics() 再按 Benchmark 的官方跨任务公式聚合任务级结果。
BaseBenchmark.aggregate_metrics() 会对 Contract 中的每个观测执行任务均值、类别均值或类别层级聚合。官方指标就是均值的 Benchmark 可以直接继承:
默认实现和自定义 hook 都返回 MetricReport。每个 MetricSeries 会记录 metric_id、reducer、k、数值、聚合方法、相互独立的 total/evaluated/error/unavailable 计数,以及可选的类别和层级明细。

保留官方语料级公式

只有官方结果不是任务级数值均值时,才需要覆盖 aggregate_metrics()。应先取得共享报告,再通过 BenchmarkAggregationContext 保留统一的 attempt reduction、覆盖计数、类别处理和报告校验:
BenchmarkAggregationContext 还提供 replace_with_sum()、append_ratio_series()、append_benchmark_series() 和 update_extra(),用于总和及 Benchmark 派生指标。不要在该 hook 中重新实现 attempt 选择,也不要修改 runtime 传入的持久化详情。

扩展 Strategy 与 Reducer

多次尝试的执行和指标计算分别由两个基于注册表的扩展点负责:
  • AttemptStrategy 选择 reducer、提供调度策略,并判断某次 attempt 是否可以停止后续执行。
  • MetricReducer 合并同一任务的精确观测,并声明自身支持的指标类型。
新实现分别通过 register_attempt_strategy() 和 register_metric_reducer() 注册。调度策略留在 strategy,数值语义留在 reducer,Benchmark 专属的跨任务公式仍由 aggregate_metrics() 负责。 只有 Benchmark 的每次 attempt 状态互相隔离,并且所选 Harness 也支持并行 attempt 时,才能设置 parallel_attempts_safe = True。否则 runtime 会串行执行同一任务的 attempts,同时仍遵循请求级 task concurrency。

聚合前检查

  • Contract 声明了所有输出指标,并且只有一个 correct 或 score 主观测。
  • 不根据 status 补齐缺失观察。最终 FATAL 使整题失效;普通 verifier reward 异常由组件显式报告 WARNING 和 fail/0。
  • avg@k 拥有完整的 k 个有效观测;值为正的 pass@k 至少有一次有效成功。
  • 自定义语料级公式保留官方分母,并返回 context.build()。
  • 每个任务都有稳定、非空的 task_id,供 attempts、resume、reuse 和指标覆盖计数使用。
落盘结构见任务结果,用户侧的指标行为见指标与聚合。