textopt 0.0.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 +65 -25
- package/dist/bootstrap-search/index.cjs +159 -73
- package/dist/bootstrap-search/index.d.cts +32 -10
- package/dist/bootstrap-search/index.d.mts +32 -10
- package/dist/bootstrap-search/index.mjs +150 -66
- package/dist/demos-9v5ts7F3.cjs +244 -0
- package/dist/{demos-B0pVQjYC.d.mts → demos-ASsSXYXA.d.mts} +10 -3
- package/dist/demos-Brobjfuc.mjs +215 -0
- package/dist/{demos-BTuzFNsp.d.cts → demos-ByaLZy-Z.d.cts} +10 -3
- package/dist/file-cache.cjs +27 -8
- package/dist/file-cache.d.cts +13 -0
- package/dist/file-cache.d.mts +13 -0
- package/dist/file-cache.mjs +27 -8
- package/dist/gepa/index.cjs +128 -80
- package/dist/gepa/index.d.cts +15 -7
- package/dist/gepa/index.d.mts +15 -7
- package/dist/gepa/index.mjs +101 -55
- package/dist/index.cjs +157 -30
- package/dist/index.d.cts +177 -7
- package/dist/index.d.mts +177 -7
- package/dist/index.mjs +139 -18
- package/dist/{math-COOofUyv.cjs → math-BhlziRPc.cjs} +60 -9
- package/dist/math-Dqme4rYz.mjs +123 -0
- package/dist/mipro/index.cjs +104 -70
- package/dist/mipro/index.d.cts +17 -14
- package/dist/mipro/index.d.mts +17 -14
- package/dist/mipro/index.mjs +90 -58
- package/dist/opro/index.cjs +136 -51
- package/dist/opro/index.d.cts +17 -9
- package/dist/opro/index.d.mts +17 -9
- package/dist/opro/index.mjs +121 -38
- package/dist/{optimizer-B7SpRwl7.d.cts → optimizer-4Zv-Zt2t.d.cts} +90 -5
- package/dist/{optimizer-DqCoth_w.d.mts → optimizer-Ds5mzYjz.d.mts} +90 -5
- package/dist/random-search/index.cjs +99 -49
- package/dist/random-search/index.d.cts +15 -13
- package/dist/random-search/index.d.mts +15 -13
- package/dist/random-search/index.mjs +89 -41
- package/dist/{reflection-Cr_upzU0.d.mts → reflection-CMezGu6u.d.mts} +38 -14
- package/dist/{reflection-CQToe-5B.d.cts → reflection-D0A7eahD.d.cts} +38 -14
- package/dist/reporting-bq007_2z.d.cts +294 -0
- package/dist/reporting-bq007_2z.d.mts +294 -0
- package/dist/simba/index.cjs +216 -83
- package/dist/simba/index.d.cts +53 -13
- package/dist/simba/index.d.mts +53 -13
- package/dist/simba/index.mjs +206 -75
- package/dist/testing.cjs +1 -0
- package/dist/testing.d.cts +5 -3
- package/dist/testing.d.mts +5 -3
- package/dist/testing.mjs +1 -1
- package/dist/{evaluation-OZOp6TB7.cjs → warnings-CWRJF-jA.cjs} +228 -5
- package/dist/{evaluation-BV0nSZVx.mjs → warnings-OxvDi9kN.mjs} +175 -6
- 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 +6 -4
- package/dist/demos-B9BJiNKz.cjs +0 -143
- package/dist/demos-Degx6UmP.mjs +0 -126
- package/dist/math-DhrDmpFS.mjs +0 -78
- package/dist/types-CWv4IQFF.d.cts +0 -129
- package/dist/types-CWv4IQFF.d.mts +0 -129
package/dist/mipro/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { S as createBudget, _ as componentNames, a as instanceRow, b as defaultInstanceId, c as BudgetExhausted, d as measuredMean, f as requireMeasuredMean, g as runFingerprint, i as flushReporters, l as costExhausted, m as assertResumable, 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
|
-
import {
|
|
4
|
-
import { n as
|
|
3
|
+
import { r as mean } from "../math-Dqme4rYz.mjs";
|
|
4
|
+
import { n as harvestFewShotExamples, t as formatDemos } from "../demos-Brobjfuc.mjs";
|
|
5
5
|
import { t as parseProposedText } from "../text--v4Ffbus.mjs";
|
|
6
6
|
import { t as createSeededRng } from "../rng-Dtc5eZ_W.mjs";
|
|
7
7
|
import { t as createEpochShuffledSampler } from "../sampling-CfHt7Gue.mjs";
|
|
@@ -211,10 +211,14 @@ var MiproOptimizer = class {
|
|
|
211
211
|
this.#config = config;
|
|
212
212
|
}
|
|
213
213
|
async optimize(task) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
214
|
+
try {
|
|
215
|
+
return await runMipro({
|
|
216
|
+
config: this.#config,
|
|
217
|
+
task
|
|
218
|
+
});
|
|
219
|
+
} finally {
|
|
220
|
+
await flushReporters(task.reporters ?? []);
|
|
221
|
+
}
|
|
218
222
|
}
|
|
219
223
|
};
|
|
220
224
|
function buildMiproPrompt(args) {
|
|
@@ -273,7 +277,12 @@ function buildDatasetSummaryPrompt(examples) {
|
|
|
273
277
|
async function runMipro(args) {
|
|
274
278
|
const { config, task } = args;
|
|
275
279
|
const { instructionsPerComponent = DEFAULT_INSTRUCTIONS, minibatchSize = DEFAULT_MINIBATCH_SIZE, maxTrials = DEFAULT_MAX_TRIALS, startupTrials, gamma, surrogateSamples, multivariate, fullEvalInterval = DEFAULT_FULL_EVAL_INTERVAL, demoSets = DEFAULT_DEMO_SETS, maxDemos = DEFAULT_MAX_DEMOS, demoMinScore, exemplars = DEFAULT_EXEMPLARS, datasetSummary = true, summaryExamples = DEFAULT_SUMMARY_EXAMPLES, concurrency = 1, seed = 0, buildPrompt = buildMiproPrompt, tips = DEFAULT_TIPS, trackBestOutputs = false, checkpointCache = true } = config;
|
|
276
|
-
const { seedCandidate, trainingSet, validationSet
|
|
280
|
+
const { seedCandidate, trainingSet, validationSet: requestedValidationSet, testSet, adapter, reflect, componentOptions, demoComponents, renderDemo, goldOutput, maxMetricCalls, renderDatum = renderDefault, batchSampler = createEpochShuffledSampler({ minibatchSize }), cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
|
|
281
|
+
const { validationSet, warnings } = resolveValidationSet({
|
|
282
|
+
validationSet: requestedValidationSet,
|
|
283
|
+
trainingSet
|
|
284
|
+
});
|
|
285
|
+
const emit = createEmitter(reporters);
|
|
277
286
|
const deadline = createDeadline({ maxWallClockMs });
|
|
278
287
|
const components = componentNames(seedCandidate);
|
|
279
288
|
if (trainingSet.length === 0) throw new Error("optimize requires a non-empty trainingSet");
|
|
@@ -318,15 +327,16 @@ async function runMipro(args) {
|
|
|
318
327
|
...evaluationCache === void 0 ? {} : { cache: evaluationCache },
|
|
319
328
|
trackOutputs: trackBestOutputs,
|
|
320
329
|
cacheHits: resumeFrom?.cacheHits ?? 0,
|
|
330
|
+
...resumeFrom?.usage === void 0 ? {} : { usage: resumeFrom.usage },
|
|
321
331
|
...signal === void 0 ? {} : { signal },
|
|
322
|
-
onEvaluation: (event) =>
|
|
332
|
+
onEvaluation: (event) => emit({
|
|
323
333
|
type: "evaluation",
|
|
324
334
|
...event
|
|
325
335
|
})
|
|
326
336
|
});
|
|
327
337
|
evaluator.restore(resumeFrom?.cache ?? []);
|
|
328
338
|
if (resumeFrom?.sampler !== void 0) batchSampler.restore?.(resumeFrom.sampler);
|
|
329
|
-
|
|
339
|
+
emit({
|
|
330
340
|
type: "start",
|
|
331
341
|
components,
|
|
332
342
|
validationSetSize: validationSet.length
|
|
@@ -373,20 +383,26 @@ async function runMipro(args) {
|
|
|
373
383
|
for (let index = 0; index < demoSets; index += 1) {
|
|
374
384
|
const affordable = Math.min(trainingSet.length, budget.remaining() - validationSet.length);
|
|
375
385
|
if (affordable < 1) break;
|
|
386
|
+
if (costExhausted({
|
|
387
|
+
usage: evaluator.usage(),
|
|
388
|
+
maxCostUsd
|
|
389
|
+
})) break;
|
|
376
390
|
const requested = demoSets === 1 ? maxDemos : Math.round(1 + index * (maxDemos - 1) / (demoSets - 1));
|
|
377
|
-
const harvest = await
|
|
391
|
+
const harvest = await harvestFewShotExamples({
|
|
378
392
|
adapter,
|
|
379
393
|
candidate: seedCandidate,
|
|
380
394
|
trainingSet,
|
|
381
395
|
...demoMinScore === void 0 ? {} : { minScore: demoMinScore },
|
|
382
396
|
maxDemos: requested,
|
|
383
397
|
maxMetricCalls: affordable,
|
|
398
|
+
...maxCostUsd === void 0 ? {} : { maxCostUsd: maxCostUsd - evaluator.usage().costUsd },
|
|
384
399
|
rng,
|
|
385
400
|
...renderDemo === void 0 ? {} : { renderDemo },
|
|
386
401
|
...signal === void 0 ? {} : { signal }
|
|
387
402
|
});
|
|
388
403
|
bootstrapMetricCalls += harvest.metricCalls;
|
|
389
404
|
budget.reserve(harvest.metricCalls);
|
|
405
|
+
evaluator.absorbUsage(harvest.usage);
|
|
390
406
|
if (harvest.demos.length > 0) blocks.push(formatDemos(harvest.demos, renderDemo === void 0 ? {} : { render: renderDemo }));
|
|
391
407
|
}
|
|
392
408
|
return [.../* @__PURE__ */ new Set([
|
|
@@ -431,7 +447,7 @@ async function runMipro(args) {
|
|
|
431
447
|
});
|
|
432
448
|
menu[name] = [seedCandidate[name], ...drawn.filter((text) => text.length > 0)];
|
|
433
449
|
}
|
|
434
|
-
|
|
450
|
+
emit({
|
|
435
451
|
type: "menu",
|
|
436
452
|
menu,
|
|
437
453
|
reflectionCalls
|
|
@@ -466,6 +482,15 @@ async function runMipro(args) {
|
|
|
466
482
|
phase: "seed"
|
|
467
483
|
});
|
|
468
484
|
if (seedEvaluation !== void 0) fullEvaluations += 1;
|
|
485
|
+
if (seedEvaluation !== void 0) emit({
|
|
486
|
+
type: "candidateAccepted",
|
|
487
|
+
trial: 0,
|
|
488
|
+
candidateId: 0,
|
|
489
|
+
candidate: seedCandidate,
|
|
490
|
+
aggregateScore: seedScore,
|
|
491
|
+
instanceScores: instanceRow(seedEvaluation),
|
|
492
|
+
...trackBestOutputs ? { outputs: seedEvaluation.outputs } : {}
|
|
493
|
+
});
|
|
469
494
|
if (resumeFrom === void 0) surrogateInput.push({
|
|
470
495
|
choices: menuSizes.map(() => 0),
|
|
471
496
|
score: seedScore
|
|
@@ -473,6 +498,7 @@ async function runMipro(args) {
|
|
|
473
498
|
let best = resumeFrom?.best ?? seedCandidate;
|
|
474
499
|
let bestScore = resumeFrom?.bestScore ?? seedScore;
|
|
475
500
|
/** Absent on a resumed run until a sweep wins: outputs are not checkpointed. */
|
|
501
|
+
let acceptedCandidates = resumeFrom?.acceptedCandidates ?? 0;
|
|
476
502
|
let bestOutputs = seedEvaluation?.outputs;
|
|
477
503
|
const readings = new Map(resumeFrom?.readings ?? []);
|
|
478
504
|
const swept = new Set(resumeFrom?.swept ?? []);
|
|
@@ -492,6 +518,8 @@ async function runMipro(args) {
|
|
|
492
518
|
bootstrapMetricCalls,
|
|
493
519
|
metricCalls: budget.spent(),
|
|
494
520
|
cacheHits: evaluator.cacheHits(),
|
|
521
|
+
usage: evaluator.usage(),
|
|
522
|
+
acceptedCandidates,
|
|
495
523
|
rngState: rng.state(),
|
|
496
524
|
observations: [...observations],
|
|
497
525
|
surrogateInput: surrogateInput.map((entry) => ({
|
|
@@ -553,11 +581,15 @@ async function runMipro(args) {
|
|
|
553
581
|
best = candidate;
|
|
554
582
|
bestScore = score;
|
|
555
583
|
bestOutputs = evaluation.outputs;
|
|
556
|
-
|
|
557
|
-
|
|
584
|
+
acceptedCandidates += 1;
|
|
585
|
+
emit({
|
|
586
|
+
type: "candidateAccepted",
|
|
558
587
|
trial,
|
|
559
|
-
|
|
560
|
-
|
|
588
|
+
candidateId: acceptedCandidates,
|
|
589
|
+
candidate,
|
|
590
|
+
aggregateScore: score,
|
|
591
|
+
instanceScores: instanceRow(evaluation),
|
|
592
|
+
...trackBestOutputs ? { outputs: evaluation.outputs } : {}
|
|
561
593
|
});
|
|
562
594
|
}
|
|
563
595
|
return "swept";
|
|
@@ -624,47 +656,44 @@ async function runMipro(args) {
|
|
|
624
656
|
}
|
|
625
657
|
throw err;
|
|
626
658
|
}
|
|
627
|
-
if (minibatchScore
|
|
628
|
-
|
|
629
|
-
|
|
659
|
+
if (minibatchScore !== void 0) {
|
|
660
|
+
surrogateInput.push({
|
|
661
|
+
choices,
|
|
662
|
+
score: minibatchScore
|
|
663
|
+
});
|
|
664
|
+
const key = choices.join(",");
|
|
665
|
+
readings.set(key, [...readings.get(key) ?? [], minibatchScore]);
|
|
666
|
+
const observation = {
|
|
667
|
+
trial,
|
|
668
|
+
choices,
|
|
669
|
+
minibatchScore,
|
|
670
|
+
promoted: false
|
|
671
|
+
};
|
|
672
|
+
observations.push(observation);
|
|
673
|
+
emit({
|
|
674
|
+
type: "trial",
|
|
675
|
+
trial,
|
|
676
|
+
choices,
|
|
677
|
+
minibatchScore,
|
|
678
|
+
promoted: false
|
|
679
|
+
});
|
|
630
680
|
}
|
|
631
|
-
surrogateInput.push({
|
|
632
|
-
choices,
|
|
633
|
-
score: minibatchScore
|
|
634
|
-
});
|
|
635
|
-
const key = choices.join(",");
|
|
636
|
-
readings.set(key, [...readings.get(key) ?? [], minibatchScore]);
|
|
637
|
-
const observation = {
|
|
638
|
-
trial,
|
|
639
|
-
choices,
|
|
640
|
-
minibatchScore,
|
|
641
|
-
promoted: false
|
|
642
|
-
};
|
|
643
|
-
observations.push(observation);
|
|
644
|
-
onEvent?.({
|
|
645
|
-
type: "trial",
|
|
646
|
-
trial,
|
|
647
|
-
choices,
|
|
648
|
-
minibatchScore,
|
|
649
|
-
promoted: false
|
|
650
|
-
});
|
|
651
681
|
trial += 1;
|
|
652
|
-
|
|
682
|
+
let cadenceStop;
|
|
653
683
|
if (trial % fullEvalInterval === 0) {
|
|
654
684
|
const outcome = await sweepBestUnswept();
|
|
655
|
-
if (outcome === "budgetExhausted" || outcome === "aborted")
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
}
|
|
685
|
+
if (outcome === "budgetExhausted" || outcome === "aborted") cadenceStop = outcome;
|
|
686
|
+
if (outcome === "unaffordable") cadenceStop = "budgetExhausted";
|
|
687
|
+
}
|
|
688
|
+
await checkpoint();
|
|
689
|
+
if (cadenceStop !== void 0) {
|
|
690
|
+
stopReason = cadenceStop;
|
|
691
|
+
break;
|
|
663
692
|
}
|
|
664
693
|
}
|
|
665
694
|
if (stopReason === "maxTrials" && !signal?.aborted) await sweepBestUnswept();
|
|
666
695
|
if (signal?.aborted) stopReason = "aborted";
|
|
667
|
-
const
|
|
696
|
+
const heldOut = testSet === void 0 ? void 0 : await evaluator.evaluate({
|
|
668
697
|
candidate: best,
|
|
669
698
|
batch: testSet,
|
|
670
699
|
ids: testIds,
|
|
@@ -673,13 +702,18 @@ async function runMipro(args) {
|
|
|
673
702
|
candidateId: null,
|
|
674
703
|
iteration: trial,
|
|
675
704
|
charge: false
|
|
676
|
-
})
|
|
677
|
-
|
|
705
|
+
});
|
|
706
|
+
const testScore = heldOut === void 0 ? void 0 : measuredMean(heldOut);
|
|
707
|
+
emit({
|
|
678
708
|
type: "finish",
|
|
679
709
|
reason: stopReason,
|
|
710
|
+
warnings,
|
|
711
|
+
bestCandidateId: acceptedCandidates,
|
|
680
712
|
bestScore,
|
|
681
713
|
metricCalls: budget.spent(),
|
|
682
|
-
...testScore === void 0 ? {} : { testScore }
|
|
714
|
+
...testScore === void 0 ? {} : { testScore },
|
|
715
|
+
...heldOut === void 0 ? {} : { testInstanceScores: instanceRow(heldOut) },
|
|
716
|
+
...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
|
|
683
717
|
});
|
|
684
718
|
return {
|
|
685
719
|
snapshot: takeSnapshot(),
|
|
@@ -690,7 +724,8 @@ async function runMipro(args) {
|
|
|
690
724
|
...trackBestOutputs ? { bestOutputs } : {},
|
|
691
725
|
...testScore === void 0 ? {} : {
|
|
692
726
|
testScore,
|
|
693
|
-
testMetricCalls: evaluator.unchargedCalls()
|
|
727
|
+
testMetricCalls: evaluator.unchargedCalls(),
|
|
728
|
+
testUsage: evaluator.unchargedUsage()
|
|
694
729
|
},
|
|
695
730
|
trials: trial,
|
|
696
731
|
menu,
|
|
@@ -700,6 +735,7 @@ async function runMipro(args) {
|
|
|
700
735
|
metricCalls: budget.spent(),
|
|
701
736
|
reflectionCalls,
|
|
702
737
|
cacheHits: evaluator.cacheHits(),
|
|
738
|
+
warnings,
|
|
703
739
|
stopReason
|
|
704
740
|
};
|
|
705
741
|
}
|
|
@@ -728,9 +764,5 @@ function assertConfig(config) {
|
|
|
728
764
|
if (config.gamma !== void 0 && (!Number.isFinite(config.gamma) || config.gamma <= 0 || config.gamma > 1)) throw new Error(`gamma must be within (0, 1], received ${config.gamma}`);
|
|
729
765
|
if (config.tips !== void 0 && config.tips.length === 0) throw new Error("tips must not be empty");
|
|
730
766
|
}
|
|
731
|
-
function defaultInstanceId(args) {
|
|
732
|
-
const hash = stableHash(args.datum);
|
|
733
|
-
return hash === "" ? String(args.index) : hash;
|
|
734
|
-
}
|
|
735
767
|
//#endregion
|
|
736
|
-
export { MiproOptimizer, buildMiproPrompt, proposeConfiguration };
|
|
768
|
+
export { MiproOptimizer, buildMiproPrompt, isCandidateAccepted, isRunFinished, proposeConfiguration };
|
package/dist/opro/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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_text = require("../text-CK_HB3su.cjs");
|
|
5
5
|
const require_rng = require("../rng-DbA_rPIo.cjs");
|
|
@@ -43,10 +43,14 @@ var OproOptimizer = class {
|
|
|
43
43
|
this.#config = config;
|
|
44
44
|
}
|
|
45
45
|
async optimize(task) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
try {
|
|
47
|
+
return await runOpro({
|
|
48
|
+
config: this.#config,
|
|
49
|
+
task
|
|
50
|
+
});
|
|
51
|
+
} finally {
|
|
52
|
+
await require_warnings.flushReporters(task.reporters ?? []);
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
};
|
|
52
56
|
/**
|
|
@@ -91,9 +95,14 @@ function buildOproPrompt(args) {
|
|
|
91
95
|
async function runOpro(args) {
|
|
92
96
|
const { config, task } = args;
|
|
93
97
|
const { proposalsPerRound = DEFAULT_PROPOSALS_PER_ROUND, concurrency = 1, maxRounds = Number.POSITIVE_INFINITY, maxReflectionCalls = Number.POSITIVE_INFINITY, seed = 0, historySize = DEFAULT_HISTORY_SIZE, exemplars = DEFAULT_EXEMPLARS, scoringSetSize, fullEvalInterval = DEFAULT_FULL_EVAL_INTERVAL, scoreScale = DEFAULT_SCORE_SCALE, buildPrompt = buildOproPrompt, trackBestOutputs = false, checkpointCache = true } = config;
|
|
94
|
-
const { seedCandidate, trainingSet, validationSet
|
|
95
|
-
const
|
|
96
|
-
|
|
98
|
+
const { seedCandidate, trainingSet, validationSet: requestedValidationSet, testSet, adapter, reflect, maxMetricCalls, renderDatum = renderDefault, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = require_warnings.defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
|
|
99
|
+
const { validationSet, warnings } = require_warnings.resolveValidationSet({
|
|
100
|
+
validationSet: requestedValidationSet,
|
|
101
|
+
trainingSet
|
|
102
|
+
});
|
|
103
|
+
const emit = require_warnings.createEmitter(reporters);
|
|
104
|
+
const deadline = require_warnings.createDeadline({ maxWallClockMs });
|
|
105
|
+
const components = require_warnings.componentNames(seedCandidate);
|
|
97
106
|
if (trainingSet.length === 0) throw new Error("optimize requires a non-empty trainingSet");
|
|
98
107
|
if (validationSet.length === 0) throw new Error("optimize requires a non-empty validationSet");
|
|
99
108
|
if (components.length === 0) throw new Error("optimize requires a seed candidate with at least one component");
|
|
@@ -106,7 +115,7 @@ async function runOpro(args) {
|
|
|
106
115
|
datum,
|
|
107
116
|
index
|
|
108
117
|
})) ?? [];
|
|
109
|
-
const fingerprint =
|
|
118
|
+
const fingerprint = require_warnings.runFingerprint({
|
|
110
119
|
seedCandidate,
|
|
111
120
|
trainingIds: trainingSet.map((datum, index) => instanceId({
|
|
112
121
|
datum,
|
|
@@ -116,17 +125,17 @@ async function runOpro(args) {
|
|
|
116
125
|
seed,
|
|
117
126
|
...cacheNamespace === void 0 ? {} : { cacheNamespace }
|
|
118
127
|
});
|
|
119
|
-
|
|
128
|
+
require_warnings.assertResumable({
|
|
120
129
|
fingerprint,
|
|
121
130
|
...resumeFrom === void 0 ? {} : { snapshot: resumeFrom }
|
|
122
131
|
});
|
|
123
132
|
const rng = require_rng.createSeededRng(seed, resumeFrom?.rngState);
|
|
124
|
-
const budget =
|
|
133
|
+
const budget = require_warnings.createBudget({
|
|
125
134
|
maxMetricCalls,
|
|
126
135
|
spent: resumeFrom?.metricCalls ?? 0
|
|
127
136
|
});
|
|
128
|
-
const evaluationCache = cache === false ? void 0 : cache ??
|
|
129
|
-
const evaluator =
|
|
137
|
+
const evaluationCache = cache === false ? void 0 : cache ?? require_warnings.createMemoryCache();
|
|
138
|
+
const evaluator = require_warnings.createEvaluator({
|
|
130
139
|
adapter,
|
|
131
140
|
budget,
|
|
132
141
|
...retry === void 0 ? {} : { retry },
|
|
@@ -134,8 +143,9 @@ async function runOpro(args) {
|
|
|
134
143
|
...evaluationCache === void 0 ? {} : { cache: evaluationCache },
|
|
135
144
|
trackOutputs: trackBestOutputs,
|
|
136
145
|
cacheHits: resumeFrom?.cacheHits ?? 0,
|
|
146
|
+
...resumeFrom?.usage === void 0 ? {} : { usage: resumeFrom.usage },
|
|
137
147
|
...signal === void 0 ? {} : { signal },
|
|
138
|
-
onEvaluation: (event) =>
|
|
148
|
+
onEvaluation: (event) => emit({
|
|
139
149
|
type: "evaluation",
|
|
140
150
|
...event
|
|
141
151
|
})
|
|
@@ -154,13 +164,13 @@ async function runOpro(args) {
|
|
|
154
164
|
function contextOf(candidate, component) {
|
|
155
165
|
const rest = {};
|
|
156
166
|
for (const name of components) if (name !== component) rest[name] = candidate[name];
|
|
157
|
-
return
|
|
167
|
+
return require_warnings.stableHash(rest);
|
|
158
168
|
}
|
|
159
169
|
const trajectory = [];
|
|
160
170
|
let round = resumeFrom?.round ?? 0;
|
|
161
171
|
let reflectionCalls = resumeFrom?.reflectionCalls ?? 0;
|
|
162
172
|
let stopReason = "maxRounds";
|
|
163
|
-
|
|
173
|
+
emit({
|
|
164
174
|
type: "start",
|
|
165
175
|
components,
|
|
166
176
|
validationSetSize: validationSet.length
|
|
@@ -193,19 +203,41 @@ async function runOpro(args) {
|
|
|
193
203
|
iteration: round
|
|
194
204
|
});
|
|
195
205
|
}
|
|
206
|
+
/** What screening a candidate would cost, in rollouts nothing has cached. */
|
|
207
|
+
function screenCost(candidate) {
|
|
208
|
+
return scoringSet === void 0 ? evaluator.countUncached({
|
|
209
|
+
candidate,
|
|
210
|
+
ids: validationIds,
|
|
211
|
+
split: "val"
|
|
212
|
+
}) : evaluator.countUncached({
|
|
213
|
+
candidate,
|
|
214
|
+
ids: scoringIds,
|
|
215
|
+
split: "train"
|
|
216
|
+
});
|
|
217
|
+
}
|
|
196
218
|
const seedEvaluation = resumeFrom === void 0 ? await sweep(seedCandidate, "seed") : void 0;
|
|
197
|
-
const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore :
|
|
219
|
+
const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore : require_warnings.requireMeasuredMean({
|
|
198
220
|
batch: seedEvaluation,
|
|
199
221
|
phase: "seed"
|
|
200
222
|
});
|
|
223
|
+
if (seedEvaluation !== void 0) emit({
|
|
224
|
+
type: "candidateAccepted",
|
|
225
|
+
round: 0,
|
|
226
|
+
candidateId: 0,
|
|
227
|
+
candidate: seedCandidate,
|
|
228
|
+
aggregateScore: seedScore,
|
|
229
|
+
instanceScores: require_warnings.instanceRow(seedEvaluation),
|
|
230
|
+
...trackBestOutputs ? { outputs: seedEvaluation.outputs } : {}
|
|
231
|
+
});
|
|
201
232
|
let best = resumeFrom?.best ?? seedCandidate;
|
|
202
233
|
let bestScore = resumeFrom?.bestScore ?? seedScore;
|
|
203
234
|
/** Absent on a resumed run until a sweep wins: outputs are not checkpointed. */
|
|
235
|
+
let acceptedCandidates = resumeFrom?.acceptedCandidates ?? 0;
|
|
204
236
|
let bestOutputs = seedEvaluation?.outputs;
|
|
205
237
|
let reported = resumeFrom?.reported ?? seedCandidate;
|
|
206
238
|
let lastSwept = resumeFrom === void 0 ? seedCandidate : resumeFrom.incumbentSwept ? best : {};
|
|
207
239
|
let bestSearchScore = resumeFrom?.bestSearchScore ?? seedScore;
|
|
208
|
-
if (resumeFrom === void 0 && scoringSet !== void 0) bestSearchScore =
|
|
240
|
+
if (resumeFrom === void 0 && scoringSet !== void 0) bestSearchScore = require_warnings.requireMeasuredMean({
|
|
209
241
|
batch: await screen(seedCandidate, "seed"),
|
|
210
242
|
phase: "seed"
|
|
211
243
|
});
|
|
@@ -215,19 +247,42 @@ async function runOpro(args) {
|
|
|
215
247
|
* what gets reported is the best candidate a full sweep has actually seen —
|
|
216
248
|
* never a subset number wearing a validation set label.
|
|
217
249
|
*/
|
|
250
|
+
/**
|
|
251
|
+
* The incumbent moved and a full sweep measured it. Emitted from the two
|
|
252
|
+
* places that can be true — a screening run with no scoring set, where the
|
|
253
|
+
* attempt's own evaluation is the sweep, and the cadence that confirms an
|
|
254
|
+
* incumbent later — because a payload assembled twice is one that drifts.
|
|
255
|
+
*/
|
|
256
|
+
function emitAccepted(args) {
|
|
257
|
+
acceptedCandidates += 1;
|
|
258
|
+
emit({
|
|
259
|
+
type: "candidateAccepted",
|
|
260
|
+
round,
|
|
261
|
+
candidateId: acceptedCandidates,
|
|
262
|
+
candidate: args.candidate,
|
|
263
|
+
aggregateScore: args.score,
|
|
264
|
+
instanceScores: require_warnings.instanceRow(args.evaluation),
|
|
265
|
+
...trackBestOutputs ? { outputs: args.evaluation.outputs } : {}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
218
268
|
async function refreshIncumbent() {
|
|
219
269
|
if (best === lastSwept || !budget.canAfford(validationSet.length)) return "ok";
|
|
220
270
|
try {
|
|
221
271
|
const evaluation = await sweep(best, "validation");
|
|
222
|
-
const full =
|
|
272
|
+
const full = require_warnings.measuredMean(evaluation);
|
|
223
273
|
lastSwept = best;
|
|
224
274
|
if (full !== void 0 && full > bestScore) {
|
|
225
275
|
reported = best;
|
|
226
276
|
bestScore = full;
|
|
227
277
|
bestOutputs = evaluation.outputs;
|
|
278
|
+
emitAccepted({
|
|
279
|
+
candidate: best,
|
|
280
|
+
evaluation,
|
|
281
|
+
score: full
|
|
282
|
+
});
|
|
228
283
|
}
|
|
229
284
|
} catch (err) {
|
|
230
|
-
if (err instanceof
|
|
285
|
+
if (err instanceof require_warnings.BudgetExhausted || signal?.aborted) return "stop";
|
|
231
286
|
throw err;
|
|
232
287
|
}
|
|
233
288
|
return "ok";
|
|
@@ -260,6 +315,8 @@ async function runOpro(args) {
|
|
|
260
315
|
reflectionCalls,
|
|
261
316
|
metricCalls: budget.spent(),
|
|
262
317
|
cacheHits: evaluator.cacheHits(),
|
|
318
|
+
usage: evaluator.usage(),
|
|
319
|
+
acceptedCandidates,
|
|
263
320
|
rngState: rng.state(),
|
|
264
321
|
histories: Object.fromEntries([...histories].map(([name, attempts]) => [name, [...attempts]])),
|
|
265
322
|
...scoringIndices === void 0 ? {} : { scoringIndices },
|
|
@@ -281,7 +338,7 @@ async function runOpro(args) {
|
|
|
281
338
|
stopReason = "proposalsExhausted";
|
|
282
339
|
break;
|
|
283
340
|
}
|
|
284
|
-
if (
|
|
341
|
+
if (require_warnings.costExhausted({
|
|
285
342
|
usage: evaluator.usage(),
|
|
286
343
|
maxCostUsd
|
|
287
344
|
})) {
|
|
@@ -304,7 +361,7 @@ async function runOpro(args) {
|
|
|
304
361
|
const history = histories.get(component);
|
|
305
362
|
const context = contextOf(best, component);
|
|
306
363
|
const comparable = history.filter((attempt) => attempt.context === context);
|
|
307
|
-
|
|
364
|
+
emit({
|
|
308
365
|
type: "roundStart",
|
|
309
366
|
round,
|
|
310
367
|
component,
|
|
@@ -333,26 +390,44 @@ async function runOpro(args) {
|
|
|
333
390
|
const unique = [...new Set(drawn)].filter((text) => text.length > 0 && !tried.has(text));
|
|
334
391
|
barrenRounds = unique.length === 0 ? barrenRounds + 1 : 0;
|
|
335
392
|
let roundStop;
|
|
393
|
+
const scheduled = [];
|
|
394
|
+
let owed = 0;
|
|
336
395
|
for (const text of unique) {
|
|
337
396
|
const candidate = {
|
|
338
397
|
...best,
|
|
339
398
|
[component]: text
|
|
340
399
|
};
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
400
|
+
const cost = screenCost(candidate);
|
|
401
|
+
if (!budget.canAfford(owed + cost)) {
|
|
402
|
+
roundStop = "budgetExhausted";
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
owed += cost;
|
|
406
|
+
scheduled.push(candidate);
|
|
407
|
+
}
|
|
408
|
+
const screened = await require_concurrency.mapWithConcurrency({
|
|
409
|
+
items: scheduled,
|
|
410
|
+
limit: concurrency,
|
|
411
|
+
task: async (candidate) => {
|
|
412
|
+
if (signal?.aborted) return { stop: "aborted" };
|
|
413
|
+
try {
|
|
414
|
+
return { evaluation: await screen(candidate, "validation") };
|
|
415
|
+
} catch (err) {
|
|
416
|
+
if (err instanceof require_warnings.BudgetExhausted) return { stop: "budgetExhausted" };
|
|
417
|
+
if (signal?.aborted) return { stop: "aborted" };
|
|
418
|
+
throw err;
|
|
352
419
|
}
|
|
353
|
-
throw err;
|
|
354
420
|
}
|
|
355
|
-
|
|
421
|
+
});
|
|
422
|
+
for (const [index, outcome] of screened.entries()) {
|
|
423
|
+
if (outcome.stop !== void 0) {
|
|
424
|
+
roundStop = outcome.stop;
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
const candidate = scheduled[index];
|
|
428
|
+
const text = candidate[component];
|
|
429
|
+
const evaluation = outcome.evaluation;
|
|
430
|
+
const score = require_warnings.measuredMean(evaluation);
|
|
356
431
|
if (score === void 0) continue;
|
|
357
432
|
const accepted = score > bestSearchScore;
|
|
358
433
|
history.push({
|
|
@@ -366,7 +441,7 @@ async function runOpro(args) {
|
|
|
366
441
|
candidate,
|
|
367
442
|
score
|
|
368
443
|
});
|
|
369
|
-
|
|
444
|
+
emit({
|
|
370
445
|
type: "attempt",
|
|
371
446
|
round,
|
|
372
447
|
component,
|
|
@@ -381,6 +456,11 @@ async function runOpro(args) {
|
|
|
381
456
|
lastSwept = candidate;
|
|
382
457
|
bestScore = score;
|
|
383
458
|
bestOutputs = evaluation.outputs;
|
|
459
|
+
emitAccepted({
|
|
460
|
+
candidate,
|
|
461
|
+
evaluation,
|
|
462
|
+
score
|
|
463
|
+
});
|
|
384
464
|
}
|
|
385
465
|
const scaled = scaleScore(score, scoreScale);
|
|
386
466
|
for (const name of components) {
|
|
@@ -394,22 +474,22 @@ async function runOpro(args) {
|
|
|
394
474
|
}
|
|
395
475
|
}
|
|
396
476
|
round += 1;
|
|
477
|
+
let cadenceStop;
|
|
478
|
+
if (roundStop === void 0 && scoringSet !== void 0 && round % fullEvalInterval === 0 && await refreshIncumbent() === "stop") cadenceStop = signal?.aborted ? "aborted" : "budgetExhausted";
|
|
397
479
|
await checkpoint();
|
|
398
480
|
if (roundStop !== void 0) {
|
|
399
481
|
stopReason = roundStop;
|
|
400
482
|
break;
|
|
401
483
|
}
|
|
402
|
-
if (
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
break;
|
|
406
|
-
}
|
|
484
|
+
if (cadenceStop !== void 0) {
|
|
485
|
+
stopReason = cadenceStop;
|
|
486
|
+
break;
|
|
407
487
|
}
|
|
408
488
|
}
|
|
409
489
|
if (scoringSet !== void 0 && !signal?.aborted) await refreshIncumbent();
|
|
410
490
|
if (signal?.aborted) stopReason = "aborted";
|
|
411
|
-
const
|
|
412
|
-
candidate:
|
|
491
|
+
const heldOut = testSet === void 0 ? void 0 : await evaluator.evaluate({
|
|
492
|
+
candidate: reported,
|
|
413
493
|
batch: testSet,
|
|
414
494
|
ids: testIds,
|
|
415
495
|
split: "test",
|
|
@@ -417,13 +497,18 @@ async function runOpro(args) {
|
|
|
417
497
|
candidateId: null,
|
|
418
498
|
iteration: round,
|
|
419
499
|
charge: false
|
|
420
|
-
})
|
|
421
|
-
|
|
500
|
+
});
|
|
501
|
+
const testScore = heldOut === void 0 ? void 0 : require_warnings.measuredMean(heldOut);
|
|
502
|
+
emit({
|
|
422
503
|
type: "finish",
|
|
423
504
|
reason: stopReason,
|
|
505
|
+
warnings,
|
|
506
|
+
bestCandidateId: acceptedCandidates,
|
|
424
507
|
bestScore,
|
|
425
508
|
metricCalls: budget.spent(),
|
|
426
|
-
...testScore === void 0 ? {} : { testScore }
|
|
509
|
+
...testScore === void 0 ? {} : { testScore },
|
|
510
|
+
...heldOut === void 0 ? {} : { testInstanceScores: require_warnings.instanceRow(heldOut) },
|
|
511
|
+
...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
|
|
427
512
|
});
|
|
428
513
|
return {
|
|
429
514
|
snapshot: takeSnapshot(),
|
|
@@ -434,13 +519,15 @@ async function runOpro(args) {
|
|
|
434
519
|
...trackBestOutputs ? { bestOutputs } : {},
|
|
435
520
|
...testScore === void 0 ? {} : {
|
|
436
521
|
testScore,
|
|
437
|
-
testMetricCalls: evaluator.unchargedCalls()
|
|
522
|
+
testMetricCalls: evaluator.unchargedCalls(),
|
|
523
|
+
testUsage: evaluator.unchargedUsage()
|
|
438
524
|
},
|
|
439
525
|
rounds: round,
|
|
440
526
|
trajectory,
|
|
441
527
|
metricCalls: budget.spent(),
|
|
442
528
|
reflectionCalls,
|
|
443
529
|
cacheHits: evaluator.cacheHits(),
|
|
530
|
+
warnings,
|
|
444
531
|
stopReason
|
|
445
532
|
};
|
|
446
533
|
}
|
|
@@ -478,10 +565,8 @@ function assertConfig(config) {
|
|
|
478
565
|
for (const [name, value] of positive) if (value !== void 0 && (!Number.isInteger(value) || value < 1)) throw new Error(`${name} must be a positive integer, received ${value}`);
|
|
479
566
|
if (config.exemplars !== void 0 && (!Number.isInteger(config.exemplars) || config.exemplars < 0)) throw new Error(`exemplars must be a non-negative integer, received ${config.exemplars}`);
|
|
480
567
|
}
|
|
481
|
-
function defaultInstanceId(args) {
|
|
482
|
-
const hash = require_evaluation.stableHash(args.datum);
|
|
483
|
-
return hash === "" ? String(args.index) : hash;
|
|
484
|
-
}
|
|
485
568
|
//#endregion
|
|
486
569
|
exports.OproOptimizer = OproOptimizer;
|
|
487
570
|
exports.buildOproPrompt = buildOproPrompt;
|
|
571
|
+
exports.isCandidateAccepted = require_warnings.isCandidateAccepted;
|
|
572
|
+
exports.isRunFinished = require_warnings.isRunFinished;
|