@tangle-network/agent-eval 0.126.7 → 0.128.0
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 +59 -0
- package/README.md +6 -2
- package/dist/analyst/index.d.ts +52 -43
- package/dist/analyst/index.js +4 -4
- package/dist/belief-state/index.d.ts +35 -40
- package/dist/belief-state/index.js +2 -2
- package/dist/benchmarks/index.d.ts +30 -12
- package/dist/benchmarks/index.js +12 -11
- package/dist/builder-eval/index.js +1 -1
- package/dist/campaign/index.d.ts +441 -160
- package/dist/campaign/index.js +11 -10
- package/dist/{chunk-IILEIWGW.js → chunk-2JX3CFMB.js} +100 -40
- package/dist/chunk-2JX3CFMB.js.map +1 -0
- package/dist/chunk-2MKQIFS4.js +183 -0
- package/dist/chunk-2MKQIFS4.js.map +1 -0
- package/dist/{chunk-NUKSVU3W.js → chunk-5DTSBUL2.js} +2 -2
- package/dist/{chunk-H5UD2323.js → chunk-7ZZMD7UK.js} +102 -2
- package/dist/chunk-7ZZMD7UK.js.map +1 -0
- package/dist/{chunk-474LBSOX.js → chunk-BYT7ELPS.js} +45 -18
- package/dist/chunk-BYT7ELPS.js.map +1 -0
- package/dist/{chunk-LUNF2SEL.js → chunk-DJKY2TSY.js} +3 -3
- package/dist/chunk-DPUHNQLN.js +232 -0
- package/dist/chunk-DPUHNQLN.js.map +1 -0
- package/dist/chunk-DRYIUNWY.js +622 -0
- package/dist/chunk-DRYIUNWY.js.map +1 -0
- package/dist/{chunk-IPYXE555.js → chunk-EJGRPCO3.js} +36 -13
- package/dist/chunk-EJGRPCO3.js.map +1 -0
- package/dist/{chunk-OCFJACJU.js → chunk-EOSZT7PL.js} +82 -18
- package/dist/chunk-EOSZT7PL.js.map +1 -0
- package/dist/{chunk-ZVCHKKOP.js → chunk-EZJEIH2R.js} +39 -15
- package/dist/chunk-EZJEIH2R.js.map +1 -0
- package/dist/{chunk-M7AH34KV.js → chunk-IHQDPH7D.js} +32 -16
- package/dist/chunk-IHQDPH7D.js.map +1 -0
- package/dist/{chunk-PJQFMIOX.js → chunk-MHELPNRP.js} +31 -1
- package/dist/chunk-MHELPNRP.js.map +1 -0
- package/dist/{chunk-K6IAZZ6L.js → chunk-NACAGYSY.js} +153 -122
- package/dist/chunk-NACAGYSY.js.map +1 -0
- package/dist/{chunk-BTACVO2W.js → chunk-NKAGIDE2.js} +542 -258
- package/dist/chunk-NKAGIDE2.js.map +1 -0
- package/dist/{chunk-ARU2PZFM.js → chunk-NYLOYM6N.js} +43 -23
- package/dist/chunk-NYLOYM6N.js.map +1 -0
- package/dist/{chunk-QOTFXW5L.js → chunk-P5W7RQKK.js} +2 -2
- package/dist/{chunk-IR3KBHOY.js → chunk-P6FYH6K4.js} +39 -3
- package/dist/chunk-P6FYH6K4.js.map +1 -0
- package/dist/{chunk-J5SQWP6Y.js → chunk-PBE2LOSS.js} +18 -2
- package/dist/chunk-PBE2LOSS.js.map +1 -0
- package/dist/{chunk-X4UCIOTZ.js → chunk-S5YLIBFX.js} +2 -2
- package/dist/{chunk-7VYEGHWF.js → chunk-SZLVEKMJ.js} +41 -20
- package/dist/chunk-SZLVEKMJ.js.map +1 -0
- package/dist/{chunk-P22LJ3Y2.js → chunk-TBL77AUT.js} +8 -8
- package/dist/chunk-TBL77AUT.js.map +1 -0
- package/dist/{chunk-LKKT3IVV.js → chunk-TSN7JT6D.js} +6 -4
- package/dist/{chunk-LKKT3IVV.js.map → chunk-TSN7JT6D.js.map} +1 -1
- package/dist/{chunk-E3IADPLG.js → chunk-UB2LOJ6Q.js} +51 -227
- package/dist/chunk-UB2LOJ6Q.js.map +1 -0
- package/dist/{chunk-MAX3TN3C.js → chunk-UWZZKKU7.js} +7 -19
- package/dist/chunk-UWZZKKU7.js.map +1 -0
- package/dist/{chunk-DPZAEKA6.js → chunk-VLOATJQ2.js} +85 -57
- package/dist/chunk-VLOATJQ2.js.map +1 -0
- package/dist/{chunk-MOXWMGPC.js → chunk-XDWDC2MP.js} +197 -79
- package/dist/chunk-XDWDC2MP.js.map +1 -0
- package/dist/{chunk-CGG5SLH3.js → chunk-XPRT64IE.js} +2 -2
- package/dist/{chunk-FO7HEH76.js → chunk-YJBNWCAA.js} +2 -2
- package/dist/{chunk-KE2VWPZX.js → chunk-ZUUWPZCV.js} +3 -3
- package/dist/cli.js +4 -4
- package/dist/contract/index.d.ts +438 -138
- package/dist/contract/index.js +259 -113
- package/dist/contract/index.js.map +1 -1
- package/dist/control.d.ts +56 -39
- package/dist/control.js +2 -3
- package/dist/hosted/index.d.ts +152 -51
- package/dist/hosted/index.js +24 -1
- package/dist/index.d.ts +399 -277
- package/dist/index.js +363 -244
- package/dist/index.js.map +1 -1
- package/dist/meta-eval/index.d.ts +33 -36
- package/dist/meta-eval/index.js +2 -2
- package/dist/multishot/index.d.ts +1 -0
- package/dist/openapi.json +1 -1
- package/dist/pipelines/index.js +2 -2
- package/dist/reporting.d.ts +101 -80
- package/dist/reporting.js +7 -5
- package/dist/rl.d.ts +198 -142
- package/dist/rl.js +235 -127
- package/dist/rl.js.map +1 -1
- package/dist/rollout/index.d.ts +54 -67
- package/dist/rollout/index.js +6 -5
- package/dist/{run-campaign-FFRM3RH5.js → run-campaign-ISHFZ7FJ.js} +6 -3
- package/dist/supervisor-run/index.d.ts +7 -15
- package/dist/supervisor-run/index.js +2 -2
- package/dist/traces.d.ts +72 -50
- package/dist/traces.js +9 -6
- package/dist/wire/index.d.ts +1 -0
- package/dist/wire/index.js +2 -2
- package/docs/concepts.md +18 -1
- package/docs/customer-journeys.md +7 -6
- package/docs/hosted-ingest-spec.md +37 -40
- package/docs/insight-report.md +78 -7
- package/docs/research-report-methodology.md +20 -21
- package/docs/rollout.md +13 -8
- package/package.json +4 -3
- package/dist/chunk-474LBSOX.js.map +0 -1
- package/dist/chunk-7VYEGHWF.js.map +0 -1
- package/dist/chunk-ARU2PZFM.js.map +0 -1
- package/dist/chunk-BTACVO2W.js.map +0 -1
- package/dist/chunk-DPZAEKA6.js.map +0 -1
- package/dist/chunk-E3IADPLG.js.map +0 -1
- package/dist/chunk-H5UD2323.js.map +0 -1
- package/dist/chunk-IILEIWGW.js.map +0 -1
- package/dist/chunk-IPYXE555.js.map +0 -1
- package/dist/chunk-IR3KBHOY.js.map +0 -1
- package/dist/chunk-J5SQWP6Y.js.map +0 -1
- package/dist/chunk-K6IAZZ6L.js.map +0 -1
- package/dist/chunk-M7AH34KV.js.map +0 -1
- package/dist/chunk-MAX3TN3C.js.map +0 -1
- package/dist/chunk-MOXWMGPC.js.map +0 -1
- package/dist/chunk-OCFJACJU.js.map +0 -1
- package/dist/chunk-P22LJ3Y2.js.map +0 -1
- package/dist/chunk-PJQFMIOX.js.map +0 -1
- package/dist/chunk-VSMTAMNK.js +0 -53
- package/dist/chunk-VSMTAMNK.js.map +0 -1
- package/dist/chunk-ZVCHKKOP.js.map +0 -1
- package/dist/chunk-ZZUXHH3R.js +0 -99
- package/dist/chunk-ZZUXHH3R.js.map +0 -1
- /package/dist/{chunk-NUKSVU3W.js.map → chunk-5DTSBUL2.js.map} +0 -0
- /package/dist/{chunk-LUNF2SEL.js.map → chunk-DJKY2TSY.js.map} +0 -0
- /package/dist/{chunk-QOTFXW5L.js.map → chunk-P5W7RQKK.js.map} +0 -0
- /package/dist/{chunk-X4UCIOTZ.js.map → chunk-S5YLIBFX.js.map} +0 -0
- /package/dist/{chunk-CGG5SLH3.js.map → chunk-XPRT64IE.js.map} +0 -0
- /package/dist/{chunk-FO7HEH76.js.map → chunk-YJBNWCAA.js.map} +0 -0
- /package/dist/{chunk-KE2VWPZX.js.map → chunk-ZUUWPZCV.js.map} +0 -0
- /package/dist/{run-campaign-FFRM3RH5.js.map → run-campaign-ISHFZ7FJ.js.map} +0 -0
package/dist/rl.js
CHANGED
|
@@ -10,25 +10,29 @@ import {
|
|
|
10
10
|
} from "./chunk-3RF76KTD.js";
|
|
11
11
|
import {
|
|
12
12
|
runEvalCampaign
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-TBL77AUT.js";
|
|
14
14
|
import {
|
|
15
15
|
detectRewardHacking,
|
|
16
16
|
extractVerifiableReward,
|
|
17
17
|
extractVerifiableRewardsFromRecords,
|
|
18
18
|
filterDeterministicallyRewarded
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import
|
|
19
|
+
} from "./chunk-NYLOYM6N.js";
|
|
20
|
+
import {
|
|
21
|
+
campaignCellToRunRecord
|
|
22
|
+
} from "./chunk-2MKQIFS4.js";
|
|
23
|
+
import "./chunk-PBE2LOSS.js";
|
|
21
24
|
import {
|
|
22
25
|
rubricPredictiveValidity
|
|
23
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-S5YLIBFX.js";
|
|
24
27
|
import {
|
|
25
28
|
evaluateInterimReleaseConfidence
|
|
26
29
|
} from "./chunk-MAZ26DC7.js";
|
|
27
|
-
import "./chunk-
|
|
30
|
+
import "./chunk-VLOATJQ2.js";
|
|
31
|
+
import "./chunk-DPUHNQLN.js";
|
|
28
32
|
import {
|
|
29
33
|
benjaminiHochberg,
|
|
30
34
|
wilcoxonSignedRank
|
|
31
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-MHELPNRP.js";
|
|
32
36
|
import {
|
|
33
37
|
observationsFromRunRecords,
|
|
34
38
|
thompsonCurriculum,
|
|
@@ -39,9 +43,10 @@ import "./chunk-VI2UW6B6.js";
|
|
|
39
43
|
import "./chunk-TT4KNT67.js";
|
|
40
44
|
import "./chunk-PC4UYEBM.js";
|
|
41
45
|
import "./chunk-VQMK5FMP.js";
|
|
42
|
-
import
|
|
46
|
+
import {
|
|
47
|
+
runTaskScore
|
|
48
|
+
} from "./chunk-2JX3CFMB.js";
|
|
43
49
|
import "./chunk-MA6HLL3S.js";
|
|
44
|
-
import "./chunk-VSMTAMNK.js";
|
|
45
50
|
import {
|
|
46
51
|
ValidationError
|
|
47
52
|
} from "./chunk-ONWEPEDO.js";
|
|
@@ -366,13 +371,19 @@ import { dirname } from "path";
|
|
|
366
371
|
async function toDpoRows(triples, lookups) {
|
|
367
372
|
const out = [];
|
|
368
373
|
for (const t of triples) {
|
|
369
|
-
const [
|
|
374
|
+
const [chosenPrompt, rejectedPrompt, chosen, rejected] = await Promise.all([
|
|
370
375
|
Promise.resolve(lookups.promptOf(t.chosenRunId)),
|
|
376
|
+
Promise.resolve(lookups.promptOf(t.rejectedRunId)),
|
|
371
377
|
Promise.resolve(lookups.completionOf(t.chosenRunId)),
|
|
372
378
|
Promise.resolve(lookups.completionOf(t.rejectedRunId))
|
|
373
379
|
]);
|
|
380
|
+
if (chosenPrompt !== rejectedPrompt) {
|
|
381
|
+
throw new Error(
|
|
382
|
+
`toDpoRows: preference "${t.chosenRunId}"/"${t.rejectedRunId}" resolves to different prompts`
|
|
383
|
+
);
|
|
384
|
+
}
|
|
374
385
|
out.push({
|
|
375
|
-
prompt,
|
|
386
|
+
prompt: chosenPrompt,
|
|
376
387
|
chosen,
|
|
377
388
|
rejected,
|
|
378
389
|
margin: t.marginScore,
|
|
@@ -394,29 +405,44 @@ function toDpoJsonl(rows) {
|
|
|
394
405
|
}
|
|
395
406
|
async function toGrpoRows(runs, lookups) {
|
|
396
407
|
const rewardOf2 = lookups.rewardOf ?? defaultReward;
|
|
408
|
+
const promptHashByScenario = /* @__PURE__ */ new Map();
|
|
397
409
|
const grouped = /* @__PURE__ */ new Map();
|
|
398
410
|
for (const r of runs) {
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
411
|
+
const reward2 = rewardOf2(r);
|
|
412
|
+
if (!isTrainingRunEligible(r, reward2, lookups)) continue;
|
|
413
|
+
const existingPromptHash = promptHashByScenario.get(r.scenarioId);
|
|
414
|
+
if (existingPromptHash !== void 0 && existingPromptHash !== r.promptHash) {
|
|
415
|
+
throw new Error(
|
|
416
|
+
`toGrpoRows: scenario "${r.scenarioId}" contains mixed prompt identities "${existingPromptHash}" and "${r.promptHash}"`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
promptHashByScenario.set(r.scenarioId, r.promptHash);
|
|
420
|
+
const key = `${r.scenarioId}\0${r.promptHash}`;
|
|
421
|
+
const group = grouped.get(key) ?? {
|
|
422
|
+
scenarioId: r.scenarioId,
|
|
423
|
+
promptHash: r.promptHash,
|
|
424
|
+
scored: []
|
|
425
|
+
};
|
|
426
|
+
group.scored.push({ run: r, reward: reward2 });
|
|
427
|
+
grouped.set(key, group);
|
|
403
428
|
}
|
|
404
429
|
const rows = [];
|
|
405
|
-
for (const
|
|
406
|
-
if (
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
completions.push(completion);
|
|
416
|
-
rewards.push(reward2);
|
|
417
|
-
runIds.push(r.runId);
|
|
430
|
+
for (const { scenarioId, promptHash, scored } of grouped.values()) {
|
|
431
|
+
if (scored.length < 2) continue;
|
|
432
|
+
const prompts = await Promise.all(
|
|
433
|
+
scored.map(({ run }) => Promise.resolve(lookups.promptOf(run.runId)))
|
|
434
|
+
);
|
|
435
|
+
const prompt = prompts[0];
|
|
436
|
+
if (prompts.some((value) => value !== prompt)) {
|
|
437
|
+
throw new Error(
|
|
438
|
+
`toGrpoRows: prompt identity "${promptHash}" resolves to different text within scenario "${scenarioId}"`
|
|
439
|
+
);
|
|
418
440
|
}
|
|
419
|
-
|
|
441
|
+
const completions = await Promise.all(
|
|
442
|
+
scored.map(({ run }) => Promise.resolve(lookups.completionOf(run.runId)))
|
|
443
|
+
);
|
|
444
|
+
const rewards = scored.map(({ reward: reward2 }) => reward2);
|
|
445
|
+
const runIds = scored.map(({ run }) => run.runId);
|
|
420
446
|
rows.push({
|
|
421
447
|
prompt,
|
|
422
448
|
completions,
|
|
@@ -424,6 +450,7 @@ async function toGrpoRows(runs, lookups) {
|
|
|
424
450
|
runIds,
|
|
425
451
|
meta: {
|
|
426
452
|
scenarioId,
|
|
453
|
+
promptHash,
|
|
427
454
|
n: completions.length,
|
|
428
455
|
meanReward: rewards.reduce((s, x) => s + x, 0) / rewards.length
|
|
429
456
|
}
|
|
@@ -438,6 +465,8 @@ async function toSftRows(runs, lookups) {
|
|
|
438
465
|
const include = lookups.include ?? (() => true);
|
|
439
466
|
const rows = [];
|
|
440
467
|
for (const r of runs) {
|
|
468
|
+
const score = runTaskScore(r);
|
|
469
|
+
if (!isTrainingRunEligible(r, score, lookups)) continue;
|
|
441
470
|
if (!include(r)) continue;
|
|
442
471
|
const system = lookups.systemOf?.(r);
|
|
443
472
|
const [prompt, completion] = await Promise.all([
|
|
@@ -454,7 +483,7 @@ async function toSftRows(runs, lookups) {
|
|
|
454
483
|
runId: r.runId,
|
|
455
484
|
candidateId: r.candidateId,
|
|
456
485
|
scenarioId: r.scenarioId,
|
|
457
|
-
score
|
|
486
|
+
score,
|
|
458
487
|
model: r.model
|
|
459
488
|
}
|
|
460
489
|
});
|
|
@@ -510,20 +539,65 @@ function stepRewardsToJsonl(stepRewards) {
|
|
|
510
539
|
return rows.map((r) => JSON.stringify(r)).join("\n") + (rows.length > 0 ? "\n" : "");
|
|
511
540
|
}
|
|
512
541
|
function defaultReward(run) {
|
|
513
|
-
|
|
514
|
-
|
|
542
|
+
return runTaskScore(run) ?? null;
|
|
543
|
+
}
|
|
544
|
+
function isTrainingRunEligible(run, quality, options = {}) {
|
|
545
|
+
const minimumQualityExclusive = options.minimumQualityExclusive ?? 0;
|
|
546
|
+
if (!Number.isFinite(minimumQualityExclusive)) {
|
|
547
|
+
throw new Error("minimumQualityExclusive must be finite");
|
|
548
|
+
}
|
|
549
|
+
if (quality === null || quality === void 0) return false;
|
|
550
|
+
if (!Number.isFinite(quality)) {
|
|
551
|
+
throw new Error(`training quality for run "${run.runId}" must be finite`);
|
|
552
|
+
}
|
|
553
|
+
if (quality <= minimumQualityExclusive) return false;
|
|
554
|
+
if (run.terminalOutcome !== "succeeded") return false;
|
|
555
|
+
if (run.failureClass !== void 0 || run.terminalFailureReason !== void 0) return false;
|
|
556
|
+
if (run.outcome.realness?.gated === true) return false;
|
|
557
|
+
if (run.splitTag === "search") return true;
|
|
558
|
+
return run.splitTag === "holdout" && options.allowHeldOutTrainingData === true;
|
|
515
559
|
}
|
|
516
560
|
|
|
517
561
|
// src/rl/dataset.ts
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
562
|
+
var DATASET_FORMATS = ["grpo", "sft", "dpo"];
|
|
563
|
+
var DATASET_FORMAT_SET = new Set(DATASET_FORMATS);
|
|
564
|
+
function validateDatasetFormats(value) {
|
|
565
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
566
|
+
throw new Error("buildRlDataset: formats must contain at least one of: grpo, sft, dpo");
|
|
567
|
+
}
|
|
568
|
+
const formats = [];
|
|
569
|
+
const seen = /* @__PURE__ */ new Set();
|
|
570
|
+
for (const format of value) {
|
|
571
|
+
if (!DATASET_FORMAT_SET.has(format)) {
|
|
572
|
+
throw new Error(
|
|
573
|
+
`buildRlDataset: unsupported format ${JSON.stringify(format)}; expected exactly one of: grpo, sft, dpo`
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
const datasetFormat = format;
|
|
577
|
+
if (seen.has(datasetFormat)) {
|
|
578
|
+
throw new Error(
|
|
579
|
+
`buildRlDataset: duplicate format ${JSON.stringify(datasetFormat)}; each format may be requested once`
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
seen.add(datasetFormat);
|
|
583
|
+
formats.push(datasetFormat);
|
|
584
|
+
}
|
|
585
|
+
return formats;
|
|
586
|
+
}
|
|
587
|
+
function reward(r, rewardOf2) {
|
|
588
|
+
const value = rewardOf2 ? rewardOf2(r) : runTaskScore(r) ?? null;
|
|
589
|
+
if (value !== null && !Number.isFinite(value)) {
|
|
590
|
+
throw new Error(`buildRlDataset: reward for run "${r.runId}" must be finite`);
|
|
591
|
+
}
|
|
592
|
+
return value;
|
|
521
593
|
}
|
|
522
594
|
function distinct(xs) {
|
|
523
595
|
return [...new Set(xs)].sort();
|
|
524
596
|
}
|
|
525
597
|
function computeRewardStats(values) {
|
|
526
|
-
if (values.length === 0)
|
|
598
|
+
if (values.length === 0) {
|
|
599
|
+
return { n: 0, mean: null, median: null, min: null, max: null, std: null };
|
|
600
|
+
}
|
|
527
601
|
const sorted = [...values].sort((a, b) => a - b);
|
|
528
602
|
const n = sorted.length;
|
|
529
603
|
const mean = sorted.reduce((s, x) => s + x, 0) / n;
|
|
@@ -532,7 +606,7 @@ function computeRewardStats(values) {
|
|
|
532
606
|
const variance = sorted.reduce((s, x) => s + (x - mean) ** 2, 0) / n;
|
|
533
607
|
return { n, mean, median, min: sorted[0], max: sorted[n - 1], std: Math.sqrt(variance) };
|
|
534
608
|
}
|
|
535
|
-
function computeStats(records) {
|
|
609
|
+
function computeStats(records, rewardOf2) {
|
|
536
610
|
const splits = { search: 0, dev: 0, holdout: 0 };
|
|
537
611
|
let inTok = 0;
|
|
538
612
|
let outTok = 0;
|
|
@@ -542,12 +616,13 @@ function computeStats(records) {
|
|
|
542
616
|
splits[r.splitTag] = (splits[r.splitTag] ?? 0) + 1;
|
|
543
617
|
inTok += r.tokenUsage.input;
|
|
544
618
|
outTok += r.tokenUsage.output;
|
|
545
|
-
cost += r.costUsd;
|
|
546
|
-
const rw = reward(r);
|
|
619
|
+
cost += r.costUsd ?? 0;
|
|
620
|
+
const rw = reward(r, rewardOf2);
|
|
547
621
|
if (rw !== null) rewards.push(rw);
|
|
548
622
|
}
|
|
549
623
|
return {
|
|
550
624
|
records: records.length,
|
|
625
|
+
scoredRecords: rewards.length,
|
|
551
626
|
splits,
|
|
552
627
|
reward: computeRewardStats(rewards),
|
|
553
628
|
models: distinct(records.map((r) => r.model)),
|
|
@@ -561,16 +636,18 @@ async function buildRlDataset(records, lookups, config, preferences) {
|
|
|
561
636
|
if (records.length === 0) {
|
|
562
637
|
throw new Error("buildRlDataset: no records \u2014 refusing to package an empty dataset");
|
|
563
638
|
}
|
|
564
|
-
const formats = config.formats
|
|
639
|
+
const formats = validateDatasetFormats(config.formats === void 0 ? ["sft"] : config.formats);
|
|
565
640
|
const files = {};
|
|
566
641
|
const rowCounts = {};
|
|
567
642
|
if (formats.includes("grpo")) {
|
|
568
643
|
const rows = await toGrpoRows(records, lookups);
|
|
644
|
+
requireRows("grpo", rows.length);
|
|
569
645
|
files["train.grpo.jsonl"] = toGrpoJsonl(rows);
|
|
570
646
|
rowCounts.grpo = rows.length;
|
|
571
647
|
}
|
|
572
648
|
if (formats.includes("sft")) {
|
|
573
649
|
const rows = await toSftRows(records, lookups);
|
|
650
|
+
requireRows("sft", rows.length);
|
|
574
651
|
files["train.sft.jsonl"] = toSftJsonl(rows);
|
|
575
652
|
rowCounts.sft = rows.length;
|
|
576
653
|
}
|
|
@@ -579,23 +656,35 @@ async function buildRlDataset(records, lookups, config, preferences) {
|
|
|
579
656
|
throw new Error("buildRlDataset: format 'dpo' requires `preferences` (triples + lookups)");
|
|
580
657
|
}
|
|
581
658
|
const rows = await toDpoRows(preferences.triples, preferences.lookups);
|
|
659
|
+
requireRows("dpo", rows.length);
|
|
582
660
|
files["train.dpo.jsonl"] = toDpoJsonl(rows);
|
|
583
661
|
rowCounts.dpo = rows.length;
|
|
584
662
|
}
|
|
663
|
+
if (!Object.keys(files).some((name) => name.startsWith("train.") && name.endsWith(".jsonl"))) {
|
|
664
|
+
throw new Error("buildRlDataset: no trainer file was emitted");
|
|
665
|
+
}
|
|
585
666
|
const manifest = {
|
|
586
667
|
...config,
|
|
587
668
|
formats,
|
|
588
669
|
rowCounts,
|
|
589
|
-
stats: computeStats(records)
|
|
670
|
+
stats: computeStats(records, lookups.rewardOf)
|
|
590
671
|
};
|
|
591
672
|
files["manifest.json"] = `${JSON.stringify(manifest, null, 2)}
|
|
592
673
|
`;
|
|
593
674
|
files["DATASHEET.md"] = datasheetToMarkdown(manifest);
|
|
594
675
|
return { manifest, files };
|
|
595
676
|
}
|
|
677
|
+
function requireRows(format, rows) {
|
|
678
|
+
if (rows === 0) {
|
|
679
|
+
throw new Error(`buildRlDataset: requested '${format}' format produced no trainable rows`);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
596
682
|
function pct(x) {
|
|
597
683
|
return `${(x * 100).toFixed(1)}%`;
|
|
598
684
|
}
|
|
685
|
+
function stat(value) {
|
|
686
|
+
return value === null ? "n/a" : value.toFixed(3);
|
|
687
|
+
}
|
|
599
688
|
function datasheetToMarkdown(m) {
|
|
600
689
|
const s = m.stats;
|
|
601
690
|
const total = s.records || 1;
|
|
@@ -604,31 +693,32 @@ function datasheetToMarkdown(m) {
|
|
|
604
693
|
return [
|
|
605
694
|
`# Dataset: ${m.name} \`v${m.version}\``,
|
|
606
695
|
"",
|
|
607
|
-
`**Domain:** ${m.domain}
|
|
696
|
+
`**Domain:** ${m.domain} | **Created:** ${m.createdAtIso} | **License:** ${m.license}`,
|
|
608
697
|
"",
|
|
609
698
|
"## Reward provenance",
|
|
610
|
-
`- **Kind:** ${m.reward.kind}${deterministic ? "
|
|
699
|
+
`- **Kind:** ${m.reward.kind}${deterministic ? " (decidable, not judge noise)" : ""}`,
|
|
611
700
|
`- **Source:** ${m.reward.source}`,
|
|
612
701
|
`- **Description:** ${m.reward.description}`,
|
|
613
702
|
"",
|
|
614
703
|
"## Composition",
|
|
615
704
|
`- **Records (trajectories):** ${s.records}`,
|
|
705
|
+
`- **Scored records:** ${s.scoredRecords}`,
|
|
616
706
|
`- **Formats:** ${m.formats.map((f) => `${f} (${m.rowCounts[f] ?? 0} rows)`).join(", ")}`,
|
|
617
707
|
"- **Splits:**",
|
|
618
708
|
splitLines,
|
|
619
709
|
"",
|
|
620
710
|
"## Reward distribution",
|
|
621
|
-
`- n=${s.reward.n}
|
|
711
|
+
`- n=${s.reward.n} | mean=${stat(s.reward.mean)} | median=${stat(s.reward.median)} | min=${stat(s.reward.min)} | max=${stat(s.reward.max)} | std=${stat(s.reward.std)}`,
|
|
622
712
|
"",
|
|
623
713
|
"## Provenance",
|
|
624
714
|
`- **Models:** ${s.models.join(", ")}`,
|
|
625
715
|
`- **Prompt/agent versions (sha256):** ${s.promptHashes.length} distinct`,
|
|
626
716
|
`- **Commits:** ${s.commitShas.join(", ")}`,
|
|
627
|
-
`- **Tokens:** ${s.totalTokens.input} in / ${s.totalTokens.output} out
|
|
717
|
+
`- **Tokens:** ${s.totalTokens.input} in / ${s.totalTokens.output} out | **Cost:** $${s.totalCostUsd.toFixed(2)}`,
|
|
628
718
|
"",
|
|
629
719
|
"## Quality gates",
|
|
630
720
|
`- Contamination probe: ${m.qualityGates?.contaminationProbe ?? "not-run"}`,
|
|
631
|
-
`- Dedup: ${m.qualityGates?.dedup ? "yes" : "no"}
|
|
721
|
+
`- Dedup: ${m.qualityGates?.dedup ? "yes" : "no"} | Verifiable-reward filter: ${m.qualityGates?.verifiableRewardFilter ? "yes" : "no"}`,
|
|
632
722
|
"",
|
|
633
723
|
"## Recommended uses",
|
|
634
724
|
m.intendedUse,
|
|
@@ -640,7 +730,7 @@ function datasheetToMarkdown(m) {
|
|
|
640
730
|
m.limitations,
|
|
641
731
|
"",
|
|
642
732
|
"## Token rendering",
|
|
643
|
-
"For RL/SFT training, tokenize with the per-model renderer (DeepSeek-V3 / Kimi-K2 / Qwen3) to preserve token identity and per-token loss masks across tool-call turns
|
|
733
|
+
"For RL/SFT training, tokenize with the per-model renderer (DeepSeek-V3 / Kimi-K2 / Qwen3) to preserve token identity and per-token loss masks across tool-call turns. See `renderers` (PrimeIntellect). The `messages` / `completions` here are the renderer input.",
|
|
644
734
|
""
|
|
645
735
|
].join("\n");
|
|
646
736
|
}
|
|
@@ -675,21 +765,27 @@ function readCorpus(corpusPath) {
|
|
|
675
765
|
return out;
|
|
676
766
|
}
|
|
677
767
|
function rewardOf(r) {
|
|
678
|
-
|
|
679
|
-
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
768
|
+
return runTaskScore(r) ?? null;
|
|
680
769
|
}
|
|
681
770
|
async function buildDatasetFromCorpus(corpusPath, config, opts = {}) {
|
|
682
771
|
let records = readCorpus(corpusPath).filter(
|
|
683
772
|
(r) => typeof r.prompt === "string" && typeof r.completion === "string"
|
|
684
773
|
);
|
|
685
774
|
if (opts.splits) records = records.filter((r) => opts.splits.includes(r.splitTag));
|
|
686
|
-
|
|
775
|
+
records = records.filter((r) => rewardOf(r) !== null);
|
|
776
|
+
if (opts.minScore != null) {
|
|
777
|
+
records = records.filter((r) => {
|
|
778
|
+
const reward2 = rewardOf(r);
|
|
779
|
+
return reward2 !== null && reward2 >= opts.minScore;
|
|
780
|
+
});
|
|
781
|
+
}
|
|
687
782
|
const text = new Map(
|
|
688
783
|
records.map((r) => [r.runId, { prompt: r.prompt, completion: r.completion }])
|
|
689
784
|
);
|
|
690
785
|
const lookups = {
|
|
691
786
|
promptOf: (id) => text.get(id)?.prompt ?? "",
|
|
692
|
-
completionOf: (id) => text.get(id)?.completion ?? ""
|
|
787
|
+
completionOf: (id) => text.get(id)?.completion ?? "",
|
|
788
|
+
allowHeldOutTrainingData: opts.allowHeldOutTrainingData
|
|
693
789
|
};
|
|
694
790
|
return buildRlDataset(records, lookups, config);
|
|
695
791
|
}
|
|
@@ -705,7 +801,7 @@ var PredictiveValidityResearcher = class {
|
|
|
705
801
|
const threshold = this.opts.failureThreshold ?? 0.5;
|
|
706
802
|
const failures = [];
|
|
707
803
|
const failingRuns = runs.filter((r) => {
|
|
708
|
-
const score = r
|
|
804
|
+
const score = runTaskScore(r);
|
|
709
805
|
return typeof score === "number" && score < threshold;
|
|
710
806
|
});
|
|
711
807
|
if (failingRuns.length === 0) return failures;
|
|
@@ -717,8 +813,11 @@ var PredictiveValidityResearcher = class {
|
|
|
717
813
|
}
|
|
718
814
|
for (const [candidateId, group] of grouped.entries()) {
|
|
719
815
|
const meanScore = group.reduce((s, r) => {
|
|
720
|
-
const
|
|
721
|
-
|
|
816
|
+
const score = runTaskScore(r);
|
|
817
|
+
if (score === void 0) {
|
|
818
|
+
throw new Error(`failing run ${r.runId} unexpectedly has no task score`);
|
|
819
|
+
}
|
|
820
|
+
return s + score;
|
|
722
821
|
}, 0) / group.length;
|
|
723
822
|
failures.push({
|
|
724
823
|
code: `low-score-${candidateId}`,
|
|
@@ -788,15 +887,17 @@ var PredictiveValidityResearcher = class {
|
|
|
788
887
|
baselineId: plan.baselineCandidateId,
|
|
789
888
|
evidence: {
|
|
790
889
|
productiveRuns: 0,
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
890
|
+
unpairedCandidateRuns: 0,
|
|
891
|
+
unpairedBaselineRuns: 0,
|
|
892
|
+
medianPairedDelta: null,
|
|
893
|
+
pairedCI: null,
|
|
894
|
+
pairedPValue: null,
|
|
895
|
+
searchScore: null,
|
|
896
|
+
holdoutScore: null,
|
|
897
|
+
overfitGap: null,
|
|
898
|
+
baselineOverfitGap: null,
|
|
899
|
+
medianCandidateCost: null,
|
|
900
|
+
medianBaselineCost: null
|
|
800
901
|
},
|
|
801
902
|
reason: "predictive-validity researcher does not execute plans; the caller is expected to run the sweep and call rubricPredictiveValidity directly with the resulting RunRecord[].",
|
|
802
903
|
rejectionCode: "few_runs"
|
|
@@ -837,21 +938,27 @@ var PredictiveValidityResearcher = class {
|
|
|
837
938
|
};
|
|
838
939
|
|
|
839
940
|
// src/rl/preferences.ts
|
|
840
|
-
var SPLIT_TAG_DEFAULT = "holdout";
|
|
841
941
|
var DEFAULT_REWARD = (run) => {
|
|
842
|
-
|
|
843
|
-
return typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
942
|
+
return runTaskScore(run) ?? null;
|
|
844
943
|
};
|
|
845
944
|
function extractPreferences(runs, opts = {}) {
|
|
846
945
|
const strategy = opts.strategy ?? "paired-by-scenario-and-seed";
|
|
847
946
|
const minMargin = opts.minMargin ?? 0.05;
|
|
848
|
-
const splitTag = opts.splitTag
|
|
947
|
+
const splitTag = opts.splitTag;
|
|
849
948
|
const rewardOf2 = opts.rewardOf ?? DEFAULT_REWARD;
|
|
850
|
-
|
|
949
|
+
if (splitTag === "holdout" && opts.allowHeldOutTrainingData !== true) {
|
|
950
|
+
throw new Error(
|
|
951
|
+
'extractPreferences: splitTag "holdout" requires allowHeldOutTrainingData: true'
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
if (splitTag === "dev") {
|
|
955
|
+
throw new Error('extractPreferences: splitTag "dev" is evaluation-only; train from "search"');
|
|
956
|
+
}
|
|
851
957
|
const scoredEntries = [];
|
|
852
|
-
for (const run of
|
|
958
|
+
for (const run of runs) {
|
|
959
|
+
if (splitTag !== void 0 && run.splitTag !== splitTag) continue;
|
|
853
960
|
const s = rewardOf2(run);
|
|
854
|
-
if (s
|
|
961
|
+
if (!isTrainingRunEligible(run, s, opts)) continue;
|
|
855
962
|
scoredEntries.push({ run, score: s });
|
|
856
963
|
}
|
|
857
964
|
const pairs = [];
|
|
@@ -946,14 +1053,6 @@ function extractPreferences(runs, opts = {}) {
|
|
|
946
1053
|
}
|
|
947
1054
|
return { pairs, cellsInspected, pairsBelowMargin, cellsSingleton, strategy };
|
|
948
1055
|
}
|
|
949
|
-
function toTRLFormat(triples, promptOf) {
|
|
950
|
-
return triples.map((t) => ({
|
|
951
|
-
prompt: promptOf(t.meta.chosenPromptHash),
|
|
952
|
-
chosen: t.meta.chosenPromptHash,
|
|
953
|
-
// caller substitutes the model output via the runId map
|
|
954
|
-
rejected: t.meta.rejectedPromptHash
|
|
955
|
-
}));
|
|
956
|
-
}
|
|
957
1056
|
function toAnthropicFormat(triples) {
|
|
958
1057
|
return triples.map((t) => ({
|
|
959
1058
|
scenarioId: t.scenarioId,
|
|
@@ -989,11 +1088,7 @@ function makePair(a, b, scenarioId, minMargin) {
|
|
|
989
1088
|
};
|
|
990
1089
|
}
|
|
991
1090
|
function scenarioOf(run) {
|
|
992
|
-
|
|
993
|
-
const fromRaw = run.outcome.raw.scenario_id;
|
|
994
|
-
if (typeof fromRaw === "number" && Number.isFinite(fromRaw)) return String(fromRaw);
|
|
995
|
-
if (typeof fromRaw === "string") return fromRaw;
|
|
996
|
-
return run.experimentId;
|
|
1091
|
+
return run.scenarioId;
|
|
997
1092
|
}
|
|
998
1093
|
|
|
999
1094
|
// src/rl/process-reward.ts
|
|
@@ -1123,16 +1218,17 @@ function prmTrainingPairs(stepRewardsByRun, opts = {}) {
|
|
|
1123
1218
|
|
|
1124
1219
|
// src/rl/rl-campaign.ts
|
|
1125
1220
|
async function runRLCampaign(opts) {
|
|
1126
|
-
const
|
|
1221
|
+
const splitTag = opts.splitTag ?? "search";
|
|
1222
|
+
const campaign = await runEvalCampaign({ ...opts, splitTag });
|
|
1127
1223
|
const rewardSignals = extractVerifiableRewardsFromRecords(
|
|
1128
1224
|
campaign.runs,
|
|
1129
1225
|
opts.verifiableReward ?? {}
|
|
1130
1226
|
);
|
|
1131
1227
|
const preferences = extractPreferences(campaign.runs, {
|
|
1228
|
+
...opts.preferences,
|
|
1132
1229
|
strategy: opts.preferences?.strategy ?? "paired-by-scenario-and-seed",
|
|
1133
1230
|
minMargin: opts.preferences?.minMargin ?? 0.05,
|
|
1134
|
-
splitTag: opts.preferences?.splitTag ??
|
|
1135
|
-
rewardOf: opts.preferences?.rewardOf
|
|
1231
|
+
splitTag: opts.preferences?.splitTag ?? splitTag
|
|
1136
1232
|
});
|
|
1137
1233
|
let interimConfidence = null;
|
|
1138
1234
|
if (opts.report?.comparator) {
|
|
@@ -1192,17 +1288,17 @@ function collectPairedDeltaSeries(runs, comparator) {
|
|
|
1192
1288
|
const baseline = /* @__PURE__ */ new Map();
|
|
1193
1289
|
for (const r of runs) {
|
|
1194
1290
|
if (r.candidateId !== comparator) continue;
|
|
1195
|
-
const sid = r.scenarioId
|
|
1196
|
-
const score = r
|
|
1197
|
-
if (
|
|
1291
|
+
const sid = r.scenarioId;
|
|
1292
|
+
const score = runTaskScore(r);
|
|
1293
|
+
if (score === void 0) continue;
|
|
1198
1294
|
baseline.set(`${sid}::${r.seed}`, score);
|
|
1199
1295
|
}
|
|
1200
1296
|
const byCandidate = /* @__PURE__ */ new Map();
|
|
1201
1297
|
for (const r of runs) {
|
|
1202
1298
|
if (r.candidateId === comparator) continue;
|
|
1203
|
-
const sid = r.scenarioId
|
|
1204
|
-
const score = r
|
|
1205
|
-
if (
|
|
1299
|
+
const sid = r.scenarioId;
|
|
1300
|
+
const score = runTaskScore(r);
|
|
1301
|
+
if (score === void 0) continue;
|
|
1206
1302
|
const baseScore = baseline.get(`${sid}::${r.seed}`);
|
|
1207
1303
|
if (typeof baseScore !== "number") continue;
|
|
1208
1304
|
const arr = byCandidate.get(r.candidateId) ?? [];
|
|
@@ -1238,62 +1334,68 @@ function buildSummary(args) {
|
|
|
1238
1334
|
function campaignToRunRecords(campaign, ctx) {
|
|
1239
1335
|
const splitTag = ctx.splitTag ?? "search";
|
|
1240
1336
|
const candidateId = ctx.candidateId ?? campaign.manifestHash;
|
|
1241
|
-
return campaign.cells.map(
|
|
1242
|
-
|
|
1243
|
-
const score = composites.length > 0 ? composites.reduce((a, b) => a + b, 0) / composites.length : 0;
|
|
1244
|
-
const raw = { rep: cell.rep, duration_ms: cell.durationMs };
|
|
1245
|
-
for (const judge of Object.values(cell.judgeScores)) {
|
|
1246
|
-
for (const [dim, value] of Object.entries(judge.dimensions)) {
|
|
1247
|
-
if (Number.isFinite(value)) raw[`dim.${dim}`] = value;
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
if (typeof cell.generation === "number") raw.generation = cell.generation;
|
|
1251
|
-
const outcome = { raw };
|
|
1252
|
-
if (splitTag === "holdout") outcome.holdoutScore = score;
|
|
1253
|
-
else outcome.searchScore = score;
|
|
1254
|
-
return {
|
|
1337
|
+
return campaign.cells.map(
|
|
1338
|
+
(cell) => campaignCellToRunRecord(cell, {
|
|
1255
1339
|
runId: cell.cellId,
|
|
1256
1340
|
experimentId: ctx.experimentId,
|
|
1257
1341
|
candidateId,
|
|
1258
|
-
seed: cell.seed,
|
|
1259
1342
|
model: ctx.model,
|
|
1260
1343
|
promptHash: ctx.promptHash,
|
|
1261
1344
|
configHash: ctx.configHash,
|
|
1262
1345
|
commitSha: ctx.commitSha,
|
|
1263
|
-
wallMs: cell.durationMs,
|
|
1264
|
-
costUsd: Number.isFinite(cell.costUsd) ? cell.costUsd : ctx.defaultCostUsd ?? 0,
|
|
1265
|
-
tokenUsage: { input: 0, output: 0 },
|
|
1266
|
-
outcome,
|
|
1267
|
-
failureMode: cell.error ? "cell_error" : void 0,
|
|
1268
1346
|
splitTag,
|
|
1269
|
-
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1347
|
+
defaultCostUsd: ctx.defaultCostUsd
|
|
1348
|
+
})
|
|
1349
|
+
);
|
|
1272
1350
|
}
|
|
1273
1351
|
function verificationReportToRunRecord(report, ctx, opts = {}) {
|
|
1274
1352
|
const splitTag = ctx.splitTag ?? "search";
|
|
1275
1353
|
const runId = opts.runId ?? `run-${ctx.candidateId}-${ctx.experimentId}-${report.startedAt}`;
|
|
1354
|
+
const hasValidLayerMeasurement = report.layers.some(hasValidTaskMeasurement);
|
|
1355
|
+
const taskScore = hasValidLayerMeasurement && isValidScore(report.taskScore) ? report.taskScore : void 0;
|
|
1356
|
+
let executionErrorCount = 0;
|
|
1357
|
+
let judgeErrorCount = 0;
|
|
1358
|
+
let layerErrorCount = 0;
|
|
1359
|
+
let layerTimeoutCount = 0;
|
|
1360
|
+
let unscoredLayerCount = 0;
|
|
1276
1361
|
const raw = {
|
|
1277
1362
|
pass_count: report.passCount,
|
|
1278
1363
|
fail_count: report.failCount,
|
|
1279
1364
|
error_count: report.errorCount,
|
|
1280
1365
|
skipped_count: report.skippedCount,
|
|
1281
1366
|
duration_ms: report.durationMs,
|
|
1282
|
-
|
|
1367
|
+
execution_error_count: 0
|
|
1283
1368
|
};
|
|
1284
1369
|
for (const layer of report.layers) {
|
|
1285
|
-
if (
|
|
1370
|
+
if (hasValidTaskMeasurement(layer)) raw[`layer.${layer.layer}`] = layer.score;
|
|
1371
|
+
else unscoredLayerCount++;
|
|
1286
1372
|
raw[`layer_${layer.layer}_pass`] = layer.status === "pass" ? 1 : 0;
|
|
1373
|
+
if (layer.status === "error" || layer.status === "timeout") {
|
|
1374
|
+
if (layer.errorSource === "judge") judgeErrorCount++;
|
|
1375
|
+
else executionErrorCount++;
|
|
1376
|
+
if (layer.status === "error") layerErrorCount++;
|
|
1377
|
+
else layerTimeoutCount++;
|
|
1378
|
+
}
|
|
1287
1379
|
if (layer.diagnostics) {
|
|
1288
1380
|
for (const [k, v] of Object.entries(layer.diagnostics)) {
|
|
1289
1381
|
if (typeof v === "number" && Number.isFinite(v)) raw[`layer.${layer.layer}.${k}`] = v;
|
|
1290
1382
|
}
|
|
1291
1383
|
}
|
|
1292
1384
|
}
|
|
1293
|
-
|
|
1385
|
+
raw.execution_error_count = executionErrorCount;
|
|
1386
|
+
if (judgeErrorCount > 0) raw.judge_error_count = judgeErrorCount;
|
|
1387
|
+
if (layerErrorCount > 0) raw.layer_error_count = layerErrorCount;
|
|
1388
|
+
if (layerTimeoutCount > 0) raw.layer_timeout_count = layerTimeoutCount;
|
|
1389
|
+
if (unscoredLayerCount > 0) raw.unscored_layer_count = unscoredLayerCount;
|
|
1390
|
+
if (taskScore !== void 0) raw.blended_score = taskScore;
|
|
1391
|
+
const firstScoredFailure = report.layers.find(
|
|
1392
|
+
(layer) => layer.status === "fail" && hasValidTaskMeasurement(layer)
|
|
1393
|
+
);
|
|
1294
1394
|
const outcome = { raw };
|
|
1295
|
-
if (
|
|
1296
|
-
|
|
1395
|
+
if (taskScore !== void 0) {
|
|
1396
|
+
if (splitTag === "holdout") outcome.holdoutScore = taskScore;
|
|
1397
|
+
else outcome.searchScore = taskScore;
|
|
1398
|
+
}
|
|
1297
1399
|
return {
|
|
1298
1400
|
runId,
|
|
1299
1401
|
experimentId: ctx.experimentId,
|
|
@@ -1304,19 +1406,24 @@ function verificationReportToRunRecord(report, ctx, opts = {}) {
|
|
|
1304
1406
|
configHash: ctx.configHash,
|
|
1305
1407
|
commitSha: ctx.commitSha,
|
|
1306
1408
|
wallMs: report.durationMs,
|
|
1307
|
-
costUsd: ctx.defaultCostUsd ??
|
|
1409
|
+
costUsd: ctx.defaultCostUsd ?? null,
|
|
1410
|
+
costProvenance: ctx.defaultCostUsd === void 0 ? { kind: "uncaptured", usd: null } : { kind: "estimated", usd: ctx.defaultCostUsd },
|
|
1308
1411
|
tokenUsage: { input: 0, output: 0 },
|
|
1412
|
+
terminalOutcome: "succeeded",
|
|
1309
1413
|
outcome,
|
|
1310
|
-
|
|
1414
|
+
...firstScoredFailure ? {
|
|
1415
|
+
failureClass: "unknown",
|
|
1416
|
+
failureMode: `layer_${firstScoredFailure.layer}_fail`
|
|
1417
|
+
} : {},
|
|
1311
1418
|
splitTag,
|
|
1312
1419
|
scenarioId: ctx.scenarioId
|
|
1313
1420
|
};
|
|
1314
1421
|
}
|
|
1315
|
-
function
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
return
|
|
1422
|
+
function hasValidTaskMeasurement(layer) {
|
|
1423
|
+
return (layer.status === "pass" || layer.status === "fail") && isValidScore(layer.score);
|
|
1424
|
+
}
|
|
1425
|
+
function isValidScore(score) {
|
|
1426
|
+
return typeof score === "number" && Number.isFinite(score) && score >= 0 && score <= 1;
|
|
1320
1427
|
}
|
|
1321
1428
|
|
|
1322
1429
|
// src/rl/sim-fidelity.ts
|
|
@@ -1689,6 +1796,7 @@ export {
|
|
|
1689
1796
|
fitBradleyTerry,
|
|
1690
1797
|
injectIrrelevantClause,
|
|
1691
1798
|
inverseProbabilityWeighting,
|
|
1799
|
+
isTrainingRunEligible,
|
|
1692
1800
|
jsDivergence,
|
|
1693
1801
|
observationsFromRunRecords,
|
|
1694
1802
|
offPolicyEstimateAll,
|
|
@@ -1718,7 +1826,7 @@ export {
|
|
|
1718
1826
|
toPrmRows,
|
|
1719
1827
|
toSftJsonl,
|
|
1720
1828
|
toSftRows,
|
|
1721
|
-
|
|
1829
|
+
validateDatasetFormats,
|
|
1722
1830
|
varianceBasedCurriculum,
|
|
1723
1831
|
verificationReportToRunRecord
|
|
1724
1832
|
};
|