Workflow

从 CLI 输入到 artifacts、metrics、scorecard 和 report 的端到端执行流。

本页内容

简介

本文追踪一次 evaluation run 从 CLI 到磁盘 artifact 的完整路径。当你需要知道某个 flag 落在哪段代码、哪个 runner 负责写文件、或 model mode 为何会分叉到 ContractRunnerExistingResultsRunner 时读这里。面向用户的命令示例见 评测指南;本文聚焦执行 plumbing。

入口

每条用户可见命令最终都会到达 evaluation/tasks/execution/evaluate.py 中的 run_evaluate()。控制台入口是 worldfoundry/cli/main.py,子命令会分发到以下四种形态之一:

  • evaluate — 归一化输入、选择 run mode,返回一个 EvaluateRunResult
  • existing outputs — 通过 existing_results.py 评分磁盘上已有 artifact,不加载模型。
  • model run — 经 resolver.py 解析 model runner,调用 generate(),再评分归一化结果。
  • model plus benchmark — 经 model_benchmark.py 先生成,再端到端调用 benchmark-zoo runner。

第一个实质分支始终是 mode 选择:本次 run 是否需要在 GPU 上加载权重,还是只消费已有文件。

Evaluate 主流程

主流程如下:一个 EvaluateRunRequest 进入 facade,选定 mode,从 task registry 加载或物化输入,再由 delegate runner 写出标准 artifact bundle。若输出目录缺文件,沿此流程查应由哪个 runner 阶段产出。

# worldfoundry/cli/main.py → evaluation/tasks/execution/evaluate.py
result = run_evaluate(EvaluateRunRequest(...))

mode = _mode(request)
requests, results = load_or_materialize(request)  # task registry / 磁盘路径
runner = pick_delegate_runner(mode, request)

runner.run(requests, results)
# 写入 output_dir/:
write("run_manifest.json")
write("execution_plan.json")
write("requests.jsonl")
write("results.jsonl")
write("sample_ledger.jsonl")
write("metrics/summary.json")
write("scorecard.json")
write("summary.json")
write("report.md")

Facade 本身很小。run_evaluate() 只做请求校验、模式选择和 runner 分发;真正的文件写入和样本级 accounting 由 delegate runner 负责。

模式行为

Mode 选择是第一个影响成本与前置条件的分支。existing-results 不加载权重,只评分磁盘上已有内容,因此 hosted API 批处理与离线 demo 常用它。model 会先解析 runner 并调用 generate();传入的 metrics 类型决定 scoring 留在进程内(ContractRunner)还是复用 existing-results 路径(ExistingResultsRunner)。

Mode必需输入是否加载模型指标路径什么时候用
existing-resultsresultsresults_path;requests 可选Built-in metric ids 或 artifact checksDemo、hosted job 或离线脚本已经产出 artifacts。
modelRequests 加 runner config 或 model-zoo id传 Metric objects 时走 ContractRunner;传 metric ids/artifact checks 时走 ExistingResultsRunner希望由框架执行模型。

Model Mode 细节

runner.generate() 返回后,_align_model_results() 保证每个 request 都有对应 result 行(含显式失败)。下面分叉容易被忽略:传入 Metric 对象则整次 run 留在 ContractRunner;传入 string metric ids 则 scoring 走与 existing-results 相同的代码路径。

runner = resolve_model_zoo_runner(request.model_id)
results = runner.generate(requests)
results = _align_model_results(requests, results)

if isinstance(request.metrics[0], Metric):
    return ContractRunner(...).score(results)          # Metric objects → 进程内
else:
    return ExistingResultsRunner(...).score(results)  # metric ids → existing-results 路径

关键点:模型执行和 benchmark scoring 是分开的。Model runner 只输出 GenerationResult;结果归一化后才评分。

Contract Runner 细节

run_contract() 是最严格的 in-process path,也是 artifact 布局的参考实现。每个阶段都会写出或更新下游 validation、docs export 与 leaderboard 工具期望找到的文件。调试不完整 run 时按阶段顺序排查:缺少 metrics/per_sample.jsonl 通常是 generation 未完成对齐,而非 reporting 失败。

# evaluation/tasks/execution/contract.py → run_contract()
requests = _normalize_requests(request)
write_execution_plan(requests)                # execution_plan.json
write_run_manifest(status="running")          # run_manifest.json

results = run_generation_with_cache(runner, requests)
write_artifacts_jsonl(_artifact_rows(results)) # artifacts.jsonl
write_per_sample_metrics(...)                 # metrics/per_sample.jsonl
summary = _build_summary(...)                 # metrics/summary.json
write_scorecard(summary)                      # scorecard.json
write_run_report_artifacts(summary)           # summary.json + report.md
write_run_manifest(status="finished")         # 最终 run_manifest.json

Generation 是最耗时的阶段:runner 异常会变成 failed samples,确定性输出可复用 SQLite generation cache。Reporting 阶段只在每个样本都有对齐 result 行之后才运行。

Artifact 契约

这些文件构成 评测指南 中的 audit trail。各 run mode 下形态稳定:existing-results 仍会写 sample_ledger.jsonlscorecard.json,便于与同一 benchmark 上的完整 model run 对比。路径均相对 run_manifest.json 中记录的 run 输出目录。

文件生产者含义
run_manifest.jsonRunnerRun identity、status、model、benchmark、dataset、context metadata、output paths。
execution_plan.jsonRunner 或 RunPlanPlanned stages、sample ids、materialization details、output files。
requests.jsonlRunner每个样本一个归一化 GenerationRequest
results.jsonlModel runner through evaluation runner每个样本一个归一化 GenerationResult
sample_ledger.jsonlRunner样本级 pass/fail 状态和 stage-level errors。
artifacts.jsonlRunner相对 output directory enrich 后的 flattened artifact refs。
metrics/per_sample.jsonlMetrics layer样本级 metric output 或 skipped state。
metrics/summary.jsonMetrics layerAggregates、failed ids、skipped ids、leaderboard fields。
scorecard.jsonReporting layerRelease/review surface,供 validation 和 docs 消费。
report.mdReporting layer从 scorecard 派生的人类可读摘要。

Task Materialization

Task-driven run 在任意模型代码运行之前固定 sample id、split 与 input keys,使 rerun 与 cache 复现可预期:相同 task YAML 与 dataset manifest 应在每台机器上产出相同的 requests.jsonl 行。下方代码把 catalog task YAML 接到 run_evaluate() 已理解的 EvaluateRunRequest;YAML 文件位置见 基准和数据

registry = load_task_registry_from_paths(task_yaml_paths)
plan = build_run_plan_from_task_registry(registry, dataset_manifest)
requests = _materialize_requests_from_task(plan)
requests = materialize_generation_requests(requests)
return EvaluateRunRequest(requests=requests, ...)

当 sample id、split、input keys、output keys 和 cache policy 需要在 generation 前可复现时,用这条路径。