@tangle-network/agent-bench 0.4.1 → 0.4.3
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 +9 -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 +17 -14
- package/scripts/verify-packed-consumer.mjs +20 -17
- package/src/corpus.test.mts +13 -0
- package/src/corpus.ts +4 -0
- 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
package/dist/chunk-5H5XV76F.js
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
// src/benchmarks/humaneval.ts
|
|
2
|
-
import { execFile } from "child_process";
|
|
3
|
-
import { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
4
|
-
import { tmpdir } from "os";
|
|
5
|
-
import { join } from "path";
|
|
6
|
-
import { gunzipSync } from "zlib";
|
|
7
|
-
var humanevalUrl = "https://github.com/openai/human-eval/raw/master/data/HumanEval.jsonl.gz";
|
|
8
|
-
var dockerImage = "python:3.12-slim";
|
|
9
|
-
var dockerTimeoutMs = Number(process.env.DOCKER_TIMEOUT_MS ?? 2e4);
|
|
10
|
-
async function loadHumanEval(limit, offset = 0) {
|
|
11
|
-
const localGz = process.env.HUMANEVAL_GZ;
|
|
12
|
-
let gz;
|
|
13
|
-
if (localGz) {
|
|
14
|
-
gz = readFileSync(localGz);
|
|
15
|
-
} else {
|
|
16
|
-
const res = await fetch(humanevalUrl);
|
|
17
|
-
if (!res.ok) throw new Error(`HumanEval fetch HTTP ${res.status}: ${humanevalUrl}`);
|
|
18
|
-
gz = Buffer.from(await res.arrayBuffer());
|
|
19
|
-
}
|
|
20
|
-
const text = gunzipSync(gz).toString("utf8");
|
|
21
|
-
const tasks = [];
|
|
22
|
-
for (const line of text.split("\n")) {
|
|
23
|
-
if (line.trim() === "") continue;
|
|
24
|
-
const d = JSON.parse(line);
|
|
25
|
-
if (!d.task_id || !d.prompt || !d.test || !d.entry_point) {
|
|
26
|
-
throw new Error(`malformed HumanEval record: ${line.slice(0, 120)}`);
|
|
27
|
-
}
|
|
28
|
-
tasks.push({
|
|
29
|
-
taskId: d.task_id,
|
|
30
|
-
prompt: d.prompt,
|
|
31
|
-
test: d.test,
|
|
32
|
-
entryPoint: d.entry_point,
|
|
33
|
-
...d.canonical_solution ? { canonicalSolution: d.canonical_solution } : {}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
if (tasks.length === 0) throw new Error("HumanEval parsed to 0 tasks");
|
|
37
|
-
if (offset >= tasks.length) throw new Error(`OFFSET ${offset} >= dataset size ${tasks.length}`);
|
|
38
|
-
return tasks.slice(offset, offset + limit);
|
|
39
|
-
}
|
|
40
|
-
var solveInstruction = "Complete the following Python function. Output the COMPLETE function definition (signature, docstring optional, body) inside a single ```python code block. Include any imports the function needs. Do not write tests or example calls.";
|
|
41
|
-
function basePrompt(task) {
|
|
42
|
-
return `${solveInstruction}
|
|
43
|
-
|
|
44
|
-
\`\`\`python
|
|
45
|
-
${task.prompt}\`\`\``;
|
|
46
|
-
}
|
|
47
|
-
function extractCode(reply) {
|
|
48
|
-
const fenced = reply.match(/```(?:python|py)?\s*\n([\s\S]*?)```/i);
|
|
49
|
-
if (fenced && typeof fenced[1] === "string") return fenced[1].trim();
|
|
50
|
-
return reply.trim();
|
|
51
|
-
}
|
|
52
|
-
function buildProgram(task, candidate) {
|
|
53
|
-
return `${task.prompt}
|
|
54
|
-
${candidate}
|
|
55
|
-
|
|
56
|
-
${task.test}
|
|
57
|
-
|
|
58
|
-
check(${task.entryPoint})
|
|
59
|
-
`;
|
|
60
|
-
}
|
|
61
|
-
var dockerRunSeq = 0;
|
|
62
|
-
function runPythonProgram(program, timeoutMs = dockerTimeoutMs) {
|
|
63
|
-
const dir = mkdtempSync(join(tmpdir(), "hev-"));
|
|
64
|
-
chmodSync(dir, 493);
|
|
65
|
-
writeFileSync(join(dir, "p.py"), program, { mode: 420 });
|
|
66
|
-
const name = `hev-${process.pid}-${dockerRunSeq++}`;
|
|
67
|
-
const startMarker = `__AGENT_RUNTIME_CANDIDATE_STARTED_${name}__`;
|
|
68
|
-
return new Promise((resolvePromise, reject) => {
|
|
69
|
-
let settled = false;
|
|
70
|
-
const cleanup = () => {
|
|
71
|
-
rmSync(dir, { recursive: true, force: true });
|
|
72
|
-
execFile("docker", ["rm", "-f", name], () => {
|
|
73
|
-
});
|
|
74
|
-
};
|
|
75
|
-
const finish = (res) => {
|
|
76
|
-
if (settled) return;
|
|
77
|
-
settled = true;
|
|
78
|
-
clearTimeout(backstop);
|
|
79
|
-
cleanup();
|
|
80
|
-
resolvePromise(res);
|
|
81
|
-
};
|
|
82
|
-
const fail = (e) => {
|
|
83
|
-
if (settled) return;
|
|
84
|
-
settled = true;
|
|
85
|
-
clearTimeout(backstop);
|
|
86
|
-
cleanup();
|
|
87
|
-
reject(e);
|
|
88
|
-
};
|
|
89
|
-
const outerTimeoutMs = timeoutMs + 3e3;
|
|
90
|
-
const backstop = setTimeout(
|
|
91
|
-
() => fail(new Error(`docker checker did not return within ${outerTimeoutMs + 3e3}ms`)),
|
|
92
|
-
outerTimeoutMs + 3e3
|
|
93
|
-
);
|
|
94
|
-
const inContainerSeconds = Math.max(1, Math.ceil(timeoutMs / 1e3));
|
|
95
|
-
execFile(
|
|
96
|
-
"docker",
|
|
97
|
-
[
|
|
98
|
-
"run",
|
|
99
|
-
"--rm",
|
|
100
|
-
"--pull=never",
|
|
101
|
-
"--name",
|
|
102
|
-
name,
|
|
103
|
-
"--network=none",
|
|
104
|
-
"--cpus=1",
|
|
105
|
-
"--memory=512m",
|
|
106
|
-
"--pids-limit=64",
|
|
107
|
-
"--cap-drop=ALL",
|
|
108
|
-
"--security-opt=no-new-privileges",
|
|
109
|
-
"--read-only",
|
|
110
|
-
"--tmpfs",
|
|
111
|
-
"/tmp:rw,nosuid,nodev,noexec,size=64m,mode=1777",
|
|
112
|
-
"--user",
|
|
113
|
-
"65534:65534",
|
|
114
|
-
"-v",
|
|
115
|
-
`${dir}:/w:ro`,
|
|
116
|
-
"-w",
|
|
117
|
-
"/w",
|
|
118
|
-
dockerImage,
|
|
119
|
-
"sh",
|
|
120
|
-
"-c",
|
|
121
|
-
'command -v timeout >/dev/null 2>&1 && command -v python >/dev/null 2>&1 && [ -r /w/p.py ] || exit 126; printf "%s\\n" "$1"; exec timeout -s KILL "$2" python /w/p.py',
|
|
122
|
-
"agent-runtime-checker",
|
|
123
|
-
startMarker,
|
|
124
|
-
`${inContainerSeconds}s`
|
|
125
|
-
],
|
|
126
|
-
{ timeout: outerTimeoutMs, killSignal: "SIGKILL", maxBuffer: 4 * 1024 * 1024 },
|
|
127
|
-
(err, stdout, stderr) => {
|
|
128
|
-
const markerLine = `${startMarker}
|
|
129
|
-
`;
|
|
130
|
-
const candidateStarted = stdout?.startsWith(markerLine) === true;
|
|
131
|
-
const candidateStdout = candidateStarted ? stdout.slice(markerLine.length) : stdout ?? "";
|
|
132
|
-
if (err) {
|
|
133
|
-
const e = err;
|
|
134
|
-
if (e.code === "ENOENT") {
|
|
135
|
-
fail(new Error("docker binary not found on PATH \u2014 cannot run the deployable checker"));
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
if (e.killed) {
|
|
139
|
-
fail(new Error(`docker checker exceeded its ${outerTimeoutMs}ms outer timeout`));
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
if (!candidateStarted) {
|
|
143
|
-
if (/cannot connect to the docker daemon|is the docker daemon running|permission denied while trying to connect/i.test(
|
|
144
|
-
stderr
|
|
145
|
-
)) {
|
|
146
|
-
fail(new Error(`docker daemon unreachable: ${stderr.slice(0, 200)}`));
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
if (/unable to find image|no such image|pull access denied|manifest unknown/i.test(stderr)) {
|
|
150
|
-
fail(new Error(`docker image ${dockerImage} unavailable: ${stderr.slice(0, 200)}`));
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
fail(
|
|
154
|
-
new Error(
|
|
155
|
-
`docker checker did not start the candidate: ${stderr.slice(0, 200) || e.message}`
|
|
156
|
-
)
|
|
157
|
-
);
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
const exitCode = typeof e.code === "number" ? e.code : 1;
|
|
161
|
-
finish({
|
|
162
|
-
exitCode,
|
|
163
|
-
stdout: candidateStdout,
|
|
164
|
-
stderr: stderr ?? ""
|
|
165
|
-
});
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (!candidateStarted) {
|
|
169
|
-
fail(new Error("docker checker exited without starting the candidate"));
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
finish({ exitCode: 0, stdout: candidateStdout, stderr: stderr ?? "" });
|
|
173
|
-
}
|
|
174
|
-
);
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
async function runChecker(task, candidate) {
|
|
178
|
-
const result = await runPythonProgram(buildProgram(task, candidate));
|
|
179
|
-
return result.exitCode === 0 ? { pass: 1 } : { pass: 0, detail: result.stderr.slice(-600) || "timed out (no output)" };
|
|
180
|
-
}
|
|
181
|
-
function toBenchTask(t) {
|
|
182
|
-
const metadata = {
|
|
183
|
-
promptHeader: t.prompt,
|
|
184
|
-
test: t.test,
|
|
185
|
-
entryPoint: t.entryPoint,
|
|
186
|
-
...t.canonicalSolution ? { canonicalSolution: t.canonicalSolution } : {}
|
|
187
|
-
};
|
|
188
|
-
return { id: t.taskId, prompt: basePrompt(t), metadata };
|
|
189
|
-
}
|
|
190
|
-
function taskFromMeta(task) {
|
|
191
|
-
const m = task.metadata;
|
|
192
|
-
if (!m?.promptHeader || !m.test || !m.entryPoint) {
|
|
193
|
-
throw new Error(`HumanEval judge: task ${task.id} missing checker metadata`);
|
|
194
|
-
}
|
|
195
|
-
return { taskId: task.id, prompt: m.promptHeader, test: m.test, entryPoint: m.entryPoint };
|
|
196
|
-
}
|
|
197
|
-
function createHumanEvalAdapter() {
|
|
198
|
-
return {
|
|
199
|
-
name: "humaneval",
|
|
200
|
-
async preflight() {
|
|
201
|
-
await new Promise((resolve, reject) => {
|
|
202
|
-
execFile("docker", ["version", "--format", "{{.Server.Version}}"], (err) => {
|
|
203
|
-
if (err) reject(new Error("HumanEval judge needs a running Docker daemon (python:3.12-slim, --network=none)"));
|
|
204
|
-
else resolve();
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
await new Promise((resolve, reject) => {
|
|
208
|
-
execFile("docker", ["image", "inspect", dockerImage], (err) => {
|
|
209
|
-
if (err) reject(new Error(`HumanEval judge needs the cached Docker image ${dockerImage}`));
|
|
210
|
-
else resolve();
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
},
|
|
214
|
-
async loadTasks(opts) {
|
|
215
|
-
const offset = Number(process.env.OFFSET ?? 0);
|
|
216
|
-
const all = await loadHumanEval(opts?.ids ? 164 : opts?.limit ?? 8, offset);
|
|
217
|
-
const picked = opts?.ids ? all.filter((t) => opts.ids?.includes(t.taskId)) : all;
|
|
218
|
-
return picked.map(toBenchTask);
|
|
219
|
-
},
|
|
220
|
-
async judge(task, artifact) {
|
|
221
|
-
const { pass } = await runChecker(taskFromMeta(task), extractCode(artifact));
|
|
222
|
-
return { resolved: pass === 1, score: pass, detail: pass === 1 ? "tests passed" : "tests failed" };
|
|
223
|
-
},
|
|
224
|
-
async goldArtifact(task) {
|
|
225
|
-
const m = task.metadata;
|
|
226
|
-
const sol = m?.canonicalSolution;
|
|
227
|
-
return sol ? `${m.promptHeader}${sol}` : void 0;
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export {
|
|
233
|
-
loadHumanEval,
|
|
234
|
-
basePrompt,
|
|
235
|
-
extractCode,
|
|
236
|
-
runPythonProgram,
|
|
237
|
-
runChecker,
|
|
238
|
-
createHumanEvalAdapter
|
|
239
|
-
};
|
|
240
|
-
//# sourceMappingURL=chunk-5H5XV76F.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/benchmarks/humaneval.ts"],"sourcesContent":["/**\n * HumanEval adapter — the deployable-checker domain as a `BenchmarkAdapter`, so the\n * gate runner (`runGate`) can A/B the STEERING regime on it: a real rollout\n * through the `Supervisor` that self-corrects across rounds, vs blind\n * random@k. This is the experiment `humaneval-gate.mts` names as \"the next one\" —\n * the gate measures SELECTION over stateless single completions; this measures\n * whether observe→steer (self-correction) beats blind compute at equal k.\n *\n * Worker artifact = the model's reply (a Python function, fenced or raw). The\n * DETERMINISTIC judge runs the candidate against the task's own `test` in an\n * isolated `--network=none` python container — exit 0 = pass. No gold\n * `canonical_solution` is ever shown to the model; `goldArtifact` returns it only\n * to self-verify the judge before spending tokens.\n *\n * The primitives (loader / extractor / Docker checker) live here and are reused by\n * `humaneval-gate.mts` — one home, no duplication.\n */\n\nimport { execFile } from 'node:child_process'\nimport { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { gunzipSync } from 'node:zlib'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst humanevalUrl = 'https://github.com/openai/human-eval/raw/master/data/HumanEval.jsonl.gz'\nconst dockerImage = 'python:3.12-slim'\nconst dockerTimeoutMs = Number(process.env.DOCKER_TIMEOUT_MS ?? 20000)\n\nexport interface HumanEvalTask {\n taskId: string\n prompt: string\n test: string\n entryPoint: string\n /** Reference solution body — used ONLY to self-verify the judge, never shown to the worker. */\n canonicalSolution?: string\n}\n\n/** Pull the 164-task HumanEval JSONL.gz and parse it. Fail loud on a non-OK fetch\n * or a malformed line — a silently-short task set would poison the gate. `offset`\n * selects a deeper slice (the later tasks are harder) so the worker has a\n * correctable middle band rather than a saturated easy prefix. */\nexport async function loadHumanEval(limit: number, offset = 0): Promise<HumanEvalTask[]> {\n // Prefer a locally-cached .jsonl.gz (HUMANEVAL_GZ) — the GitHub raw URL rate-limits\n // (429) under repeated runs. Fall back to the network fetch when unset.\n const localGz = process.env.HUMANEVAL_GZ\n let gz: Buffer\n if (localGz) {\n gz = readFileSync(localGz)\n } else {\n const res = await fetch(humanevalUrl)\n if (!res.ok) throw new Error(`HumanEval fetch HTTP ${res.status}: ${humanevalUrl}`)\n gz = Buffer.from(await res.arrayBuffer())\n }\n const text = gunzipSync(gz).toString('utf8')\n const tasks: HumanEvalTask[] = []\n for (const line of text.split('\\n')) {\n if (line.trim() === '') continue\n const d = JSON.parse(line) as {\n task_id?: string\n prompt?: string\n test?: string\n entry_point?: string\n canonical_solution?: string\n }\n if (!d.task_id || !d.prompt || !d.test || !d.entry_point) {\n throw new Error(`malformed HumanEval record: ${line.slice(0, 120)}`)\n }\n tasks.push({\n taskId: d.task_id,\n prompt: d.prompt,\n test: d.test,\n entryPoint: d.entry_point,\n ...(d.canonical_solution ? { canonicalSolution: d.canonical_solution } : {}),\n })\n }\n if (tasks.length === 0) throw new Error('HumanEval parsed to 0 tasks')\n if (offset >= tasks.length) throw new Error(`OFFSET ${offset} >= dataset size ${tasks.length}`)\n return tasks.slice(offset, offset + limit)\n}\n\nconst solveInstruction =\n 'Complete the following Python function. Output the COMPLETE function definition (signature, docstring optional, body) inside a single ```python code block. Include any imports the function needs. Do not write tests or example calls.'\n\nexport function basePrompt(task: HumanEvalTask): string {\n return `${solveInstruction}\\n\\n\\`\\`\\`python\\n${task.prompt}\\`\\`\\``\n}\n\n/** Extract the function source from a model reply: prefer a fenced ```python (or\n * bare ```) block, else fall back to the raw text. The deployable program adds the\n * prompt header (imports + signature context), so a candidate that returns only a\n * body still runs; a candidate that re-defines the function shadows the header. */\nexport function extractCode(reply: string): string {\n const fenced = reply.match(/```(?:python|py)?\\s*\\n([\\s\\S]*?)```/i)\n if (fenced && typeof fenced[1] === 'string') return fenced[1].trim()\n return reply.trim()\n}\n\n/** The deployable test program: the prompt header (imports + signature/docstring the\n * model was given), then the candidate (its def shadows the header's stub), then the\n * task's own check() suite and the call. No gold solution anywhere. */\nfunction buildProgram(task: HumanEvalTask, candidate: string): string {\n return `${task.prompt}\\n${candidate}\\n\\n${task.test}\\n\\ncheck(${task.entryPoint})\\n`\n}\n\nexport interface CheckResult {\n /** {0,1} pass-count for this candidate (1 = the check() suite passed). */\n pass: number\n /** On failure: the interpreter stderr tail (traceback / failing assertion). The\n * execution-grounded feedback a self-repair loop steers on; ignored by selection. */\n detail?: string\n}\n\nexport interface PythonProgramResult {\n exitCode: number\n stdout: string\n stderr: string\n}\n\n/** Run one candidate's deployable test program in an isolated container:\n * read-only root, bounded writable `/tmp`, no network, one CPU, and 512 MiB.\n * Exit 0 → pass. A docker invocation error (binary missing, daemon down, image\n * unavailable) is NOT a test failure — it throws so the harness fails loud rather\n * than scoring every candidate 0 from a broken checker. */\nlet dockerRunSeq = 0\n\n/** Run arbitrary Python in the same isolated container used by the HumanEval\n * checker. This is also the execution-tool primitive for experiments that let\n * a model test its own snippets; model-written code must never run on the host. */\nexport function runPythonProgram(\n program: string,\n timeoutMs = dockerTimeoutMs,\n): Promise<PythonProgramResult> {\n const dir = mkdtempSync(join(tmpdir(), 'hev-'))\n // Rootless Docker maps container root to a subordinate host uid that cannot\n // traverse mkdtemp's default 0700 directory. The directory contains only the\n // disposable candidate script and is mounted read-only into the container.\n chmodSync(dir, 0o755)\n writeFileSync(join(dir, 'p.py'), program, { mode: 0o644 })\n // Unique container name so we can force-reap it regardless of the docker client's state.\n const name = `hev-${process.pid}-${dockerRunSeq++}`\n const startMarker = `__AGENT_RUNTIME_CANDIDATE_STARTED_${name}__`\n return new Promise<PythonProgramResult>((resolvePromise, reject) => {\n let settled = false\n const cleanup = () => {\n rmSync(dir, { recursive: true, force: true })\n // `execFile`'s `timeout` kills the docker CLIENT, not the container — a hung\n // `python` would otherwise pin a CPU forever. Force-reap by name (fire-and-forget;\n // the name is unique, so no reuse race).\n execFile('docker', ['rm', '-f', name], () => {})\n }\n const finish = (res: PythonProgramResult) => {\n if (settled) return\n settled = true\n clearTimeout(backstop)\n cleanup()\n resolvePromise(res)\n }\n const fail = (e: Error) => {\n if (settled) return\n settled = true\n clearTimeout(backstop)\n cleanup()\n reject(e)\n }\n // Candidate timeouts are enforced inside the container. If the outer Docker\n // client or daemon misses this larger deadline, that is infrastructure failure,\n // not a wrong answer.\n const outerTimeoutMs = timeoutMs + 3_000\n const backstop = setTimeout(\n () => fail(new Error(`docker checker did not return within ${outerTimeoutMs + 3_000}ms`)),\n outerTimeoutMs + 3_000,\n )\n const inContainerSeconds = Math.max(1, Math.ceil(timeoutMs / 1_000))\n execFile(\n 'docker',\n [\n 'run',\n '--rm',\n '--pull=never',\n '--name',\n name,\n '--network=none',\n '--cpus=1',\n '--memory=512m',\n '--pids-limit=64',\n '--cap-drop=ALL',\n '--security-opt=no-new-privileges',\n '--read-only',\n '--tmpfs',\n '/tmp:rw,nosuid,nodev,noexec,size=64m,mode=1777',\n '--user',\n '65534:65534',\n '-v',\n `${dir}:/w:ro`,\n '-w',\n '/w',\n dockerImage,\n 'sh',\n '-c',\n 'command -v timeout >/dev/null 2>&1 && command -v python >/dev/null 2>&1 && [ -r /w/p.py ] || exit 126; printf \"%s\\\\n\" \"$1\"; exec timeout -s KILL \"$2\" python /w/p.py',\n 'agent-runtime-checker',\n startMarker,\n `${inContainerSeconds}s`,\n ],\n { timeout: outerTimeoutMs, killSignal: 'SIGKILL', maxBuffer: 4 * 1024 * 1024 },\n (err, stdout, stderr) => {\n const markerLine = `${startMarker}\\n`\n const candidateStarted = stdout?.startsWith(markerLine) === true\n const candidateStdout = candidateStarted ? stdout.slice(markerLine.length) : (stdout ?? '')\n if (err) {\n const e = err as Error & { killed?: boolean; code?: number | string }\n if (e.code === 'ENOENT') {\n fail(new Error('docker binary not found on PATH — cannot run the deployable checker'))\n return\n }\n if (e.killed) {\n fail(new Error(`docker checker exceeded its ${outerTimeoutMs}ms outer timeout`))\n return\n }\n if (!candidateStarted) {\n if (\n /cannot connect to the docker daemon|is the docker daemon running|permission denied while trying to connect/i.test(\n stderr,\n )\n ) {\n fail(new Error(`docker daemon unreachable: ${stderr.slice(0, 200)}`))\n return\n }\n if (/unable to find image|no such image|pull access denied|manifest unknown/i.test(stderr)) {\n fail(new Error(`docker image ${dockerImage} unavailable: ${stderr.slice(0, 200)}`))\n return\n }\n fail(\n new Error(\n `docker checker did not start the candidate: ${stderr.slice(0, 200) || e.message}`,\n ),\n )\n return\n }\n const exitCode = typeof e.code === 'number' ? e.code : 1\n finish({\n exitCode,\n stdout: candidateStdout,\n stderr: stderr ?? '',\n })\n return\n }\n if (!candidateStarted) {\n fail(new Error('docker checker exited without starting the candidate'))\n return\n }\n finish({ exitCode: 0, stdout: candidateStdout, stderr: stderr ?? '' })\n },\n )\n })\n}\n\nexport async function runChecker(task: HumanEvalTask, candidate: string): Promise<CheckResult> {\n const result = await runPythonProgram(buildProgram(task, candidate))\n return result.exitCode === 0\n ? { pass: 1 }\n : { pass: 0, detail: result.stderr.slice(-600) || 'timed out (no output)' }\n}\n\n/** A HumanEval task carries its checker inputs in metadata so the deterministic\n * judge can rebuild the deployable program from a `BenchTask` alone. */\ninterface HumanEvalMeta extends Record<string, unknown> {\n promptHeader: string\n test: string\n entryPoint: string\n canonicalSolution?: string\n}\n\nfunction toBenchTask(t: HumanEvalTask): BenchTask {\n const metadata: HumanEvalMeta = {\n promptHeader: t.prompt,\n test: t.test,\n entryPoint: t.entryPoint,\n ...(t.canonicalSolution ? { canonicalSolution: t.canonicalSolution } : {}),\n }\n return { id: t.taskId, prompt: basePrompt(t), metadata }\n}\n\nfunction taskFromMeta(task: BenchTask): HumanEvalTask {\n const m = task.metadata as HumanEvalMeta | undefined\n if (!m?.promptHeader || !m.test || !m.entryPoint) {\n throw new Error(`HumanEval judge: task ${task.id} missing checker metadata`)\n }\n return { taskId: task.id, prompt: m.promptHeader, test: m.test, entryPoint: m.entryPoint }\n}\n\n/** The HumanEval `BenchmarkAdapter`. OFFSET (env) selects the correctable middle\n * band; loadTasks honors `limit`/`ids`. The judge is the Docker deployable checker. */\nexport function createHumanEvalAdapter(): BenchmarkAdapter {\n return {\n name: 'humaneval',\n async preflight() {\n // Prove the daemon and exact local image before any model call. Scoring uses\n // --pull=never so a registry or cold pull cannot become a candidate outcome.\n await new Promise<void>((resolve, reject) => {\n execFile('docker', ['version', '--format', '{{.Server.Version}}'], (err) => {\n if (err) reject(new Error('HumanEval judge needs a running Docker daemon (python:3.12-slim, --network=none)'))\n else resolve()\n })\n })\n await new Promise<void>((resolve, reject) => {\n execFile('docker', ['image', 'inspect', dockerImage], (err) => {\n if (err) reject(new Error(`HumanEval judge needs the cached Docker image ${dockerImage}`))\n else resolve()\n })\n })\n },\n async loadTasks(opts?: LoadOptions) {\n const offset = Number(process.env.OFFSET ?? 0)\n // Pull a generous window when filtering by id, else exactly `limit` from offset.\n const all = await loadHumanEval(opts?.ids ? 164 : (opts?.limit ?? 8), offset)\n const picked = opts?.ids ? all.filter((t) => opts.ids?.includes(t.taskId)) : all\n return picked.map(toBenchTask)\n },\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const { pass } = await runChecker(taskFromMeta(task), extractCode(artifact))\n return { resolved: pass === 1, score: pass, detail: pass === 1 ? 'tests passed' : 'tests failed' }\n },\n async goldArtifact(task: BenchTask) {\n const m = task.metadata as HumanEvalMeta | undefined\n const sol = m?.canonicalSolution\n // Return the COMPLETE function (signature header + canonical body), i.e. what a\n // real worker emits — NOT the body alone. The judge runs `extractCode`, whose\n // unfenced fallback is `reply.trim()`; trimming a body-only string strips its\n // leading indent and breaks it, so a body-only gold fails its own judge. A full\n // def starts at column 0, trims safely, and self-verifies.\n return sol ? `${m!.promptHeader}${sol}` : undefined\n },\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-67ACKDCX.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
benchRoot
|
|
3
|
-
} from "./chunk-EIETHPD5.js";
|
|
4
|
-
|
|
5
|
-
// src/benchmarks/agentbench.ts
|
|
6
|
-
import { readFile } from "fs/promises";
|
|
7
|
-
import { join } from "path";
|
|
8
|
-
var FIXTURES = join(benchRoot, "fixtures", "agentbench-dbbench.json");
|
|
9
|
-
var DEFAULT_SPLIT = "dev";
|
|
10
|
-
var agentbenchDir = () => process.env.AGENTBENCH_DIR;
|
|
11
|
-
var agentbenchAnswerOutput = {
|
|
12
|
-
parse(events) {
|
|
13
|
-
let text = "";
|
|
14
|
-
for (const ev of events) {
|
|
15
|
-
const d = ev?.data;
|
|
16
|
-
const t = d?.finalText ?? d?.text ?? d?.result;
|
|
17
|
-
if (typeof t === "string" && t.length > 0) text = t;
|
|
18
|
-
}
|
|
19
|
-
const fences = [...text.matchAll(/```(?:text|answer)?\s*\n([\s\S]*?)```/g)];
|
|
20
|
-
return (fences.at(-1)?.[1] ?? text).trim();
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
function normalizeAnswer(value) {
|
|
24
|
-
return value.toLowerCase().replace(/\s+/g, " ").replace(/^["'`]+|["'`]+$/g, "").trim();
|
|
25
|
-
}
|
|
26
|
-
function rowToTask(row, index, split) {
|
|
27
|
-
const columns = row.table?.table_info?.columns?.map((c) => `${c.name}${c.type ? ` (${c.type})` : ""}`).join(", ");
|
|
28
|
-
const sampleRows = row.table?.table_info?.rows?.slice(0, 40);
|
|
29
|
-
const meta = {
|
|
30
|
-
labels: row.label,
|
|
31
|
-
split,
|
|
32
|
-
subset: "dbbench",
|
|
33
|
-
table: row.table
|
|
34
|
-
};
|
|
35
|
-
return {
|
|
36
|
-
id: `dbbench-${split}-${index}`,
|
|
37
|
-
split,
|
|
38
|
-
prompt: [
|
|
39
|
-
"Answer this AgentBench DBBench question using the table below.",
|
|
40
|
-
"Return only the answer value.",
|
|
41
|
-
"",
|
|
42
|
-
`Question: ${row.description}`,
|
|
43
|
-
row.table?.table_name ? `Table: ${row.table.table_name}` : void 0,
|
|
44
|
-
columns ? `Columns: ${columns}` : void 0,
|
|
45
|
-
sampleRows ? `Rows JSON: ${JSON.stringify(sampleRows)}` : void 0
|
|
46
|
-
].filter(Boolean).join("\n"),
|
|
47
|
-
metadata: meta
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function readMeta(task) {
|
|
51
|
-
const md = task.metadata;
|
|
52
|
-
if (!md || !Array.isArray(md.labels)) {
|
|
53
|
-
throw new Error(`agentbench task ${task.id} missing metadata \u2014 loadTasks did not populate it`);
|
|
54
|
-
}
|
|
55
|
-
return md;
|
|
56
|
-
}
|
|
57
|
-
function selectRows(rows, opts, split) {
|
|
58
|
-
let tasks = rows.map((row, index) => rowToTask(row, index, split));
|
|
59
|
-
if (opts.ids) {
|
|
60
|
-
const want = new Set(opts.ids);
|
|
61
|
-
tasks = tasks.filter((task) => want.has(task.id));
|
|
62
|
-
} else if (opts.limit !== void 0) {
|
|
63
|
-
tasks = tasks.slice(0, opts.limit);
|
|
64
|
-
}
|
|
65
|
-
if (tasks.length === 0) throw new Error(`AgentBench DBBench: no tasks matched ${JSON.stringify(opts)}`);
|
|
66
|
-
return tasks;
|
|
67
|
-
}
|
|
68
|
-
async function loadJsonl(path) {
|
|
69
|
-
const raw = await readFile(path, "utf8");
|
|
70
|
-
return raw.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line));
|
|
71
|
-
}
|
|
72
|
-
async function loadFixtures(opts, split) {
|
|
73
|
-
const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
|
|
74
|
-
console.warn(`[agentbench] AGENTBENCH_FIXTURES=1 \u2014 loading ${rows.length} DBBench adapter fixtures`);
|
|
75
|
-
return selectRows(rows, opts, split);
|
|
76
|
-
}
|
|
77
|
-
function createAgentBenchAdapter() {
|
|
78
|
-
const fixturesMode = process.env.AGENTBENCH_FIXTURES === "1";
|
|
79
|
-
return {
|
|
80
|
-
name: "agentbench",
|
|
81
|
-
output: agentbenchAnswerOutput,
|
|
82
|
-
async preflight() {
|
|
83
|
-
if (fixturesMode) return;
|
|
84
|
-
const dir = agentbenchDir();
|
|
85
|
-
if (!dir) {
|
|
86
|
-
throw new Error("AGENTBENCH_DIR is required. Fix: clone https://github.com/THUDM/AgentBench and set AGENTBENCH_DIR=/path/to/AgentBench.");
|
|
87
|
-
}
|
|
88
|
-
await loadJsonl(join(dir, "data", "dbbench", `${DEFAULT_SPLIT}.jsonl`));
|
|
89
|
-
},
|
|
90
|
-
async loadTasks(opts = {}) {
|
|
91
|
-
const split = opts.split ?? DEFAULT_SPLIT;
|
|
92
|
-
if (fixturesMode) return loadFixtures(opts, split);
|
|
93
|
-
const dir = agentbenchDir();
|
|
94
|
-
if (!dir) throw new Error("AGENTBENCH_DIR is required to load AgentBench DBBench tasks");
|
|
95
|
-
return selectRows(await loadJsonl(join(dir, "data", "dbbench", `${split}.jsonl`)), opts, split);
|
|
96
|
-
},
|
|
97
|
-
async goldArtifact(task) {
|
|
98
|
-
return readMeta(task).labels[0];
|
|
99
|
-
},
|
|
100
|
-
async judge(task, artifact) {
|
|
101
|
-
const meta = readMeta(task);
|
|
102
|
-
const got = normalizeAnswer(artifact);
|
|
103
|
-
const expected = meta.labels.map(normalizeAnswer);
|
|
104
|
-
const resolved = expected.includes(got);
|
|
105
|
-
return {
|
|
106
|
-
resolved,
|
|
107
|
-
score: resolved ? 1 : 0,
|
|
108
|
-
detail: JSON.stringify({ subset: meta.subset, split: meta.split, expected: meta.labels, got: artifact })
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export {
|
|
115
|
-
agentbenchAnswerOutput,
|
|
116
|
-
createAgentBenchAdapter
|
|
117
|
-
};
|
|
118
|
-
//# sourceMappingURL=chunk-67ACKDCX.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/benchmarks/agentbench.ts"],"sourcesContent":["/**\n * AgentBench deterministic subset adapter.\n *\n * This targets AgentBench DBBench rows only: question + table + published label.\n * It does not wrap AgentBench's controller protocol or the non-deterministic game\n * environments. Worker artifact = final answer text. Judge = exact match against\n * the official DBBench label list after light whitespace/case normalization.\n */\n\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport { benchRoot } from './_harness'\nimport type { BenchmarkAdapter, BenchScore, BenchTask, LoadOptions } from './types'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'agentbench-dbbench.json')\nconst DEFAULT_SPLIT = 'dev'\n\ninterface AgentBenchDbRow {\n description: string\n label: string[]\n table?: {\n table_name?: string\n table_info?: {\n columns?: Array<{ name: string; type?: string }>\n rows?: unknown[][]\n }\n }\n}\n\ninterface AgentBenchMeta {\n labels: string[]\n split: string\n subset: 'dbbench'\n table?: AgentBenchDbRow['table']\n}\n\nconst agentbenchDir = (): string | undefined => process.env.AGENTBENCH_DIR\n\nexport const agentbenchAnswerOutput: 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 fences = [...text.matchAll(/```(?:text|answer)?\\s*\\n([\\s\\S]*?)```/g)]\n return (fences.at(-1)?.[1] ?? text).trim()\n },\n}\n\nfunction normalizeAnswer(value: string): string {\n return value\n .toLowerCase()\n .replace(/\\s+/g, ' ')\n .replace(/^[\"'`]+|[\"'`]+$/g, '')\n .trim()\n}\n\nfunction rowToTask(row: AgentBenchDbRow, index: number, split: string): BenchTask {\n const columns = row.table?.table_info?.columns?.map((c) => `${c.name}${c.type ? ` (${c.type})` : ''}`).join(', ')\n const sampleRows = row.table?.table_info?.rows?.slice(0, 40)\n const meta: AgentBenchMeta = {\n labels: row.label,\n split,\n subset: 'dbbench',\n table: row.table,\n }\n return {\n id: `dbbench-${split}-${index}`,\n split,\n prompt: [\n 'Answer this AgentBench DBBench question using the table below.',\n 'Return only the answer value.',\n '',\n `Question: ${row.description}`,\n row.table?.table_name ? `Table: ${row.table.table_name}` : undefined,\n columns ? `Columns: ${columns}` : undefined,\n sampleRows ? `Rows JSON: ${JSON.stringify(sampleRows)}` : undefined,\n ]\n .filter(Boolean)\n .join('\\n'),\n metadata: meta as unknown as Record<string, unknown>,\n }\n}\n\nfunction readMeta(task: BenchTask): AgentBenchMeta {\n const md = task.metadata\n if (!md || !Array.isArray(md.labels)) {\n throw new Error(`agentbench task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as AgentBenchMeta\n}\n\nfunction selectRows(rows: AgentBenchDbRow[], opts: LoadOptions, split: string): BenchTask[] {\n let tasks = rows.map((row, index) => rowToTask(row, index, split))\n if (opts.ids) {\n const want = new Set(opts.ids)\n tasks = tasks.filter((task) => want.has(task.id))\n } else if (opts.limit !== undefined) {\n tasks = tasks.slice(0, opts.limit)\n }\n if (tasks.length === 0) throw new Error(`AgentBench DBBench: no tasks matched ${JSON.stringify(opts)}`)\n return tasks\n}\n\nasync function loadJsonl(path: string): Promise<AgentBenchDbRow[]> {\n const raw = await readFile(path, 'utf8')\n return raw\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as AgentBenchDbRow)\n}\n\nasync function loadFixtures(opts: LoadOptions, split: string): Promise<BenchTask[]> {\n const rows = JSON.parse(await readFile(FIXTURES, 'utf8')) as AgentBenchDbRow[]\n console.warn(`[agentbench] AGENTBENCH_FIXTURES=1 — loading ${rows.length} DBBench adapter fixtures`)\n return selectRows(rows, opts, split)\n}\n\nexport function createAgentBenchAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.AGENTBENCH_FIXTURES === '1'\n\n return {\n name: 'agentbench',\n output: agentbenchAnswerOutput,\n\n async preflight() {\n if (fixturesMode) return\n const dir = agentbenchDir()\n if (!dir) {\n throw new Error('AGENTBENCH_DIR is required. Fix: clone https://github.com/THUDM/AgentBench and set AGENTBENCH_DIR=/path/to/AgentBench.')\n }\n await loadJsonl(join(dir, 'data', 'dbbench', `${DEFAULT_SPLIT}.jsonl`))\n },\n\n async loadTasks(opts: LoadOptions = {}) {\n const split = opts.split ?? DEFAULT_SPLIT\n if (fixturesMode) return loadFixtures(opts, split)\n const dir = agentbenchDir()\n if (!dir) throw new Error('AGENTBENCH_DIR is required to load AgentBench DBBench tasks')\n return selectRows(await loadJsonl(join(dir, 'data', 'dbbench', `${split}.jsonl`)), opts, split)\n },\n\n async goldArtifact(task: BenchTask) {\n return readMeta(task).labels[0]\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const got = normalizeAnswer(artifact)\n const expected = meta.labels.map(normalizeAnswer)\n const resolved = expected.includes(got)\n return {\n resolved,\n score: resolved ? 1 : 0,\n detail: JSON.stringify({ subset: meta.subset, split: meta.split, expected: meta.labels, got: artifact }),\n }\n },\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-7FKBWOQT.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
contextBlock,
|
|
3
|
-
contextsFrom,
|
|
4
|
-
firstString,
|
|
5
|
-
isObject,
|
|
6
|
-
ragAnswerOutput,
|
|
7
|
-
readJsonRows,
|
|
8
|
-
selectTasks,
|
|
9
|
-
stringFrom
|
|
10
|
-
} from "./chunk-X3BTXCJ4.js";
|
|
11
|
-
import {
|
|
12
|
-
benchRoot
|
|
13
|
-
} from "./chunk-EIETHPD5.js";
|
|
14
|
-
|
|
15
|
-
// src/benchmarks/nomiracl.ts
|
|
16
|
-
import { readFile } from "fs/promises";
|
|
17
|
-
import { join } from "path";
|
|
18
|
-
var FIXTURES = join(benchRoot, "fixtures", "nomiracl.json");
|
|
19
|
-
var dataFile = () => process.env.NOMIRACL_DATA_FILE;
|
|
20
|
-
function passagesFrom(value, relevant) {
|
|
21
|
-
return contextsFrom(value).map((context) => ({ ...context, relevant }));
|
|
22
|
-
}
|
|
23
|
-
function answerableFrom(raw, contexts) {
|
|
24
|
-
const direct = raw.answerable ?? raw.is_answerable ?? raw.has_answer ?? raw.label ?? raw.relevant;
|
|
25
|
-
if (typeof direct === "boolean") return direct;
|
|
26
|
-
if (typeof direct === "number") return direct > 0;
|
|
27
|
-
if (typeof direct === "string") {
|
|
28
|
-
const normalized = direct.toLowerCase();
|
|
29
|
-
if (["true", "t", "relevant", "answerable", "positive", "1", "yes"].includes(normalized)) return true;
|
|
30
|
-
if (["false", "f", "non-relevant", "non_relevant", "unanswerable", "negative", "0", "no"].includes(normalized)) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return contexts.some((context) => context.relevant === true);
|
|
35
|
-
}
|
|
36
|
-
function rowToTask(raw, index) {
|
|
37
|
-
if (!isObject(raw)) throw new Error(`NoMIRACL row ${index} must be an object`);
|
|
38
|
-
const query = firstString(raw, ["query", "question"]);
|
|
39
|
-
if (!query) throw new Error(`NoMIRACL row ${index} missing query`);
|
|
40
|
-
const labelledPassages = [
|
|
41
|
-
...passagesFrom(raw.positive_passages, true),
|
|
42
|
-
...passagesFrom(raw.negative_passages, false)
|
|
43
|
-
];
|
|
44
|
-
const contexts = labelledPassages.length > 0 ? labelledPassages : contextsFrom(raw.passages).length > 0 ? contextsFrom(raw.passages) : contextsFrom(raw.contexts).length > 0 ? contextsFrom(raw.contexts) : contextsFrom(raw.documents);
|
|
45
|
-
const answerable = answerableFrom(raw, contexts);
|
|
46
|
-
const language = stringFrom(raw.lang) ?? stringFrom(raw.language) ?? "unknown";
|
|
47
|
-
const subset = stringFrom(raw.subset) ?? (answerable ? "relevant" : "non-relevant");
|
|
48
|
-
const id = stringFrom(raw.id) ?? stringFrom(raw.query_id) ?? `nomiracl-${index}`;
|
|
49
|
-
const meta = {
|
|
50
|
-
benchmark: "nomiracl",
|
|
51
|
-
query,
|
|
52
|
-
answerable,
|
|
53
|
-
language,
|
|
54
|
-
subset,
|
|
55
|
-
contexts
|
|
56
|
-
};
|
|
57
|
-
return {
|
|
58
|
-
id,
|
|
59
|
-
split: stringFrom(raw.split) ?? language,
|
|
60
|
-
prompt: [
|
|
61
|
-
"Classify this NoMIRACL RAG relevance case.",
|
|
62
|
-
"Return exactly one word: ANSWERABLE if at least one supplied passage contains enough evidence to answer the query, otherwise UNANSWERABLE.",
|
|
63
|
-
"",
|
|
64
|
-
`Query: ${query}`,
|
|
65
|
-
contexts.length > 0 ? `
|
|
66
|
-
Passages:
|
|
67
|
-
${contextBlock(contexts)}` : void 0
|
|
68
|
-
].filter(Boolean).join("\n"),
|
|
69
|
-
metadata: meta
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function readMeta(task) {
|
|
73
|
-
const md = task.metadata;
|
|
74
|
-
if (!md || typeof md.answerable !== "boolean") {
|
|
75
|
-
throw new Error(`NoMIRACL task ${task.id} missing metadata \u2014 loadTasks did not populate it`);
|
|
76
|
-
}
|
|
77
|
-
return md;
|
|
78
|
-
}
|
|
79
|
-
function parseClassification(artifact) {
|
|
80
|
-
const normalized = artifact.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
81
|
-
if (/\bunanswerable\b|\bnot answerable\b|\bno answer\b|\bnegative\b|\bfalse\b/.test(normalized)) {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
if (/\banswerable\b|\brelevant\b|\bpositive\b|\btrue\b|\byes\b/.test(normalized)) return true;
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
async function loadRows(path) {
|
|
88
|
-
const rows = await readJsonRows(path);
|
|
89
|
-
if (rows.length === 0) throw new Error(`NoMIRACL: no rows in ${path}`);
|
|
90
|
-
return rows;
|
|
91
|
-
}
|
|
92
|
-
async function loadFixtures(opts) {
|
|
93
|
-
const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
|
|
94
|
-
console.warn(`[nomiracl] NOMIRACL_FIXTURES=1 \u2014 loading ${rows.length} adapter fixtures`);
|
|
95
|
-
return selectTasks(rows.map(rowToTask), opts, "NoMIRACL");
|
|
96
|
-
}
|
|
97
|
-
function createNoMiraclAdapter() {
|
|
98
|
-
const fixturesMode = process.env.NOMIRACL_FIXTURES === "1";
|
|
99
|
-
return {
|
|
100
|
-
name: "nomiracl",
|
|
101
|
-
output: ragAnswerOutput,
|
|
102
|
-
async preflight() {
|
|
103
|
-
if (fixturesMode) {
|
|
104
|
-
await readFile(FIXTURES, "utf8");
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
const path = dataFile();
|
|
108
|
-
if (!path) {
|
|
109
|
-
throw new Error(
|
|
110
|
-
"NOMIRACL_DATA_FILE is required. Fix: export project-miracl/nomiracl rows to JSONL and set NOMIRACL_DATA_FILE=/path/to/nomiracl.jsonl, or set NOMIRACL_FIXTURES=1 for adapter plumbing."
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
await loadRows(path);
|
|
114
|
-
},
|
|
115
|
-
async loadTasks(opts = {}) {
|
|
116
|
-
if (fixturesMode) return loadFixtures(opts);
|
|
117
|
-
const path = dataFile();
|
|
118
|
-
if (!path) throw new Error("NOMIRACL_DATA_FILE is required to load NoMIRACL tasks");
|
|
119
|
-
return selectTasks((await loadRows(path)).map(rowToTask), opts, "NoMIRACL");
|
|
120
|
-
},
|
|
121
|
-
async goldArtifact(task) {
|
|
122
|
-
return readMeta(task).answerable ? "ANSWERABLE" : "UNANSWERABLE";
|
|
123
|
-
},
|
|
124
|
-
async judge(task, artifact) {
|
|
125
|
-
const meta = readMeta(task);
|
|
126
|
-
const got = parseClassification(artifact);
|
|
127
|
-
const resolved = got === meta.answerable;
|
|
128
|
-
return {
|
|
129
|
-
resolved,
|
|
130
|
-
score: resolved ? 1 : 0,
|
|
131
|
-
detail: JSON.stringify({
|
|
132
|
-
benchmark: meta.benchmark,
|
|
133
|
-
language: meta.language,
|
|
134
|
-
subset: meta.subset,
|
|
135
|
-
expected: meta.answerable ? "ANSWERABLE" : "UNANSWERABLE",
|
|
136
|
-
got: got === null ? null : got ? "ANSWERABLE" : "UNANSWERABLE",
|
|
137
|
-
contextCount: meta.contexts.length
|
|
138
|
-
})
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export {
|
|
145
|
-
createNoMiraclAdapter
|
|
146
|
-
};
|
|
147
|
-
//# sourceMappingURL=chunk-7FKBWOQT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/benchmarks/nomiracl.ts"],"sourcesContent":["/**\n * NoMIRACL adapter.\n *\n * NoMIRACL tests robustness to irrelevant retrieved passages. The worker does\n * not generate an answer here; it classifies whether the supplied passages\n * contain enough evidence to answer the query. This directly measures false\n * positive / false negative behavior for RAG abstention.\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 contextBlock,\n contextsFrom,\n firstString,\n isObject,\n ragAnswerOutput,\n readJsonRows,\n selectTasks,\n stringFrom,\n type RagContext,\n} from './rag-shared'\n\nconst FIXTURES = join(benchRoot, 'fixtures', 'nomiracl.json')\n\ninterface NoMiraclMeta {\n benchmark: 'nomiracl'\n query: string\n answerable: boolean\n language: string\n subset: string\n contexts: RagContext[]\n}\n\nconst dataFile = (): string | undefined => process.env.NOMIRACL_DATA_FILE\n\nfunction passagesFrom(value: unknown, relevant: boolean): RagContext[] {\n return contextsFrom(value).map((context) => ({ ...context, relevant }))\n}\n\nfunction answerableFrom(raw: Record<string, unknown>, contexts: readonly RagContext[]): boolean {\n const direct = raw.answerable ?? raw.is_answerable ?? raw.has_answer ?? raw.label ?? raw.relevant\n if (typeof direct === 'boolean') return direct\n if (typeof direct === 'number') return direct > 0\n if (typeof direct === 'string') {\n const normalized = direct.toLowerCase()\n if (['true', 't', 'relevant', 'answerable', 'positive', '1', 'yes'].includes(normalized)) return true\n if (['false', 'f', 'non-relevant', 'non_relevant', 'unanswerable', 'negative', '0', 'no'].includes(normalized)) {\n return false\n }\n }\n return contexts.some((context) => context.relevant === true)\n}\n\nfunction rowToTask(raw: unknown, index: number): BenchTask {\n if (!isObject(raw)) throw new Error(`NoMIRACL row ${index} must be an object`)\n const query = firstString(raw, ['query', 'question'])\n if (!query) throw new Error(`NoMIRACL row ${index} missing query`)\n const labelledPassages = [\n ...passagesFrom(raw.positive_passages, true),\n ...passagesFrom(raw.negative_passages, false),\n ]\n const contexts =\n labelledPassages.length > 0\n ? labelledPassages\n : contextsFrom(raw.passages).length > 0\n ? contextsFrom(raw.passages)\n : contextsFrom(raw.contexts).length > 0\n ? contextsFrom(raw.contexts)\n : contextsFrom(raw.documents)\n const answerable = answerableFrom(raw, contexts)\n const language = stringFrom(raw.lang) ?? stringFrom(raw.language) ?? 'unknown'\n const subset = stringFrom(raw.subset) ?? (answerable ? 'relevant' : 'non-relevant')\n const id = stringFrom(raw.id) ?? stringFrom(raw.query_id) ?? `nomiracl-${index}`\n const meta: NoMiraclMeta = {\n benchmark: 'nomiracl',\n query,\n answerable,\n language,\n subset,\n contexts,\n }\n return {\n id,\n split: stringFrom(raw.split) ?? language,\n prompt: [\n 'Classify this NoMIRACL RAG relevance case.',\n 'Return exactly one word: ANSWERABLE if at least one supplied passage contains enough evidence to answer the query, otherwise UNANSWERABLE.',\n '',\n `Query: ${query}`,\n contexts.length > 0 ? `\\nPassages:\\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): NoMiraclMeta {\n const md = task.metadata\n if (!md || typeof md.answerable !== 'boolean') {\n throw new Error(`NoMIRACL task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as NoMiraclMeta\n}\n\nfunction parseClassification(artifact: string): boolean | null {\n const normalized = artifact.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim()\n if (/\\bunanswerable\\b|\\bnot answerable\\b|\\bno answer\\b|\\bnegative\\b|\\bfalse\\b/.test(normalized)) {\n return false\n }\n if (/\\banswerable\\b|\\brelevant\\b|\\bpositive\\b|\\btrue\\b|\\byes\\b/.test(normalized)) return true\n return null\n}\n\nasync function loadRows(path: string): Promise<unknown[]> {\n const rows = await readJsonRows(path)\n if (rows.length === 0) throw new Error(`NoMIRACL: 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(`[nomiracl] NOMIRACL_FIXTURES=1 — loading ${rows.length} adapter fixtures`)\n return selectTasks(rows.map(rowToTask), opts, 'NoMIRACL')\n}\n\nexport function createNoMiraclAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.NOMIRACL_FIXTURES === '1'\n\n return {\n name: 'nomiracl',\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 'NOMIRACL_DATA_FILE is required. Fix: export project-miracl/nomiracl rows to JSONL and set NOMIRACL_DATA_FILE=/path/to/nomiracl.jsonl, or set NOMIRACL_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('NOMIRACL_DATA_FILE is required to load NoMIRACL tasks')\n return selectTasks((await loadRows(path)).map(rowToTask), opts, 'NoMIRACL')\n },\n\n async goldArtifact(task: BenchTask) {\n return readMeta(task).answerable ? 'ANSWERABLE' : 'UNANSWERABLE'\n },\n\n async judge(task: BenchTask, artifact: string): Promise<BenchScore> {\n const meta = readMeta(task)\n const got = parseClassification(artifact)\n const resolved = got === meta.answerable\n return {\n resolved,\n score: resolved ? 1 : 0,\n detail: JSON.stringify({\n benchmark: meta.benchmark,\n language: meta.language,\n subset: meta.subset,\n expected: meta.answerable ? 'ANSWERABLE' : 'UNANSWERABLE',\n got: got === null ? null : got ? 'ANSWERABLE' : 'UNANSWERABLE',\n contextCount: meta.contexts.length,\n }),\n }\n },\n }\n}\n"],"mappings":"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","names":[]}
|