评测核心

evaluation 包内 requests、runners、metrics、catalog 与 reporting 如何衔接。

本页内容

简介

本文说明 evaluation 包如何串联——不是文件索引,而是职责顺序。端到端 run 故事先看 Workflow;需要判断改动归属哪一层、哪些面必须跨版本保持稳定时再读本文。

包内数据流是单向的:公开契约定义 JSON-safe 形状,执行 runner 产生副作用与 artifact,catalog loader 把 YAML 转为契约,reporting 把 metrics 变成 scorecard。API 模块应保持 import-light;重型 runtime 不应反向泄漏进 evaluation/api/

模块级查找见 代码库地图

端到端流程

无论是否加载模型,每次 evaluation run 都经过相同的高层阶段:

# evaluation/tasks/execution/evaluate.py
result = run_evaluate(request)

# _mode() 选择 delegate runner:
if mode == "existing-results":
    runner = ExistingResultsRunner(...)
elif mode == "model" and uses_metric_objects:
    runner = ContractRunner(...)            # model + Metric objects
elif mode == "model" and uses_benchmark:
    runner = ModelBenchmarkRunner(...)      # model + benchmark
else:
    runner = ExistingResultsRunner(...)     # model + metric ids

# 各路径最终都汇聚到 metrics + reporting:
runner.generate(...)          # 仅 ContractRunner / ModelBenchmarkRunner
metrics = runner.compute_metrics(...)
report = runner.write_scorecard_and_report(metrics)

evaluate.py 中的 facade 保持薄:校验输入、选择 delegate、转换结果。所有文件写入、sample ledger 与 manifest 更新都在 delegate runner 内完成。

公开契约

evaluation/api/ 模块定义 runner、CLI、tests、docs 导出与 validation 共用的形状。此处改动应视为 semver 敏感:下游假设 to_dict() / from_dict() 可往返且磁盘 field 名稳定。

样本级,GenerationRequest 携带 ids、task name、inputs、controls 与 expected output schema;对应的 GenerationResult 携带 artifacts、status、errors、timings 与 metadata。模型级,WorldModelRunner 是每个 backend 必须实现的最小接口:from_config()generate()cleanup()。Benchmark 级,BenchmarkSpec 聚合 tasks、metrics、splits、tags 与 dataset metadata。Metrics 通过 Metric 接口实现 compute_sample()aggregate()

这些类型刻意不包含 checkpoint 路径、subprocess 细节或 vendor-specific import。Runner 在 run time 把 catalog YAML 翻译成这些契约。

执行路径

三条 delegate runner 覆盖常见执行形态。匹配任务选路径——不要在 facade 里堆条件分支,新增 delegate 即可。

ContractRunnercontract.py)是 model 执行加 Metric 对象的 in-process 参考路径。它归一化 requests、写 execution plan、运行 generation(可选 SQLite cache 复用)、计算 per-sample metrics、聚合后产出 scorecard 与 report artifact。需要最严格 artifact 布局且 metric 对象同进程时使用。

ExistingResultsRunnerexisting_results.py)评分磁盘上已有 artifact。从 path 或 inline list 加载 results、对齐 requests、运行 built-in metric id 或 artifact check,写出与完整 model run 相同的 summary 与 scorecard bundle。用于 hosted API 批处理、离线 demo,或 generation 发生在 WorldFoundry 外部的 workflow。

ModelBenchmark runnermodel_benchmark.py)把 generation 与 benchmark-zoo runner 串联。解析 benchmark manifest、从 task registry 物化 requests、运行模型、为 external evaluator 物化生成 artifact,再把归一化 metrics 交给 reporting。用于端到端 model-plus-benchmark run。

Model mode 收到 string metric id 而非 Metric 对象时,即使 generation 已在进程内完成,scoring 也会走与 ExistingResultsRunner 相同的路径。见 Workflow — Model Mode 细节

可复现 Planning

Generation 开始前,task-driven run 通过 plan.py 中的 RunPlan 固定 sample id、split 与 input keys。Plan 连接 task registry、可选 dataset manifest 与 evaluate facade:registry lookup → 物化 requests → EvaluateRunRequest。Plan 上的 fingerprint 使 rerun 与 cache 复用跨机器可预期。

materialize.py 中的 materialization 把 dataset 行或 task sample 转为 GenerationRequest 行。耗 GPU 前用 worldfoundry-eval task materialize 证明此步——多数「本地可用、CI 失败」来自 sample id 不一致,而非 model loading。

模型解析

磁盘 YAML 经唯一 front door resolver.py 中的 resolve_model_zoo_runner() 变为可运行 model。CLI 的 --model-id、Python caller 与 Studio 预览都应在解释 checkpoint 路径前汇聚于此。

# worldfoundry/data/models/catalog/*.yaml
entry = parse_model_zoo_yaml(path)          # schema.py → ModelZooEntry
entry = ModelZooRegistry().resolve(alias)   # alias lookup
manifest = WorldModelManifest.from_entry(entry)
runner = resolve_model_zoo_runner(manifest) # resolver.py
# → WorldModelRunner instance

Built-in runner 经 builtins.pyregistry.py 注册;custom target 从 catalog runner_target 字符串解析。manifest.pyschema.py 中的 catalog metadata 是 provenance 与 readiness——不能替代可运行 runner。

Benchmark 集成

Benchmark metadata 走平行的 catalog 路径。Task YAML 描述 per-sample protocol;benchmark-zoo YAML 描述 integration status、external runner 与 metric id。

# Benchmark-zoo YAML + task YAML registry
entry = parse_benchmark_zoo_yaml(path)      # → BenchmarkZooEntry
entry = BenchmarkZooRegistry().resolve(id)
spec = BenchmarkSpec.from_catalog(entry, task_registry)
raw = ManifestBenchmarkRunner(spec).run()   # external evaluator
metrics = official_normalizers.normalize(raw)
# → metrics/summary.json + scorecard.json

External benchmark 留在 runner 边界之后:vendor evaluator 产出 raw output,normalizer 转为稳定 metrics,共享 reporting 层写 metrics/summary.jsonscorecard.json

Reporting 链路

Reporting 在 metrics 完成后运行。Scorecard 是机器可读的 eligibility 记录;Markdown report 由 scorecard 派生,非权威来源。

per_sample = read_jsonl("metrics/per_sample.jsonl")
summary = aggregate_metrics(per_sample)     # → metrics/summary.json
scorecard = build_scorecard(summary)        # → scorecard.json
write_report_md(scorecard)                  # → report.md(派生,非权威来源)

Validation 脚本与 docs generator 会 import reporting/validation.py,并期望 scorecard field 稳定。在此重命名 field 会破坏 release gate。

改动规则

改 evaluation 内部代码前先看此表。它列出其他团队与自动化依赖的兼容面;破坏它们需同步更新 validation、docs export 与示例 scorecard。

如果改这里必须保持
api/* dataclassesto_dict() / from_dict() JSON-safe payloads。
evaluation/tasks/run_* output writing文件名、JSONL row shape、sample_id 对齐、final manifest status。
models/resolver.pyError messages、runner resolution、model-zoo variant selection。
evaluation/tasks/official/* schemaManifest parsing 和 alias lookup behavior。
reporting*.py and scorecard.pyValidation、docs 和 release reports 使用的 scorecard fields。