@tangle-network/agent-bench 0.4.1 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/adapters.d.ts +4 -11
- package/dist/adapters.js +78 -41
- package/dist/adapters.js.map +1 -1
- package/dist/benchmarks/_harness.d.ts +48 -66
- package/dist/benchmarks/_harness.js +329 -33
- package/dist/benchmarks/_harness.js.map +1 -1
- package/dist/benchmarks/aec-bench.d.ts +4 -25
- package/dist/benchmarks/aec-bench.js +242 -7
- package/dist/benchmarks/aec-bench.js.map +1 -1
- package/dist/benchmarks/agentbench.d.ts +5 -13
- package/dist/benchmarks/agentbench.js +114 -9
- package/dist/benchmarks/agentbench.js.map +1 -1
- package/dist/benchmarks/appworld.d.ts +9 -29
- package/dist/benchmarks/appworld.js +317 -12
- package/dist/benchmarks/appworld.js.map +1 -1
- package/dist/benchmarks/bfcl.d.ts +5 -15
- package/dist/benchmarks/bfcl.js +264 -9
- package/dist/benchmarks/bfcl.js.map +1 -1
- package/dist/benchmarks/cad-design.d.ts +16 -41
- package/dist/benchmarks/cad-design.js +512 -6
- package/dist/benchmarks/cad-design.js.map +1 -1
- package/dist/benchmarks/cadbench.d.ts +4 -17
- package/dist/benchmarks/cadbench.js +2 -8
- package/dist/benchmarks/cadgenbench.d.ts +4 -20
- package/dist/benchmarks/cadgenbench.js +2 -8
- package/dist/benchmarks/commit0.d.ts +5 -27
- package/dist/benchmarks/commit0.js +187 -9
- package/dist/benchmarks/commit0.js.map +1 -1
- package/dist/benchmarks/crag.d.ts +4 -12
- package/dist/benchmarks/crag.js +110 -8
- package/dist/benchmarks/crag.js.map +1 -1
- package/dist/benchmarks/dabstep.d.ts +5 -15
- package/dist/benchmarks/dabstep.js +177 -9
- package/dist/benchmarks/dabstep.js.map +1 -1
- package/dist/benchmarks/enterpriseops-gym.d.ts +5 -34
- package/dist/benchmarks/enterpriseops-gym.js +236 -9
- package/dist/benchmarks/enterpriseops-gym.js.map +1 -1
- package/dist/benchmarks/finresearchbench.d.ts +4 -13
- package/dist/benchmarks/finresearchbench.js +218 -7
- package/dist/benchmarks/finresearchbench.js.map +1 -1
- package/dist/benchmarks/finsearchcomp.d.ts +8 -39
- package/dist/benchmarks/finsearchcomp.js +267 -6
- package/dist/benchmarks/finsearchcomp.js.map +1 -1
- package/dist/benchmarks/frames.d.ts +15 -37
- package/dist/benchmarks/frames.js +408 -11
- package/dist/benchmarks/frames.js.map +1 -1
- package/dist/benchmarks/hotpotqa.d.ts +4 -24
- package/dist/benchmarks/hotpotqa.js +250 -14
- package/dist/benchmarks/hotpotqa.js.map +1 -1
- package/dist/benchmarks/humaneval.d.ts +19 -37
- package/dist/benchmarks/humaneval.js +279 -16
- package/dist/benchmarks/humaneval.js.map +1 -1
- package/dist/benchmarks/mind2web.d.ts +7 -34
- package/dist/benchmarks/mind2web.js +257 -8
- package/dist/benchmarks/mind2web.js.map +1 -1
- package/dist/benchmarks/nomiracl.d.ts +4 -13
- package/dist/benchmarks/nomiracl.js +146 -8
- package/dist/benchmarks/nomiracl.js.map +1 -1
- package/dist/benchmarks/open-rag-bench.d.ts +4 -12
- package/dist/benchmarks/open-rag-bench.js +110 -8
- package/dist/benchmarks/open-rag-bench.js.map +1 -1
- package/dist/benchmarks/programbench.d.ts +5 -29
- package/dist/benchmarks/programbench.js +161 -9
- package/dist/benchmarks/programbench.js.map +1 -1
- package/dist/benchmarks/rag-shared.d.ts +21 -20
- package/dist/benchmarks/rag-shared.js +245 -38
- package/dist/benchmarks/rag-shared.js.map +1 -1
- package/dist/benchmarks/ragbench.d.ts +4 -14
- package/dist/benchmarks/ragbench.js +127 -8
- package/dist/benchmarks/ragbench.js.map +1 -1
- package/dist/benchmarks/simpleqa.d.ts +17 -44
- package/dist/benchmarks/simpleqa.js +293 -10
- package/dist/benchmarks/simpleqa.js.map +1 -1
- package/dist/benchmarks/swe-bench.d.ts +23 -36
- package/dist/benchmarks/swe-bench.js +234 -13
- package/dist/benchmarks/swe-bench.js.map +1 -1
- package/dist/benchmarks/t2-ragbench.d.ts +4 -12
- package/dist/benchmarks/t2-ragbench.js +118 -8
- package/dist/benchmarks/t2-ragbench.js.map +1 -1
- package/dist/benchmarks/tau-bench-shared.d.ts +14 -22
- package/dist/benchmarks/tau-bench-shared.js +169 -9
- package/dist/benchmarks/tau-bench-shared.js.map +1 -1
- package/dist/benchmarks/tau2-bench.d.ts +5 -5
- package/dist/benchmarks/tau2-bench.js +28 -10
- package/dist/benchmarks/tau2-bench.js.map +1 -1
- package/dist/benchmarks/tau3-banking.d.ts +4 -13
- package/dist/benchmarks/tau3-banking.js +28 -8
- package/dist/benchmarks/tau3-banking.js.map +1 -1
- package/dist/benchmarks/terminal-bench.d.ts +4 -22
- package/dist/benchmarks/terminal-bench.js +140 -7
- package/dist/benchmarks/terminal-bench.js.map +1 -1
- package/dist/benchmarks/toollm.d.ts +5 -13
- package/dist/benchmarks/toollm.js +184 -9
- package/dist/benchmarks/toollm.js.map +1 -1
- package/dist/benchmarks/trata-hedge.d.ts +4 -30
- package/dist/benchmarks/trata-hedge.js +336 -6
- package/dist/benchmarks/trata-hedge.js.map +1 -1
- package/dist/benchmarks/types.d.ts +85 -94
- package/dist/benchmarks/types.js +1 -1
- package/dist/benchmarks/webarena-verified.d.ts +5 -13
- package/dist/benchmarks/webarena-verified.js +152 -9
- package/dist/benchmarks/webarena-verified.js.map +1 -1
- package/dist/cadbench-DpQWZHp4.js +285 -0
- package/dist/cadbench-DpQWZHp4.js.map +1 -0
- package/dist/cadgenbench-DRhczfsG.js +151 -0
- package/dist/cadgenbench-DRhczfsG.js.map +1 -0
- package/dist/index.d.ts +245 -293
- package/dist/index.js +1669 -1791
- package/dist/index.js.map +1 -1
- package/package.json +18 -15
- package/scripts/verify-packed-consumer.mjs +20 -17
- package/src/corpus.test.mts +13 -0
- package/src/corpus.ts +4 -0
- package/src/pier-trial-controller.test.mts +15 -7
- package/src/profile-coordinates.ts +2 -2
- package/src/rollout-ledger/backfill-swe-arena.mts +5 -1
- package/src/rollout-ledger/settle-capture.mts +7 -1
- package/src/search-bench/profiles.ts +1 -1
- package/src/skill-sandbox-smoke.mts +2 -1
- package/src/swe-arena/gepa-seat.mts +1 -1
- package/src/swe-arena/ledger-orphans.test.mts +36 -34
- package/dist/benchmarks/cadbench.js.map +0 -1
- package/dist/benchmarks/cadgenbench.js.map +0 -1
- package/dist/benchmarks/types.js.map +0 -1
- package/dist/chunk-53UPUNBZ.js +0 -325
- package/dist/chunk-53UPUNBZ.js.map +0 -1
- package/dist/chunk-5FEQDSCT.js +0 -211
- package/dist/chunk-5FEQDSCT.js.map +0 -1
- package/dist/chunk-5H5XV76F.js +0 -240
- package/dist/chunk-5H5XV76F.js.map +0 -1
- package/dist/chunk-67ACKDCX.js +0 -118
- package/dist/chunk-67ACKDCX.js.map +0 -1
- package/dist/chunk-7FKBWOQT.js +0 -147
- package/dist/chunk-7FKBWOQT.js.map +0 -1
- package/dist/chunk-BEN6IF2X.js +0 -221
- package/dist/chunk-BEN6IF2X.js.map +0 -1
- package/dist/chunk-BZY5QARD.js +0 -120
- package/dist/chunk-BZY5QARD.js.map +0 -1
- package/dist/chunk-C7T7WEK2.js +0 -103
- package/dist/chunk-C7T7WEK2.js.map +0 -1
- package/dist/chunk-CLIKAXKH.js +0 -276
- package/dist/chunk-CLIKAXKH.js.map +0 -1
- package/dist/chunk-CWIOBFSP.js +0 -197
- package/dist/chunk-CWIOBFSP.js.map +0 -1
- package/dist/chunk-CXDUTWQE.js +0 -318
- package/dist/chunk-CXDUTWQE.js.map +0 -1
- package/dist/chunk-DWALFME7.js +0 -182
- package/dist/chunk-DWALFME7.js.map +0 -1
- package/dist/chunk-EEOC6QPJ.js +0 -144
- package/dist/chunk-EEOC6QPJ.js.map +0 -1
- package/dist/chunk-EIETHPD5.js +0 -321
- package/dist/chunk-EIETHPD5.js.map +0 -1
- package/dist/chunk-GC2EPS6L.js +0 -130
- package/dist/chunk-GC2EPS6L.js.map +0 -1
- package/dist/chunk-GCHL6XPM.js +0 -169
- package/dist/chunk-GCHL6XPM.js.map +0 -1
- package/dist/chunk-HQ5HCCKF.js +0 -142
- package/dist/chunk-HQ5HCCKF.js.map +0 -1
- package/dist/chunk-HVW25KSX.js +0 -208
- package/dist/chunk-HVW25KSX.js.map +0 -1
- package/dist/chunk-INNOYXCP.js +0 -387
- package/dist/chunk-INNOYXCP.js.map +0 -1
- package/dist/chunk-J6BU3NTM.js +0 -251
- package/dist/chunk-J6BU3NTM.js.map +0 -1
- package/dist/chunk-JSQOUKXS.js +0 -149
- package/dist/chunk-JSQOUKXS.js.map +0 -1
- package/dist/chunk-JTHWEDEW.js +0 -32
- package/dist/chunk-JTHWEDEW.js.map +0 -1
- package/dist/chunk-NRMGT25X.js +0 -116
- package/dist/chunk-NRMGT25X.js.map +0 -1
- package/dist/chunk-PA2ZKHJC.js +0 -230
- package/dist/chunk-PA2ZKHJC.js.map +0 -1
- package/dist/chunk-PUIRNYI7.js +0 -189
- package/dist/chunk-PUIRNYI7.js.map +0 -1
- package/dist/chunk-QZZEAHWJ.js +0 -136
- package/dist/chunk-QZZEAHWJ.js.map +0 -1
- package/dist/chunk-SEVJPLZC.js +0 -260
- package/dist/chunk-SEVJPLZC.js.map +0 -1
- package/dist/chunk-TBKU5XQI.js +0 -228
- package/dist/chunk-TBKU5XQI.js.map +0 -1
- package/dist/chunk-UPAMRDX4.js +0 -233
- package/dist/chunk-UPAMRDX4.js.map +0 -1
- package/dist/chunk-VQRS7VUC.js +0 -342
- package/dist/chunk-VQRS7VUC.js.map +0 -1
- package/dist/chunk-WG7TM7UV.js +0 -30
- package/dist/chunk-WG7TM7UV.js.map +0 -1
- package/dist/chunk-X3BTXCJ4.js +0 -262
- package/dist/chunk-X3BTXCJ4.js.map +0 -1
- package/dist/chunk-XXFF3RRD.js +0 -162
- package/dist/chunk-XXFF3RRD.js.map +0 -1
- package/dist/chunk-ZFNOM7WR.js +0 -27
- package/dist/chunk-ZFNOM7WR.js.map +0 -1
- package/dist/chunk-ZNCCYTFG.js +0 -170
- package/dist/chunk-ZNCCYTFG.js.map +0 -1
|
@@ -1,9 +1,111 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from "
|
|
4
|
-
import "
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { benchRoot } from "./_harness.js";
|
|
2
|
+
import { FINAL_ANSWER_SENTINEL, allStrings, answerScoreToBenchScore, contextBlock, contextsFrom, firstString, isObject, ragAnswerOutput, readJsonRows, scoreAnswerArtifact, selectTasks, stringFrom } from "./rag-shared.js";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
//#region src/benchmarks/open-rag-bench.ts
|
|
6
|
+
/**
|
|
7
|
+
* Open RAG Bench adapter.
|
|
8
|
+
*
|
|
9
|
+
* This targets Vectara-style Open RAG Bench exports over PDF-derived text,
|
|
10
|
+
* table, and image contexts. The deterministic judge scores final-answer
|
|
11
|
+
* agreement and surfaces modality/document metadata for diagnostics.
|
|
12
|
+
*/
|
|
13
|
+
const FIXTURES = join(benchRoot, "fixtures", "open-rag-bench.json");
|
|
14
|
+
const dataFile = () => process.env.OPEN_RAG_BENCH_DATA_FILE;
|
|
15
|
+
function rowToTask(raw, index) {
|
|
16
|
+
if (!isObject(raw)) throw new Error(`Open RAG Bench row ${index} must be an object`);
|
|
17
|
+
const query = firstString(raw, [
|
|
18
|
+
"question",
|
|
19
|
+
"query",
|
|
20
|
+
"prompt"
|
|
21
|
+
]);
|
|
22
|
+
const goldAnswers = allStrings(raw, [
|
|
23
|
+
"answer",
|
|
24
|
+
"answers",
|
|
25
|
+
"reference",
|
|
26
|
+
"reference_answer",
|
|
27
|
+
"gold"
|
|
28
|
+
]);
|
|
29
|
+
if (!query) throw new Error(`Open RAG Bench row ${index} missing question/query`);
|
|
30
|
+
if (goldAnswers.length === 0) throw new Error(`Open RAG Bench row ${index} missing answer`);
|
|
31
|
+
const contexts = contextsFrom(raw.contexts).length > 0 ? contextsFrom(raw.contexts) : contextsFrom(raw.chunks).length > 0 ? contextsFrom(raw.chunks) : contextsFrom(raw.pages);
|
|
32
|
+
const documentId = stringFrom(raw.document_id) ?? stringFrom(raw.doc_id) ?? stringFrom(raw.pdf_id) ?? stringFrom(raw.file_name) ?? stringFrom(raw.filename) ?? "unknown";
|
|
33
|
+
const modality = stringFrom(raw.modality) ?? stringFrom(raw.answer_modality) ?? "unknown";
|
|
34
|
+
const id = stringFrom(raw.id) ?? stringFrom(raw.query_id) ?? `open-rag-bench-${index}`;
|
|
35
|
+
const meta = {
|
|
36
|
+
benchmark: "open-rag-bench",
|
|
37
|
+
query,
|
|
38
|
+
goldAnswers,
|
|
39
|
+
contexts,
|
|
40
|
+
documentId,
|
|
41
|
+
modality
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
id,
|
|
45
|
+
split: stringFrom(raw.split) ?? modality,
|
|
46
|
+
prompt: [
|
|
47
|
+
"Answer this Open RAG Bench PDF question using the supplied document context.",
|
|
48
|
+
"Use tables, text, and image-derived notes when present.",
|
|
49
|
+
"End with a single final line: `FINAL ANSWER: <answer>`.",
|
|
50
|
+
"",
|
|
51
|
+
`Question: ${query}`,
|
|
52
|
+
`Document: ${documentId}`,
|
|
53
|
+
`Modality: ${modality}`,
|
|
54
|
+
contexts.length > 0 ? `\nDocument context:\n${contextBlock(contexts)}` : void 0
|
|
55
|
+
].filter(Boolean).join("\n"),
|
|
56
|
+
metadata: meta
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function readMeta(task) {
|
|
60
|
+
const md = task.metadata;
|
|
61
|
+
if (!md || !Array.isArray(md.goldAnswers)) throw new Error(`Open RAG Bench task ${task.id} missing metadata — loadTasks did not populate it`);
|
|
62
|
+
return md;
|
|
63
|
+
}
|
|
64
|
+
async function loadRows(path) {
|
|
65
|
+
const rows = await readJsonRows(path);
|
|
66
|
+
if (rows.length === 0) throw new Error(`Open RAG Bench: no rows in ${path}`);
|
|
67
|
+
return rows;
|
|
68
|
+
}
|
|
69
|
+
async function loadFixtures(opts) {
|
|
70
|
+
const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
|
|
71
|
+
console.warn(`[open-rag-bench] OPEN_RAG_BENCH_FIXTURES=1 — loading ${rows.length} adapter fixtures`);
|
|
72
|
+
return selectTasks(rows.map(rowToTask), opts, "Open RAG Bench");
|
|
73
|
+
}
|
|
74
|
+
function createOpenRagBenchAdapter() {
|
|
75
|
+
const fixturesMode = process.env.OPEN_RAG_BENCH_FIXTURES === "1";
|
|
76
|
+
return {
|
|
77
|
+
name: "open-rag-bench",
|
|
78
|
+
output: ragAnswerOutput,
|
|
79
|
+
async preflight() {
|
|
80
|
+
if (fixturesMode) {
|
|
81
|
+
await readFile(FIXTURES, "utf8");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const path = dataFile();
|
|
85
|
+
if (!path) throw new Error("OPEN_RAG_BENCH_DATA_FILE is required. Fix: export vectara/open-rag-bench rows to JSONL and set OPEN_RAG_BENCH_DATA_FILE=/path/to/open-rag-bench.jsonl, or set OPEN_RAG_BENCH_FIXTURES=1 for adapter plumbing.");
|
|
86
|
+
await loadRows(path);
|
|
87
|
+
},
|
|
88
|
+
async loadTasks(opts = {}) {
|
|
89
|
+
if (fixturesMode) return loadFixtures(opts);
|
|
90
|
+
const path = dataFile();
|
|
91
|
+
if (!path) throw new Error("OPEN_RAG_BENCH_DATA_FILE is required to load Open RAG Bench tasks");
|
|
92
|
+
return selectTasks((await loadRows(path)).map(rowToTask), opts, "Open RAG Bench");
|
|
93
|
+
},
|
|
94
|
+
async goldArtifact(task) {
|
|
95
|
+
return `${FINAL_ANSWER_SENTINEL} ${readMeta(task).goldAnswers[0] ?? ""}`;
|
|
96
|
+
},
|
|
97
|
+
async judge(task, artifact) {
|
|
98
|
+
const meta = readMeta(task);
|
|
99
|
+
return answerScoreToBenchScore(scoreAnswerArtifact(artifact, meta.goldAnswers), {
|
|
100
|
+
benchmark: meta.benchmark,
|
|
101
|
+
documentId: meta.documentId,
|
|
102
|
+
modality: meta.modality,
|
|
103
|
+
contextCount: meta.contexts.length
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
export { createOpenRagBenchAdapter };
|
|
110
|
+
|
|
9
111
|
//# sourceMappingURL=open-rag-bench.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"open-rag-bench.js","names":[],"sources":["../../src/benchmarks/open-rag-bench.ts"],"sourcesContent":["/**\n * Open RAG Bench adapter.\n *\n * This targets Vectara-style Open RAG Bench exports over PDF-derived text,\n * table, and image contexts. The deterministic judge scores final-answer\n * agreement and surfaces modality/document metadata for diagnostics.\n */\n\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { benchRoot } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\nimport {\n FINAL_ANSWER_SENTINEL,\n allStrings,\n answerScoreToBenchScore,\n contextBlock,\n contextsFrom,\n firstString,\n isObject,\n ragAnswerOutput,\n readJsonRows,\n scoreAnswerArtifact,\n selectTasks,\n stringFrom,\n type RagContext,\n} from './rag-shared'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'open-rag-bench.json')\n\ninterface OpenRagBenchMeta {\n benchmark: 'open-rag-bench'\n query: string\n goldAnswers: string[]\n contexts: RagContext[]\n documentId: string\n modality: string\n}\n\nconst dataFile = (): string | undefined => process.env.OPEN_RAG_BENCH_DATA_FILE\n\nfunction rowToTask(raw: unknown, index: number): BenchTask {\n if (!isObject(raw)) throw new Error(`Open RAG Bench row ${index} must be an object`)\n const query = firstString(raw, ['question', 'query', 'prompt'])\n const goldAnswers = allStrings(raw, ['answer', 'answers', 'reference', 'reference_answer', 'gold'])\n if (!query) throw new Error(`Open RAG Bench row ${index} missing question/query`)\n if (goldAnswers.length === 0) throw new Error(`Open RAG Bench row ${index} missing answer`)\n const contexts =\n contextsFrom(raw.contexts).length > 0\n ? contextsFrom(raw.contexts)\n : contextsFrom(raw.chunks).length > 0\n ? contextsFrom(raw.chunks)\n : contextsFrom(raw.pages)\n const documentId =\n stringFrom(raw.document_id) ??\n stringFrom(raw.doc_id) ??\n stringFrom(raw.pdf_id) ??\n stringFrom(raw.file_name) ??\n stringFrom(raw.filename) ??\n 'unknown'\n const modality = stringFrom(raw.modality) ?? stringFrom(raw.answer_modality) ?? 'unknown'\n const id = stringFrom(raw.id) ?? stringFrom(raw.query_id) ?? `open-rag-bench-${index}`\n const meta: OpenRagBenchMeta = {\n benchmark: 'open-rag-bench',\n query,\n goldAnswers,\n contexts,\n documentId,\n modality,\n }\n return {\n id,\n split: stringFrom(raw.split) ?? modality,\n prompt: [\n 'Answer this Open RAG Bench PDF question using the supplied document context.',\n 'Use tables, text, and image-derived notes when present.',\n 'End with a single final line: `FINAL ANSWER: <answer>`.',\n '',\n `Question: ${query}`,\n `Document: ${documentId}`,\n `Modality: ${modality}`,\n contexts.length > 0 ? `\\nDocument context:\\n${contextBlock(contexts)}` : undefined,\n ]\n .filter(Boolean)\n .join('\\n'),\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): OpenRagBenchMeta {\n const md = task.metadata\n if (!md || !Array.isArray(md.goldAnswers)) {\n throw new Error(`Open RAG Bench task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as OpenRagBenchMeta\n}\n\nasync function loadRows(path: string): Promise<unknown[]> {\n const rows = await readJsonRows(path)\n if (rows.length === 0) throw new Error(`Open RAG Bench: no rows in ${path}`)\n return rows\n}\n\nasync function loadFixtures(opts: LoadOptions): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(FIXTURES, 'utf8')) as unknown[]\n console.warn(`[open-rag-bench] OPEN_RAG_BENCH_FIXTURES=1 — loading ${rows.length} adapter fixtures`)\n return selectTasks(rows.map(rowToTask), opts, 'Open RAG Bench')\n}\n\nexport function createOpenRagBenchAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.OPEN_RAG_BENCH_FIXTURES === '1'\n\n return {\n name: 'open-rag-bench',\n output: ragAnswerOutput,\n\n async preflight() {\n if (fixturesMode) {\n await readFile(FIXTURES, 'utf8')\n return\n }\n const path = dataFile()\n if (!path) {\n throw new Error(\n 'OPEN_RAG_BENCH_DATA_FILE is required. Fix: export vectara/open-rag-bench rows to JSONL and set OPEN_RAG_BENCH_DATA_FILE=/path/to/open-rag-bench.jsonl, or set OPEN_RAG_BENCH_FIXTURES=1 for adapter plumbing.',\n )\n }\n await loadRows(path)\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n if (fixturesMode) return loadFixtures(opts)\n const path = dataFile()\n if (!path) throw new Error('OPEN_RAG_BENCH_DATA_FILE is required to load Open RAG Bench tasks')\n return selectTasks((await loadRows(path)).map(rowToTask), opts, 'Open RAG Bench')\n },\n\n async goldArtifact(task: BenchTask) {\n return `${FINAL_ANSWER_SENTINEL} ${readMeta(task).goldAnswers[0] ?? ''}`\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const score = scoreAnswerArtifact(artifact, meta.goldAnswers)\n return answerScoreToBenchScore(score, {\n benchmark: meta.benchmark,\n documentId: meta.documentId,\n modality: meta.modality,\n contextCount: meta.contexts.length,\n })\n },\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,31 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* ProgramBench adapter (facebookresearch/ProgramBench) — cleanroom
|
|
6
|
-
* reverse-engineering: rebuild a black-box executable's behavior from scratch.
|
|
7
|
-
* The agent is given only the gold `./executable` (run-only) + stripped docs and
|
|
8
|
-
* must produce a `submission.tar.gz` whose `./compile.sh` builds an `./executable`
|
|
9
|
-
* with identical observable behavior. Judge = the official `programbench`
|
|
10
|
-
* harness: it extracts the submission, runs compile.sh in the per-task cleanroom
|
|
11
|
-
* Docker image, then runs the HIDDEN behavioral pytest suites (pulled via
|
|
12
|
-
* `programbench blob sync`). Score = fraction of non-ignored tests passed
|
|
13
|
-
* (GRADED, applying the tests.json ignore mask); resolved = all non-ignored tests
|
|
14
|
-
* pass. Fully deterministic — no LLM judge.
|
|
15
|
-
*
|
|
16
|
-
* OutputAdapter is stream-only, so the worker emits its codebase as fenced
|
|
17
|
-
* `path:`-prefixed file blocks (including compile.sh); the adapter materializes
|
|
18
|
-
* those into submission.tar.gz. Test execution is delegated to the real
|
|
19
|
-
* `programbench eval`/`info` harness — pytest scoring + the ignore mask are NOT
|
|
20
|
-
* reimplemented here.
|
|
21
|
-
*
|
|
22
|
-
* Requires for a live run: the bench `.venv` with `programbench` installed +
|
|
23
|
-
* Docker on linux/amd64 (per-task `<image>:task_cleanroom` images) + HF access for
|
|
24
|
-
* the hidden test blobs. For offline/CI listing set PROGRAMBENCH_FIXTURES=1 to load
|
|
25
|
-
* the committed instance ids (bench/fixtures/programbench.json); judging still
|
|
26
|
-
* needs the harness + Docker and fails loud without them — never a fabricated score.
|
|
27
|
-
*/
|
|
28
|
-
|
|
1
|
+
import { BenchmarkAdapter } from "./types.js";
|
|
2
|
+
import { OutputAdapter } from "@tangle-network/agent-runtime/loops";
|
|
3
|
+
//#region src/benchmarks/programbench.d.ts
|
|
29
4
|
/**
|
|
30
5
|
* Parse the worker stream into the submission text the driver materializes: the
|
|
31
6
|
* concatenation of every ```path:<p>``` fenced block. Passed through verbatim to
|
|
@@ -34,5 +9,6 @@ import { BenchmarkAdapter } from './types.js';
|
|
|
34
9
|
*/
|
|
35
10
|
declare const programbenchSubmissionOutput: OutputAdapter<string>;
|
|
36
11
|
declare function createProgrambenchAdapter(): BenchmarkAdapter;
|
|
37
|
-
|
|
12
|
+
//#endregion
|
|
38
13
|
export { createProgrambenchAdapter, programbenchSubmissionOutput };
|
|
14
|
+
//# sourceMappingURL=programbench.d.ts.map
|
|
@@ -1,10 +1,162 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { benchRoot, preflightVenvImports, runVenvScriptStdin } from "./_harness.js";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
//#region src/benchmarks/programbench.ts
|
|
5
|
+
/**
|
|
6
|
+
* ProgramBench adapter (facebookresearch/ProgramBench) — cleanroom
|
|
7
|
+
* reverse-engineering: rebuild a black-box executable's behavior from scratch.
|
|
8
|
+
* The agent is given only the gold `./executable` (run-only) + stripped docs and
|
|
9
|
+
* must produce a `submission.tar.gz` whose `./compile.sh` builds an `./executable`
|
|
10
|
+
* with identical observable behavior. Judge = the official `programbench`
|
|
11
|
+
* harness: it extracts the submission, runs compile.sh in the per-task cleanroom
|
|
12
|
+
* Docker image, then runs the HIDDEN behavioral pytest suites (pulled via
|
|
13
|
+
* `programbench blob sync`). Score = fraction of non-ignored tests passed
|
|
14
|
+
* (GRADED, applying the tests.json ignore mask); resolved = all non-ignored tests
|
|
15
|
+
* pass. Fully deterministic — no LLM judge.
|
|
16
|
+
*
|
|
17
|
+
* OutputAdapter is stream-only, so the worker emits its codebase as fenced
|
|
18
|
+
* `path:`-prefixed file blocks (including compile.sh); the adapter materializes
|
|
19
|
+
* those into submission.tar.gz. Test execution is delegated to the real
|
|
20
|
+
* `programbench eval`/`info` harness — pytest scoring + the ignore mask are NOT
|
|
21
|
+
* reimplemented here.
|
|
22
|
+
*
|
|
23
|
+
* Requires for a live run: the bench `.venv` with `programbench` installed +
|
|
24
|
+
* Docker on linux/amd64 (per-task `<image>:task_cleanroom` images) + HF access for
|
|
25
|
+
* the hidden test blobs. For offline/CI listing set PROGRAMBENCH_FIXTURES=1 to load
|
|
26
|
+
* the committed instance ids (bench/fixtures/programbench.json); judging still
|
|
27
|
+
* needs the harness + Docker and fails loud without them — never a fabricated score.
|
|
28
|
+
*/
|
|
29
|
+
const FIXTURES = join(benchRoot, "fixtures", "programbench.json");
|
|
30
|
+
const TESTS_DATASET = "programbench/ProgramBench-Tests";
|
|
31
|
+
const TREE_API = `https://huggingface.co/api/datasets/${TESTS_DATASET}/tree/main`;
|
|
32
|
+
const PROMPT = [
|
|
33
|
+
"This is a cleanroom reverse-engineering task. You are given a compiled black-box `./executable` (run-only) and stripped documentation in the workspace.",
|
|
34
|
+
"Write an ORIGINAL codebase from scratch that, when built, produces an `./executable` with byte-for-byte identical observable behavior (stdout/stderr/exit codes/filesystem effects) to the original. You may run `./executable` to probe its behavior.",
|
|
35
|
+
"You MUST include a `./compile.sh` at the workspace root that builds your source into `./executable` at the workspace root.",
|
|
36
|
+
"Emit your COMPLETE submission as the LAST thing in your reply: one fenced block per file, each opening fence line being exactly ```path:<relative/path>``` followed by the file contents, then a closing fence. Include compile.sh and every source file. Nothing after the final closing fence."
|
|
37
|
+
].join("\n");
|
|
38
|
+
function fixtureToTask(f) {
|
|
39
|
+
const meta = {
|
|
40
|
+
instanceId: f.instance_id,
|
|
41
|
+
imageName: f.image_name
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
id: f.instance_id,
|
|
45
|
+
prompt: PROMPT,
|
|
46
|
+
metadata: meta
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function readMeta(task) {
|
|
50
|
+
const md = task.metadata;
|
|
51
|
+
if (!md || typeof md.instanceId !== "string") throw new Error(`programbench task ${task.id} missing metadata.instanceId — loadTasks did not populate it`);
|
|
52
|
+
return md;
|
|
53
|
+
}
|
|
54
|
+
function selectTasks(fixtures, opts) {
|
|
55
|
+
let tasks = fixtures.map(fixtureToTask);
|
|
56
|
+
if (opts.ids) {
|
|
57
|
+
const want = new Set(opts.ids);
|
|
58
|
+
tasks = tasks.filter((t) => want.has(t.id));
|
|
59
|
+
} else if (opts.limit !== void 0) tasks = tasks.slice(0, opts.limit);
|
|
60
|
+
return tasks;
|
|
61
|
+
}
|
|
62
|
+
/** `owner__repo.commit` → DockerHub image name `owner/repo` for `<image>:task_cleanroom`. */
|
|
63
|
+
function imageName(instanceId) {
|
|
64
|
+
return instanceId.split(".")[0].replace("__", "/");
|
|
65
|
+
}
|
|
66
|
+
async function loadFixtures(opts) {
|
|
67
|
+
const fixtures = JSON.parse(await readFile(FIXTURES, "utf8"));
|
|
68
|
+
console.warn(`[programbench] PROGRAMBENCH_FIXTURES=1 — loading ${fixtures.length} committed instance ids from ${FIXTURES} (no HF tree fetch)`);
|
|
69
|
+
return selectTasks(fixtures, opts);
|
|
70
|
+
}
|
|
71
|
+
/** Enumerate real instance ids from the HF Tests dataset tree (one dir per
|
|
72
|
+
* instance). Throws on a non-OK response (fail loud). */
|
|
73
|
+
async function fetchInstanceIds() {
|
|
74
|
+
const res = await fetch(TREE_API);
|
|
75
|
+
if (!res.ok) throw new Error(`programbench tree HTTP ${res.status}: ${TREE_API}`);
|
|
76
|
+
const ids = (await res.json()).filter((e) => e.type === "directory" && e.path.includes("__")).map((e) => e.path);
|
|
77
|
+
if (ids.length === 0) throw new Error(`programbench: no instance dirs in ${TESTS_DATASET} tree`);
|
|
78
|
+
return ids.map((id) => ({
|
|
79
|
+
instance_id: id,
|
|
80
|
+
image_name: imageName(id)
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Run the official programbench harness for one instance over the worker's
|
|
85
|
+
* file-manifest submission. The driver builds the run-dir layout (one folder
|
|
86
|
+
* holding submission.tar.gz), runs `programbench blob sync` + `programbench eval`,
|
|
87
|
+
* then parses <instance_id>.eval.json applying the tests.json ignore mask via
|
|
88
|
+
* `programbench info` logic. Emits {passed,total,resolved} as the last stdout line.
|
|
89
|
+
*/
|
|
90
|
+
async function runHarness(meta, submission) {
|
|
91
|
+
const judge = join(benchRoot, "scripts", "programbench_judge.py");
|
|
92
|
+
let stdout;
|
|
93
|
+
try {
|
|
94
|
+
stdout = await runVenvScriptStdin(judge, ["--instance", meta.instanceId], submission, { cwd: benchRoot });
|
|
95
|
+
} catch (err) {
|
|
96
|
+
const e = err;
|
|
97
|
+
throw new Error(`programbench harness failed for ${meta.instanceId}: ${(e.message || String(err)).slice(0, 1500)}`);
|
|
98
|
+
}
|
|
99
|
+
const report = JSON.parse(stdout.trim().split("\n").at(-1) ?? "{}");
|
|
100
|
+
if (report.error) throw new Error(`programbench harness error for ${meta.instanceId}: ${report.error}`);
|
|
101
|
+
if (typeof report.passed !== "number" || typeof report.total !== "number") throw new Error(`programbench judge returned no {passed,total}: ${stdout.slice(0, 400)}`);
|
|
102
|
+
const score = report.total > 0 ? report.passed / report.total : 0;
|
|
103
|
+
return {
|
|
104
|
+
resolved: report.resolved ?? (report.total > 0 && report.passed === report.total),
|
|
105
|
+
score,
|
|
106
|
+
detail: JSON.stringify({
|
|
107
|
+
instanceId: meta.instanceId,
|
|
108
|
+
passed: report.passed,
|
|
109
|
+
total: report.total
|
|
110
|
+
})
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Parse the worker stream into the submission text the driver materializes: the
|
|
115
|
+
* concatenation of every ```path:<p>``` fenced block. Passed through verbatim to
|
|
116
|
+
* the python driver, which tars it. Empty when the worker emitted no file block
|
|
117
|
+
* (fail-closed → the harness scores a missing compile.sh as 0).
|
|
118
|
+
*/
|
|
119
|
+
const programbenchSubmissionOutput = { parse(events) {
|
|
120
|
+
let text = "";
|
|
121
|
+
for (const ev of events) {
|
|
122
|
+
const d = ev?.data;
|
|
123
|
+
const t = d?.finalText ?? d?.text ?? d?.result;
|
|
124
|
+
if (typeof t === "string" && t.length > 0) text = t;
|
|
125
|
+
}
|
|
126
|
+
const blocks = [...text.matchAll(/```path:([^\n`]+)\n([\s\S]*?)```/g)];
|
|
127
|
+
if (blocks.length === 0) return "";
|
|
128
|
+
return blocks.map((m) => `===FILE:${m[1].trim()}===\n${m[2]}`).join("\n");
|
|
129
|
+
} };
|
|
130
|
+
function createProgrambenchAdapter() {
|
|
131
|
+
const fixturesMode = process.env.PROGRAMBENCH_FIXTURES === "1";
|
|
132
|
+
return {
|
|
133
|
+
name: "programbench",
|
|
134
|
+
output: programbenchSubmissionOutput,
|
|
135
|
+
async preflight() {
|
|
136
|
+
await preflightVenvImports({
|
|
137
|
+
modules: ["programbench"],
|
|
138
|
+
requireDocker: true,
|
|
139
|
+
fix: "Fix: (1) python3 -m venv bench/.venv && bench/.venv/bin/pip install programbench ; (2) Docker on linux/amd64 (per-task <image>:task_cleanroom images; will NOT run on ARM) ; (3) HF access for the hidden test blobs (the driver runs `programbench blob sync`). Set PROGRAMBENCH_FIXTURES=1 to list the committed instance ids offline."
|
|
140
|
+
});
|
|
141
|
+
},
|
|
142
|
+
async loadTasks(opts = {}) {
|
|
143
|
+
if (fixturesMode) return loadFixtures(opts);
|
|
144
|
+
let fixtures;
|
|
145
|
+
try {
|
|
146
|
+
fixtures = await fetchInstanceIds();
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.warn(`[programbench] live tree fetch failed (${err instanceof Error ? err.message : err}); falling back to committed fixtures at ${FIXTURES}`);
|
|
149
|
+
return loadFixtures(opts);
|
|
150
|
+
}
|
|
151
|
+
return selectTasks(fixtures, opts);
|
|
152
|
+
},
|
|
153
|
+
async goldArtifact() {},
|
|
154
|
+
async judge(task, artifact) {
|
|
155
|
+
return runHarness(readMeta(task), artifact);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//#endregion
|
|
160
|
+
export { createProgrambenchAdapter, programbenchSubmissionOutput };
|
|
161
|
+
|
|
10
162
|
//# sourceMappingURL=programbench.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"file":"programbench.js","names":[],"sources":["../../src/benchmarks/programbench.ts"],"sourcesContent":["/**\n * ProgramBench adapter (facebookresearch/ProgramBench) — cleanroom\n * reverse-engineering: rebuild a black-box executable's behavior from scratch.\n * The agent is given only the gold `./executable` (run-only) + stripped docs and\n * must produce a `submission.tar.gz` whose `./compile.sh` builds an `./executable`\n * with identical observable behavior. Judge = the official `programbench`\n * harness: it extracts the submission, runs compile.sh in the per-task cleanroom\n * Docker image, then runs the HIDDEN behavioral pytest suites (pulled via\n * `programbench blob sync`). Score = fraction of non-ignored tests passed\n * (GRADED, applying the tests.json ignore mask); resolved = all non-ignored tests\n * pass. Fully deterministic — no LLM judge.\n *\n * OutputAdapter is stream-only, so the worker emits its codebase as fenced\n * `path:`-prefixed file blocks (including compile.sh); the adapter materializes\n * those into submission.tar.gz. Test execution is delegated to the real\n * `programbench eval`/`info` harness — pytest scoring + the ignore mask are NOT\n * reimplemented here.\n *\n * Requires for a live run: the bench `.venv` with `programbench` installed +\n * Docker on linux/amd64 (per-task `<image>:task_cleanroom` images) + HF access for\n * the hidden test blobs. For offline/CI listing set PROGRAMBENCH_FIXTURES=1 to load\n * the committed instance ids (bench/fixtures/programbench.json); judging still\n * needs the harness + Docker and fails loud without them — never a fabricated score.\n */\n\nimport { join } from 'node:path'\nimport { readFile } from 'node:fs/promises'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport { benchRoot, preflightVenvImports, runVenvScriptStdin } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'programbench.json')\n\nconst TESTS_DATASET = 'programbench/ProgramBench-Tests'\nconst TREE_API = `https://huggingface.co/api/datasets/${TESTS_DATASET}/tree/main`\n\ninterface PbFixture {\n instance_id: string\n image_name: string\n note?: string\n}\n\ninterface PbMeta {\n instanceId: string\n imageName: string\n}\n\nconst PROMPT = [\n 'This is a cleanroom reverse-engineering task. You are given a compiled black-box `./executable` (run-only) and stripped documentation in the workspace.',\n 'Write an ORIGINAL codebase from scratch that, when built, produces an `./executable` with byte-for-byte identical observable behavior (stdout/stderr/exit codes/filesystem effects) to the original. You may run `./executable` to probe its behavior.',\n 'You MUST include a `./compile.sh` at the workspace root that builds your source into `./executable` at the workspace root.',\n 'Emit your COMPLETE submission as the LAST thing in your reply: one fenced block per file, each opening fence line being exactly ```path:<relative/path>``` followed by the file contents, then a closing fence. Include compile.sh and every source file. Nothing after the final closing fence.',\n].join('\\n')\n\nfunction fixtureToTask(f: PbFixture): BenchTask {\n const meta: PbMeta = { instanceId: f.instance_id, imageName: f.image_name }\n return {\n id: f.instance_id,\n prompt: PROMPT,\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): PbMeta {\n const md = task.metadata\n if (!md || typeof md.instanceId !== 'string') {\n throw new Error(`programbench task ${task.id} missing metadata.instanceId — loadTasks did not populate it`)\n }\n return md as unknown as PbMeta\n}\n\nfunction selectTasks(fixtures: PbFixture[], opts: LoadOptions): BenchTask[] {\n let tasks = fixtures.map(fixtureToTask)\n if (opts.ids) {\n const want = new Set(opts.ids)\n tasks = tasks.filter((t) => want.has(t.id))\n } else if (opts.limit !== undefined) {\n tasks = tasks.slice(0, opts.limit)\n }\n return tasks\n}\n\n/** `owner__repo.commit` → DockerHub image name `owner/repo` for `<image>:task_cleanroom`. */\nfunction imageName(instanceId: string): string {\n return instanceId.split('.')[0].replace('__', '/')\n}\n\nasync function loadFixtures(opts: LoadOptions): Promise<BenchTask[]> {\n const fixtures = JSON.parse(await readFile(FIXTURES, 'utf8')) as PbFixture[]\n console.warn(\n `[programbench] PROGRAMBENCH_FIXTURES=1 — loading ${fixtures.length} committed instance ids from ${FIXTURES} (no HF tree fetch)`,\n )\n return selectTasks(fixtures, opts)\n}\n\n/** Enumerate real instance ids from the HF Tests dataset tree (one dir per\n * instance). Throws on a non-OK response (fail loud). */\nasync function fetchInstanceIds(): Promise<PbFixture[]> {\n const res = await fetch(TREE_API)\n if (!res.ok) throw new Error(`programbench tree HTTP ${res.status}: ${TREE_API}`)\n const tree = (await res.json()) as Array<{ path: string; type: string }>\n const ids = tree.filter((e) => e.type === 'directory' && e.path.includes('__')).map((e) => e.path)\n if (ids.length === 0) throw new Error(`programbench: no instance dirs in ${TESTS_DATASET} tree`)\n return ids.map((id) => ({ instance_id: id, image_name: imageName(id) }))\n}\n\n/**\n * Run the official programbench harness for one instance over the worker's\n * file-manifest submission. The driver builds the run-dir layout (one folder\n * holding submission.tar.gz), runs `programbench blob sync` + `programbench eval`,\n * then parses <instance_id>.eval.json applying the tests.json ignore mask via\n * `programbench info` logic. Emits {passed,total,resolved} as the last stdout line.\n */\nasync function runHarness(meta: PbMeta, submission: string): Promise<BenchScore> {\n const judge = join(benchRoot, 'scripts', 'programbench_judge.py')\n let stdout: string\n try {\n // The submission manifest is piped to the driver's stdin via the shared\n // stdin-aware runner — execFile's `input` option is not honored async and\n // hangs the driver's sys.stdin.read() forever.\n stdout = await runVenvScriptStdin(judge, ['--instance', meta.instanceId], submission, { cwd: benchRoot })\n } catch (err) {\n const e = err as { message?: string }\n throw new Error(`programbench harness failed for ${meta.instanceId}: ${(e.message || String(err)).slice(0, 1500)}`)\n }\n const report = JSON.parse(stdout.trim().split('\\n').at(-1) ?? '{}') as {\n passed?: number\n total?: number\n resolved?: boolean\n error?: string\n }\n if (report.error) throw new Error(`programbench harness error for ${meta.instanceId}: ${report.error}`)\n if (typeof report.passed !== 'number' || typeof report.total !== 'number') {\n throw new Error(`programbench judge returned no {passed,total}: ${stdout.slice(0, 400)}`)\n }\n const score = report.total > 0 ? report.passed / report.total : 0\n return {\n resolved: report.resolved ?? (report.total > 0 && report.passed === report.total),\n score,\n detail: JSON.stringify({ instanceId: meta.instanceId, passed: report.passed, total: report.total }),\n }\n}\n\n/**\n * Parse the worker stream into the submission text the driver materializes: the\n * concatenation of every ```path:<p>``` fenced block. Passed through verbatim to\n * the python driver, which tars it. Empty when the worker emitted no file block\n * (fail-closed → the harness scores a missing compile.sh as 0).\n */\nexport const programbenchSubmissionOutput: OutputAdapter<string> = {\n parse(events) {\n let text = ''\n for (const ev of events) {\n const d = (ev as { data?: Record<string, unknown> })?.data\n const t = d?.finalText ?? d?.text ?? d?.result\n if (typeof t === 'string' && t.length > 0) text = t\n }\n const blocks = [...text.matchAll(/```path:([^\\n`]+)\\n([\\s\\S]*?)```/g)]\n if (blocks.length === 0) return ''\n // Re-serialize in the same path:<p> envelope the driver splits on.\n return blocks.map((m) => `===FILE:${m[1].trim()}===\\n${m[2]}`).join('\\n')\n },\n}\n\nexport function createProgrambenchAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.PROGRAMBENCH_FIXTURES === '1'\n\n return {\n name: 'programbench',\n output: programbenchSubmissionOutput,\n\n async preflight() {\n await preflightVenvImports({\n modules: ['programbench'],\n requireDocker: true,\n fix:\n `Fix: (1) python3 -m venv bench/.venv && bench/.venv/bin/pip install programbench ; ` +\n `(2) Docker on linux/amd64 (per-task <image>:task_cleanroom images; will NOT run on ARM) ; ` +\n `(3) HF access for the hidden test blobs (the driver runs \\`programbench blob sync\\`). ` +\n `Set PROGRAMBENCH_FIXTURES=1 to list the committed instance ids offline.`,\n })\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n if (fixturesMode) return loadFixtures(opts)\n let fixtures: PbFixture[]\n try {\n fixtures = await fetchInstanceIds()\n } catch (err) {\n console.warn(\n `[programbench] live tree fetch failed (${err instanceof Error ? err.message : err}); falling back to committed fixtures at ${FIXTURES}`,\n )\n return loadFixtures(opts)\n }\n return selectTasks(fixtures, opts)\n },\n\n async goldArtifact() {\n // The oracle is the original repo's source (stripped from the task image),\n // not redistributable as a portable submission string. Judge correctness is\n // proven by running the real harness on a real solve, not a synthetic gold.\n return undefined\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n return runHarness(meta, artifact)\n },\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { BenchScore, BenchTask, LoadOptions } from "./types.js";
|
|
2
|
+
import { OutputAdapter } from "@tangle-network/agent-runtime/loops";
|
|
3
|
+
//#region src/benchmarks/rag-shared.d.ts
|
|
4
4
|
declare const FINAL_ANSWER_SENTINEL = "FINAL ANSWER:";
|
|
5
5
|
interface RagContext {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
id: string;
|
|
7
|
+
text: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
source?: string;
|
|
10
|
+
relevant?: boolean;
|
|
11
11
|
}
|
|
12
12
|
interface RagAnswerScore {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
resolved: boolean;
|
|
14
|
+
score: number;
|
|
15
|
+
finalAnswer: string;
|
|
16
|
+
bestGold: string | null;
|
|
17
|
+
exact: boolean;
|
|
18
|
+
numeric: boolean;
|
|
19
|
+
f1: number;
|
|
20
|
+
threshold: number;
|
|
21
21
|
}
|
|
22
22
|
declare const ragAnswerOutput: OutputAdapter<string>;
|
|
23
23
|
declare function parseFinalAnswer(artifact: string): string;
|
|
@@ -25,8 +25,8 @@ declare function parseCitations(artifact: string): string[];
|
|
|
25
25
|
declare function normalizeAnswer(input: string): string;
|
|
26
26
|
declare function tokenF1(candidate: string, gold: string): number;
|
|
27
27
|
declare function scoreAnswerArtifact(artifact: string, golds: readonly string[], options?: {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
threshold?: number;
|
|
29
|
+
numericTolerance?: number;
|
|
30
30
|
}): RagAnswerScore;
|
|
31
31
|
declare function answerScoreToBenchScore(score: RagAnswerScore, detail: Record<string, unknown>): BenchScore;
|
|
32
32
|
declare function readJsonRows(path: string): Promise<unknown[]>;
|
|
@@ -38,5 +38,6 @@ declare function allStrings(row: Record<string, unknown>, keys: readonly string[
|
|
|
38
38
|
declare function contextsFrom(value: unknown): RagContext[];
|
|
39
39
|
declare function contextBlock(contexts: readonly RagContext[]): string;
|
|
40
40
|
declare function isObject(value: unknown): value is Record<string, unknown>;
|
|
41
|
-
|
|
42
|
-
export { FINAL_ANSWER_SENTINEL,
|
|
41
|
+
//#endregion
|
|
42
|
+
export { FINAL_ANSWER_SENTINEL, RagAnswerScore, RagContext, allStrings, answerScoreToBenchScore, contextBlock, contextsFrom, firstString, isObject, normalizeAnswer, parseCitations, parseFinalAnswer, ragAnswerOutput, readJsonRows, scoreAnswerArtifact, selectTasks, stringArrayFrom, stringFrom, tokenF1 };
|
|
43
|
+
//# sourceMappingURL=rag-shared.d.ts.map
|