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