@tangle-network/agent-bench 0.4.0 → 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.
Files changed (200) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/adapters.d.ts +4 -11
  3. package/dist/adapters.js +78 -41
  4. package/dist/adapters.js.map +1 -1
  5. package/dist/benchmarks/_harness.d.ts +51 -66
  6. package/dist/benchmarks/_harness.js +329 -31
  7. package/dist/benchmarks/_harness.js.map +1 -1
  8. package/dist/benchmarks/aec-bench.d.ts +4 -25
  9. package/dist/benchmarks/aec-bench.js +242 -7
  10. package/dist/benchmarks/aec-bench.js.map +1 -1
  11. package/dist/benchmarks/agentbench.d.ts +5 -13
  12. package/dist/benchmarks/agentbench.js +114 -9
  13. package/dist/benchmarks/agentbench.js.map +1 -1
  14. package/dist/benchmarks/appworld.d.ts +9 -29
  15. package/dist/benchmarks/appworld.js +317 -12
  16. package/dist/benchmarks/appworld.js.map +1 -1
  17. package/dist/benchmarks/bfcl.d.ts +5 -15
  18. package/dist/benchmarks/bfcl.js +264 -9
  19. package/dist/benchmarks/bfcl.js.map +1 -1
  20. package/dist/benchmarks/cad-design.d.ts +16 -41
  21. package/dist/benchmarks/cad-design.js +512 -6
  22. package/dist/benchmarks/cad-design.js.map +1 -1
  23. package/dist/benchmarks/cadbench.d.ts +4 -17
  24. package/dist/benchmarks/cadbench.js +2 -8
  25. package/dist/benchmarks/cadgenbench.d.ts +4 -20
  26. package/dist/benchmarks/cadgenbench.js +2 -8
  27. package/dist/benchmarks/commit0.d.ts +5 -27
  28. package/dist/benchmarks/commit0.js +187 -9
  29. package/dist/benchmarks/commit0.js.map +1 -1
  30. package/dist/benchmarks/crag.d.ts +4 -12
  31. package/dist/benchmarks/crag.js +110 -8
  32. package/dist/benchmarks/crag.js.map +1 -1
  33. package/dist/benchmarks/dabstep.d.ts +5 -15
  34. package/dist/benchmarks/dabstep.js +177 -9
  35. package/dist/benchmarks/dabstep.js.map +1 -1
  36. package/dist/benchmarks/enterpriseops-gym.d.ts +5 -34
  37. package/dist/benchmarks/enterpriseops-gym.js +236 -9
  38. package/dist/benchmarks/enterpriseops-gym.js.map +1 -1
  39. package/dist/benchmarks/finresearchbench.d.ts +4 -13
  40. package/dist/benchmarks/finresearchbench.js +218 -7
  41. package/dist/benchmarks/finresearchbench.js.map +1 -1
  42. package/dist/benchmarks/finsearchcomp.d.ts +8 -39
  43. package/dist/benchmarks/finsearchcomp.js +267 -6
  44. package/dist/benchmarks/finsearchcomp.js.map +1 -1
  45. package/dist/benchmarks/frames.d.ts +15 -37
  46. package/dist/benchmarks/frames.js +408 -11
  47. package/dist/benchmarks/frames.js.map +1 -1
  48. package/dist/benchmarks/hotpotqa.d.ts +4 -24
  49. package/dist/benchmarks/hotpotqa.js +250 -14
  50. package/dist/benchmarks/hotpotqa.js.map +1 -1
  51. package/dist/benchmarks/humaneval.d.ts +19 -37
  52. package/dist/benchmarks/humaneval.js +279 -16
  53. package/dist/benchmarks/humaneval.js.map +1 -1
  54. package/dist/benchmarks/mind2web.d.ts +7 -34
  55. package/dist/benchmarks/mind2web.js +257 -8
  56. package/dist/benchmarks/mind2web.js.map +1 -1
  57. package/dist/benchmarks/nomiracl.d.ts +4 -13
  58. package/dist/benchmarks/nomiracl.js +146 -8
  59. package/dist/benchmarks/nomiracl.js.map +1 -1
  60. package/dist/benchmarks/open-rag-bench.d.ts +4 -12
  61. package/dist/benchmarks/open-rag-bench.js +110 -8
  62. package/dist/benchmarks/open-rag-bench.js.map +1 -1
  63. package/dist/benchmarks/programbench.d.ts +5 -29
  64. package/dist/benchmarks/programbench.js +161 -9
  65. package/dist/benchmarks/programbench.js.map +1 -1
  66. package/dist/benchmarks/rag-shared.d.ts +21 -20
  67. package/dist/benchmarks/rag-shared.js +245 -38
  68. package/dist/benchmarks/rag-shared.js.map +1 -1
  69. package/dist/benchmarks/ragbench.d.ts +4 -14
  70. package/dist/benchmarks/ragbench.js +127 -8
  71. package/dist/benchmarks/ragbench.js.map +1 -1
  72. package/dist/benchmarks/simpleqa.d.ts +17 -44
  73. package/dist/benchmarks/simpleqa.js +293 -10
  74. package/dist/benchmarks/simpleqa.js.map +1 -1
  75. package/dist/benchmarks/swe-bench.d.ts +23 -36
  76. package/dist/benchmarks/swe-bench.js +234 -13
  77. package/dist/benchmarks/swe-bench.js.map +1 -1
  78. package/dist/benchmarks/t2-ragbench.d.ts +4 -12
  79. package/dist/benchmarks/t2-ragbench.js +118 -8
  80. package/dist/benchmarks/t2-ragbench.js.map +1 -1
  81. package/dist/benchmarks/tau-bench-shared.d.ts +14 -22
  82. package/dist/benchmarks/tau-bench-shared.js +169 -9
  83. package/dist/benchmarks/tau-bench-shared.js.map +1 -1
  84. package/dist/benchmarks/tau2-bench.d.ts +5 -5
  85. package/dist/benchmarks/tau2-bench.js +28 -10
  86. package/dist/benchmarks/tau2-bench.js.map +1 -1
  87. package/dist/benchmarks/tau3-banking.d.ts +4 -13
  88. package/dist/benchmarks/tau3-banking.js +28 -8
  89. package/dist/benchmarks/tau3-banking.js.map +1 -1
  90. package/dist/benchmarks/terminal-bench.d.ts +4 -22
  91. package/dist/benchmarks/terminal-bench.js +140 -7
  92. package/dist/benchmarks/terminal-bench.js.map +1 -1
  93. package/dist/benchmarks/toollm.d.ts +5 -13
  94. package/dist/benchmarks/toollm.js +184 -9
  95. package/dist/benchmarks/toollm.js.map +1 -1
  96. package/dist/benchmarks/trata-hedge.d.ts +4 -30
  97. package/dist/benchmarks/trata-hedge.js +336 -6
  98. package/dist/benchmarks/trata-hedge.js.map +1 -1
  99. package/dist/benchmarks/types.d.ts +85 -94
  100. package/dist/benchmarks/types.js +1 -1
  101. package/dist/benchmarks/webarena-verified.d.ts +5 -13
  102. package/dist/benchmarks/webarena-verified.js +152 -9
  103. package/dist/benchmarks/webarena-verified.js.map +1 -1
  104. package/dist/cadbench-DpQWZHp4.js +285 -0
  105. package/dist/cadbench-DpQWZHp4.js.map +1 -0
  106. package/dist/cadgenbench-DRhczfsG.js +151 -0
  107. package/dist/cadgenbench-DRhczfsG.js.map +1 -0
  108. package/dist/index.d.ts +245 -293
  109. package/dist/index.js +1669 -1791
  110. package/dist/index.js.map +1 -1
  111. package/package.json +17 -14
  112. package/pier_agents/candidate_contract.py +238 -24
  113. package/pier_agents/tangle_candidate.py +75 -5
  114. package/scripts/verify-packed-consumer.mjs +84 -17
  115. package/scripts/verify-pier-agent.mts +6 -4
  116. package/src/benchmarks/_harness.test.mts +16 -1
  117. package/src/benchmarks/_harness.ts +9 -2
  118. package/src/benchmarks/terminal-bench.ts +2 -1
  119. package/src/corpus.test.mts +13 -0
  120. package/src/corpus.ts +4 -0
  121. package/src/profile-coordinates.ts +2 -2
  122. package/src/rollout-ledger/backfill-swe-arena.mts +5 -1
  123. package/src/rollout-ledger/settle-capture.mts +7 -1
  124. package/src/search-bench/profiles.ts +1 -1
  125. package/src/skill-sandbox-smoke.mts +2 -1
  126. package/src/swe-arena/gepa-seat.mts +1 -1
  127. package/src/swe-arena/ledger-orphans.test.mts +36 -34
  128. package/dist/benchmarks/cadbench.js.map +0 -1
  129. package/dist/benchmarks/cadgenbench.js.map +0 -1
  130. package/dist/benchmarks/types.js.map +0 -1
  131. package/dist/chunk-3U5TXJZS.js +0 -251
  132. package/dist/chunk-3U5TXJZS.js.map +0 -1
  133. package/dist/chunk-53UPUNBZ.js +0 -325
  134. package/dist/chunk-53UPUNBZ.js.map +0 -1
  135. package/dist/chunk-5H5XV76F.js +0 -240
  136. package/dist/chunk-5H5XV76F.js.map +0 -1
  137. package/dist/chunk-7GRVHU22.js +0 -208
  138. package/dist/chunk-7GRVHU22.js.map +0 -1
  139. package/dist/chunk-C7T7WEK2.js +0 -103
  140. package/dist/chunk-C7T7WEK2.js.map +0 -1
  141. package/dist/chunk-HWST3SED.js +0 -162
  142. package/dist/chunk-HWST3SED.js.map +0 -1
  143. package/dist/chunk-IA2FBTWC.js +0 -318
  144. package/dist/chunk-IA2FBTWC.js.map +0 -1
  145. package/dist/chunk-IFVINJ4B.js +0 -142
  146. package/dist/chunk-IFVINJ4B.js.map +0 -1
  147. package/dist/chunk-INNOYXCP.js +0 -387
  148. package/dist/chunk-INNOYXCP.js.map +0 -1
  149. package/dist/chunk-IZ5M6OAC.js +0 -169
  150. package/dist/chunk-IZ5M6OAC.js.map +0 -1
  151. package/dist/chunk-JTHWEDEW.js +0 -32
  152. package/dist/chunk-JTHWEDEW.js.map +0 -1
  153. package/dist/chunk-K3BQGZCT.js +0 -221
  154. package/dist/chunk-K3BQGZCT.js.map +0 -1
  155. package/dist/chunk-KP5KD6EN.js +0 -276
  156. package/dist/chunk-KP5KD6EN.js.map +0 -1
  157. package/dist/chunk-MQMRLGOG.js +0 -136
  158. package/dist/chunk-MQMRLGOG.js.map +0 -1
  159. package/dist/chunk-NQG5XDSB.js +0 -147
  160. package/dist/chunk-NQG5XDSB.js.map +0 -1
  161. package/dist/chunk-PA2ZKHJC.js +0 -230
  162. package/dist/chunk-PA2ZKHJC.js.map +0 -1
  163. package/dist/chunk-PB64GYIG.js +0 -118
  164. package/dist/chunk-PB64GYIG.js.map +0 -1
  165. package/dist/chunk-PUIRNYI7.js +0 -189
  166. package/dist/chunk-PUIRNYI7.js.map +0 -1
  167. package/dist/chunk-RCYQEFNX.js +0 -30
  168. package/dist/chunk-RCYQEFNX.js.map +0 -1
  169. package/dist/chunk-RH5F53JT.js +0 -182
  170. package/dist/chunk-RH5F53JT.js.map +0 -1
  171. package/dist/chunk-SEVJPLZC.js +0 -260
  172. package/dist/chunk-SEVJPLZC.js.map +0 -1
  173. package/dist/chunk-SFLA7OH3.js +0 -27
  174. package/dist/chunk-SFLA7OH3.js.map +0 -1
  175. package/dist/chunk-SHM6MRRF.js +0 -130
  176. package/dist/chunk-SHM6MRRF.js.map +0 -1
  177. package/dist/chunk-SHYIRB7I.js +0 -120
  178. package/dist/chunk-SHYIRB7I.js.map +0 -1
  179. package/dist/chunk-SVR2LKYI.js +0 -116
  180. package/dist/chunk-SVR2LKYI.js.map +0 -1
  181. package/dist/chunk-TBKU5XQI.js +0 -228
  182. package/dist/chunk-TBKU5XQI.js.map +0 -1
  183. package/dist/chunk-UPAMRDX4.js +0 -233
  184. package/dist/chunk-UPAMRDX4.js.map +0 -1
  185. package/dist/chunk-V7AEBY6U.js +0 -144
  186. package/dist/chunk-V7AEBY6U.js.map +0 -1
  187. package/dist/chunk-VQRS7VUC.js +0 -342
  188. package/dist/chunk-VQRS7VUC.js.map +0 -1
  189. package/dist/chunk-WSKWVEQB.js +0 -317
  190. package/dist/chunk-WSKWVEQB.js.map +0 -1
  191. package/dist/chunk-X3BTXCJ4.js +0 -262
  192. package/dist/chunk-X3BTXCJ4.js.map +0 -1
  193. package/dist/chunk-XKEFIFIC.js +0 -197
  194. package/dist/chunk-XKEFIFIC.js.map +0 -1
  195. package/dist/chunk-XYA4XSNU.js +0 -148
  196. package/dist/chunk-XYA4XSNU.js.map +0 -1
  197. package/dist/chunk-YSMEKBTD.js +0 -211
  198. package/dist/chunk-YSMEKBTD.js.map +0 -1
  199. package/dist/chunk-Z4TZ76N7.js +0 -170
  200. package/dist/chunk-Z4TZ76N7.js.map +0 -1
@@ -1,39 +1,246 @@
1
- import {
2
- FINAL_ANSWER_SENTINEL,
3
- allStrings,
4
- answerScoreToBenchScore,
5
- contextBlock,
6
- contextsFrom,
7
- firstString,
8
- isObject,
9
- normalizeAnswer,
10
- parseCitations,
11
- parseFinalAnswer,
12
- ragAnswerOutput,
13
- readJsonRows,
14
- scoreAnswerArtifact,
15
- selectTasks,
16
- stringArrayFrom,
17
- stringFrom,
18
- tokenF1
19
- } from "../chunk-X3BTXCJ4.js";
20
- export {
21
- FINAL_ANSWER_SENTINEL,
22
- allStrings,
23
- answerScoreToBenchScore,
24
- contextBlock,
25
- contextsFrom,
26
- firstString,
27
- isObject,
28
- normalizeAnswer,
29
- parseCitations,
30
- parseFinalAnswer,
31
- ragAnswerOutput,
32
- readJsonRows,
33
- scoreAnswerArtifact,
34
- selectTasks,
35
- stringArrayFrom,
36
- stringFrom,
37
- tokenF1
38
- };
1
+ import { readFile } from "node:fs/promises";
2
+ //#region src/benchmarks/rag-shared.ts
3
+ const FINAL_ANSWER_SENTINEL = "FINAL ANSWER:";
4
+ const ragAnswerOutput = { parse(events) {
5
+ let text = "";
6
+ for (const ev of events) {
7
+ const d = ev?.data;
8
+ const t = d?.finalText ?? d?.text ?? d?.result;
9
+ if (typeof t === "string" && t.length > 0) text = t;
10
+ }
11
+ return text.trim();
12
+ } };
13
+ function parseFinalAnswer(artifact) {
14
+ const lines = artifact.split(/\r?\n/);
15
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
16
+ const line = lines[i] ?? "";
17
+ const idx = line.toUpperCase().indexOf(FINAL_ANSWER_SENTINEL);
18
+ if (idx !== -1) return line.slice(idx + 13).trim();
19
+ }
20
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
21
+ const trimmed = (lines[i] ?? "").trim();
22
+ if (trimmed.length > 0) return trimmed;
23
+ }
24
+ return "";
25
+ }
26
+ function parseCitations(artifact) {
27
+ const urls = /* @__PURE__ */ new Set();
28
+ for (const match of artifact.matchAll(/https?:\/\/[^\s)<>"']+/g)) urls.add(match[0].replace(/[.,;]+$/, ""));
29
+ return [...urls];
30
+ }
31
+ function normalizeAnswer(input) {
32
+ return input.toLowerCase().replace(/(\d),(?=\d{3}\b)/g, "$1").replace(/[^\p{L}\p{N}\s.-]+/gu, " ").split(/\s+/).filter((token) => token.length > 0).filter((token) => ![
33
+ "a",
34
+ "an",
35
+ "the"
36
+ ].includes(token)).join(" ").trim();
37
+ }
38
+ function tokens(input) {
39
+ const normalized = normalizeAnswer(input);
40
+ return normalized.length === 0 ? [] : normalized.split(/\s+/);
41
+ }
42
+ function tokenF1(candidate, gold) {
43
+ const candidateTokens = tokens(candidate);
44
+ const goldTokens = tokens(gold);
45
+ if (candidateTokens.length === 0 || goldTokens.length === 0) return candidateTokens.length === 0 && goldTokens.length === 0 ? 1 : 0;
46
+ const counts = /* @__PURE__ */ new Map();
47
+ for (const token of goldTokens) counts.set(token, (counts.get(token) ?? 0) + 1);
48
+ let common = 0;
49
+ for (const token of candidateTokens) {
50
+ const left = counts.get(token);
51
+ if (left !== void 0 && left > 0) {
52
+ common += 1;
53
+ counts.set(token, left - 1);
54
+ }
55
+ }
56
+ if (common === 0) return 0;
57
+ const precision = common / candidateTokens.length;
58
+ const recall = common / goldTokens.length;
59
+ return 2 * precision * recall / (precision + recall);
60
+ }
61
+ function exactOrContains(candidate, gold) {
62
+ const normalizedCandidate = normalizeAnswer(candidate);
63
+ const normalizedGold = normalizeAnswer(gold);
64
+ if (normalizedGold.length === 0) return false;
65
+ if (normalizedCandidate === normalizedGold) return true;
66
+ const escaped = normalizedGold.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
67
+ return new RegExp(`(^|\\s)${escaped}(\\s|$)`).test(normalizedCandidate);
68
+ }
69
+ function numbers(input) {
70
+ return [...input.replace(/,/g, "").matchAll(/-?\d+(?:\.\d+)?/g)].map((match) => Number(match[0])).filter(Number.isFinite);
71
+ }
72
+ function numericMatch(candidate, gold, relativeTolerance) {
73
+ const got = numbers(candidate);
74
+ const want = numbers(gold);
75
+ if (got.length === 0 || want.length === 0) return false;
76
+ return want.some((expected) => got.some((actual) => {
77
+ const tolerance = Math.max(Math.abs(expected) * relativeTolerance, relativeTolerance);
78
+ return Math.abs(actual - expected) <= tolerance;
79
+ }));
80
+ }
81
+ function scoreAnswerArtifact(artifact, golds, options = {}) {
82
+ const finalAnswer = parseFinalAnswer(artifact);
83
+ const threshold = options.threshold ?? .72;
84
+ const numericTolerance = options.numericTolerance ?? .01;
85
+ let best = {
86
+ resolved: false,
87
+ score: 0,
88
+ finalAnswer,
89
+ bestGold: null,
90
+ exact: false,
91
+ numeric: false,
92
+ f1: 0,
93
+ threshold
94
+ };
95
+ if (finalAnswer.length === 0 || golds.length === 0) return best;
96
+ for (const gold of golds) {
97
+ const exact = exactOrContains(finalAnswer, gold);
98
+ const numeric = numericMatch(finalAnswer, gold, numericTolerance);
99
+ const f1 = tokenF1(finalAnswer, gold);
100
+ const resolved = exact || numeric || f1 >= threshold;
101
+ const score = exact || numeric ? 1 : f1;
102
+ if (score > best.score || resolved && !best.resolved) best = {
103
+ resolved,
104
+ score,
105
+ finalAnswer,
106
+ bestGold: gold,
107
+ exact,
108
+ numeric,
109
+ f1,
110
+ threshold
111
+ };
112
+ }
113
+ return best;
114
+ }
115
+ function answerScoreToBenchScore(score, detail) {
116
+ return {
117
+ resolved: score.resolved,
118
+ score: score.score,
119
+ detail: JSON.stringify({
120
+ ...detail,
121
+ finalAnswer: score.finalAnswer,
122
+ bestGold: score.bestGold,
123
+ exact: score.exact,
124
+ numeric: score.numeric,
125
+ f1: score.f1,
126
+ threshold: score.threshold
127
+ })
128
+ };
129
+ }
130
+ async function readJsonRows(path) {
131
+ const raw = (await readFile(path, "utf8")).trim();
132
+ if (raw.length === 0) return [];
133
+ if (raw.startsWith("[")) {
134
+ const parsed = JSON.parse(raw);
135
+ if (Array.isArray(parsed)) return parsed;
136
+ throw new Error(`${path} must contain a JSON array when it starts with [`);
137
+ }
138
+ if (raw.startsWith("{")) try {
139
+ const parsed = JSON.parse(raw);
140
+ if (isObject(parsed)) {
141
+ for (const key of [
142
+ "rows",
143
+ "data",
144
+ "examples",
145
+ "items"
146
+ ]) {
147
+ const value = parsed[key];
148
+ if (Array.isArray(value)) return value;
149
+ }
150
+ return [parsed];
151
+ }
152
+ throw new Error(`${path} must contain a JSON object, JSON array, JSONL rows, or an object with rows/data/examples/items`);
153
+ } catch (err) {
154
+ if (!raw.includes("\n")) throw err;
155
+ }
156
+ return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => JSON.parse(line));
157
+ }
158
+ function selectTasks(tasks, opts, label) {
159
+ let selected = tasks;
160
+ if (opts.split) selected = selected.filter((task) => task.split === opts.split);
161
+ if (opts.ids) {
162
+ const ids = new Set(opts.ids);
163
+ selected = selected.filter((task) => ids.has(task.id));
164
+ } else if (opts.limit !== void 0) selected = selected.slice(0, opts.limit);
165
+ if (selected.length === 0) throw new Error(`${label}: no tasks matched ${JSON.stringify(opts)}`);
166
+ return selected;
167
+ }
168
+ function stringFrom(value) {
169
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
170
+ }
171
+ function stringArrayFrom(value) {
172
+ if (typeof value === "string" && value.trim().length > 0) return [value.trim()];
173
+ if (!Array.isArray(value)) return [];
174
+ return value.flatMap((entry) => {
175
+ if (typeof entry === "string" && entry.trim().length > 0) return [entry.trim()];
176
+ if (isObject(entry)) {
177
+ const text = stringFrom(entry.answer) ?? stringFrom(entry.value) ?? stringFrom(entry.text);
178
+ return text ? [text] : [];
179
+ }
180
+ return [];
181
+ });
182
+ }
183
+ function firstString(row, keys) {
184
+ for (const key of keys) {
185
+ const value = stringFrom(row[key]);
186
+ if (value) return value;
187
+ }
188
+ return "";
189
+ }
190
+ function allStrings(row, keys) {
191
+ const out = [];
192
+ for (const key of keys) out.push(...stringArrayFrom(row[key]));
193
+ return [...new Set(out)];
194
+ }
195
+ function contextsFrom(value) {
196
+ if (typeof value === "string" && value.trim().length > 0) return [{
197
+ id: "ctx-1",
198
+ text: value.trim()
199
+ }];
200
+ if (!Array.isArray(value)) return [];
201
+ return value.flatMap((entry, index) => {
202
+ if (typeof entry === "string" && entry.trim().length > 0) return [{
203
+ id: `ctx-${index + 1}`,
204
+ text: entry.trim()
205
+ }];
206
+ if (Array.isArray(entry)) {
207
+ const [first, second] = entry;
208
+ if (typeof first === "string" && typeof second === "string") return [{
209
+ id: first,
210
+ text: second.trim()
211
+ }];
212
+ return entry.flatMap((nested, nestedIndex) => contextsFrom([nested]).map((ctx) => ({
213
+ ...ctx,
214
+ id: ctx.id.startsWith("ctx-") ? `ctx-${index + 1}-${nestedIndex + 1}` : ctx.id
215
+ })));
216
+ }
217
+ if (!isObject(entry)) return [];
218
+ const text = stringFrom(entry.text) ?? stringFrom(entry.context) ?? stringFrom(entry.content) ?? stringFrom(entry.passage) ?? stringFrom(entry.document) ?? stringFrom(entry.page_content) ?? stringFrom(entry.chunk);
219
+ if (!text) return [];
220
+ const id = stringFrom(entry.id) ?? stringFrom(entry.docid) ?? stringFrom(entry.doc_id) ?? stringFrom(entry.document_id) ?? `ctx-${index + 1}`;
221
+ const relevantRaw = entry.relevant ?? entry.is_relevant ?? entry.label ?? entry.relevance;
222
+ const relevant = typeof relevantRaw === "boolean" ? relevantRaw : typeof relevantRaw === "number" ? relevantRaw > 0 : void 0;
223
+ return [{
224
+ id,
225
+ text,
226
+ ...stringFrom(entry.title) ? { title: stringFrom(entry.title) } : {},
227
+ ...stringFrom(entry.source) ?? stringFrom(entry.url) ? { source: stringFrom(entry.source) ?? stringFrom(entry.url) } : {},
228
+ ...relevant !== void 0 ? { relevant } : {}
229
+ }];
230
+ });
231
+ }
232
+ function contextBlock(contexts) {
233
+ if (contexts.length === 0) return "";
234
+ return contexts.map((ctx, index) => [
235
+ `[${index + 1}] ${ctx.title ?? ctx.id}`,
236
+ ctx.source ? `Source: ${ctx.source}` : void 0,
237
+ ctx.text
238
+ ].filter(Boolean).join("\n")).join("\n\n");
239
+ }
240
+ function isObject(value) {
241
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
242
+ }
243
+ //#endregion
244
+ export { FINAL_ANSWER_SENTINEL, allStrings, answerScoreToBenchScore, contextBlock, contextsFrom, firstString, isObject, normalizeAnswer, parseCitations, parseFinalAnswer, ragAnswerOutput, readJsonRows, scoreAnswerArtifact, selectTasks, stringArrayFrom, stringFrom, tokenF1 };
245
+
39
246
  //# sourceMappingURL=rag-shared.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"file":"rag-shared.js","names":[],"sources":["../../src/benchmarks/rag-shared.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\nimport type { OutputAdapter } from '@tangle-network/agent-runtime/loops'\nimport type { BenchScore, BenchTask, LoadOptions } from './types'\n\nexport const FINAL_ANSWER_SENTINEL = 'FINAL ANSWER:'\n\nexport interface RagContext {\n id: string\n text: string\n title?: string\n source?: string\n relevant?: boolean\n}\n\nexport interface RagAnswerScore {\n resolved: boolean\n score: number\n finalAnswer: string\n bestGold: string | null\n exact: boolean\n numeric: boolean\n f1: number\n threshold: number\n}\n\nexport const ragAnswerOutput: 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 return text.trim()\n },\n}\n\nexport function parseFinalAnswer(artifact: string): string {\n const lines = artifact.split(/\\r?\\n/)\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n const line = lines[i] ?? ''\n const idx = line.toUpperCase().indexOf(FINAL_ANSWER_SENTINEL)\n if (idx !== -1) return line.slice(idx + FINAL_ANSWER_SENTINEL.length).trim()\n }\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n const trimmed = (lines[i] ?? '').trim()\n if (trimmed.length > 0) return trimmed\n }\n return ''\n}\n\nexport function parseCitations(artifact: string): string[] {\n const urls = new Set<string>()\n for (const match of artifact.matchAll(/https?:\\/\\/[^\\s)<>\"']+/g)) {\n urls.add(match[0].replace(/[.,;]+$/, ''))\n }\n return [...urls]\n}\n\nexport function normalizeAnswer(input: string): string {\n return input\n .toLowerCase()\n .replace(/(\\d),(?=\\d{3}\\b)/g, '$1')\n .replace(/[^\\p{L}\\p{N}\\s.-]+/gu, ' ')\n .split(/\\s+/)\n .filter((token) => token.length > 0)\n .filter((token) => !['a', 'an', 'the'].includes(token))\n .join(' ')\n .trim()\n}\n\nfunction tokens(input: string): string[] {\n const normalized = normalizeAnswer(input)\n return normalized.length === 0 ? [] : normalized.split(/\\s+/)\n}\n\nexport function tokenF1(candidate: string, gold: string): number {\n const candidateTokens = tokens(candidate)\n const goldTokens = tokens(gold)\n if (candidateTokens.length === 0 || goldTokens.length === 0) {\n return candidateTokens.length === 0 && goldTokens.length === 0 ? 1 : 0\n }\n const counts = new Map<string, number>()\n for (const token of goldTokens) counts.set(token, (counts.get(token) ?? 0) + 1)\n let common = 0\n for (const token of candidateTokens) {\n const left = counts.get(token)\n if (left !== undefined && left > 0) {\n common += 1\n counts.set(token, left - 1)\n }\n }\n if (common === 0) return 0\n const precision = common / candidateTokens.length\n const recall = common / goldTokens.length\n return (2 * precision * recall) / (precision + recall)\n}\n\nfunction exactOrContains(candidate: string, gold: string): boolean {\n const normalizedCandidate = normalizeAnswer(candidate)\n const normalizedGold = normalizeAnswer(gold)\n if (normalizedGold.length === 0) return false\n if (normalizedCandidate === normalizedGold) return true\n const escaped = normalizedGold.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n return new RegExp(`(^|\\\\s)${escaped}(\\\\s|$)`).test(normalizedCandidate)\n}\n\nfunction numbers(input: string): number[] {\n return [...input.replace(/,/g, '').matchAll(/-?\\d+(?:\\.\\d+)?/g)]\n .map((match) => Number(match[0]))\n .filter(Number.isFinite)\n}\n\nfunction numericMatch(candidate: string, gold: string, relativeTolerance: number): boolean {\n const got = numbers(candidate)\n const want = numbers(gold)\n if (got.length === 0 || want.length === 0) return false\n return want.some((expected) =>\n got.some((actual) => {\n const tolerance = Math.max(Math.abs(expected) * relativeTolerance, relativeTolerance)\n return Math.abs(actual - expected) <= tolerance\n }),\n )\n}\n\nexport function scoreAnswerArtifact(\n artifact: string,\n golds: readonly string[],\n options: { threshold?: number; numericTolerance?: number } = {},\n): RagAnswerScore {\n const finalAnswer = parseFinalAnswer(artifact)\n const threshold = options.threshold ?? 0.72\n const numericTolerance = options.numericTolerance ?? 0.01\n let best: RagAnswerScore = {\n resolved: false,\n score: 0,\n finalAnswer,\n bestGold: null,\n exact: false,\n numeric: false,\n f1: 0,\n threshold,\n }\n if (finalAnswer.length === 0 || golds.length === 0) return best\n\n for (const gold of golds) {\n const exact = exactOrContains(finalAnswer, gold)\n const numeric = numericMatch(finalAnswer, gold, numericTolerance)\n const f1 = tokenF1(finalAnswer, gold)\n const resolved = exact || numeric || f1 >= threshold\n const score = exact || numeric ? 1 : f1\n if (score > best.score || (resolved && !best.resolved)) {\n best = { resolved, score, finalAnswer, bestGold: gold, exact, numeric, f1, threshold }\n }\n }\n return best\n}\n\nexport function answerScoreToBenchScore(\n score: RagAnswerScore,\n detail: Record<string, unknown>,\n): BenchScore {\n return {\n resolved: score.resolved,\n score: score.score,\n detail: JSON.stringify({\n ...detail,\n finalAnswer: score.finalAnswer,\n bestGold: score.bestGold,\n exact: score.exact,\n numeric: score.numeric,\n f1: score.f1,\n threshold: score.threshold,\n }),\n }\n}\n\nexport async function readJsonRows(path: string): Promise<unknown[]> {\n const raw = (await readFile(path, 'utf8')).trim()\n if (raw.length === 0) return []\n if (raw.startsWith('[')) {\n const parsed = JSON.parse(raw) as unknown\n if (Array.isArray(parsed)) return parsed\n throw new Error(`${path} must contain a JSON array when it starts with [`)\n }\n if (raw.startsWith('{')) {\n try {\n const parsed = JSON.parse(raw) as unknown\n if (isObject(parsed)) {\n for (const key of ['rows', 'data', 'examples', 'items']) {\n const value = parsed[key]\n if (Array.isArray(value)) return value\n }\n return [parsed]\n }\n throw new Error(`${path} must contain a JSON object, JSON array, JSONL rows, or an object with rows/data/examples/items`)\n } catch (err) {\n if (!raw.includes('\\n')) throw err\n }\n }\n return raw\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => JSON.parse(line) as unknown)\n}\n\nexport function selectTasks(tasks: BenchTask[], opts: LoadOptions, label: string): BenchTask[] {\n let selected = tasks\n if (opts.split) selected = selected.filter((task) => task.split === opts.split)\n if (opts.ids) {\n const ids = new Set(opts.ids)\n selected = selected.filter((task) => ids.has(task.id))\n } else if (opts.limit !== undefined) {\n selected = selected.slice(0, opts.limit)\n }\n if (selected.length === 0) throw new Error(`${label}: no tasks matched ${JSON.stringify(opts)}`)\n return selected\n}\n\nexport function stringFrom(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined\n}\n\nexport function stringArrayFrom(value: unknown): string[] {\n if (typeof value === 'string' && value.trim().length > 0) return [value.trim()]\n if (!Array.isArray(value)) return []\n return value.flatMap((entry) => {\n if (typeof entry === 'string' && entry.trim().length > 0) return [entry.trim()]\n if (isObject(entry)) {\n const text = stringFrom(entry.answer) ?? stringFrom(entry.value) ?? stringFrom(entry.text)\n return text ? [text] : []\n }\n return []\n })\n}\n\nexport function firstString(row: Record<string, unknown>, keys: readonly string[]): string {\n for (const key of keys) {\n const value = stringFrom(row[key])\n if (value) return value\n }\n return ''\n}\n\nexport function allStrings(row: Record<string, unknown>, keys: readonly string[]): string[] {\n const out: string[] = []\n for (const key of keys) out.push(...stringArrayFrom(row[key]))\n return [...new Set(out)]\n}\n\nexport function contextsFrom(value: unknown): RagContext[] {\n if (typeof value === 'string' && value.trim().length > 0) {\n return [{ id: 'ctx-1', text: value.trim() }]\n }\n if (!Array.isArray(value)) return []\n return value.flatMap((entry, index): RagContext[] => {\n if (typeof entry === 'string' && entry.trim().length > 0) {\n return [{ id: `ctx-${index + 1}`, text: entry.trim() }]\n }\n if (Array.isArray(entry)) {\n const [first, second] = entry\n if (typeof first === 'string' && typeof second === 'string') {\n return [{ id: first, text: second.trim() }]\n }\n return entry.flatMap((nested, nestedIndex) =>\n contextsFrom([nested]).map((ctx) => ({\n ...ctx,\n id: ctx.id.startsWith('ctx-') ? `ctx-${index + 1}-${nestedIndex + 1}` : ctx.id,\n })),\n )\n }\n if (!isObject(entry)) return []\n const text =\n stringFrom(entry.text) ??\n stringFrom(entry.context) ??\n stringFrom(entry.content) ??\n stringFrom(entry.passage) ??\n stringFrom(entry.document) ??\n stringFrom(entry.page_content) ??\n stringFrom(entry.chunk)\n if (!text) return []\n const id =\n stringFrom(entry.id) ??\n stringFrom(entry.docid) ??\n stringFrom(entry.doc_id) ??\n stringFrom(entry.document_id) ??\n `ctx-${index + 1}`\n const relevantRaw = entry.relevant ?? entry.is_relevant ?? entry.label ?? entry.relevance\n const relevant =\n typeof relevantRaw === 'boolean'\n ? relevantRaw\n : typeof relevantRaw === 'number'\n ? relevantRaw > 0\n : undefined\n return [\n {\n id,\n text,\n ...(stringFrom(entry.title) ? { title: stringFrom(entry.title) } : {}),\n ...(stringFrom(entry.source) ?? stringFrom(entry.url)\n ? { source: stringFrom(entry.source) ?? stringFrom(entry.url) }\n : {}),\n ...(relevant !== undefined ? { relevant } : {}),\n },\n ]\n })\n}\n\nexport function contextBlock(contexts: readonly RagContext[]): string {\n if (contexts.length === 0) return ''\n return contexts\n .map((ctx, index) =>\n [\n `[${index + 1}] ${ctx.title ?? ctx.id}`,\n ctx.source ? `Source: ${ctx.source}` : undefined,\n ctx.text,\n ]\n .filter(Boolean)\n .join('\\n'),\n )\n .join('\\n\\n')\n}\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n"],"mappings":"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"}
@@ -1,16 +1,6 @@
1
- import { BenchmarkAdapter } from './types.js';
2
- import '@tangle-network/agent-runtime/loops';
3
-
4
- /**
5
- * RAGBench-compatible adapter.
6
- *
7
- * Live mode expects a local JSON/JSONL export from rungalileo/ragbench or a
8
- * compatible table. Rows must carry a query and at least one reference answer.
9
- * Contexts, TRACe labels, and source metadata are preserved in task metadata
10
- * for diagnostics; the deterministic judge scores the worker's final answer
11
- * against the reference answer(s).
12
- */
13
-
1
+ import { BenchmarkAdapter } from "./types.js";
2
+ //#region src/benchmarks/ragbench.d.ts
14
3
  declare function createRagBenchAdapter(): BenchmarkAdapter;
15
-
4
+ //#endregion
16
5
  export { createRagBenchAdapter };
6
+ //# sourceMappingURL=ragbench.d.ts.map
@@ -1,9 +1,128 @@
1
- import {
2
- createRagBenchAdapter
3
- } from "../chunk-IFVINJ4B.js";
4
- import "../chunk-X3BTXCJ4.js";
5
- import "../chunk-WSKWVEQB.js";
6
- export {
7
- createRagBenchAdapter
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/ragbench.ts
6
+ /**
7
+ * RAGBench-compatible adapter.
8
+ *
9
+ * Live mode expects a local JSON/JSONL export from rungalileo/ragbench or a
10
+ * compatible table. Rows must carry a query and at least one reference answer.
11
+ * Contexts, TRACe labels, and source metadata are preserved in task metadata
12
+ * for diagnostics; the deterministic judge scores the worker's final answer
13
+ * against the reference answer(s).
14
+ */
15
+ const FIXTURES = join(benchRoot, "fixtures", "ragbench.json");
16
+ const dataFile = () => process.env.RAGBENCH_DATA_FILE;
17
+ function rowToTask(raw, index) {
18
+ if (!isObject(raw)) throw new Error(`RAGBench row ${index} must be an object`);
19
+ const query = firstString(raw, [
20
+ "question",
21
+ "query",
22
+ "user_input",
23
+ "prompt"
24
+ ]);
25
+ const goldAnswers = allStrings(raw, [
26
+ "response",
27
+ "responses",
28
+ "model_response",
29
+ "generated_response",
30
+ "reference",
31
+ "references",
32
+ "reference_answer",
33
+ "reference_answers",
34
+ "answer",
35
+ "answers",
36
+ "gold",
37
+ "gold_answer",
38
+ "ground_truth",
39
+ "expected_answer"
40
+ ]);
41
+ if (!query) throw new Error(`RAGBench row ${index} missing question/query`);
42
+ if (goldAnswers.length === 0) throw new Error(`RAGBench row ${index} missing reference answer`);
43
+ const contexts = contextsFrom(raw.contexts).length > 0 ? contextsFrom(raw.contexts) : contextsFrom(raw.retrieved_contexts).length > 0 ? contextsFrom(raw.retrieved_contexts) : contextsFrom(raw.documents);
44
+ const traceLabels = {};
45
+ for (const key of [
46
+ "adherence",
47
+ "completeness",
48
+ "relevance",
49
+ "utilization",
50
+ "all_relevant_sentence_keys",
51
+ "all_utilized_sentence_keys"
52
+ ]) if (raw[key] !== void 0) traceLabels[key] = raw[key];
53
+ const dataset = stringFrom(raw.dataset) ?? stringFrom(raw.source_dataset);
54
+ const id = stringFrom(raw.id) ?? stringFrom(raw.example_id) ?? `ragbench-${index}`;
55
+ const meta = {
56
+ benchmark: "ragbench",
57
+ query,
58
+ goldAnswers,
59
+ contexts,
60
+ ...dataset ? { dataset } : {},
61
+ traceLabels
62
+ };
63
+ return {
64
+ id,
65
+ split: stringFrom(raw.split) ?? dataset ?? "ragbench",
66
+ prompt: [
67
+ "Answer this RAGBench question using the supplied retrieved context.",
68
+ "End with a single final line: `FINAL ANSWER: <answer>`.",
69
+ "",
70
+ `Question: ${query}`,
71
+ contexts.length > 0 ? `\nRetrieved context:\n${contextBlock(contexts)}` : void 0
72
+ ].filter(Boolean).join("\n"),
73
+ metadata: meta
74
+ };
75
+ }
76
+ function readMeta(task) {
77
+ const md = task.metadata;
78
+ if (!md || !Array.isArray(md.goldAnswers)) throw new Error(`RAGBench task ${task.id} missing metadata — loadTasks did not populate it`);
79
+ return md;
80
+ }
81
+ async function loadRows(path) {
82
+ const rows = await readJsonRows(path);
83
+ if (rows.length === 0) throw new Error(`RAGBench: no rows in ${path}`);
84
+ return rows;
85
+ }
86
+ async function loadFixtures(opts) {
87
+ const rows = JSON.parse(await readFile(FIXTURES, "utf8"));
88
+ console.warn(`[ragbench] RAGBENCH_FIXTURES=1 — loading ${rows.length} adapter fixtures`);
89
+ return selectTasks(rows.map(rowToTask), opts, "RAGBench");
90
+ }
91
+ function createRagBenchAdapter() {
92
+ const fixturesMode = process.env.RAGBENCH_FIXTURES === "1";
93
+ return {
94
+ name: "ragbench",
95
+ output: ragAnswerOutput,
96
+ async preflight() {
97
+ if (fixturesMode) {
98
+ await readFile(FIXTURES, "utf8");
99
+ return;
100
+ }
101
+ const path = dataFile();
102
+ if (!path) throw new Error("RAGBENCH_DATA_FILE is required. Fix: export rungalileo/ragbench rows to JSONL and set RAGBENCH_DATA_FILE=/path/to/ragbench.jsonl, or set RAGBENCH_FIXTURES=1 for adapter plumbing.");
103
+ await loadRows(path);
104
+ },
105
+ async loadTasks(opts = {}) {
106
+ if (fixturesMode) return loadFixtures(opts);
107
+ const path = dataFile();
108
+ if (!path) throw new Error("RAGBENCH_DATA_FILE is required to load RAGBench tasks");
109
+ return selectTasks((await loadRows(path)).map(rowToTask), opts, "RAGBench");
110
+ },
111
+ async goldArtifact(task) {
112
+ return `${FINAL_ANSWER_SENTINEL} ${readMeta(task).goldAnswers[0] ?? ""}`;
113
+ },
114
+ async judge(task, artifact) {
115
+ const meta = readMeta(task);
116
+ return answerScoreToBenchScore(scoreAnswerArtifact(artifact, meta.goldAnswers), {
117
+ benchmark: meta.benchmark,
118
+ dataset: meta.dataset ?? null,
119
+ traceLabels: meta.traceLabels,
120
+ contextCount: meta.contexts.length
121
+ });
122
+ }
123
+ };
124
+ }
125
+ //#endregion
126
+ export { createRagBenchAdapter };
127
+
9
128
  //# sourceMappingURL=ragbench.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"file":"ragbench.js","names":[],"sources":["../../src/benchmarks/ragbench.ts"],"sourcesContent":["/**\n * RAGBench-compatible adapter.\n *\n * Live mode expects a local JSON/JSONL export from rungalileo/ragbench or a\n * compatible table. Rows must carry a query and at least one reference answer.\n * Contexts, TRACe labels, and source metadata are preserved in task metadata\n * for diagnostics; the deterministic judge scores the worker's final answer\n * against the reference answer(s).\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', 'ragbench.json')\n\ninterface RagBenchMeta {\n benchmark: 'ragbench'\n query: string\n goldAnswers: string[]\n contexts: RagContext[]\n dataset?: string\n traceLabels: Record<string, unknown>\n}\n\nconst dataFile = (): string | undefined => process.env.RAGBENCH_DATA_FILE\n\nfunction rowToTask(raw: unknown, index: number): BenchTask {\n if (!isObject(raw)) throw new Error(`RAGBench row ${index} must be an object`)\n const query = firstString(raw, ['question', 'query', 'user_input', 'prompt'])\n const goldAnswers = allStrings(raw, [\n 'response',\n 'responses',\n 'model_response',\n 'generated_response',\n 'reference',\n 'references',\n 'reference_answer',\n 'reference_answers',\n 'answer',\n 'answers',\n 'gold',\n 'gold_answer',\n 'ground_truth',\n 'expected_answer',\n ])\n if (!query) throw new Error(`RAGBench row ${index} missing question/query`)\n if (goldAnswers.length === 0) throw new Error(`RAGBench row ${index} missing reference answer`)\n const contexts =\n contextsFrom(raw.contexts).length > 0\n ? contextsFrom(raw.contexts)\n : contextsFrom(raw.retrieved_contexts).length > 0\n ? contextsFrom(raw.retrieved_contexts)\n : contextsFrom(raw.documents)\n const traceLabels: Record<string, unknown> = {}\n for (const key of [\n 'adherence',\n 'completeness',\n 'relevance',\n 'utilization',\n 'all_relevant_sentence_keys',\n 'all_utilized_sentence_keys',\n ]) {\n if (raw[key] !== undefined) traceLabels[key] = raw[key]\n }\n const dataset = stringFrom(raw.dataset) ?? stringFrom(raw.source_dataset)\n const id = stringFrom(raw.id) ?? stringFrom(raw.example_id) ?? `ragbench-${index}`\n const meta: RagBenchMeta = {\n benchmark: 'ragbench',\n query,\n goldAnswers,\n contexts,\n ...(dataset ? { dataset } : {}),\n traceLabels,\n }\n return {\n id,\n split: stringFrom(raw.split) ?? dataset ?? 'ragbench',\n prompt: [\n 'Answer this RAGBench question using the supplied retrieved context.',\n 'End with a single final line: `FINAL ANSWER: <answer>`.',\n '',\n `Question: ${query}`,\n contexts.length > 0 ? `\\nRetrieved 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): RagBenchMeta {\n const md = task.metadata\n if (!md || !Array.isArray(md.goldAnswers)) {\n throw new Error(`RAGBench task ${task.id} missing metadata — loadTasks did not populate it`)\n }\n return md as unknown as RagBenchMeta\n}\n\nasync function loadRows(path: string): Promise<unknown[]> {\n const rows = await readJsonRows(path)\n if (rows.length === 0) throw new Error(`RAGBench: 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(`[ragbench] RAGBENCH_FIXTURES=1 — loading ${rows.length} adapter fixtures`)\n return selectTasks(rows.map(rowToTask), opts, 'RAGBench')\n}\n\nexport function createRagBenchAdapter(): BenchmarkAdapter {\n const fixturesMode = process.env.RAGBENCH_FIXTURES === '1'\n\n return {\n name: 'ragbench',\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 'RAGBENCH_DATA_FILE is required. Fix: export rungalileo/ragbench rows to JSONL and set RAGBENCH_DATA_FILE=/path/to/ragbench.jsonl, or set RAGBENCH_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('RAGBENCH_DATA_FILE is required to load RAGBench tasks')\n return selectTasks((await loadRows(path)).map(rowToTask), opts, 'RAGBench')\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 dataset: meta.dataset ?? null,\n traceLabels: meta.traceLabels,\n contextCount: meta.contexts.length,\n })\n },\n }\n}\n"],"mappings":"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"}
@@ -1,33 +1,5 @@
1
- import { BenchmarkAdapter } from './types.js';
2
- import '@tangle-network/agent-runtime/loops';
3
-
4
- /**
5
- * SimpleQA adapter (OpenAI simple-evals; short-form factual QA). Worker artifact
6
- * = a single free-text final answer string (optionally preceded by a CITATIONS:
7
- * block). Each item ships a short gold `answer` plus metadata (topic,
8
- * answer_type, source urls).
9
- *
10
- * Judge is the official SimpleQA grader — an LLM classifier that maps
11
- * (question, gold target, predicted answer) to exactly one of:
12
- * A = CORRECT — fully contains the gold, no contradiction
13
- * B = INCORRECT — contradicts / contains a different factual value
14
- * C = NOT_ATTEMPTED — hedged, non-committal, or no value given
15
- * resolved = (grade == CORRECT). score = 1 for CORRECT else 0. The grade letter
16
- * (with its label) rides in `detail`; NOT_ATTEMPTED is surfaced distinctly from
17
- * INCORRECT so the scorecard can separate abstention from error.
18
- *
19
- * There is no deterministic tier: SimpleQA's rubric (containment + abstention)
20
- * is the grader's job by design, so judge() always calls the pinned grader model
21
- * (temperature 0) and fails loud on unparseable grader output. The final-answer
22
- * extraction IS deterministic (FINAL ANSWER: sentinel, fail-closed to '').
23
- *
24
- * Requires for a live run: the bench `.venv` with `datasets`/`requests` not
25
- * needed — the test set is a single public CSV fetched over HTTP — plus a
26
- * grader key (TANGLE_API_KEY). For offline/CI verification set
27
- * SIMPLEQA_FIXTURES=1 to load the committed fixtures
28
- * (bench/fixtures/simpleqa.json) — no network.
29
- */
30
-
1
+ import { BenchmarkAdapter } from "./types.js";
2
+ //#region src/benchmarks/simpleqa.d.ts
31
3
  /**
32
4
  * Typed seam for the research worker. The benchmark adapter scores a plain
33
5
  * `string` artifact (the BenchmarkAdapter contract); the loop worker decodes its
@@ -35,20 +7,20 @@ import '@tangle-network/agent-runtime/loops';
35
7
  * optional `CITATIONS:` block) into that string before judging.
36
8
  */
37
9
  interface ResearchTask {
38
- id: string;
39
- question: string;
40
- /** Gold short answer — the grader's target. */
41
- gold: string;
42
- /** Source URLs cited by the dataset for this item — SOFT provenance signal, never a hard gate. */
43
- goldSources: string[];
44
- /** SimpleQA topic, e.g. 'Politics' — slices the scorecard by domain. */
45
- topic: string;
46
- /** SimpleQA answer_type, e.g. 'Person' | 'Date' | 'Number' | 'Place'. */
47
- answerType: string;
10
+ id: string;
11
+ question: string;
12
+ /** Gold short answer — the grader's target. */
13
+ gold: string;
14
+ /** Source URLs cited by the dataset for this item — SOFT provenance signal, never a hard gate. */
15
+ goldSources: string[];
16
+ /** SimpleQA topic, e.g. 'Politics' — slices the scorecard by domain. */
17
+ topic: string;
18
+ /** SimpleQA answer_type, e.g. 'Person' | 'Date' | 'Number' | 'Place'. */
19
+ answerType: string;
48
20
  }
49
21
  interface ResearchAnswer {
50
- finalAnswer: string;
51
- citations: string[];
22
+ finalAnswer: string;
23
+ citations: string[];
52
24
  }
53
25
  /**
54
26
  * Parse the worker artifact into the final answer string.
@@ -60,5 +32,6 @@ declare function parseFinalAnswer(artifact: string): string;
60
32
  /** Extract every bare URL in the artifact (CITATIONS: block + inline). SOFT provenance signal. */
61
33
  declare function parseCitations(artifact: string): string[];
62
34
  declare function createSimpleQaAdapter(): BenchmarkAdapter;
63
-
64
- export { type ResearchAnswer, type ResearchTask, createSimpleQaAdapter, parseCitations, parseFinalAnswer };
35
+ //#endregion
36
+ export { ResearchAnswer, ResearchTask, createSimpleQaAdapter, parseCitations, parseFinalAnswer };
37
+ //# sourceMappingURL=simpleqa.d.ts.map