@tangle-network/agent-eval 0.86.0 → 0.89.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/dist/adapters/http.d.ts +3 -3
- package/dist/adapters/langchain.d.ts +3 -3
- package/dist/adapters/otel.d.ts +6 -6
- package/dist/adversarial-DIVcDoI_.d.ts +88 -0
- package/dist/analyst/index.d.ts +11 -10
- package/dist/analyst/index.js +13 -8
- package/dist/analyst/index.js.map +1 -1
- package/dist/analyze-runs-DwCEkpO_.d.ts +81 -0
- package/dist/belief-state/index.d.ts +4 -4
- package/dist/belief-state/index.js +1 -1
- package/dist/benchmarks/index.d.ts +3 -3
- package/dist/campaign/index.d.ts +165 -18
- package/dist/campaign/index.js +289 -14
- package/dist/campaign/index.js.map +1 -1
- package/dist/chunk-45EEMHTC.js +35 -0
- package/dist/chunk-45EEMHTC.js.map +1 -0
- package/dist/{chunk-FZWAFVAA.js → chunk-4FBZZIYD.js} +2 -2
- package/dist/{chunk-YV7J7X5N.js → chunk-5HRORJQY.js} +22 -12
- package/dist/chunk-5HRORJQY.js.map +1 -0
- package/dist/{chunk-OTYQPHPL.js → chunk-6SOJM3VR.js} +5 -5
- package/dist/chunk-BOD4O7OF.js +40 -0
- package/dist/chunk-BOD4O7OF.js.map +1 -0
- package/dist/{chunk-Z7VFTS2J.js → chunk-CY6U5S3X.js} +2 -2
- package/dist/{chunk-VIDQF3F5.js → chunk-D3V5B42D.js} +5 -34
- package/dist/chunk-D3V5B42D.js.map +1 -0
- package/dist/{chunk-YGYXHNAQ.js → chunk-FIUKOSWI.js} +21 -8
- package/dist/chunk-FIUKOSWI.js.map +1 -0
- package/dist/{chunk-WJL2NJXN.js → chunk-GSH6QNNS.js} +2 -2
- package/dist/{chunk-RBNA5AZT.js → chunk-L3JOU6XM.js} +2 -2
- package/dist/{chunk-IDVBLYCY.js → chunk-LMZQ2Z4U.js} +56 -2
- package/dist/{chunk-IDVBLYCY.js.map → chunk-LMZQ2Z4U.js.map} +1 -1
- package/dist/{chunk-VUINJM5M.js → chunk-QAY5UIJO.js} +2 -193
- package/dist/chunk-QAY5UIJO.js.map +1 -0
- package/dist/{chunk-P2J6SOXT.js → chunk-QG2OVF2D.js} +5 -3
- package/dist/{chunk-P2J6SOXT.js.map → chunk-QG2OVF2D.js.map} +1 -1
- package/dist/chunk-REVYNR6C.js +100 -0
- package/dist/chunk-REVYNR6C.js.map +1 -0
- package/dist/{chunk-ZZ2HOPME.js → chunk-TWS7AZEY.js} +2 -2
- package/dist/chunk-UHMJT4T7.js +200 -0
- package/dist/chunk-UHMJT4T7.js.map +1 -0
- package/dist/chunk-UMMZHCPB.js +190 -0
- package/dist/chunk-UMMZHCPB.js.map +1 -0
- package/dist/chunk-VZSRQ272.js +149 -0
- package/dist/chunk-VZSRQ272.js.map +1 -0
- package/dist/{chunk-L5G7OUKD.js → chunk-XY4DDNEG.js} +8 -190
- package/dist/chunk-XY4DDNEG.js.map +1 -0
- package/dist/chunk-Y47J2LJ3.js +859 -0
- package/dist/chunk-Y47J2LJ3.js.map +1 -0
- package/dist/{chunk-BABOZOSN.js → chunk-ZFIBGEOL.js} +3 -3
- package/dist/chunk-ZFIBGEOL.js.map +1 -0
- package/dist/{code-agent-session-BRXmavYv.d.ts → code-agent-session-BO8nCnv3.d.ts} +1 -1
- package/dist/contract/index.d.ts +24 -95
- package/dist/contract/index.js +16 -755
- package/dist/contract/index.js.map +1 -1
- package/dist/{control-GeE8OhpN.d.ts → control-_Qb7skHX.d.ts} +2 -2
- package/dist/control.d.ts +5 -5
- package/dist/corpus-BoR-041R.d.ts +560 -0
- package/dist/cost-ledger-DuSqlw5B.d.ts +113 -0
- package/dist/counterfactual-Dwibr5IW.d.ts +85 -0
- package/dist/{dataset-B2kL-fSM.d.ts → dataset-BbGkaN2I.d.ts} +1 -1
- package/dist/{registry-DrEQ3Luj.d.ts → default-registry-zoGHUQEH.d.ts} +29 -2
- package/dist/diagnose.d.ts +251 -0
- package/dist/diagnose.js +381 -0
- package/dist/diagnose.js.map +1 -0
- package/dist/{errors-Dwqw-T_m.d.ts → errors-CzMUYo7b.d.ts} +1 -1
- package/dist/{feedback-trajectory-B3rErRsh.d.ts → feedback-trajectory-D9OVLrg9.d.ts} +1 -1
- package/dist/fuzz.d.ts +484 -0
- package/dist/fuzz.js +613 -0
- package/dist/fuzz.js.map +1 -0
- package/dist/governance/index.d.ts +4 -4
- package/dist/hosted/index.d.ts +6 -6
- package/dist/{index-DE3RXAXD.d.ts → index-Bx3gZ8xl.d.ts} +1 -1
- package/dist/index.d.ts +717 -455
- package/dist/index.js +1590 -793
- package/dist/index.js.map +1 -1
- package/dist/{insight-report-3ADTfClO.d.ts → insight-report-BBwvOh6x.d.ts} +2 -2
- package/dist/{integrity-CJzrpUua.d.ts → integrity-VJ9A7aST.d.ts} +1 -1
- package/dist/{judge-calibration-DilmB3Ml.d.ts → judge-calibration-0p2QcWNE.d.ts} +1 -1
- package/dist/{kind-factory-CVecZZG_.d.ts → kind-factory-5b7xXXOr.d.ts} +2 -2
- package/dist/{llm-client-CuUg2Mn3.d.ts → llm-client-BeEcAokY.d.ts} +1 -1
- package/dist/matrix/index.d.ts +2 -2
- package/dist/meta-eval/index.d.ts +177 -3
- package/dist/meta-eval/index.js +260 -1
- package/dist/meta-eval/index.js.map +1 -1
- package/dist/{multi-layer-verifier-DlWCXuxL.d.ts → multi-layer-verifier-DUZXrPDA.d.ts} +7 -1
- package/dist/multishot/index.d.ts +25 -11
- package/dist/multishot/index.js +36 -7
- package/dist/multishot/index.js.map +1 -1
- package/dist/openapi.json +1 -1
- package/dist/pipelines/index.js +2 -2
- package/dist/{agent-profile-D0PBIWlV.d.ts → pre-registration-DELOEJ8v.d.ts} +144 -4
- package/dist/{provenance-DPpNIOJD.d.ts → provenance-LnqRT0sS.d.ts} +5 -5
- package/dist/{red-team-DW9Ca_tj.d.ts → red-team-BXHil6c8.d.ts} +1 -1
- package/dist/{release-report-hlNtD12q.d.ts → release-report-euXIV_Sk.d.ts} +3 -3
- package/dist/reporting.d.ts +8 -8
- package/dist/reporting.js +3 -3
- package/dist/{researcher-BLPHBbNV.d.ts → researcher-DE6Gpnb4.d.ts} +4 -4
- package/dist/rl.d.ts +194 -656
- package/dist/rl.js +236 -154
- package/dist/rl.js.map +1 -1
- package/dist/{rubric-predictive-validity-CnEl9Jc8.d.ts → rubric-predictive-validity-Cy_W-hWZ.d.ts} +1 -1
- package/dist/{run-campaign-4Y5V5CN3.js → run-campaign-RDGAM5KJ.js} +3 -3
- package/dist/{run-improvement-loop-CNqQckTj.d.ts → run-improvement-loop-5z_l5zDz.d.ts} +2 -2
- package/dist/{run-record-De9VarXR.d.ts → run-record-e7vj1uZQ.d.ts} +1 -1
- package/dist/{runtime-trajectory-BLRiaifm.d.ts → runtime-trajectory-BDgfGZSr.d.ts} +1 -1
- package/dist/{semantic-concept-judge-DIEgr_6v.d.ts → semantic-concept-judge-Dn8Z6KEG.d.ts} +5 -31
- package/dist/series-convergence-D5OWMBg6.d.ts +33 -0
- package/dist/{statistics-CnC1FMbx.d.ts → statistics-C7PozGrZ.d.ts} +71 -2
- package/dist/{summary-report-Db0dDSWP.d.ts → summary-report-DGmUucwQ.d.ts} +1 -1
- package/dist/traces.d.ts +3 -3
- package/dist/traces.js +8 -6
- package/dist/{types-Cu3u_x59.d.ts → types-2VVIL04s.d.ts} +2 -2
- package/dist/{types-D7lLRYe9.d.ts → types-BU-7W85F.d.ts} +21 -1
- package/dist/{types-CqPax19X.d.ts → types-mn5Aqk7x.d.ts} +1 -1
- package/dist/{verdict-CeEgtjyI.d.ts → verdict-C9MlYujm.d.ts} +3 -0
- package/dist/wire/index.d.ts +3 -3
- package/dist/workflow/index.d.ts +12 -11
- package/dist/workflow/index.js +1 -1
- package/package.json +11 -1
- package/dist/chunk-BABOZOSN.js.map +0 -1
- package/dist/chunk-L5G7OUKD.js.map +0 -1
- package/dist/chunk-SHTXZ4O2.js +0 -113
- package/dist/chunk-SHTXZ4O2.js.map +0 -1
- package/dist/chunk-VIDQF3F5.js.map +0 -1
- package/dist/chunk-VUINJM5M.js.map +0 -1
- package/dist/chunk-YGYXHNAQ.js.map +0 -1
- package/dist/chunk-YV7J7X5N.js.map +0 -1
- /package/dist/{chunk-FZWAFVAA.js.map → chunk-4FBZZIYD.js.map} +0 -0
- /package/dist/{chunk-OTYQPHPL.js.map → chunk-6SOJM3VR.js.map} +0 -0
- /package/dist/{chunk-Z7VFTS2J.js.map → chunk-CY6U5S3X.js.map} +0 -0
- /package/dist/{chunk-WJL2NJXN.js.map → chunk-GSH6QNNS.js.map} +0 -0
- /package/dist/{chunk-RBNA5AZT.js.map → chunk-L3JOU6XM.js.map} +0 -0
- /package/dist/{chunk-ZZ2HOPME.js.map → chunk-TWS7AZEY.js.map} +0 -0
- /package/dist/{run-campaign-4Y5V5CN3.js.map → run-campaign-RDGAM5KJ.js.map} +0 -0
package/dist/rl.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectRewardHacking,
|
|
3
|
+
extractVerifiableReward,
|
|
4
|
+
extractVerifiableRewardsFromRecords,
|
|
5
|
+
filterDeterministicallyRewarded
|
|
6
|
+
} from "./chunk-5HRORJQY.js";
|
|
1
7
|
import {
|
|
2
8
|
doublyRobust,
|
|
3
9
|
inverseProbabilityWeighting,
|
|
4
10
|
offPolicyEstimateAll,
|
|
5
11
|
selfNormalizedImportanceWeighting
|
|
6
12
|
} from "./chunk-4DIJWVUT.js";
|
|
7
|
-
import {
|
|
8
|
-
detectRewardHacking,
|
|
9
|
-
extractVerifiableReward,
|
|
10
|
-
extractVerifiableRewardsFromRecords,
|
|
11
|
-
filterDeterministicallyRewarded
|
|
12
|
-
} from "./chunk-YV7J7X5N.js";
|
|
13
13
|
import {
|
|
14
14
|
FileSystemOutcomeStore,
|
|
15
15
|
InMemoryOutcomeStore
|
|
16
16
|
} from "./chunk-3RF76KTD.js";
|
|
17
17
|
import {
|
|
18
18
|
runEvalCampaign
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-GSH6QNNS.js";
|
|
20
20
|
import "./chunk-CVVHBFGN.js";
|
|
21
21
|
import {
|
|
22
22
|
rubricPredictiveValidity
|
|
@@ -24,11 +24,16 @@ import {
|
|
|
24
24
|
import {
|
|
25
25
|
evaluateInterimReleaseConfidence
|
|
26
26
|
} from "./chunk-MAZ26DC7.js";
|
|
27
|
-
import "./chunk-
|
|
27
|
+
import "./chunk-CY6U5S3X.js";
|
|
28
28
|
import {
|
|
29
29
|
benjaminiHochberg,
|
|
30
30
|
wilcoxonSignedRank
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-LMZQ2Z4U.js";
|
|
32
|
+
import {
|
|
33
|
+
observationsFromRunRecords,
|
|
34
|
+
thompsonCurriculum,
|
|
35
|
+
varianceBasedCurriculum
|
|
36
|
+
} from "./chunk-VZSRQ272.js";
|
|
32
37
|
import "./chunk-SBCB6VZY.js";
|
|
33
38
|
import "./chunk-PC4UYEBM.js";
|
|
34
39
|
import "./chunk-KWRRMR3J.js";
|
|
@@ -612,149 +617,6 @@ function buildPairwiseFromCampaign(input) {
|
|
|
612
617
|
return outcomes;
|
|
613
618
|
}
|
|
614
619
|
|
|
615
|
-
// src/rl/active-curriculum.ts
|
|
616
|
-
function varianceBasedCurriculum(observations, candidateCells, opts) {
|
|
617
|
-
const variancePrior = opts.variancePrior ?? 0.05;
|
|
618
|
-
const floor = opts.floorPerCell ?? 1;
|
|
619
|
-
const budget = opts.budget;
|
|
620
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
621
|
-
for (const o of observations) {
|
|
622
|
-
const k = `${o.variantId}::${o.scenarioId}`;
|
|
623
|
-
const arr = grouped.get(k) ?? [];
|
|
624
|
-
arr.push(o.score);
|
|
625
|
-
grouped.set(k, arr);
|
|
626
|
-
}
|
|
627
|
-
const cellStats = candidateCells.map((c) => {
|
|
628
|
-
const k = `${c.variantId}::${c.scenarioId}`;
|
|
629
|
-
const samples = grouped.get(k) ?? [];
|
|
630
|
-
const n = samples.length;
|
|
631
|
-
const mean = n === 0 ? 0.5 : samples.reduce((s, v) => s + v, 0) / n;
|
|
632
|
-
const variance = n < 2 ? variancePrior : samples.reduce((s, v) => s + (v - mean) ** 2, 0) / (n - 1) + variancePrior;
|
|
633
|
-
const weight = Math.sqrt(variance) + 1 / Math.sqrt(Math.max(1, n));
|
|
634
|
-
return { variantId: c.variantId, scenarioId: c.scenarioId, n, mean, variance, weight };
|
|
635
|
-
});
|
|
636
|
-
const floorTotal = floor * cellStats.length;
|
|
637
|
-
if (floorTotal >= budget) {
|
|
638
|
-
const each = Math.max(1, Math.floor(budget / Math.max(1, cellStats.length)));
|
|
639
|
-
return cellStats.map((c) => ({
|
|
640
|
-
variantId: c.variantId,
|
|
641
|
-
scenarioId: c.scenarioId,
|
|
642
|
-
count: each,
|
|
643
|
-
reason: `floor allocation (budget tight; n=${c.n})`
|
|
644
|
-
}));
|
|
645
|
-
}
|
|
646
|
-
const remaining = budget - floorTotal;
|
|
647
|
-
const totalWeight = cellStats.reduce((s, c) => s + c.weight, 0);
|
|
648
|
-
return cellStats.map((c) => {
|
|
649
|
-
const proportional = totalWeight === 0 ? 0 : Math.round(c.weight / totalWeight * remaining);
|
|
650
|
-
return {
|
|
651
|
-
variantId: c.variantId,
|
|
652
|
-
scenarioId: c.scenarioId,
|
|
653
|
-
count: floor + proportional,
|
|
654
|
-
reason: `variance ${c.variance.toFixed(3)} (n=${c.n}, mean=${c.mean.toFixed(3)})`
|
|
655
|
-
};
|
|
656
|
-
});
|
|
657
|
-
}
|
|
658
|
-
function thompsonCurriculum(observations, candidateCells, opts) {
|
|
659
|
-
const threshold = opts.decisionThreshold ?? 0.5;
|
|
660
|
-
const alpha0 = opts.priorAlpha ?? 1;
|
|
661
|
-
const beta0 = opts.priorBeta ?? 1;
|
|
662
|
-
const rng = makeRng(opts.seed);
|
|
663
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
664
|
-
for (const o of observations) {
|
|
665
|
-
const k = `${o.variantId}::${o.scenarioId}`;
|
|
666
|
-
const cur = grouped.get(k) ?? { passes: 0, failures: 0 };
|
|
667
|
-
const pass = o.pass ?? o.score >= threshold;
|
|
668
|
-
if (pass) cur.passes += 1;
|
|
669
|
-
else cur.failures += 1;
|
|
670
|
-
grouped.set(k, cur);
|
|
671
|
-
}
|
|
672
|
-
const stats = candidateCells.map((c) => {
|
|
673
|
-
const k = `${c.variantId}::${c.scenarioId}`;
|
|
674
|
-
const cur = grouped.get(k) ?? { passes: 0, failures: 0 };
|
|
675
|
-
const a = alpha0 + cur.passes;
|
|
676
|
-
const b = beta0 + cur.failures;
|
|
677
|
-
const sampled = sampleBeta(a, b, rng);
|
|
678
|
-
const distance = Math.abs(sampled - threshold);
|
|
679
|
-
const variance = a * b / ((a + b) ** 2 * (a + b + 1));
|
|
680
|
-
const sigma = Math.max(0.05, Math.sqrt(variance));
|
|
681
|
-
const weight = Math.exp(-((distance / sigma) ** 2));
|
|
682
|
-
return {
|
|
683
|
-
variantId: c.variantId,
|
|
684
|
-
scenarioId: c.scenarioId,
|
|
685
|
-
n: cur.passes + cur.failures,
|
|
686
|
-
sampled,
|
|
687
|
-
sigma,
|
|
688
|
-
weight,
|
|
689
|
-
a,
|
|
690
|
-
b
|
|
691
|
-
};
|
|
692
|
-
});
|
|
693
|
-
const totalWeight = stats.reduce((s, c) => s + c.weight, 0);
|
|
694
|
-
return stats.map((c) => {
|
|
695
|
-
const proportional = totalWeight === 0 ? 0 : Math.round(c.weight / totalWeight * opts.budget);
|
|
696
|
-
return {
|
|
697
|
-
variantId: c.variantId,
|
|
698
|
-
scenarioId: c.scenarioId,
|
|
699
|
-
count: Math.max(0, proportional),
|
|
700
|
-
reason: `Beta(${c.a.toFixed(1)},${c.b.toFixed(1)}) sample=${c.sampled.toFixed(3)} (target ${threshold})`
|
|
701
|
-
};
|
|
702
|
-
});
|
|
703
|
-
}
|
|
704
|
-
function observationsFromRunRecords(runs, opts = {}) {
|
|
705
|
-
const threshold = opts.passThreshold ?? 0.5;
|
|
706
|
-
const useHoldout = opts.useHoldout ?? true;
|
|
707
|
-
const out = [];
|
|
708
|
-
for (const r of runs) {
|
|
709
|
-
if (!r.scenarioId) continue;
|
|
710
|
-
const score = useHoldout ? r.outcome.holdoutScore ?? r.outcome.searchScore : r.outcome.searchScore ?? r.outcome.holdoutScore;
|
|
711
|
-
if (typeof score !== "number" || !Number.isFinite(score)) continue;
|
|
712
|
-
out.push({
|
|
713
|
-
variantId: r.candidateId,
|
|
714
|
-
scenarioId: r.scenarioId,
|
|
715
|
-
score,
|
|
716
|
-
pass: score >= threshold
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
return out;
|
|
720
|
-
}
|
|
721
|
-
function makeRng(seed) {
|
|
722
|
-
if (seed === void 0) return Math.random;
|
|
723
|
-
let s = seed >>> 0;
|
|
724
|
-
return () => {
|
|
725
|
-
s = s + 1831565813 >>> 0;
|
|
726
|
-
let t = s;
|
|
727
|
-
t = Math.imul(t ^ t >>> 15, t | 1);
|
|
728
|
-
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
|
729
|
-
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
function sampleBeta(alpha, beta, rng) {
|
|
733
|
-
const a = Math.max(1, alpha);
|
|
734
|
-
const b = Math.max(1, beta);
|
|
735
|
-
const x = sampleGamma(a, rng);
|
|
736
|
-
const y = sampleGamma(b, rng);
|
|
737
|
-
return x / (x + y);
|
|
738
|
-
}
|
|
739
|
-
function sampleGamma(shape, rng) {
|
|
740
|
-
const d = shape - 1 / 3;
|
|
741
|
-
const c = 1 / Math.sqrt(9 * d);
|
|
742
|
-
while (true) {
|
|
743
|
-
let x;
|
|
744
|
-
let v;
|
|
745
|
-
do {
|
|
746
|
-
const u1 = rng() || 1e-12;
|
|
747
|
-
const u2 = rng() || 1e-12;
|
|
748
|
-
x = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
|
|
749
|
-
v = 1 + c * x;
|
|
750
|
-
} while (v <= 0);
|
|
751
|
-
v = v * v * v;
|
|
752
|
-
const u = rng();
|
|
753
|
-
if (u < 1 - 0.0331 * x ** 4) return d * v;
|
|
754
|
-
if (Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v))) return d * v;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
620
|
// src/rl/adaptation-eval.ts
|
|
759
621
|
async function runAdaptationCurve(opts) {
|
|
760
622
|
const ks = opts.ks ?? [0, 1, 2, 4, 8, 16];
|
|
@@ -809,7 +671,7 @@ async function runAdaptationCurve(opts) {
|
|
|
809
671
|
function compareAdaptationCurves(a, b, opts = {}) {
|
|
810
672
|
const conf = opts.confidence ?? 0.95;
|
|
811
673
|
const resamples = opts.bootstrapResamples ?? 500;
|
|
812
|
-
const rng =
|
|
674
|
+
const rng = makeRng(opts.seed);
|
|
813
675
|
const perK = [];
|
|
814
676
|
for (const ap of a.points) {
|
|
815
677
|
const bp = b.points.find((p) => p.k === ap.k);
|
|
@@ -841,7 +703,7 @@ function compareAdaptationCurves(a, b, opts = {}) {
|
|
|
841
703
|
function firstPassK(curve, threshold = 0.5) {
|
|
842
704
|
return curve.points.find((p) => p.passRate >= threshold)?.k ?? null;
|
|
843
705
|
}
|
|
844
|
-
function
|
|
706
|
+
function makeRng(seed) {
|
|
845
707
|
if (seed === void 0) return Math.random;
|
|
846
708
|
let s = seed >>> 0;
|
|
847
709
|
return () => {
|
|
@@ -1661,22 +1523,239 @@ function buildSummary(args) {
|
|
|
1661
1523
|
}
|
|
1662
1524
|
return lines.join(" | ");
|
|
1663
1525
|
}
|
|
1526
|
+
|
|
1527
|
+
// src/rl/sim-fidelity.ts
|
|
1528
|
+
var ABSENT_CATEGORY = "(absent)";
|
|
1529
|
+
var DEFAULT_MIN_N_PER_FEATURE = 20;
|
|
1530
|
+
var DEFAULT_QUANTILE_BUCKETS = 4;
|
|
1531
|
+
var REPRESENTATIVE_MIN_FIDELITY = 0.8;
|
|
1532
|
+
var TOP_SHIFT_COUNT = 5;
|
|
1533
|
+
var defaultBehaviorFeatures = (record) => {
|
|
1534
|
+
const raw = record.outcome?.raw ?? {};
|
|
1535
|
+
const toolErrors = finiteOrNull(raw.tool_errors);
|
|
1536
|
+
const turnsAborted = finiteOrNull(raw.turns_aborted);
|
|
1537
|
+
const completion = record.completion;
|
|
1538
|
+
return {
|
|
1539
|
+
score: finiteOrNull(record.outcome?.holdoutScore) ?? finiteOrNull(record.outcome?.searchScore),
|
|
1540
|
+
failure_class: record.failureClass ?? null,
|
|
1541
|
+
wall_ms: finiteOrNull(record.wallMs),
|
|
1542
|
+
output_tokens: finiteOrNull(record.tokenUsage?.output),
|
|
1543
|
+
turn_count: finiteOrNull(raw.turns_completed) ?? finiteOrNull(raw.assistant_messages),
|
|
1544
|
+
tool_errors: toolErrors,
|
|
1545
|
+
tool_error_recovery: toolErrorRecovery(toolErrors, turnsAborted, record.failureClass),
|
|
1546
|
+
completion_length: typeof completion === "string" ? completion.length : null
|
|
1547
|
+
};
|
|
1548
|
+
};
|
|
1549
|
+
function toolErrorRecovery(toolErrors, turnsAborted, failureClass) {
|
|
1550
|
+
if (toolErrors === null) return null;
|
|
1551
|
+
if (toolErrors === 0) return "no-tool-errors";
|
|
1552
|
+
const failed = (turnsAborted ?? 0) > 0 || failureClass !== void 0 && failureClass !== "success";
|
|
1553
|
+
return failed ? "unrecovered" : "recovered";
|
|
1554
|
+
}
|
|
1555
|
+
function finiteOrNull(value) {
|
|
1556
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1557
|
+
}
|
|
1558
|
+
function jsDivergence(p, q) {
|
|
1559
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(p), ...Object.keys(q)]);
|
|
1560
|
+
if (keys.size === 0) {
|
|
1561
|
+
throw new ValidationError("jsDivergence: both histograms are empty");
|
|
1562
|
+
}
|
|
1563
|
+
let pSum = 0;
|
|
1564
|
+
let qSum = 0;
|
|
1565
|
+
for (const key of keys) {
|
|
1566
|
+
const pv = p[key] ?? 0;
|
|
1567
|
+
const qv = q[key] ?? 0;
|
|
1568
|
+
if (!Number.isFinite(pv) || !Number.isFinite(qv) || pv < 0 || qv < 0) {
|
|
1569
|
+
throw new ValidationError(`jsDivergence: negative or non-finite count for category "${key}"`);
|
|
1570
|
+
}
|
|
1571
|
+
pSum += pv;
|
|
1572
|
+
qSum += qv;
|
|
1573
|
+
}
|
|
1574
|
+
if (pSum === 0 || qSum === 0) {
|
|
1575
|
+
throw new ValidationError("jsDivergence: a histogram with zero total mass has no distribution");
|
|
1576
|
+
}
|
|
1577
|
+
let divergence = 0;
|
|
1578
|
+
for (const key of keys) {
|
|
1579
|
+
const pp = (p[key] ?? 0) / pSum;
|
|
1580
|
+
const qp = (q[key] ?? 0) / qSum;
|
|
1581
|
+
const m = (pp + qp) / 2;
|
|
1582
|
+
if (pp > 0) divergence += 0.5 * pp * Math.log2(pp / m);
|
|
1583
|
+
if (qp > 0) divergence += 0.5 * qp * Math.log2(qp / m);
|
|
1584
|
+
}
|
|
1585
|
+
return Math.min(1, Math.max(0, divergence));
|
|
1586
|
+
}
|
|
1587
|
+
function quantileEdges(values, bucketCount = DEFAULT_QUANTILE_BUCKETS) {
|
|
1588
|
+
if (values.length === 0) {
|
|
1589
|
+
throw new ValidationError("quantileEdges: requires at least one value");
|
|
1590
|
+
}
|
|
1591
|
+
if (!Number.isInteger(bucketCount) || bucketCount < 2) {
|
|
1592
|
+
throw new ValidationError(
|
|
1593
|
+
`quantileEdges: bucketCount must be an integer >= 2, got ${bucketCount}`
|
|
1594
|
+
);
|
|
1595
|
+
}
|
|
1596
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
1597
|
+
const edges = [];
|
|
1598
|
+
for (let k = 1; k < bucketCount; k++) {
|
|
1599
|
+
const pos = k / bucketCount * (sorted.length - 1);
|
|
1600
|
+
const lo = sorted[Math.floor(pos)];
|
|
1601
|
+
const hi = sorted[Math.ceil(pos)];
|
|
1602
|
+
edges.push(lo + (pos - Math.floor(pos)) * (hi - lo));
|
|
1603
|
+
}
|
|
1604
|
+
return [...new Set(edges)];
|
|
1605
|
+
}
|
|
1606
|
+
function bucketLabel(value, edges) {
|
|
1607
|
+
let i = 0;
|
|
1608
|
+
while (i < edges.length && value >= edges[i]) i++;
|
|
1609
|
+
const lo = i === 0 ? "-inf" : String(edges[i - 1]);
|
|
1610
|
+
const hi = i === edges.length ? "+inf" : String(edges[i]);
|
|
1611
|
+
return `[${lo},${hi})`;
|
|
1612
|
+
}
|
|
1613
|
+
function simFidelityReport(simulated, production, opts = {}) {
|
|
1614
|
+
if (simulated.length === 0) {
|
|
1615
|
+
throw new ValidationError("simFidelityReport: simulated records are empty");
|
|
1616
|
+
}
|
|
1617
|
+
if (production.length === 0) {
|
|
1618
|
+
throw new ValidationError("simFidelityReport: production records are empty");
|
|
1619
|
+
}
|
|
1620
|
+
const extract = opts.features ?? defaultBehaviorFeatures;
|
|
1621
|
+
const minN = opts.minNPerFeature ?? DEFAULT_MIN_N_PER_FEATURE;
|
|
1622
|
+
const simMaps = simulated.map(extract);
|
|
1623
|
+
const prodMaps = production.map(extract);
|
|
1624
|
+
const featureNames = [];
|
|
1625
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1626
|
+
for (const map of [...simMaps, ...prodMaps]) {
|
|
1627
|
+
for (const name of Object.keys(map)) {
|
|
1628
|
+
if (!seen.has(name)) {
|
|
1629
|
+
seen.add(name);
|
|
1630
|
+
featureNames.push(name);
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
const perDimension = [];
|
|
1635
|
+
const insufficientData = [];
|
|
1636
|
+
for (const feature of featureNames) {
|
|
1637
|
+
const simVals = simMaps.map((m) => m[feature] ?? null);
|
|
1638
|
+
const prodVals = prodMaps.map((m) => m[feature] ?? null);
|
|
1639
|
+
const nSim = simVals.filter((v) => v !== null).length;
|
|
1640
|
+
const nProd = prodVals.filter((v) => v !== null).length;
|
|
1641
|
+
if (nSim < minN || nProd < minN) {
|
|
1642
|
+
insufficientData.push(feature);
|
|
1643
|
+
continue;
|
|
1644
|
+
}
|
|
1645
|
+
const { sim, prod } = histograms(feature, simVals, prodVals);
|
|
1646
|
+
perDimension.push({
|
|
1647
|
+
feature,
|
|
1648
|
+
divergence: jsDivergence(sim, prod),
|
|
1649
|
+
topShifts: topShifts(sim, simVals.length, prod, prodVals.length),
|
|
1650
|
+
nSim,
|
|
1651
|
+
nProd
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
if (perDimension.length === 0) {
|
|
1655
|
+
return { perDimension, fidelity: Number.NaN, insufficientData, verdict: "insufficient-data" };
|
|
1656
|
+
}
|
|
1657
|
+
const fidelity = 1 - perDimension.reduce((sum, d) => sum + d.divergence, 0) / perDimension.length;
|
|
1658
|
+
return {
|
|
1659
|
+
perDimension,
|
|
1660
|
+
fidelity,
|
|
1661
|
+
insufficientData,
|
|
1662
|
+
verdict: fidelity >= REPRESENTATIVE_MIN_FIDELITY ? "representative" : "skewed"
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
function histograms(feature, simVals, prodVals) {
|
|
1666
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
1667
|
+
for (const v of [...simVals, ...prodVals]) {
|
|
1668
|
+
if (v !== null) kinds.add(typeof v);
|
|
1669
|
+
}
|
|
1670
|
+
if (kinds.size > 1) {
|
|
1671
|
+
throw new ValidationError(
|
|
1672
|
+
`simFidelityReport: feature "${feature}" mixes string and number values \u2014 an extractor must return one kind per feature`
|
|
1673
|
+
);
|
|
1674
|
+
}
|
|
1675
|
+
let toCategory;
|
|
1676
|
+
if (kinds.has("number")) {
|
|
1677
|
+
const union = [];
|
|
1678
|
+
for (const v of [...simVals, ...prodVals]) {
|
|
1679
|
+
if (v !== null) union.push(v);
|
|
1680
|
+
}
|
|
1681
|
+
const edges = quantileEdges(union);
|
|
1682
|
+
toCategory = (v) => bucketLabel(v, edges);
|
|
1683
|
+
} else {
|
|
1684
|
+
toCategory = (v) => v;
|
|
1685
|
+
}
|
|
1686
|
+
const count = (vals) => {
|
|
1687
|
+
const hist = {};
|
|
1688
|
+
for (const v of vals) {
|
|
1689
|
+
const key = v === null ? ABSENT_CATEGORY : toCategory(v);
|
|
1690
|
+
hist[key] = (hist[key] ?? 0) + 1;
|
|
1691
|
+
}
|
|
1692
|
+
return hist;
|
|
1693
|
+
};
|
|
1694
|
+
return { sim: count(simVals), prod: count(prodVals) };
|
|
1695
|
+
}
|
|
1696
|
+
function topShifts(sim, simTotal, prod, prodTotal) {
|
|
1697
|
+
const keys = [.../* @__PURE__ */ new Set([...Object.keys(sim), ...Object.keys(prod)])];
|
|
1698
|
+
const shifts = keys.map((value) => ({
|
|
1699
|
+
value,
|
|
1700
|
+
pSim: (sim[value] ?? 0) / simTotal,
|
|
1701
|
+
pProd: (prod[value] ?? 0) / prodTotal
|
|
1702
|
+
}));
|
|
1703
|
+
shifts.sort((a, b) => {
|
|
1704
|
+
const delta = Math.abs(b.pSim - b.pProd) - Math.abs(a.pSim - a.pProd);
|
|
1705
|
+
return delta !== 0 ? delta : a.value.localeCompare(b.value);
|
|
1706
|
+
});
|
|
1707
|
+
return shifts.slice(0, TOP_SHIFT_COUNT);
|
|
1708
|
+
}
|
|
1709
|
+
function easyModeCheck(simulated, production, opts = {}) {
|
|
1710
|
+
if (simulated.length === 0) {
|
|
1711
|
+
throw new ValidationError("easyModeCheck: simulated records are empty");
|
|
1712
|
+
}
|
|
1713
|
+
if (production.length === 0) {
|
|
1714
|
+
throw new ValidationError("easyModeCheck: production records are empty");
|
|
1715
|
+
}
|
|
1716
|
+
const threshold = opts.passThreshold ?? 0.5;
|
|
1717
|
+
const tolerance = opts.inflationTolerance ?? 0.1;
|
|
1718
|
+
const passRate = (records, side) => {
|
|
1719
|
+
let passes = 0;
|
|
1720
|
+
for (const r of records) {
|
|
1721
|
+
const score = finiteOrNull(r.outcome?.holdoutScore) ?? finiteOrNull(r.outcome?.searchScore);
|
|
1722
|
+
if (score === null) {
|
|
1723
|
+
throw new ValidationError(
|
|
1724
|
+
`easyModeCheck: ${side} run "${r.runId}" carries neither holdoutScore nor searchScore`
|
|
1725
|
+
);
|
|
1726
|
+
}
|
|
1727
|
+
if (score >= threshold) passes++;
|
|
1728
|
+
}
|
|
1729
|
+
return passes / records.length;
|
|
1730
|
+
};
|
|
1731
|
+
const simPassRate = passRate(simulated, "simulated");
|
|
1732
|
+
const prodPassRate = passRate(production, "production");
|
|
1733
|
+
const gap = simPassRate - prodPassRate;
|
|
1734
|
+
return { simPassRate, prodPassRate, gap, inflated: gap > tolerance };
|
|
1735
|
+
}
|
|
1664
1736
|
export {
|
|
1737
|
+
ABSENT_CATEGORY,
|
|
1738
|
+
DEFAULT_MIN_N_PER_FEATURE,
|
|
1739
|
+
DEFAULT_QUANTILE_BUCKETS,
|
|
1665
1740
|
FileSystemOutcomeStore,
|
|
1666
1741
|
InMemoryOutcomeStore,
|
|
1667
1742
|
PredictiveValidityResearcher,
|
|
1743
|
+
REPRESENTATIVE_MIN_FIDELITY,
|
|
1668
1744
|
adversarialScenarioSearch,
|
|
1669
1745
|
appendToCorpus,
|
|
1670
1746
|
applyEloUpdate,
|
|
1671
1747
|
bestOfN,
|
|
1748
|
+
bucketLabel,
|
|
1672
1749
|
buildDatasetFromCorpus,
|
|
1673
1750
|
buildPairwiseFromCampaign,
|
|
1674
1751
|
buildRlDataset,
|
|
1675
1752
|
campaignToRunRecords,
|
|
1676
1753
|
compareAdaptationCurves,
|
|
1677
1754
|
datasheetToMarkdown,
|
|
1755
|
+
defaultBehaviorFeatures,
|
|
1678
1756
|
detectRewardHacking,
|
|
1679
1757
|
doublyRobust,
|
|
1758
|
+
easyModeCheck,
|
|
1680
1759
|
extractPreferences,
|
|
1681
1760
|
extractStepRewards,
|
|
1682
1761
|
extractVerifiableReward,
|
|
@@ -1686,10 +1765,12 @@ export {
|
|
|
1686
1765
|
fitBradleyTerry,
|
|
1687
1766
|
injectIrrelevantClause,
|
|
1688
1767
|
inverseProbabilityWeighting,
|
|
1768
|
+
jsDivergence,
|
|
1689
1769
|
observationsFromRunRecords,
|
|
1690
1770
|
offPolicyEstimateAll,
|
|
1691
1771
|
paretoFrontier,
|
|
1692
1772
|
prmTrainingPairs,
|
|
1773
|
+
quantileEdges,
|
|
1693
1774
|
readCorpus,
|
|
1694
1775
|
renameVariables,
|
|
1695
1776
|
runAdaptationCurve,
|
|
@@ -1701,6 +1782,7 @@ export {
|
|
|
1701
1782
|
selfConsistency,
|
|
1702
1783
|
selfNormalizedImportanceWeighting,
|
|
1703
1784
|
shuffleOrder,
|
|
1785
|
+
simFidelityReport,
|
|
1704
1786
|
stepRewardsToJsonl,
|
|
1705
1787
|
thompsonCurriculum,
|
|
1706
1788
|
toAnthropicFormat,
|