textopt 0.1.0 → 0.2.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/README.md +24 -6
- package/dist/bootstrap-search/index.cjs +29 -23
- package/dist/bootstrap-search/index.d.cts +3 -3
- package/dist/bootstrap-search/index.d.mts +3 -3
- package/dist/bootstrap-search/index.mjs +9 -3
- package/dist/{demos-D2o0qSSo.cjs → demos-9v5ts7F3.cjs} +4 -4
- package/dist/{demos-1b7JiUue.d.mts → demos-ASsSXYXA.d.mts} +1 -1
- package/dist/{demos-DE2oxNWX.mjs → demos-Brobjfuc.mjs} +1 -1
- package/dist/{demos-CU9dy2oT.d.cts → demos-ByaLZy-Z.d.cts} +1 -1
- package/dist/file-cache.cjs +16 -5
- package/dist/file-cache.d.cts +13 -0
- package/dist/file-cache.d.mts +13 -0
- package/dist/file-cache.mjs +16 -5
- package/dist/gepa/index.cjs +87 -44
- package/dist/gepa/index.d.cts +8 -6
- package/dist/gepa/index.d.mts +8 -6
- package/dist/gepa/index.mjs +55 -12
- package/dist/index.cjs +44 -19
- package/dist/index.d.cts +37 -5
- package/dist/index.d.mts +37 -5
- package/dist/index.mjs +29 -6
- package/dist/mipro/index.cjs +31 -25
- package/dist/mipro/index.d.cts +3 -3
- package/dist/mipro/index.d.mts +3 -3
- package/dist/mipro/index.mjs +9 -3
- package/dist/opro/index.cjs +31 -25
- package/dist/opro/index.d.cts +2 -2
- package/dist/opro/index.d.mts +2 -2
- package/dist/opro/index.mjs +8 -2
- package/dist/{optimizer-Bh5DPRMH.d.cts → optimizer-4Zv-Zt2t.d.cts} +41 -2
- package/dist/{optimizer-Ck6-e_8o.d.mts → optimizer-Ds5mzYjz.d.mts} +41 -2
- package/dist/random-search/index.cjs +27 -21
- package/dist/random-search/index.d.cts +2 -2
- package/dist/random-search/index.d.mts +2 -2
- package/dist/random-search/index.mjs +8 -2
- package/dist/{reflection-LRaAZP4e.d.mts → reflection-CMezGu6u.d.mts} +32 -4
- package/dist/{reflection-Dt3QrXhM.d.cts → reflection-D0A7eahD.d.cts} +32 -4
- package/dist/{reporting-DQbAohc9.d.cts → reporting-bq007_2z.d.cts} +55 -1
- package/dist/{reporting-DQbAohc9.d.mts → reporting-bq007_2z.d.mts} +55 -1
- package/dist/simba/index.cjs +31 -25
- package/dist/simba/index.d.cts +24 -5
- package/dist/simba/index.d.mts +24 -5
- package/dist/simba/index.mjs +9 -3
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.mts +2 -2
- package/dist/{reporting-CNHzbJC-.cjs → warnings-CWRJF-jA.cjs} +63 -0
- package/dist/{reporting-DY-DC4HG.mjs → warnings-OxvDi9kN.mjs} +52 -1
- package/docs/adapters.md +169 -0
- package/docs/benchmark.md +90 -0
- package/docs/data-prep.md +113 -0
- package/docs/distillation.md +128 -0
- package/docs/evaluation.md +87 -0
- package/docs/metric-preflight.md +132 -0
- package/docs/optimizers.md +293 -0
- package/docs/tuning.md +130 -0
- package/package.json +3 -2
package/dist/gepa/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
2
|
+
const require_warnings = require("../warnings-CWRJF-jA.cjs");
|
|
3
3
|
const require_concurrency = require("../concurrency-C-cFzWW2.cjs");
|
|
4
4
|
const require_math = require("../math-BhlziRPc.cjs");
|
|
5
|
-
const require_demos = require("../demos-
|
|
5
|
+
const require_demos = require("../demos-9v5ts7F3.cjs");
|
|
6
6
|
const require_rng = require("../rng-DbA_rPIo.cjs");
|
|
7
7
|
const require_reflection = require("../reflection-DRfbk6hu.cjs");
|
|
8
8
|
const require_sampling = require("../sampling-Dars7ctR.cjs");
|
|
@@ -334,7 +334,7 @@ function isEligibleAncestor(args) {
|
|
|
334
334
|
*/
|
|
335
335
|
function hasComplementaryComponent(args) {
|
|
336
336
|
const { ancestor, left, right } = args;
|
|
337
|
-
return
|
|
337
|
+
return require_warnings.componentNames(ancestor).some((name) => {
|
|
338
338
|
const base = ancestor[name];
|
|
339
339
|
return (base === left[name] || base === right[name]) && left[name] !== right[name];
|
|
340
340
|
});
|
|
@@ -347,7 +347,7 @@ function mergeComponents(args) {
|
|
|
347
347
|
const rightRecord = records[rightId];
|
|
348
348
|
const candidate = { ...ancestor };
|
|
349
349
|
const sources = [];
|
|
350
|
-
for (const name of
|
|
350
|
+
for (const name of require_warnings.componentNames(ancestor)) {
|
|
351
351
|
const base = ancestor[name];
|
|
352
352
|
const leftText = leftRecord.candidate[name];
|
|
353
353
|
const rightText = rightRecord.candidate[name];
|
|
@@ -391,7 +391,7 @@ function buildAncestries(records) {
|
|
|
391
391
|
return ancestries;
|
|
392
392
|
}
|
|
393
393
|
function fingerprint(candidate) {
|
|
394
|
-
return JSON.stringify(
|
|
394
|
+
return JSON.stringify(require_warnings.componentNames(candidate).sort().map((name) => [name, candidate[name]]));
|
|
395
395
|
}
|
|
396
396
|
//#endregion
|
|
397
397
|
//#region src/gepa/pareto.ts
|
|
@@ -513,7 +513,9 @@ function hasSurvivor(args) {
|
|
|
513
513
|
* `frontier` chooses what the fronts are taken over. "instance" is GEPA as
|
|
514
514
|
* published. "objective" tracks candidates leading each named objective the
|
|
515
515
|
* adapter reports, and "hybrid" pools both — a candidate then earns selection
|
|
516
|
-
* weight for every instance it wins *and* every objective it leads.
|
|
516
|
+
* weight for every instance it wins *and* every objective it leads. The
|
|
517
|
+
* objectives are whatever the adapter put in `objectiveScores`, which for a
|
|
518
|
+
* judge is every criterion it graded, including any at `weight: 0`.
|
|
517
519
|
*/
|
|
518
520
|
function paretoSelector(args = {}) {
|
|
519
521
|
const { epsilon = 0, frontier = "instance" } = args;
|
|
@@ -628,14 +630,14 @@ function subsampledEvaluationPolicy(args) {
|
|
|
628
630
|
*/
|
|
629
631
|
function roundRobinComponentSelector() {
|
|
630
632
|
return ({ candidate, cursor }) => {
|
|
631
|
-
const names =
|
|
633
|
+
const names = require_warnings.componentNames(candidate);
|
|
632
634
|
if (names.length === 0) throw new Error("Candidate has no components to update");
|
|
633
635
|
return [names[cursor % names.length]];
|
|
634
636
|
};
|
|
635
637
|
}
|
|
636
638
|
/** Update every component in a single reflection call. */
|
|
637
639
|
function allComponentsSelector() {
|
|
638
|
-
return ({ candidate }) =>
|
|
640
|
+
return ({ candidate }) => require_warnings.componentNames(candidate);
|
|
639
641
|
}
|
|
640
642
|
/**
|
|
641
643
|
* Accept a mutation only when it beats its parent on the same minibatch. Cheap
|
|
@@ -660,7 +662,8 @@ function improvementAcceptance(args = {}) {
|
|
|
660
662
|
*/
|
|
661
663
|
function pairedPermutationAcceptance(args = {}) {
|
|
662
664
|
const { alpha = .2, maxExact = 16 } = args;
|
|
663
|
-
|
|
665
|
+
if (!Number.isFinite(alpha) || alpha <= 0 || alpha > 1) throw new Error(`alpha must be greater than 0 and at most 1, received ${alpha}`);
|
|
666
|
+
const policy = ({ parentScores, childScores }) => {
|
|
664
667
|
const differences = [];
|
|
665
668
|
for (let index = 0; index < parentScores.length; index += 1) differences.push(childScores[index] - parentScores[index]);
|
|
666
669
|
const observed = require_math.sum(differences);
|
|
@@ -671,6 +674,33 @@ function pairedPermutationAcceptance(args = {}) {
|
|
|
671
674
|
maxExact
|
|
672
675
|
}) <= alpha;
|
|
673
676
|
};
|
|
677
|
+
policy.minimumPairs = smallestAcceptableBatch({
|
|
678
|
+
alpha,
|
|
679
|
+
maxExact
|
|
680
|
+
});
|
|
681
|
+
return policy;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Smallest paired batch on which a sign-flip test at `alpha` could return a
|
|
685
|
+
* verdict of "accept" at all.
|
|
686
|
+
*
|
|
687
|
+
* Enumerating n non-zero differences gives 2^n equally likely sign
|
|
688
|
+
* assignments, so the smallest attainable p-value is 2^-n and no batch below
|
|
689
|
+
* `log2(1/alpha)` pairs can clear the bar. Past `maxExact` the p-value comes
|
|
690
|
+
* from a normal approximation, which has no such floor — so when the exact
|
|
691
|
+
* requirement is out of that regime's reach, the first batch that leaves the
|
|
692
|
+
* regime is the honest answer rather than an exact size that never applies.
|
|
693
|
+
*/
|
|
694
|
+
function smallestAcceptableBatch(args) {
|
|
695
|
+
const { alpha, maxExact } = args;
|
|
696
|
+
let pairs = 1;
|
|
697
|
+
let smallestPValue = .5;
|
|
698
|
+
while (smallestPValue > alpha) {
|
|
699
|
+
pairs += 1;
|
|
700
|
+
smallestPValue /= 2;
|
|
701
|
+
if (pairs > maxExact) return maxExact + 1;
|
|
702
|
+
}
|
|
703
|
+
return pairs;
|
|
674
704
|
}
|
|
675
705
|
/**
|
|
676
706
|
* Highest mean over the instances it was scored on, with wider coverage
|
|
@@ -745,16 +775,20 @@ var GepaOptimizer = class {
|
|
|
745
775
|
task
|
|
746
776
|
});
|
|
747
777
|
} finally {
|
|
748
|
-
await
|
|
778
|
+
await require_warnings.flushReporters(task.reporters ?? []);
|
|
749
779
|
}
|
|
750
780
|
}
|
|
751
781
|
};
|
|
752
782
|
async function runGepa(args) {
|
|
753
783
|
const { config, task } = args;
|
|
754
784
|
const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, seed = 0, candidateSelector = paretoSelector(), acceptance = improvementAcceptance(), merge, skipPerfectScore = true, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals, reflection, checkpointCache = true, trackBestOutputs = false, raiseOnError = true } = config;
|
|
755
|
-
const { seedCandidate, trainingSet, validationSet
|
|
756
|
-
const
|
|
757
|
-
|
|
785
|
+
const { seedCandidate, trainingSet, validationSet: requestedValidationSet, testSet, adapter, reflect, maxMetricCalls, componentSelector = roundRobinComponentSelector(), batchSampler = require_sampling.createEpochShuffledSampler({ minibatchSize }), valEvaluationPolicy = fullEvaluationPolicy(), cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = require_warnings.defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
|
|
786
|
+
const { validationSet, warnings } = require_warnings.resolveValidationSet({
|
|
787
|
+
validationSet: requestedValidationSet,
|
|
788
|
+
trainingSet
|
|
789
|
+
});
|
|
790
|
+
const deadline = require_warnings.createDeadline({ maxWallClockMs });
|
|
791
|
+
const seedComponents = require_warnings.componentNames(seedCandidate);
|
|
758
792
|
const mergeConfig = {
|
|
759
793
|
enabled: merge?.enabled ?? seedComponents.length > 1,
|
|
760
794
|
maxInvocations: merge?.maxInvocations ?? DEFAULT_MAX_MERGES,
|
|
@@ -767,7 +801,7 @@ async function runGepa(args) {
|
|
|
767
801
|
if (validationSet.length === 0) throw new Error("optimize requires a non-empty validationSet; the Pareto frontier is tracked over validation instances");
|
|
768
802
|
if (seedComponents.length === 0) throw new Error("optimize requires a seed candidate with at least one component");
|
|
769
803
|
if (testSet !== void 0 && testSet.length === 0) throw new Error("optimize requires a non-empty testSet when one is given; omit it to skip held-out evaluation");
|
|
770
|
-
const evaluationCache = cache === false ? void 0 : cache ??
|
|
804
|
+
const evaluationCache = cache === false ? void 0 : cache ?? require_warnings.createMemoryCache();
|
|
771
805
|
const propose = adapter.proposeNewTexts?.bind(adapter) ?? require_reflection.createDefaultProposer({
|
|
772
806
|
...reflection?.buildPrompt === void 0 ? {} : { buildPrompt: reflection.buildPrompt },
|
|
773
807
|
...reflection?.strategies === void 0 ? {} : { strategies: reflection.strategies },
|
|
@@ -788,19 +822,19 @@ async function runGepa(args) {
|
|
|
788
822
|
datum,
|
|
789
823
|
index
|
|
790
824
|
})) ?? [];
|
|
791
|
-
const fingerprint =
|
|
825
|
+
const fingerprint = require_warnings.runFingerprint({
|
|
792
826
|
seedCandidate,
|
|
793
827
|
trainingIds,
|
|
794
828
|
validationIds,
|
|
795
829
|
seed,
|
|
796
830
|
...cacheNamespace === void 0 ? {} : { cacheNamespace }
|
|
797
831
|
});
|
|
798
|
-
|
|
832
|
+
require_warnings.assertResumable({
|
|
799
833
|
fingerprint,
|
|
800
834
|
...resumeFrom === void 0 ? {} : { snapshot: resumeFrom }
|
|
801
835
|
});
|
|
802
836
|
const rng = require_rng.createSeededRng(seed, resumeFrom?.rngState);
|
|
803
|
-
const budget =
|
|
837
|
+
const budget = require_warnings.createBudget({
|
|
804
838
|
maxMetricCalls,
|
|
805
839
|
spent: resumeFrom?.metricCalls ?? 0
|
|
806
840
|
});
|
|
@@ -820,7 +854,7 @@ async function runGepa(args) {
|
|
|
820
854
|
records: resumeFrom?.records ?? [],
|
|
821
855
|
seedCandidate
|
|
822
856
|
});
|
|
823
|
-
const seenCandidates = new Set(records.map((record) =>
|
|
857
|
+
const seenCandidates = new Set(records.map((record) => require_warnings.candidateFingerprint(record.candidate)));
|
|
824
858
|
const outputsByCandidate = /* @__PURE__ */ new Map();
|
|
825
859
|
const rejectedProposals = restoreRejections({
|
|
826
860
|
rejections: resumeFrom?.rejectedProposals ?? {},
|
|
@@ -832,7 +866,7 @@ async function runGepa(args) {
|
|
|
832
866
|
let mergesDue = resumeFrom?.merge.due ?? 0;
|
|
833
867
|
let totalMergesTested = resumeFrom?.merge.tested ?? 0;
|
|
834
868
|
let lastIterationAccepted = resumeFrom?.merge.lastIterationAccepted ?? false;
|
|
835
|
-
const emit =
|
|
869
|
+
const emit = require_warnings.createEmitter(reporters);
|
|
836
870
|
/**
|
|
837
871
|
* Everything an acceptance means, in one event: the text, the aggregate, and
|
|
838
872
|
* the row it put on the frontier. Emitted from one place because the merge
|
|
@@ -889,7 +923,7 @@ async function runGepa(args) {
|
|
|
889
923
|
if (onCheckpoint === void 0) return;
|
|
890
924
|
await onCheckpoint(takeSnapshot());
|
|
891
925
|
}
|
|
892
|
-
const evaluator =
|
|
926
|
+
const evaluator = require_warnings.createEvaluator({
|
|
893
927
|
adapter,
|
|
894
928
|
budget,
|
|
895
929
|
...retry === void 0 ? {} : { retry },
|
|
@@ -977,7 +1011,7 @@ async function runGepa(args) {
|
|
|
977
1011
|
componentCursor: inheritedCursor(args.parentIds)
|
|
978
1012
|
};
|
|
979
1013
|
records.push(record);
|
|
980
|
-
seenCandidates.add(
|
|
1014
|
+
seenCandidates.add(require_warnings.candidateFingerprint(args.candidate));
|
|
981
1015
|
if (trackBestOutputs) outputsByCandidate.set(record.id, args.evaluation.outputs);
|
|
982
1016
|
if (args.source !== "merge") {
|
|
983
1017
|
lastIterationAccepted = true;
|
|
@@ -989,7 +1023,7 @@ async function runGepa(args) {
|
|
|
989
1023
|
function rememberRejection(args) {
|
|
990
1024
|
const { proposed, parentScore, childScore } = args;
|
|
991
1025
|
if (rejectedProposalMemory <= 0) return;
|
|
992
|
-
for (const component of
|
|
1026
|
+
for (const component of require_warnings.componentNames(proposed)) {
|
|
993
1027
|
const text = proposed[component];
|
|
994
1028
|
if (text === void 0) continue;
|
|
995
1029
|
const history = rejectedProposals[component] ?? [];
|
|
@@ -1017,18 +1051,23 @@ async function runGepa(args) {
|
|
|
1017
1051
|
if (records.length === 0) {
|
|
1018
1052
|
const seedInstances = selectValInstances(seedCandidate);
|
|
1019
1053
|
if (!budget.canAfford(seedInstances.length)) throw new Error(`maxMetricCalls (${maxMetricCalls}) is smaller than the ${seedInstances.length} validation instances selected for scoring; the seed candidate cannot be scored`);
|
|
1054
|
+
const seedEvaluation = await evaluateValidation({
|
|
1055
|
+
candidate: seedCandidate,
|
|
1056
|
+
instances: seedInstances,
|
|
1057
|
+
phase: "seed",
|
|
1058
|
+
candidateId: 0
|
|
1059
|
+
});
|
|
1020
1060
|
emitAccepted(addCandidate({
|
|
1021
1061
|
candidate: seedCandidate,
|
|
1022
1062
|
parentIds: [],
|
|
1023
|
-
evaluation:
|
|
1024
|
-
candidate: seedCandidate,
|
|
1025
|
-
instances: seedInstances,
|
|
1026
|
-
phase: "seed",
|
|
1027
|
-
candidateId: 0
|
|
1028
|
-
}),
|
|
1063
|
+
evaluation: seedEvaluation,
|
|
1029
1064
|
source: "seed",
|
|
1030
1065
|
updatedComponents: []
|
|
1031
1066
|
}));
|
|
1067
|
+
warnings.push(...require_warnings.seedScoreWarnings({
|
|
1068
|
+
scores: seedEvaluation.scores,
|
|
1069
|
+
perfectScore
|
|
1070
|
+
}));
|
|
1032
1071
|
lastIterationAccepted = false;
|
|
1033
1072
|
mergesDue = 0;
|
|
1034
1073
|
await checkpoint();
|
|
@@ -1115,7 +1154,7 @@ async function runGepa(args) {
|
|
|
1115
1154
|
parentIds: [...proposal.parentIds],
|
|
1116
1155
|
evaluation,
|
|
1117
1156
|
source: "merge",
|
|
1118
|
-
updatedComponents:
|
|
1157
|
+
updatedComponents: require_warnings.componentNames(proposal.candidate).filter((name) => proposal.candidate[name] !== ancestor.candidate[name])
|
|
1119
1158
|
});
|
|
1120
1159
|
mergesDue -= 1;
|
|
1121
1160
|
totalMergesTested += 1;
|
|
@@ -1158,7 +1197,7 @@ async function runGepa(args) {
|
|
|
1158
1197
|
candidate: parent.candidate,
|
|
1159
1198
|
source: "componentSelector"
|
|
1160
1199
|
});
|
|
1161
|
-
parent.componentCursor = (parent.componentCursor + 1) % Math.max(1,
|
|
1200
|
+
parent.componentCursor = (parent.componentCursor + 1) % Math.max(1, require_warnings.componentNames(parent.candidate).length);
|
|
1162
1201
|
plans.push({
|
|
1163
1202
|
parent,
|
|
1164
1203
|
batch: batchIndices.map((index) => trainingSet[index]),
|
|
@@ -1208,7 +1247,7 @@ async function runGepa(args) {
|
|
|
1208
1247
|
throw err;
|
|
1209
1248
|
}
|
|
1210
1249
|
assertComponents({
|
|
1211
|
-
names:
|
|
1250
|
+
names: require_warnings.componentNames(proposed),
|
|
1212
1251
|
candidate: parent.candidate,
|
|
1213
1252
|
source: "proposeNewTexts"
|
|
1214
1253
|
});
|
|
@@ -1216,7 +1255,7 @@ async function runGepa(args) {
|
|
|
1216
1255
|
...parent.candidate,
|
|
1217
1256
|
...proposed
|
|
1218
1257
|
};
|
|
1219
|
-
const changed =
|
|
1258
|
+
const changed = require_warnings.componentNames(proposed).length > 0 && !seenCandidates.has(require_warnings.candidateFingerprint(child));
|
|
1220
1259
|
emit({
|
|
1221
1260
|
type: "proposal",
|
|
1222
1261
|
iteration,
|
|
@@ -1236,7 +1275,7 @@ async function runGepa(args) {
|
|
|
1236
1275
|
candidateId: null
|
|
1237
1276
|
});
|
|
1238
1277
|
} catch (err) {
|
|
1239
|
-
if (err instanceof
|
|
1278
|
+
if (err instanceof require_warnings.BudgetExhausted) return { status: "budgetExhausted" };
|
|
1240
1279
|
throw err;
|
|
1241
1280
|
}
|
|
1242
1281
|
const screened = pairMeasured({
|
|
@@ -1279,7 +1318,7 @@ async function runGepa(args) {
|
|
|
1279
1318
|
stop ??= "reflectionBudgetExhausted";
|
|
1280
1319
|
continue;
|
|
1281
1320
|
}
|
|
1282
|
-
const fingerprint =
|
|
1321
|
+
const fingerprint = require_warnings.candidateFingerprint(outcome.child);
|
|
1283
1322
|
if (claimed.has(fingerprint)) continue;
|
|
1284
1323
|
claimed.add(fingerprint);
|
|
1285
1324
|
if (!outcome.accepted) {
|
|
@@ -1351,7 +1390,7 @@ async function runGepa(args) {
|
|
|
1351
1390
|
})
|
|
1352
1391
|
};
|
|
1353
1392
|
} catch (err) {
|
|
1354
|
-
if (err instanceof
|
|
1393
|
+
if (err instanceof require_warnings.BudgetExhausted) return {
|
|
1355
1394
|
item,
|
|
1356
1395
|
evaluation: void 0
|
|
1357
1396
|
};
|
|
@@ -1369,7 +1408,7 @@ async function runGepa(args) {
|
|
|
1369
1408
|
parentIds: [item.outcome.plan.parent.id],
|
|
1370
1409
|
evaluation,
|
|
1371
1410
|
source: "mutation",
|
|
1372
|
-
updatedComponents:
|
|
1411
|
+
updatedComponents: require_warnings.componentNames(item.outcome.proposed)
|
|
1373
1412
|
}));
|
|
1374
1413
|
}
|
|
1375
1414
|
return stop;
|
|
@@ -1387,7 +1426,7 @@ async function runGepa(args) {
|
|
|
1387
1426
|
stopReason = "aborted";
|
|
1388
1427
|
break;
|
|
1389
1428
|
}
|
|
1390
|
-
if (
|
|
1429
|
+
if (require_warnings.costExhausted({
|
|
1391
1430
|
usage: evaluator.usage(),
|
|
1392
1431
|
maxCostUsd
|
|
1393
1432
|
})) {
|
|
@@ -1434,7 +1473,7 @@ async function runGepa(args) {
|
|
|
1434
1473
|
stopReason = "aborted";
|
|
1435
1474
|
break;
|
|
1436
1475
|
}
|
|
1437
|
-
if (err instanceof
|
|
1476
|
+
if (err instanceof require_warnings.BudgetExhausted) {
|
|
1438
1477
|
stopReason = "budgetExhausted";
|
|
1439
1478
|
break;
|
|
1440
1479
|
}
|
|
@@ -1463,15 +1502,16 @@ async function runGepa(args) {
|
|
|
1463
1502
|
candidateId: bestCandidateId,
|
|
1464
1503
|
charge: false
|
|
1465
1504
|
});
|
|
1466
|
-
const testScore = heldOut === void 0 ? void 0 :
|
|
1505
|
+
const testScore = heldOut === void 0 ? void 0 : require_warnings.measuredMean(heldOut);
|
|
1467
1506
|
emit({
|
|
1468
1507
|
type: "finish",
|
|
1469
1508
|
reason: stopReason,
|
|
1509
|
+
warnings,
|
|
1470
1510
|
bestCandidateId,
|
|
1471
1511
|
bestScore: best.aggregateScore,
|
|
1472
1512
|
metricCalls: budget.spent(),
|
|
1473
1513
|
...testScore === void 0 ? {} : { testScore },
|
|
1474
|
-
...heldOut === void 0 ? {} : { testInstanceScores:
|
|
1514
|
+
...heldOut === void 0 ? {} : { testInstanceScores: require_warnings.instanceRow(heldOut) },
|
|
1475
1515
|
...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
|
|
1476
1516
|
});
|
|
1477
1517
|
const perObjectiveBest = collectPerObjectiveBest(records);
|
|
@@ -1495,6 +1535,7 @@ async function runGepa(args) {
|
|
|
1495
1535
|
reflectionCalls,
|
|
1496
1536
|
cacheHits: evaluator.cacheHits(),
|
|
1497
1537
|
iterations: iteration,
|
|
1538
|
+
warnings,
|
|
1498
1539
|
stopReason,
|
|
1499
1540
|
snapshot: takeSnapshot()
|
|
1500
1541
|
};
|
|
@@ -1507,13 +1548,15 @@ async function runGepa(args) {
|
|
|
1507
1548
|
function assertGepaConfig(config) {
|
|
1508
1549
|
if (config.reflection?.buildPrompt !== void 0 && config.reflection.strategies !== void 0) throw new Error("reflection takes buildPrompt or strategies, not both");
|
|
1509
1550
|
if (config.reflection?.strategies?.length === 0) throw new Error("reflection.strategies must not be empty");
|
|
1510
|
-
const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals } = config;
|
|
1551
|
+
const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, acceptance, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals } = config;
|
|
1511
1552
|
const proposalsPerIteration = proposals?.perIteration ?? 1;
|
|
1512
1553
|
const proposalConcurrency = proposals?.concurrency ?? 1;
|
|
1513
1554
|
if (!Number.isInteger(proposalsPerIteration) || proposalsPerIteration < 1) throw new Error(`proposals.perIteration must be a positive integer, received ${proposalsPerIteration}`);
|
|
1514
1555
|
if (!Number.isInteger(proposalConcurrency) || proposalConcurrency < 1) throw new Error(`proposals.concurrency must be a positive integer, received ${proposalConcurrency}`);
|
|
1515
1556
|
keepCount(proposals?.selection ?? "all");
|
|
1516
1557
|
if (!Number.isInteger(minibatchSize) || minibatchSize < 1) throw new Error(`minibatchSize must be a positive integer, received ${minibatchSize}`);
|
|
1558
|
+
const minimumPairs = acceptance?.minimumPairs;
|
|
1559
|
+
if (minimumPairs !== void 0 && minibatchSize < minimumPairs) throw new Error(`this acceptance policy cannot accept anything on fewer than ${minimumPairs} instances, but minibatchSize is ${minibatchSize}; raise minibatchSize or loosen the policy`);
|
|
1517
1560
|
if (!Number.isFinite(perfectScore)) throw new Error(`perfectScore must be a finite number, received ${perfectScore}`);
|
|
1518
1561
|
if (!Number.isInteger(rejectedProposalMemory) || rejectedProposalMemory < 0) throw new Error(`rejectedProposalMemory must be a non-negative integer, received ${rejectedProposalMemory}`);
|
|
1519
1562
|
if (maxIterations !== Number.POSITIVE_INFINITY && (!Number.isInteger(maxIterations) || maxIterations < 0)) throw new Error(`maxIterations must be a non-negative integer or Infinity, received ${maxIterations}`);
|
|
@@ -1527,7 +1570,7 @@ function assertGepaConfig(config) {
|
|
|
1527
1570
|
*/
|
|
1528
1571
|
function restoreRecords(args) {
|
|
1529
1572
|
const { records, seedCandidate } = args;
|
|
1530
|
-
const known = new Set(
|
|
1573
|
+
const known = new Set(require_warnings.componentNames(seedCandidate));
|
|
1531
1574
|
for (const record of records) {
|
|
1532
1575
|
const named = [...Object.keys(record.candidate), ...record.updatedComponents];
|
|
1533
1576
|
for (const name of named) if (!known.has(name)) throw new Error(`checkpoint names the component "${name}", which the seed candidate does not have (${[...known].join(", ")})`);
|
|
@@ -1666,8 +1709,8 @@ exports.diverseReflectionStrategies = require_reflection.diverseReflectionStrate
|
|
|
1666
1709
|
exports.epsilonGreedySelector = epsilonGreedySelector;
|
|
1667
1710
|
exports.fullEvaluationPolicy = fullEvaluationPolicy;
|
|
1668
1711
|
exports.improvementAcceptance = improvementAcceptance;
|
|
1669
|
-
exports.isCandidateAccepted =
|
|
1670
|
-
exports.isRunFinished =
|
|
1712
|
+
exports.isCandidateAccepted = require_warnings.isCandidateAccepted;
|
|
1713
|
+
exports.isRunFinished = require_warnings.isRunFinished;
|
|
1671
1714
|
exports.lowerBoundEvaluationPolicy = lowerBoundEvaluationPolicy;
|
|
1672
1715
|
exports.pairedPermutationAcceptance = pairedPermutationAcceptance;
|
|
1673
1716
|
exports.paretoSelector = paretoSelector;
|
package/dist/gepa/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as RunFinished, b as ScoreResult, i as Reporter, n as OptimizerEvent, o as isCandidateAccepted, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, x as TextModel } from "../reporting-bq007_2z.cjs";
|
|
2
2
|
import { n as EvaluationCache } from "../cache-CuSo0NJ8.cjs";
|
|
3
|
-
import { r as DemoRenderer } from "../demos-
|
|
4
|
-
import { n as OptimizerResult, r as OptimizerTask, t as Optimizer } from "../optimizer-
|
|
5
|
-
import { C as
|
|
3
|
+
import { r as DemoRenderer } from "../demos-ByaLZy-Z.cjs";
|
|
4
|
+
import { n as OptimizerResult, r as OptimizerTask, t as Optimizer } from "../optimizer-4Zv-Zt2t.cjs";
|
|
5
|
+
import { C as ReflectiveRecord, E as ValEvaluationPolicy, S as ReflectiveDataset, T as SelectionState, _ as GepaStopReason, a as buildRewritePrompt, b as ProposeArgs, c as AcceptancePolicy, d as CandidateSource, f as ComponentPatch, g as GepaSnapshot, h as GepaEvent, i as buildReflectionPrompt, l as CandidateRecord, m as GepaAdapter, n as ReflectionPromptBuilder, o as buildSimplifyPrompt, p as ComponentSelector, r as buildGeneralizePrompt, s as diverseReflectionStrategies, t as ReflectionPromptArgs, u as CandidateSelector, v as MakeReflectiveDatasetArgs, w as RejectedProposal, x as ReflectiveBatch, y as ParetoFrontier } from "../reflection-D0A7eahD.cjs";
|
|
6
6
|
import { t as BatchSampler } from "../sampling-axOwfZf5.cjs";
|
|
7
7
|
//#region src/gepa/demos.d.ts
|
|
8
8
|
/**
|
|
@@ -305,7 +305,9 @@ declare class GepaOptimizer implements Optimizer<GepaStopReason> {
|
|
|
305
305
|
* `frontier` chooses what the fronts are taken over. "instance" is GEPA as
|
|
306
306
|
* published. "objective" tracks candidates leading each named objective the
|
|
307
307
|
* adapter reports, and "hybrid" pools both — a candidate then earns selection
|
|
308
|
-
* weight for every instance it wins *and* every objective it leads.
|
|
308
|
+
* weight for every instance it wins *and* every objective it leads. The
|
|
309
|
+
* objectives are whatever the adapter put in `objectiveScores`, which for a
|
|
310
|
+
* judge is every criterion it graded, including any at `weight: 0`.
|
|
309
311
|
*/
|
|
310
312
|
declare function paretoSelector(args?: {
|
|
311
313
|
epsilon?: number;
|
|
@@ -388,4 +390,4 @@ declare function pairedPermutationAcceptance(args?: {
|
|
|
388
390
|
maxExact?: number;
|
|
389
391
|
}): AcceptancePolicy;
|
|
390
392
|
//#endregion
|
|
391
|
-
export { type AcceptancePolicy, type CandidateAccepted, type CandidateRecord, type CandidateSelector, type CandidateSource, type ComponentPatch, type ComponentSelector, type GepaAdapter, type GepaConfig, type GepaEvent, GepaOptimizer, type GepaResult, type GepaSnapshot, type GepaStopReason, type GepaTask, type MakeReflectiveDatasetArgs, type OptimizerEvent, type PipelineModule, type PipelineStep, type PipelineTrace, type ProposeArgs, type ReflectionPromptArgs, type ReflectionPromptBuilder, type ReflectiveDataset, type ReflectiveRecord, type RejectedProposal, type ReportableEvent, type Reporter, type RunFinished, type SelectionState, type ValEvaluationPolicy, allComponentsSelector, buildGeneralizePrompt, buildReflectionPrompt, buildRewritePrompt, buildSimplifyPrompt, createDemoProposer, createPipelineAdapter, currentBestSelector, diverseReflectionStrategies, epsilonGreedySelector, fullEvaluationPolicy, improvementAcceptance, isCandidateAccepted, isRunFinished, lowerBoundEvaluationPolicy, pairedPermutationAcceptance, paretoSelector, roundRobinComponentSelector, subsampledEvaluationPolicy, topKParetoSelector };
|
|
393
|
+
export { type AcceptancePolicy, type CandidateAccepted, type CandidateRecord, type CandidateSelector, type CandidateSource, type ComponentPatch, type ComponentSelector, type GepaAdapter, type GepaConfig, type GepaEvent, GepaOptimizer, type GepaResult, type GepaSnapshot, type GepaStopReason, type GepaTask, type MakeReflectiveDatasetArgs, type OptimizerEvent, type PipelineModule, type PipelineStep, type PipelineTrace, type ProposeArgs, type ReflectionPromptArgs, type ReflectionPromptBuilder, type ReflectiveBatch, type ReflectiveDataset, type ReflectiveRecord, type RejectedProposal, type ReportableEvent, type Reporter, type RunFinished, type SelectionState, type ValEvaluationPolicy, allComponentsSelector, buildGeneralizePrompt, buildReflectionPrompt, buildRewritePrompt, buildSimplifyPrompt, createDemoProposer, createPipelineAdapter, currentBestSelector, diverseReflectionStrategies, epsilonGreedySelector, fullEvaluationPolicy, improvementAcceptance, isCandidateAccepted, isRunFinished, lowerBoundEvaluationPolicy, pairedPermutationAcceptance, paretoSelector, roundRobinComponentSelector, subsampledEvaluationPolicy, topKParetoSelector };
|
package/dist/gepa/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as RunFinished, b as ScoreResult, i as Reporter, n as OptimizerEvent, o as isCandidateAccepted, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, x as TextModel } from "../reporting-bq007_2z.mjs";
|
|
2
2
|
import { n as EvaluationCache } from "../cache-CuSo0NJ8.mjs";
|
|
3
|
-
import { r as DemoRenderer } from "../demos-
|
|
4
|
-
import { n as OptimizerResult, r as OptimizerTask, t as Optimizer } from "../optimizer-
|
|
5
|
-
import { C as
|
|
3
|
+
import { r as DemoRenderer } from "../demos-ASsSXYXA.mjs";
|
|
4
|
+
import { n as OptimizerResult, r as OptimizerTask, t as Optimizer } from "../optimizer-Ds5mzYjz.mjs";
|
|
5
|
+
import { C as ReflectiveRecord, E as ValEvaluationPolicy, S as ReflectiveDataset, T as SelectionState, _ as GepaStopReason, a as buildRewritePrompt, b as ProposeArgs, c as AcceptancePolicy, d as CandidateSource, f as ComponentPatch, g as GepaSnapshot, h as GepaEvent, i as buildReflectionPrompt, l as CandidateRecord, m as GepaAdapter, n as ReflectionPromptBuilder, o as buildSimplifyPrompt, p as ComponentSelector, r as buildGeneralizePrompt, s as diverseReflectionStrategies, t as ReflectionPromptArgs, u as CandidateSelector, v as MakeReflectiveDatasetArgs, w as RejectedProposal, x as ReflectiveBatch, y as ParetoFrontier } from "../reflection-CMezGu6u.mjs";
|
|
6
6
|
import { t as BatchSampler } from "../sampling-DFo_7RNJ.mjs";
|
|
7
7
|
//#region src/gepa/demos.d.ts
|
|
8
8
|
/**
|
|
@@ -305,7 +305,9 @@ declare class GepaOptimizer implements Optimizer<GepaStopReason> {
|
|
|
305
305
|
* `frontier` chooses what the fronts are taken over. "instance" is GEPA as
|
|
306
306
|
* published. "objective" tracks candidates leading each named objective the
|
|
307
307
|
* adapter reports, and "hybrid" pools both — a candidate then earns selection
|
|
308
|
-
* weight for every instance it wins *and* every objective it leads.
|
|
308
|
+
* weight for every instance it wins *and* every objective it leads. The
|
|
309
|
+
* objectives are whatever the adapter put in `objectiveScores`, which for a
|
|
310
|
+
* judge is every criterion it graded, including any at `weight: 0`.
|
|
309
311
|
*/
|
|
310
312
|
declare function paretoSelector(args?: {
|
|
311
313
|
epsilon?: number;
|
|
@@ -388,4 +390,4 @@ declare function pairedPermutationAcceptance(args?: {
|
|
|
388
390
|
maxExact?: number;
|
|
389
391
|
}): AcceptancePolicy;
|
|
390
392
|
//#endregion
|
|
391
|
-
export { type AcceptancePolicy, type CandidateAccepted, type CandidateRecord, type CandidateSelector, type CandidateSource, type ComponentPatch, type ComponentSelector, type GepaAdapter, type GepaConfig, type GepaEvent, GepaOptimizer, type GepaResult, type GepaSnapshot, type GepaStopReason, type GepaTask, type MakeReflectiveDatasetArgs, type OptimizerEvent, type PipelineModule, type PipelineStep, type PipelineTrace, type ProposeArgs, type ReflectionPromptArgs, type ReflectionPromptBuilder, type ReflectiveDataset, type ReflectiveRecord, type RejectedProposal, type ReportableEvent, type Reporter, type RunFinished, type SelectionState, type ValEvaluationPolicy, allComponentsSelector, buildGeneralizePrompt, buildReflectionPrompt, buildRewritePrompt, buildSimplifyPrompt, createDemoProposer, createPipelineAdapter, currentBestSelector, diverseReflectionStrategies, epsilonGreedySelector, fullEvaluationPolicy, improvementAcceptance, isCandidateAccepted, isRunFinished, lowerBoundEvaluationPolicy, pairedPermutationAcceptance, paretoSelector, roundRobinComponentSelector, subsampledEvaluationPolicy, topKParetoSelector };
|
|
393
|
+
export { type AcceptancePolicy, type CandidateAccepted, type CandidateRecord, type CandidateSelector, type CandidateSource, type ComponentPatch, type ComponentSelector, type GepaAdapter, type GepaConfig, type GepaEvent, GepaOptimizer, type GepaResult, type GepaSnapshot, type GepaStopReason, type GepaTask, type MakeReflectiveDatasetArgs, type OptimizerEvent, type PipelineModule, type PipelineStep, type PipelineTrace, type ProposeArgs, type ReflectionPromptArgs, type ReflectionPromptBuilder, type ReflectiveBatch, type ReflectiveDataset, type ReflectiveRecord, type RejectedProposal, type ReportableEvent, type Reporter, type RunFinished, type SelectionState, type ValEvaluationPolicy, allComponentsSelector, buildGeneralizePrompt, buildReflectionPrompt, buildRewritePrompt, buildSimplifyPrompt, createDemoProposer, createPipelineAdapter, currentBestSelector, diverseReflectionStrategies, epsilonGreedySelector, fullEvaluationPolicy, improvementAcceptance, isCandidateAccepted, isRunFinished, lowerBoundEvaluationPolicy, pairedPermutationAcceptance, paretoSelector, roundRobinComponentSelector, subsampledEvaluationPolicy, topKParetoSelector };
|
package/dist/gepa/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { S as createBudget, _ as componentNames, a as instanceRow, b as defaultInstanceId, c as BudgetExhausted, d as measuredMean, g as runFingerprint, h as candidateFingerprint, i as flushReporters, l as costExhausted, m as assertResumable, n as seedScoreWarnings, o as isCandidateAccepted, p as createDeadline, r as createEmitter, s as isRunFinished, t as resolveValidationSet, u as createEvaluator, y as createMemoryCache } from "../warnings-OxvDi9kN.mjs";
|
|
2
2
|
import { t as mapWithConcurrency } from "../concurrency-D58PWeSk.mjs";
|
|
3
3
|
import { a as sum, i as signFlipPValue, r as mean, t as argmax } from "../math-Dqme4rYz.mjs";
|
|
4
|
-
import { r as parseDemos, t as formatDemos } from "../demos-
|
|
4
|
+
import { r as parseDemos, t as formatDemos } from "../demos-Brobjfuc.mjs";
|
|
5
5
|
import { t as createSeededRng } from "../rng-Dtc5eZ_W.mjs";
|
|
6
6
|
import { a as createDefaultProposer, i as buildSimplifyPrompt, n as buildReflectionPrompt, o as diverseReflectionStrategies, r as buildRewritePrompt, t as buildGeneralizePrompt } from "../reflection-mwMhrjs_.mjs";
|
|
7
7
|
import { t as createEpochShuffledSampler } from "../sampling-CfHt7Gue.mjs";
|
|
@@ -512,7 +512,9 @@ function hasSurvivor(args) {
|
|
|
512
512
|
* `frontier` chooses what the fronts are taken over. "instance" is GEPA as
|
|
513
513
|
* published. "objective" tracks candidates leading each named objective the
|
|
514
514
|
* adapter reports, and "hybrid" pools both — a candidate then earns selection
|
|
515
|
-
* weight for every instance it wins *and* every objective it leads.
|
|
515
|
+
* weight for every instance it wins *and* every objective it leads. The
|
|
516
|
+
* objectives are whatever the adapter put in `objectiveScores`, which for a
|
|
517
|
+
* judge is every criterion it graded, including any at `weight: 0`.
|
|
516
518
|
*/
|
|
517
519
|
function paretoSelector(args = {}) {
|
|
518
520
|
const { epsilon = 0, frontier = "instance" } = args;
|
|
@@ -659,7 +661,8 @@ function improvementAcceptance(args = {}) {
|
|
|
659
661
|
*/
|
|
660
662
|
function pairedPermutationAcceptance(args = {}) {
|
|
661
663
|
const { alpha = .2, maxExact = 16 } = args;
|
|
662
|
-
|
|
664
|
+
if (!Number.isFinite(alpha) || alpha <= 0 || alpha > 1) throw new Error(`alpha must be greater than 0 and at most 1, received ${alpha}`);
|
|
665
|
+
const policy = ({ parentScores, childScores }) => {
|
|
663
666
|
const differences = [];
|
|
664
667
|
for (let index = 0; index < parentScores.length; index += 1) differences.push(childScores[index] - parentScores[index]);
|
|
665
668
|
const observed = sum(differences);
|
|
@@ -670,6 +673,33 @@ function pairedPermutationAcceptance(args = {}) {
|
|
|
670
673
|
maxExact
|
|
671
674
|
}) <= alpha;
|
|
672
675
|
};
|
|
676
|
+
policy.minimumPairs = smallestAcceptableBatch({
|
|
677
|
+
alpha,
|
|
678
|
+
maxExact
|
|
679
|
+
});
|
|
680
|
+
return policy;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Smallest paired batch on which a sign-flip test at `alpha` could return a
|
|
684
|
+
* verdict of "accept" at all.
|
|
685
|
+
*
|
|
686
|
+
* Enumerating n non-zero differences gives 2^n equally likely sign
|
|
687
|
+
* assignments, so the smallest attainable p-value is 2^-n and no batch below
|
|
688
|
+
* `log2(1/alpha)` pairs can clear the bar. Past `maxExact` the p-value comes
|
|
689
|
+
* from a normal approximation, which has no such floor — so when the exact
|
|
690
|
+
* requirement is out of that regime's reach, the first batch that leaves the
|
|
691
|
+
* regime is the honest answer rather than an exact size that never applies.
|
|
692
|
+
*/
|
|
693
|
+
function smallestAcceptableBatch(args) {
|
|
694
|
+
const { alpha, maxExact } = args;
|
|
695
|
+
let pairs = 1;
|
|
696
|
+
let smallestPValue = .5;
|
|
697
|
+
while (smallestPValue > alpha) {
|
|
698
|
+
pairs += 1;
|
|
699
|
+
smallestPValue /= 2;
|
|
700
|
+
if (pairs > maxExact) return maxExact + 1;
|
|
701
|
+
}
|
|
702
|
+
return pairs;
|
|
673
703
|
}
|
|
674
704
|
/**
|
|
675
705
|
* Highest mean over the instances it was scored on, with wider coverage
|
|
@@ -751,7 +781,11 @@ var GepaOptimizer = class {
|
|
|
751
781
|
async function runGepa(args) {
|
|
752
782
|
const { config, task } = args;
|
|
753
783
|
const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, seed = 0, candidateSelector = paretoSelector(), acceptance = improvementAcceptance(), merge, skipPerfectScore = true, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals, reflection, checkpointCache = true, trackBestOutputs = false, raiseOnError = true } = config;
|
|
754
|
-
const { seedCandidate, trainingSet, validationSet
|
|
784
|
+
const { seedCandidate, trainingSet, validationSet: requestedValidationSet, testSet, adapter, reflect, maxMetricCalls, componentSelector = roundRobinComponentSelector(), batchSampler = createEpochShuffledSampler({ minibatchSize }), valEvaluationPolicy = fullEvaluationPolicy(), cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
|
|
785
|
+
const { validationSet, warnings } = resolveValidationSet({
|
|
786
|
+
validationSet: requestedValidationSet,
|
|
787
|
+
trainingSet
|
|
788
|
+
});
|
|
755
789
|
const deadline = createDeadline({ maxWallClockMs });
|
|
756
790
|
const seedComponents = componentNames(seedCandidate);
|
|
757
791
|
const mergeConfig = {
|
|
@@ -1016,18 +1050,23 @@ async function runGepa(args) {
|
|
|
1016
1050
|
if (records.length === 0) {
|
|
1017
1051
|
const seedInstances = selectValInstances(seedCandidate);
|
|
1018
1052
|
if (!budget.canAfford(seedInstances.length)) throw new Error(`maxMetricCalls (${maxMetricCalls}) is smaller than the ${seedInstances.length} validation instances selected for scoring; the seed candidate cannot be scored`);
|
|
1053
|
+
const seedEvaluation = await evaluateValidation({
|
|
1054
|
+
candidate: seedCandidate,
|
|
1055
|
+
instances: seedInstances,
|
|
1056
|
+
phase: "seed",
|
|
1057
|
+
candidateId: 0
|
|
1058
|
+
});
|
|
1019
1059
|
emitAccepted(addCandidate({
|
|
1020
1060
|
candidate: seedCandidate,
|
|
1021
1061
|
parentIds: [],
|
|
1022
|
-
evaluation:
|
|
1023
|
-
candidate: seedCandidate,
|
|
1024
|
-
instances: seedInstances,
|
|
1025
|
-
phase: "seed",
|
|
1026
|
-
candidateId: 0
|
|
1027
|
-
}),
|
|
1062
|
+
evaluation: seedEvaluation,
|
|
1028
1063
|
source: "seed",
|
|
1029
1064
|
updatedComponents: []
|
|
1030
1065
|
}));
|
|
1066
|
+
warnings.push(...seedScoreWarnings({
|
|
1067
|
+
scores: seedEvaluation.scores,
|
|
1068
|
+
perfectScore
|
|
1069
|
+
}));
|
|
1031
1070
|
lastIterationAccepted = false;
|
|
1032
1071
|
mergesDue = 0;
|
|
1033
1072
|
await checkpoint();
|
|
@@ -1466,6 +1505,7 @@ async function runGepa(args) {
|
|
|
1466
1505
|
emit({
|
|
1467
1506
|
type: "finish",
|
|
1468
1507
|
reason: stopReason,
|
|
1508
|
+
warnings,
|
|
1469
1509
|
bestCandidateId,
|
|
1470
1510
|
bestScore: best.aggregateScore,
|
|
1471
1511
|
metricCalls: budget.spent(),
|
|
@@ -1494,6 +1534,7 @@ async function runGepa(args) {
|
|
|
1494
1534
|
reflectionCalls,
|
|
1495
1535
|
cacheHits: evaluator.cacheHits(),
|
|
1496
1536
|
iterations: iteration,
|
|
1537
|
+
warnings,
|
|
1497
1538
|
stopReason,
|
|
1498
1539
|
snapshot: takeSnapshot()
|
|
1499
1540
|
};
|
|
@@ -1506,13 +1547,15 @@ async function runGepa(args) {
|
|
|
1506
1547
|
function assertGepaConfig(config) {
|
|
1507
1548
|
if (config.reflection?.buildPrompt !== void 0 && config.reflection.strategies !== void 0) throw new Error("reflection takes buildPrompt or strategies, not both");
|
|
1508
1549
|
if (config.reflection?.strategies?.length === 0) throw new Error("reflection.strategies must not be empty");
|
|
1509
|
-
const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals } = config;
|
|
1550
|
+
const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, acceptance, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals } = config;
|
|
1510
1551
|
const proposalsPerIteration = proposals?.perIteration ?? 1;
|
|
1511
1552
|
const proposalConcurrency = proposals?.concurrency ?? 1;
|
|
1512
1553
|
if (!Number.isInteger(proposalsPerIteration) || proposalsPerIteration < 1) throw new Error(`proposals.perIteration must be a positive integer, received ${proposalsPerIteration}`);
|
|
1513
1554
|
if (!Number.isInteger(proposalConcurrency) || proposalConcurrency < 1) throw new Error(`proposals.concurrency must be a positive integer, received ${proposalConcurrency}`);
|
|
1514
1555
|
keepCount(proposals?.selection ?? "all");
|
|
1515
1556
|
if (!Number.isInteger(minibatchSize) || minibatchSize < 1) throw new Error(`minibatchSize must be a positive integer, received ${minibatchSize}`);
|
|
1557
|
+
const minimumPairs = acceptance?.minimumPairs;
|
|
1558
|
+
if (minimumPairs !== void 0 && minibatchSize < minimumPairs) throw new Error(`this acceptance policy cannot accept anything on fewer than ${minimumPairs} instances, but minibatchSize is ${minibatchSize}; raise minibatchSize or loosen the policy`);
|
|
1516
1559
|
if (!Number.isFinite(perfectScore)) throw new Error(`perfectScore must be a finite number, received ${perfectScore}`);
|
|
1517
1560
|
if (!Number.isInteger(rejectedProposalMemory) || rejectedProposalMemory < 0) throw new Error(`rejectedProposalMemory must be a non-negative integer, received ${rejectedProposalMemory}`);
|
|
1518
1561
|
if (maxIterations !== Number.POSITIVE_INFINITY && (!Number.isInteger(maxIterations) || maxIterations < 0)) throw new Error(`maxIterations must be a non-negative integer or Infinity, received ${maxIterations}`);
|