conjugate / scripts /bench.ts
Ryukijano's picture
Deploy 77868c1: premise gate and live source checks (LIVE_RETRIEVAL=on) (part 2)
76a204b verified
Raw History Blame Contribute Delete
1.75 kB
import { writeFile } from 'node:fs/promises';
import { BenchmarkArmSchema } from '@her2/shared';
import { runBenchmark } from '../apps/api/src/bench.js';
// Usage: npm run bench -- --offline | --live [--max-calls N] [--arms plain_claude,harness_claude,harness_rules] [--out evals/benchmark.json]
const argv = process.argv.slice(2);
const flag = (name: string) => { const index = argv.indexOf(name); return index >= 0 ? argv[index + 1] : undefined; };
const live = argv.includes('--live');
if (live === argv.includes('--offline')) throw new Error('Pass exactly one of --offline or --live.');
const maxCalls = Number(flag('--max-calls') ?? 220);
const arms = flag('--arms')?.split(',').map(arm => BenchmarkArmSchema.parse(arm.trim()));
const out = new URL(flag('--out') ?? '../evals/benchmark.json', flag('--out') ? `file://${process.cwd()}/` : import.meta.url);
let done = 0;
const apiKey = process.env.ANTHROPIC_API_KEY;
const model = process.env.CLAUDE_MODEL;
const artifact = await runBenchmark({
mode: live ? 'live' : 'offline', maxCalls, ...(arms ? { arms } : {}), ...(apiKey ? { apiKey } : {}), ...(model ? { model } : {}),
onRow: row => { done++; if (live) console.error(`${done} ${row.arm} ${row.item_id} ${row.outcome}`); }
});
await writeFile(out, JSON.stringify(artifact, null, 2) + '\n');
const totals = Object.fromEntries(artifact.arms.map(arm => [arm, Object.values(artifact.summary[arm] ?? {}).reduce((sum, cell) => ({ n: sum.n + cell.n, correct: sum.correct + cell.correct, errors: sum.errors + cell.errors }), { n: 0, correct: 0, errors: 0 })]));
console.log(JSON.stringify({ mode: artifact.mode, items: artifact.items.length, calls_used: artifact.budget.calls_used, max_calls: artifact.budget.max_calls, retries: 0, totals }));