oh-my-pi metaharness:统一 Harbor、TypeScript edit 与 SnapCompact 的基准评测管理平台
2026/9/13 1:41:25 网站建设 项目流程

oh-my-pi metaharness:统一 Harbor、TypeScript edit 与 SnapCompact 的基准评测管理平台

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

packages/metaharness@oh-my-pi/pi-metaharness)是 oh-my-pi 的基准评测管理中枢(benchmark harness):它把 Harbor、TypeScript edit 与 SnapCompact 三类完全不同的评测任务统一进同一套experiment → run → trace数据模型,用一份 SQLite 存储、一套 REST/SSE API 和一个实时 Web 仪表盘统一管理。阅读本文后,你将掌握如何用bun run serve一键启动评测仪表盘与 API、通过POST /api/runs从同一张表单发起任意 benchmark、理解 Harbor 评测在容器内的三条关键设计(本地源码挂载、凭据不进入容器、Harbor 拥有 trial),并能使用bench:tb在 Vibemon KVM 微虚拟机上运行原生 Terminal-Bench 2.1,以及用trace-report把单次 run 的 trace 转成可读的叙事性 Markdown 报告。

一个 Manager 统一三类 Benchmark

在 oh-my-pi 的评测体系里,metaharness解决的核心问题是:不同 benchmark 的原生产物格式完全不同,但评测者关心的东西是一致的——进度、分数、token 消耗、成本与 trace。因此它引入了统一的抽象层:

  • experiment:一次评测目标(goal),按 job 名前缀分组(sb2-n8sb2-gemini都归入 experimentsb2),多个 arm 共享同一任务样本以便横向对比;
  • run:一次具体的评测运行,对应磁盘上的一个 job 目录;
  • trace:run 内每个 trial 的归一化轨迹。

benchmark 原生的产物仍然保留在磁盘上,adapter 负责把它们规范化为统一的 run 行、trial 行与指标。三种内置 benchmark 的指标定义见 benchmarks.ts:

BenchmarkLabel指标
harborHarborsuccess_rate(成功率,percent)
editTypeScript edittask_success_rateedit_success_rate
snapcompactSnapCompactf1exact_match

指标定义带format(percent/number/usd)与higherIsBetter语义,存储层与 UI 不硬编码任何 benchmark 语义,因此新增 benchmark 只需新增一个 adapter。

启动整个服务(Dashboard + API,端口 4700)只需一行命令:

bun run serve --port 4700

所有 benchmark 都可以从同一个 "new run" 表单发起。对应脚本定义在 package.json(serve/bench:edit/bench:tb/bench:tb-floor/dev/test)。

Harbor 评测的三条执行主线

README 明确了 Harbor run 在 oh-my-pi 中的执行方式,结合 runner.ts 的源码可以还原完整链路:metaharnessrunner 进程(src/runner.ts)负责组装harbor run命令、注入环境变量、渲染实时仪表盘并最终写出报告。

1. 本地 omp,而非 npm

默认情况下 runner 将仓库只读 bind-mount进每个任务容器(--install source),直接运行packages/coding-agent/src/cli.ts中的 omp——也就是说TypeScript 改动在下一个 trial 立即生效,无需重新构建

其实现细节在prepareSourceDeps(runner.ts):首次运行时(或 lockfile 变化时),runner 会在<jobs-dir>/_bench/_deps/下用oven/bun:<版本>镜像构建一份缓存的linuxnode_modules骨架树bun install --production --ignore-scripts),用来遮蔽宿主机 darwin 平台的那一份;同时把镜像里的 linuxbun二进制挂到/opt/omp/bin。这套缓存的构建用 manifest + lockfile 的 sha256 指纹(sourceDepsStamp)决定是否需要重建,TS 改动永远不会使其失效,因此 trial 初始化阶段零出网

两种替代方案:

  • --install local:每次 run 用bun pm pack打一个 tarball(buildTarball,见 runner.ts);
  • --binary:使用预构建的dist/omp-linux-*自包含二进制(文件名需含arm64/x64以便推断架构,见 runner.ts)。

2. 凭据永不进入容器

生成的models.yml把 provider 的baseUrl全部指向宿主机 pm2 上的 auth-gateway,凭据由网关在宿主机侧解析。writeModelsYaml(runner.ts)为每个 provider 生成baseUrl: <gateway-url>auth: oauthtransport: pi-native的配置;runner 启动前还会对网关做一次/healthz健康检查(gatewayHealthOk)。在 Apple Container 环境下,由于没有host.docker.internal,runner 会启动一个192.168.64.1:4000 → 127.0.0.1:4000的反向转发(startVmnetGatewayForward,见 runner.ts),保证容器内只能访问到网关而接触不到真实密钥。如果你确实想直接把宿主机 provider key 传进容器,可用--no-gateway

3. Harbor 拥有 trials

runner/serve 层不干预 trial 的执行,而是轮询每个 trial 的result.json获取进度、花费与结果。运行期间 runner 会渲染一个实时终端仪表盘(进度条 / pass% / spend / tokens / ETA,见 runner.ts);对于仍在运行的 trial,还会增量解析agent/omp.txtJSONL 日志来实时累计 token 与成本(probeTrialCost,见 runner.ts,只读取新增字节、跳过超大行,避免大日志阻塞事件循环)。

Server:REST + SSE API 全览

服务入口是 src/server.ts:bun run src/server.ts [--port 4700] [--jobs-dir <path>]。启动时执行discover()(自动发现历史 CLI run 目录并回填为数据库行)与syncAll(),随后每 2 秒同步一次运行中的 run(syncActive),并通过 SSE 广播 run 列表快照。

完整端点清单(实现见 server.ts):

方法路径说明
GET/实验、run、归一化 trace,以及所有 benchmark 的发起表单(Web Dashboard,Bun 直接打包 React/TSX,单进程无 Vite)
GET/api/experiments[?q=]跨所有 benchmark 类型的实验摘要;q按 id/goal 子串过滤
POST/api/experiments在第一个 arm 之前注册实验,Body{ "id": "sb2", "goal": "..." };id 是无横线的 token,job 名按它分组(sb2-n8→ experimentsb2
GET/api/experiments/:idarm 列表、按任务的矩阵(matrix)以及校准投影
PUT/api/experiments/:id更新 goal 与每个 run 的 role/note/label
POST/api/experiments/:id/arms发起一个可对比的新 arm;样本与配置从同级 arm 继承
DELETE/api/experiments/:id删除所有 arm(DB 行job 目录)以及 goal 行;有 arm 运行中时拒绝
GET/api/runs[?experiment=&status=&benchmark=]统一 run 行(benchmark、score、progress、spend、tokens)
POST/api/runs通过 benchmark adapter 发起 run
GET/api/runs/:name{ run, traces }(读取时同步磁盘上的原生产物)
POST/api/runs/:name/cancel取消 manager 发起的 run
DELETE/api/runs/:name永久删除已结束的 run(DB 行 + job 目录;残留目录会在重启时被discover()重新发现),运行中拒绝
POST/api/runs/:name/resume原地恢复未完成的 Harbor run(见下节)
GET/api/runs/:name/traces/:trace[?raw=1]归一化或原生 trace
GET/api/eventsSSE 流,run 列表快照(变化时推送)

POST /api/runs 的请求体

发起任何 benchmark 的 run 使用统一的请求体:

{ "benchmark": "edit", "model": "anthropic/claude-opus-4-8", "tasks": 20, "concurrency": 4, "attempts": 2, "jobName": "edit-baseline", "role": "baseline", "goal": "compare edit strategies" }

benchmarkharboreditsnapcompact之一,各自的专属字段不同:

  • Harbor:使用datasetincludetimeoutMultiplierprewalk
  • edit:使用include作为任务 ID 列表;
  • SnapCompact:使用conditions,且tasks被当作段落数上限(--limit-paras)。

请求体与 Harbor runner CLI argv 的映射逻辑在 launch-args.ts:显式include列表就是样本本身(不会被默认任务数截断);prewalk会转换成--agent-arg --prewalk [--prewalk-into <model>]并自动补上--providersprebuiltBinaries会自动查找并传入dist/omp-linux-arm64/omp-linux-x64。三种 benchmark 的启动命令组装见ManagerServer.launch(server.ts):edit 走adapters/edit/cli.ts,snapcompact 走uv run src/adapters/snapcompact.py,harbor 走bun src/runner.ts。job 名缺省时按<model-slug>-<timestamp>生成,并要求是单段安全 token(防止路径逃逸,见 server.ts)。

状态存储与恢复

所有状态落在<jobs-dir>/_manager/metaharness.sqlite(默认<repo>/runs/harbor,见 server.ts)。文件系统始终是事实来源——Harbor 每 job 每 trial 写result.json,SQLite 只是镜像成可查询行并补充 manager 自有元数据(启动 pid、请求的 config、生命周期状态)。存储层实现见 store.ts:三张表runs/trials/experiments,启用 WAL journal 并对SQLITE_BUSY重试(enableWal),syncRun会按磁盘快照 upsert trial 行、清除消失的 trial 幽灵行,并对无主进程的 run 用result.jsonfinishedAt或目录新鲜度推断终态。

历史 CLI run 会被自动发现:discover()(store.ts)扫描 jobs 目录下没有 DB 行的子目录(跳过_bench_manager),从config.json尽力回填 dataset/agent/models 后插入为running行再同步。

Resume:原地恢复未完成的 Harbor run

POST /api/runs/:name/resume只支持 Harbor run。已完成 trial(及其花费)会被复用,被中断/挂起的 trial 重跑,出错 trial 重试。请求体{ "filterErrorTypes": [...] }可覆盖重试集合,缺省时默认重试 job 的result.json里记录的所有异常类型(reward-0 的失败是已决结果,不会被重试)。runner 从_bench/<name>/runner-config.json(启动时快照的完整 Config)或该 run 的manager.json恢复原始启动参数——无需重新指定任何 flagresolveResumeConfig,见 runner.ts)。resume 命令本身为harbor job resume -p <jobDir>,且CancelledError恒被加入重试集合(见buildResumeArgs,runner.ts)。

取消采用"SIGTERM 优先、5 秒后 SIGKILL 升级"的策略(server.ts),确保 runner 能把信号转发给 Harbor 子进程,避免直接 SIGKILL 把 harbor 变成孤儿继续写 job 目录。

实验对比与校准投影

实验层在 experiments.ts:job 名的第一个-前的 token 即 experiment id(experimentOf);新增 arm 时resolveArmLaunch(server.ts)从样本最完整的同级 arm 继承 benchmark、dataset 与精确任务样本(记录的include,否则从该 arm 的 trial 任务反推),从而保证 arm 之间直接可比。-fix/-backfill/-retry等重跑后缀会被折叠进基础 arm(canonicalArmOf),每任务取"已决优先、最新优先"的 trial(pickMergedTrials)。

对仍在运行的 arm,除了线性投影外,实验详情页还会给出按难度校准的最终通过率投影calibratedFinalPassPct,experiments.ts):把所有同级 arm 的结果当作每个任务的难度信号(smoothed pass rate),对当前 arm 拟合一个 log-odds 技能偏移,再对剩余任务打分——避免"已决子集碰巧全是简单任务"导致 100% 的乐观误报。

原生 Terminal-Bench 2.1 Runner(bench:tb)

bench:tb是独立于 Harbor 和 Docker 的另一种运行方式:它把每个任务发布的 OCI 镜像作为 x86_64 KVM 微虚拟机(microVM)启动在 Vibemon 宿主机上,通过vmon exec --pipe流式传输 omp 的--mode rpc协议,在同一个被修改的 VM 里运行 verifier,并把可恢复的 epoch 与产物写入runs/tb。实现位于 src/tb/(cli、agent、dataset、store、trial、vmon、types 各司其职)。

bun run bench:tb \ --dataset /path/to/terminal-bench-2-1 \ --concurrency 4 --forever --budget 25

工作站默认值的可恢复包装器

对于 README 中说明的实测工作站默认值(七模型池、:floor、concurrency 20),使用可恢复的包装脚本:

bun --cwd packages/metaharness run bench:tb-floor

它写入runs/tb-floor;重复运行会恢复未完成的 epoch,或在完成后开启下一个 epoch。环境变量覆盖:TB_JOBS_DIRTB_CONCURRENCYTB_DATASETTB_BUDGET_USDTB_ATTEMPTSTB_FOREVER=1。额外 CLI flag 会透传并优先于包装器默认值

默认模型池与 OpenRouter 路由

默认七模型池(源码FLASH_POOL见 tb/cli.ts):

  • Ling 3.0 Flash
  • DeepSeek V4 Flash 两个路由(0731 与未版本化/0423)
  • Nemotron 3.5 Lightning
  • Laguna S 2.1
  • Tencent Hy3
  • Step 3.7 Flash

全部通过 OpenRouter 访问。请求默认使用 OpenRouter 的:floor(最便宜 provider)路由;用--openrouter-variant default|nitro|online|exacto覆盖。用重复的--model provider/id替换整个模型池。

基础设施参数

默认目标为工作站的xeon.internalKVM 宿主与本地/work/vibevmmcheckout(--vmon-url默认http://xeon.internal:17970)。runner 在远端副本缺少 raw pipe 支持时会交叉构建并缓存打过补丁的vmon二进制;运行期间自持一个特权 TAP broker,并把回环的 omp auth 网关反向隧道化,确保 provider 凭据永不进入任务 VM。trial agent 使用精简的终端工具 allowlist、edit.mode: replace与低成本的openrouter/qwen/qwen3.7-flashvision 角色,benchmark prompt 中省略通用编排工具。基础设施覆盖参数:

--vmon-host --vmon-source --vmon-bin --vmon-home --vmon-kernel --vmon-agent --gateway-url

完整参数表见 tb/cli.ts 的 HELP 文本。

Harbor Runner 参数一览(节选)

下表完整摘自 README,配合 runner.ts 的 HELP 文本使用:

选项默认值说明
-m, --model <provider/model>anthropic/claude-sonnet-4-6可重复
-l, --tasks <N>20最大任务数
-n, --concurrency <N>4并发 trial 数
-k, --attempts <N>1每任务尝试次数(pass@k)
-d, --dataset <name>terminal-bench@2.0任意 Harbor dataset id
-i/-x, --include/--exclude <glob>任务过滤器(可重复)
--timeout-multiplier <x>缩放任务 agent/verifier 超时
--agent-arg <arg>原样转发给容器内 omp CLI 的额外参数(可重复)
--env <KEY[=VALUE]>转发环境变量进 omp 容器(可重复);仅KEY时转发宿主值
--binary <path>预构建 omp 二进制(arm64+x64 各重复一次)
--install <source\|local\|published>sourcesource= 仓库 bind-mount;local= tarball 打包;published= npm@oh-my-pi/pi-coding-agent
--environment <docker\|apple-container>dockerapple-container用 Apple 的containerCLI 跑 trial(无需 Docker);source/deps 挂载走harbor --mounts,网关从192.168.64.1:4000自动转发到回环绑定的网关
--gateway-url <url>http://host.docker.internal:4000--environment apple-container下为http://192.168.64.1:4000
--no-gateway关闭直接把宿主 provider key 传进容器
-o, --jobs-dir <path><repo>/runs/harbor与 server 共享
--resume <name\|path>通过harbor job resume恢复该 job 目录;原始参数自动恢复
--filter-error-type <T>CancelledError配合--resume:对异常类型为T的已完成 trial 也重跑(可重复)
--dry-run关闭打印 harbor 命令 + models.yml 后退出

补充说明(源码层面):

  • 环境变量注入规则见collectForwardEnv/buildHarborEnv(runner.ts):所有宿主PI_*变量(除目录/profile/session 等容器敌意白名单外)自动转发,显式--env始终优先;配置与密钥通过OMP_BENCH_*环境变量传给agent/omp_local.py
  • --thinking <level>可取off|minimal|low|medium|high|xhigh|max--web-search默认关闭(无法经网关鉴权);
  • docker 后端还提供--cleanup(安全清理退出/已建的 Harbor 容器与空闲 trial 网络)与--cleanup-force(强停并删除所有Harbor 容器与网络),以及实验性的--host-network
  • --install source是单架构的:deps 树与 docker daemon 原生架构一致,仿真镜像(如 arm64 宿主跑 x64 任务)会在 setup 阶段以架构不匹配报错,此类场景应改用--binary

输出产物

一次 Harbor run 结束后,磁盘上会产生以下产物(完整清单见 README):

  • <jobs-dir>/<jobName>/—— Harbor trial 目录(每 trial 一个result.json);
  • <jobs-dir>/_bench/<jobName>/report.md—— markdown 汇总表(数据集 / 模型 / tasks/attempts/concurrency / install 模式 / 通过率 / spend / tokens / 逐任务表,生成逻辑见writeReport,runner.ts);
  • <jobs-dir>/_bench/<jobName>/harbor.log—— Harbor 完整输出;
  • <jobs-dir>/_manager/logs/<jobName>.log—— API 发起 run 的 runner 输出。

此外,--dry-run会打印将要执行的 harbor 命令、生成的models.yml与注入的 omp 环境变量(值隐藏),方便上线前核对配置。

Trace 报告:把一次 run 变成叙事文档

scripts/trace-report.ts把单次 run 的 trace 转成叙事性 markdown 报告:带编号的 Turn Log(每个 assistant 回合配一句有依据的摘要,harness notice 保留原位)、Story Arc,以及失败 run 的 failure analysis。它通过两个便宜的 OpenRouter 模型对归一化 trace 做 map/reduce(默认每回合inclusionai/ling-2.6-flash、arc 用openai/gpt-oss-120b,约 $0.001/报告);API key 通过 omp 的 auth storage 解析。

bun scripts/trace-report.ts <run> <trace> [--focus "reviewer notes"] [--out report.md] bun scripts/trace-report.ts "sb3-ntg|django__django-12325__ddQroP4" # run|trace 也支持

Flags:--base(server 地址,默认http://localhost:4700)、--tiny/--synth<provider>/<model-id>覆盖)、--focus(额外 reviewer 上下文,例如失败任务的已知正确修复)、--concurrency(默认 8)。

Caveats:使用边界与注意事项

  • 网络策略:Harbor 本地 Docker 后端只支持publicregistry;任务容器经宿主网关访问模型。
  • --install source即时反映本地 TS 改动(无需重建),但 Rust natives 从树内packages/natives/native/pi_natives.linux-*.nodeprebuild 加载——Rust 有改动时必须先重建(workspace 加载会跳过版本 sentinel,陈旧的.node会静默运行)。
  • source 模式是单架构的:deps 树匹配 docker daemon 原生架构;仿真镜像上的 trial 会以架构不匹配失败,请改用--binary
  • source 模式下仓库在任务容器内可见(只读):对精选 benchmark 没问题,但不要指向不受信任的任务。
  • Apple Container 特例--environment apple-container需要brew install container && container system start(macOS 26+,Apple silicon);--host-network--cleanup*仅限 docker;bind mount 是读写模式(后端忽略read_only)。
  • --install local反映本地 TS 改动(内联进dist/cli.js),但不含未提交的 Rust natives——先按目标平台重建packages/natives(版本 sentinel 必须匹配)。

相关测试与进一步阅读

  • 服务端 API、launch/resume/删除语义与实验分组均有对应测试:test/server 相关用例、experiments.test.ts、manager.test.ts、runner.test.ts;
  • TB runner 测试:tb-cli.test.ts、tb-dataset.test.ts、tb-store.test.ts;
  • Harbor 侧的容器内 agent 实现:agent/omp_local.py;edit 基准的 adapter 与提示词在 adapters/edit/(含 benchmark-task/system/retry 提示词与 runner);SnapCompact adapter 为 src/adapters/snapcompact.py。

整体上,metaharness把"跑评测、看进度、对指标、出报告"这条链路收敛到了一个服务里:无论评测来源是 Harbor 容器、TypeScript edit 还是 SnapCompact 段落检索,最终都以统一的 run 行、trial 矩阵与 trace 呈现,历史 CLI run 也能被自动发现并纳入同一套查询与可视化体系。

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询