textopt 0.0.0 → 0.1.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 +44 -22
- package/dist/bootstrap-search/index.cjs +153 -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 +144 -66
- package/dist/{demos-B0pVQjYC.d.mts → demos-1b7JiUue.d.mts} +10 -3
- package/dist/{demos-BTuzFNsp.d.cts → demos-CU9dy2oT.d.cts} +10 -3
- package/dist/demos-D2o0qSSo.cjs +244 -0
- package/dist/demos-DE2oxNWX.mjs +215 -0
- package/dist/file-cache.cjs +11 -3
- package/dist/file-cache.mjs +11 -3
- package/dist/gepa/index.cjs +76 -71
- package/dist/gepa/index.d.cts +12 -6
- package/dist/gepa/index.d.mts +12 -6
- package/dist/gepa/index.mjs +49 -46
- package/dist/index.cjs +129 -27
- package/dist/index.d.cts +145 -7
- package/dist/index.d.mts +145 -7
- package/dist/index.mjs +113 -15
- package/dist/{math-COOofUyv.cjs → math-BhlziRPc.cjs} +60 -9
- package/dist/math-Dqme4rYz.mjs +123 -0
- package/dist/mipro/index.cjs +98 -70
- package/dist/mipro/index.d.cts +17 -14
- package/dist/mipro/index.d.mts +17 -14
- package/dist/mipro/index.mjs +84 -58
- package/dist/opro/index.cjs +130 -51
- package/dist/opro/index.d.cts +17 -9
- package/dist/opro/index.d.mts +17 -9
- package/dist/opro/index.mjs +115 -38
- package/dist/{optimizer-B7SpRwl7.d.cts → optimizer-Bh5DPRMH.d.cts} +50 -4
- package/dist/{optimizer-DqCoth_w.d.mts → optimizer-Ck6-e_8o.d.mts} +50 -4
- package/dist/random-search/index.cjs +93 -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 +83 -41
- package/dist/{reflection-CQToe-5B.d.cts → reflection-Dt3QrXhM.d.cts} +7 -11
- package/dist/{reflection-Cr_upzU0.d.mts → reflection-LRaAZP4e.d.mts} +7 -11
- package/dist/{evaluation-OZOp6TB7.cjs → reporting-CNHzbJC-.cjs} +165 -5
- package/dist/reporting-DQbAohc9.d.cts +240 -0
- package/dist/reporting-DQbAohc9.d.mts +240 -0
- package/dist/{evaluation-BV0nSZVx.mjs → reporting-DY-DC4HG.mjs} +124 -6
- package/dist/simba/index.cjs +210 -83
- package/dist/simba/index.d.cts +32 -11
- package/dist/simba/index.d.mts +32 -11
- package/dist/simba/index.mjs +200 -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/package.json +4 -3
- 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 { _ as createMemoryCache, a as isRunFinished, b as createBudget, c as createEvaluator, d as createDeadline, f as assertResumable, h as componentNames, i as isCandidateAccepted, l as measuredMean, m as runFingerprint, n as flushReporters, o as BudgetExhausted, r as instanceRow, s as costExhausted, t as createEmitter, u as requireMeasuredMean, v as defaultInstanceId } from "../reporting-DY-DC4HG.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-DE2oxNWX.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,8 @@ 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 = trainingSet, testSet, adapter, reflect, componentOptions, demoComponents, renderDemo, goldOutput, maxMetricCalls, renderDatum = renderDefault, batchSampler = createEpochShuffledSampler({ minibatchSize }), cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId,
|
|
280
|
+
const { seedCandidate, trainingSet, validationSet = trainingSet, 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 emit = createEmitter(reporters);
|
|
277
282
|
const deadline = createDeadline({ maxWallClockMs });
|
|
278
283
|
const components = componentNames(seedCandidate);
|
|
279
284
|
if (trainingSet.length === 0) throw new Error("optimize requires a non-empty trainingSet");
|
|
@@ -318,15 +323,16 @@ async function runMipro(args) {
|
|
|
318
323
|
...evaluationCache === void 0 ? {} : { cache: evaluationCache },
|
|
319
324
|
trackOutputs: trackBestOutputs,
|
|
320
325
|
cacheHits: resumeFrom?.cacheHits ?? 0,
|
|
326
|
+
...resumeFrom?.usage === void 0 ? {} : { usage: resumeFrom.usage },
|
|
321
327
|
...signal === void 0 ? {} : { signal },
|
|
322
|
-
onEvaluation: (event) =>
|
|
328
|
+
onEvaluation: (event) => emit({
|
|
323
329
|
type: "evaluation",
|
|
324
330
|
...event
|
|
325
331
|
})
|
|
326
332
|
});
|
|
327
333
|
evaluator.restore(resumeFrom?.cache ?? []);
|
|
328
334
|
if (resumeFrom?.sampler !== void 0) batchSampler.restore?.(resumeFrom.sampler);
|
|
329
|
-
|
|
335
|
+
emit({
|
|
330
336
|
type: "start",
|
|
331
337
|
components,
|
|
332
338
|
validationSetSize: validationSet.length
|
|
@@ -373,20 +379,26 @@ async function runMipro(args) {
|
|
|
373
379
|
for (let index = 0; index < demoSets; index += 1) {
|
|
374
380
|
const affordable = Math.min(trainingSet.length, budget.remaining() - validationSet.length);
|
|
375
381
|
if (affordable < 1) break;
|
|
382
|
+
if (costExhausted({
|
|
383
|
+
usage: evaluator.usage(),
|
|
384
|
+
maxCostUsd
|
|
385
|
+
})) break;
|
|
376
386
|
const requested = demoSets === 1 ? maxDemos : Math.round(1 + index * (maxDemos - 1) / (demoSets - 1));
|
|
377
|
-
const harvest = await
|
|
387
|
+
const harvest = await harvestFewShotExamples({
|
|
378
388
|
adapter,
|
|
379
389
|
candidate: seedCandidate,
|
|
380
390
|
trainingSet,
|
|
381
391
|
...demoMinScore === void 0 ? {} : { minScore: demoMinScore },
|
|
382
392
|
maxDemos: requested,
|
|
383
393
|
maxMetricCalls: affordable,
|
|
394
|
+
...maxCostUsd === void 0 ? {} : { maxCostUsd: maxCostUsd - evaluator.usage().costUsd },
|
|
384
395
|
rng,
|
|
385
396
|
...renderDemo === void 0 ? {} : { renderDemo },
|
|
386
397
|
...signal === void 0 ? {} : { signal }
|
|
387
398
|
});
|
|
388
399
|
bootstrapMetricCalls += harvest.metricCalls;
|
|
389
400
|
budget.reserve(harvest.metricCalls);
|
|
401
|
+
evaluator.absorbUsage(harvest.usage);
|
|
390
402
|
if (harvest.demos.length > 0) blocks.push(formatDemos(harvest.demos, renderDemo === void 0 ? {} : { render: renderDemo }));
|
|
391
403
|
}
|
|
392
404
|
return [.../* @__PURE__ */ new Set([
|
|
@@ -431,7 +443,7 @@ async function runMipro(args) {
|
|
|
431
443
|
});
|
|
432
444
|
menu[name] = [seedCandidate[name], ...drawn.filter((text) => text.length > 0)];
|
|
433
445
|
}
|
|
434
|
-
|
|
446
|
+
emit({
|
|
435
447
|
type: "menu",
|
|
436
448
|
menu,
|
|
437
449
|
reflectionCalls
|
|
@@ -466,6 +478,15 @@ async function runMipro(args) {
|
|
|
466
478
|
phase: "seed"
|
|
467
479
|
});
|
|
468
480
|
if (seedEvaluation !== void 0) fullEvaluations += 1;
|
|
481
|
+
if (seedEvaluation !== void 0) emit({
|
|
482
|
+
type: "candidateAccepted",
|
|
483
|
+
trial: 0,
|
|
484
|
+
candidateId: 0,
|
|
485
|
+
candidate: seedCandidate,
|
|
486
|
+
aggregateScore: seedScore,
|
|
487
|
+
instanceScores: instanceRow(seedEvaluation),
|
|
488
|
+
...trackBestOutputs ? { outputs: seedEvaluation.outputs } : {}
|
|
489
|
+
});
|
|
469
490
|
if (resumeFrom === void 0) surrogateInput.push({
|
|
470
491
|
choices: menuSizes.map(() => 0),
|
|
471
492
|
score: seedScore
|
|
@@ -473,6 +494,7 @@ async function runMipro(args) {
|
|
|
473
494
|
let best = resumeFrom?.best ?? seedCandidate;
|
|
474
495
|
let bestScore = resumeFrom?.bestScore ?? seedScore;
|
|
475
496
|
/** Absent on a resumed run until a sweep wins: outputs are not checkpointed. */
|
|
497
|
+
let acceptedCandidates = resumeFrom?.acceptedCandidates ?? 0;
|
|
476
498
|
let bestOutputs = seedEvaluation?.outputs;
|
|
477
499
|
const readings = new Map(resumeFrom?.readings ?? []);
|
|
478
500
|
const swept = new Set(resumeFrom?.swept ?? []);
|
|
@@ -492,6 +514,8 @@ async function runMipro(args) {
|
|
|
492
514
|
bootstrapMetricCalls,
|
|
493
515
|
metricCalls: budget.spent(),
|
|
494
516
|
cacheHits: evaluator.cacheHits(),
|
|
517
|
+
usage: evaluator.usage(),
|
|
518
|
+
acceptedCandidates,
|
|
495
519
|
rngState: rng.state(),
|
|
496
520
|
observations: [...observations],
|
|
497
521
|
surrogateInput: surrogateInput.map((entry) => ({
|
|
@@ -553,11 +577,15 @@ async function runMipro(args) {
|
|
|
553
577
|
best = candidate;
|
|
554
578
|
bestScore = score;
|
|
555
579
|
bestOutputs = evaluation.outputs;
|
|
556
|
-
|
|
557
|
-
|
|
580
|
+
acceptedCandidates += 1;
|
|
581
|
+
emit({
|
|
582
|
+
type: "candidateAccepted",
|
|
558
583
|
trial,
|
|
559
|
-
|
|
560
|
-
|
|
584
|
+
candidateId: acceptedCandidates,
|
|
585
|
+
candidate,
|
|
586
|
+
aggregateScore: score,
|
|
587
|
+
instanceScores: instanceRow(evaluation),
|
|
588
|
+
...trackBestOutputs ? { outputs: evaluation.outputs } : {}
|
|
561
589
|
});
|
|
562
590
|
}
|
|
563
591
|
return "swept";
|
|
@@ -624,47 +652,44 @@ async function runMipro(args) {
|
|
|
624
652
|
}
|
|
625
653
|
throw err;
|
|
626
654
|
}
|
|
627
|
-
if (minibatchScore
|
|
628
|
-
|
|
629
|
-
|
|
655
|
+
if (minibatchScore !== void 0) {
|
|
656
|
+
surrogateInput.push({
|
|
657
|
+
choices,
|
|
658
|
+
score: minibatchScore
|
|
659
|
+
});
|
|
660
|
+
const key = choices.join(",");
|
|
661
|
+
readings.set(key, [...readings.get(key) ?? [], minibatchScore]);
|
|
662
|
+
const observation = {
|
|
663
|
+
trial,
|
|
664
|
+
choices,
|
|
665
|
+
minibatchScore,
|
|
666
|
+
promoted: false
|
|
667
|
+
};
|
|
668
|
+
observations.push(observation);
|
|
669
|
+
emit({
|
|
670
|
+
type: "trial",
|
|
671
|
+
trial,
|
|
672
|
+
choices,
|
|
673
|
+
minibatchScore,
|
|
674
|
+
promoted: false
|
|
675
|
+
});
|
|
630
676
|
}
|
|
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
677
|
trial += 1;
|
|
652
|
-
|
|
678
|
+
let cadenceStop;
|
|
653
679
|
if (trial % fullEvalInterval === 0) {
|
|
654
680
|
const outcome = await sweepBestUnswept();
|
|
655
|
-
if (outcome === "budgetExhausted" || outcome === "aborted")
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
}
|
|
681
|
+
if (outcome === "budgetExhausted" || outcome === "aborted") cadenceStop = outcome;
|
|
682
|
+
if (outcome === "unaffordable") cadenceStop = "budgetExhausted";
|
|
683
|
+
}
|
|
684
|
+
await checkpoint();
|
|
685
|
+
if (cadenceStop !== void 0) {
|
|
686
|
+
stopReason = cadenceStop;
|
|
687
|
+
break;
|
|
663
688
|
}
|
|
664
689
|
}
|
|
665
690
|
if (stopReason === "maxTrials" && !signal?.aborted) await sweepBestUnswept();
|
|
666
691
|
if (signal?.aborted) stopReason = "aborted";
|
|
667
|
-
const
|
|
692
|
+
const heldOut = testSet === void 0 ? void 0 : await evaluator.evaluate({
|
|
668
693
|
candidate: best,
|
|
669
694
|
batch: testSet,
|
|
670
695
|
ids: testIds,
|
|
@@ -673,13 +698,17 @@ async function runMipro(args) {
|
|
|
673
698
|
candidateId: null,
|
|
674
699
|
iteration: trial,
|
|
675
700
|
charge: false
|
|
676
|
-
})
|
|
677
|
-
|
|
701
|
+
});
|
|
702
|
+
const testScore = heldOut === void 0 ? void 0 : measuredMean(heldOut);
|
|
703
|
+
emit({
|
|
678
704
|
type: "finish",
|
|
679
705
|
reason: stopReason,
|
|
706
|
+
bestCandidateId: acceptedCandidates,
|
|
680
707
|
bestScore,
|
|
681
708
|
metricCalls: budget.spent(),
|
|
682
|
-
...testScore === void 0 ? {} : { testScore }
|
|
709
|
+
...testScore === void 0 ? {} : { testScore },
|
|
710
|
+
...heldOut === void 0 ? {} : { testInstanceScores: instanceRow(heldOut) },
|
|
711
|
+
...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
|
|
683
712
|
});
|
|
684
713
|
return {
|
|
685
714
|
snapshot: takeSnapshot(),
|
|
@@ -690,7 +719,8 @@ async function runMipro(args) {
|
|
|
690
719
|
...trackBestOutputs ? { bestOutputs } : {},
|
|
691
720
|
...testScore === void 0 ? {} : {
|
|
692
721
|
testScore,
|
|
693
|
-
testMetricCalls: evaluator.unchargedCalls()
|
|
722
|
+
testMetricCalls: evaluator.unchargedCalls(),
|
|
723
|
+
testUsage: evaluator.unchargedUsage()
|
|
694
724
|
},
|
|
695
725
|
trials: trial,
|
|
696
726
|
menu,
|
|
@@ -728,9 +758,5 @@ function assertConfig(config) {
|
|
|
728
758
|
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
759
|
if (config.tips !== void 0 && config.tips.length === 0) throw new Error("tips must not be empty");
|
|
730
760
|
}
|
|
731
|
-
function defaultInstanceId(args) {
|
|
732
|
-
const hash = stableHash(args.datum);
|
|
733
|
-
return hash === "" ? String(args.index) : hash;
|
|
734
|
-
}
|
|
735
761
|
//#endregion
|
|
736
|
-
export { MiproOptimizer, buildMiproPrompt, proposeConfiguration };
|
|
762
|
+
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_reporting = require("../reporting-CNHzbJC-.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_reporting.flushReporters(task.reporters ?? []);
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
};
|
|
52
56
|
/**
|
|
@@ -91,9 +95,10 @@ 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 = trainingSet, testSet, adapter, reflect, maxMetricCalls, renderDatum = renderDefault, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId,
|
|
95
|
-
const
|
|
96
|
-
const
|
|
98
|
+
const { seedCandidate, trainingSet, validationSet = trainingSet, testSet, adapter, reflect, maxMetricCalls, renderDatum = renderDefault, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = require_reporting.defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
|
|
99
|
+
const emit = require_reporting.createEmitter(reporters);
|
|
100
|
+
const deadline = require_reporting.createDeadline({ maxWallClockMs });
|
|
101
|
+
const components = require_reporting.componentNames(seedCandidate);
|
|
97
102
|
if (trainingSet.length === 0) throw new Error("optimize requires a non-empty trainingSet");
|
|
98
103
|
if (validationSet.length === 0) throw new Error("optimize requires a non-empty validationSet");
|
|
99
104
|
if (components.length === 0) throw new Error("optimize requires a seed candidate with at least one component");
|
|
@@ -106,7 +111,7 @@ async function runOpro(args) {
|
|
|
106
111
|
datum,
|
|
107
112
|
index
|
|
108
113
|
})) ?? [];
|
|
109
|
-
const fingerprint =
|
|
114
|
+
const fingerprint = require_reporting.runFingerprint({
|
|
110
115
|
seedCandidate,
|
|
111
116
|
trainingIds: trainingSet.map((datum, index) => instanceId({
|
|
112
117
|
datum,
|
|
@@ -116,17 +121,17 @@ async function runOpro(args) {
|
|
|
116
121
|
seed,
|
|
117
122
|
...cacheNamespace === void 0 ? {} : { cacheNamespace }
|
|
118
123
|
});
|
|
119
|
-
|
|
124
|
+
require_reporting.assertResumable({
|
|
120
125
|
fingerprint,
|
|
121
126
|
...resumeFrom === void 0 ? {} : { snapshot: resumeFrom }
|
|
122
127
|
});
|
|
123
128
|
const rng = require_rng.createSeededRng(seed, resumeFrom?.rngState);
|
|
124
|
-
const budget =
|
|
129
|
+
const budget = require_reporting.createBudget({
|
|
125
130
|
maxMetricCalls,
|
|
126
131
|
spent: resumeFrom?.metricCalls ?? 0
|
|
127
132
|
});
|
|
128
|
-
const evaluationCache = cache === false ? void 0 : cache ??
|
|
129
|
-
const evaluator =
|
|
133
|
+
const evaluationCache = cache === false ? void 0 : cache ?? require_reporting.createMemoryCache();
|
|
134
|
+
const evaluator = require_reporting.createEvaluator({
|
|
130
135
|
adapter,
|
|
131
136
|
budget,
|
|
132
137
|
...retry === void 0 ? {} : { retry },
|
|
@@ -134,8 +139,9 @@ async function runOpro(args) {
|
|
|
134
139
|
...evaluationCache === void 0 ? {} : { cache: evaluationCache },
|
|
135
140
|
trackOutputs: trackBestOutputs,
|
|
136
141
|
cacheHits: resumeFrom?.cacheHits ?? 0,
|
|
142
|
+
...resumeFrom?.usage === void 0 ? {} : { usage: resumeFrom.usage },
|
|
137
143
|
...signal === void 0 ? {} : { signal },
|
|
138
|
-
onEvaluation: (event) =>
|
|
144
|
+
onEvaluation: (event) => emit({
|
|
139
145
|
type: "evaluation",
|
|
140
146
|
...event
|
|
141
147
|
})
|
|
@@ -154,13 +160,13 @@ async function runOpro(args) {
|
|
|
154
160
|
function contextOf(candidate, component) {
|
|
155
161
|
const rest = {};
|
|
156
162
|
for (const name of components) if (name !== component) rest[name] = candidate[name];
|
|
157
|
-
return
|
|
163
|
+
return require_reporting.stableHash(rest);
|
|
158
164
|
}
|
|
159
165
|
const trajectory = [];
|
|
160
166
|
let round = resumeFrom?.round ?? 0;
|
|
161
167
|
let reflectionCalls = resumeFrom?.reflectionCalls ?? 0;
|
|
162
168
|
let stopReason = "maxRounds";
|
|
163
|
-
|
|
169
|
+
emit({
|
|
164
170
|
type: "start",
|
|
165
171
|
components,
|
|
166
172
|
validationSetSize: validationSet.length
|
|
@@ -193,19 +199,41 @@ async function runOpro(args) {
|
|
|
193
199
|
iteration: round
|
|
194
200
|
});
|
|
195
201
|
}
|
|
202
|
+
/** What screening a candidate would cost, in rollouts nothing has cached. */
|
|
203
|
+
function screenCost(candidate) {
|
|
204
|
+
return scoringSet === void 0 ? evaluator.countUncached({
|
|
205
|
+
candidate,
|
|
206
|
+
ids: validationIds,
|
|
207
|
+
split: "val"
|
|
208
|
+
}) : evaluator.countUncached({
|
|
209
|
+
candidate,
|
|
210
|
+
ids: scoringIds,
|
|
211
|
+
split: "train"
|
|
212
|
+
});
|
|
213
|
+
}
|
|
196
214
|
const seedEvaluation = resumeFrom === void 0 ? await sweep(seedCandidate, "seed") : void 0;
|
|
197
|
-
const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore :
|
|
215
|
+
const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore : require_reporting.requireMeasuredMean({
|
|
198
216
|
batch: seedEvaluation,
|
|
199
217
|
phase: "seed"
|
|
200
218
|
});
|
|
219
|
+
if (seedEvaluation !== void 0) emit({
|
|
220
|
+
type: "candidateAccepted",
|
|
221
|
+
round: 0,
|
|
222
|
+
candidateId: 0,
|
|
223
|
+
candidate: seedCandidate,
|
|
224
|
+
aggregateScore: seedScore,
|
|
225
|
+
instanceScores: require_reporting.instanceRow(seedEvaluation),
|
|
226
|
+
...trackBestOutputs ? { outputs: seedEvaluation.outputs } : {}
|
|
227
|
+
});
|
|
201
228
|
let best = resumeFrom?.best ?? seedCandidate;
|
|
202
229
|
let bestScore = resumeFrom?.bestScore ?? seedScore;
|
|
203
230
|
/** Absent on a resumed run until a sweep wins: outputs are not checkpointed. */
|
|
231
|
+
let acceptedCandidates = resumeFrom?.acceptedCandidates ?? 0;
|
|
204
232
|
let bestOutputs = seedEvaluation?.outputs;
|
|
205
233
|
let reported = resumeFrom?.reported ?? seedCandidate;
|
|
206
234
|
let lastSwept = resumeFrom === void 0 ? seedCandidate : resumeFrom.incumbentSwept ? best : {};
|
|
207
235
|
let bestSearchScore = resumeFrom?.bestSearchScore ?? seedScore;
|
|
208
|
-
if (resumeFrom === void 0 && scoringSet !== void 0) bestSearchScore =
|
|
236
|
+
if (resumeFrom === void 0 && scoringSet !== void 0) bestSearchScore = require_reporting.requireMeasuredMean({
|
|
209
237
|
batch: await screen(seedCandidate, "seed"),
|
|
210
238
|
phase: "seed"
|
|
211
239
|
});
|
|
@@ -215,19 +243,42 @@ async function runOpro(args) {
|
|
|
215
243
|
* what gets reported is the best candidate a full sweep has actually seen —
|
|
216
244
|
* never a subset number wearing a validation set label.
|
|
217
245
|
*/
|
|
246
|
+
/**
|
|
247
|
+
* The incumbent moved and a full sweep measured it. Emitted from the two
|
|
248
|
+
* places that can be true — a screening run with no scoring set, where the
|
|
249
|
+
* attempt's own evaluation is the sweep, and the cadence that confirms an
|
|
250
|
+
* incumbent later — because a payload assembled twice is one that drifts.
|
|
251
|
+
*/
|
|
252
|
+
function emitAccepted(args) {
|
|
253
|
+
acceptedCandidates += 1;
|
|
254
|
+
emit({
|
|
255
|
+
type: "candidateAccepted",
|
|
256
|
+
round,
|
|
257
|
+
candidateId: acceptedCandidates,
|
|
258
|
+
candidate: args.candidate,
|
|
259
|
+
aggregateScore: args.score,
|
|
260
|
+
instanceScores: require_reporting.instanceRow(args.evaluation),
|
|
261
|
+
...trackBestOutputs ? { outputs: args.evaluation.outputs } : {}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
218
264
|
async function refreshIncumbent() {
|
|
219
265
|
if (best === lastSwept || !budget.canAfford(validationSet.length)) return "ok";
|
|
220
266
|
try {
|
|
221
267
|
const evaluation = await sweep(best, "validation");
|
|
222
|
-
const full =
|
|
268
|
+
const full = require_reporting.measuredMean(evaluation);
|
|
223
269
|
lastSwept = best;
|
|
224
270
|
if (full !== void 0 && full > bestScore) {
|
|
225
271
|
reported = best;
|
|
226
272
|
bestScore = full;
|
|
227
273
|
bestOutputs = evaluation.outputs;
|
|
274
|
+
emitAccepted({
|
|
275
|
+
candidate: best,
|
|
276
|
+
evaluation,
|
|
277
|
+
score: full
|
|
278
|
+
});
|
|
228
279
|
}
|
|
229
280
|
} catch (err) {
|
|
230
|
-
if (err instanceof
|
|
281
|
+
if (err instanceof require_reporting.BudgetExhausted || signal?.aborted) return "stop";
|
|
231
282
|
throw err;
|
|
232
283
|
}
|
|
233
284
|
return "ok";
|
|
@@ -260,6 +311,8 @@ async function runOpro(args) {
|
|
|
260
311
|
reflectionCalls,
|
|
261
312
|
metricCalls: budget.spent(),
|
|
262
313
|
cacheHits: evaluator.cacheHits(),
|
|
314
|
+
usage: evaluator.usage(),
|
|
315
|
+
acceptedCandidates,
|
|
263
316
|
rngState: rng.state(),
|
|
264
317
|
histories: Object.fromEntries([...histories].map(([name, attempts]) => [name, [...attempts]])),
|
|
265
318
|
...scoringIndices === void 0 ? {} : { scoringIndices },
|
|
@@ -281,7 +334,7 @@ async function runOpro(args) {
|
|
|
281
334
|
stopReason = "proposalsExhausted";
|
|
282
335
|
break;
|
|
283
336
|
}
|
|
284
|
-
if (
|
|
337
|
+
if (require_reporting.costExhausted({
|
|
285
338
|
usage: evaluator.usage(),
|
|
286
339
|
maxCostUsd
|
|
287
340
|
})) {
|
|
@@ -304,7 +357,7 @@ async function runOpro(args) {
|
|
|
304
357
|
const history = histories.get(component);
|
|
305
358
|
const context = contextOf(best, component);
|
|
306
359
|
const comparable = history.filter((attempt) => attempt.context === context);
|
|
307
|
-
|
|
360
|
+
emit({
|
|
308
361
|
type: "roundStart",
|
|
309
362
|
round,
|
|
310
363
|
component,
|
|
@@ -333,26 +386,44 @@ async function runOpro(args) {
|
|
|
333
386
|
const unique = [...new Set(drawn)].filter((text) => text.length > 0 && !tried.has(text));
|
|
334
387
|
barrenRounds = unique.length === 0 ? barrenRounds + 1 : 0;
|
|
335
388
|
let roundStop;
|
|
389
|
+
const scheduled = [];
|
|
390
|
+
let owed = 0;
|
|
336
391
|
for (const text of unique) {
|
|
337
392
|
const candidate = {
|
|
338
393
|
...best,
|
|
339
394
|
[component]: text
|
|
340
395
|
};
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
396
|
+
const cost = screenCost(candidate);
|
|
397
|
+
if (!budget.canAfford(owed + cost)) {
|
|
398
|
+
roundStop = "budgetExhausted";
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
owed += cost;
|
|
402
|
+
scheduled.push(candidate);
|
|
403
|
+
}
|
|
404
|
+
const screened = await require_concurrency.mapWithConcurrency({
|
|
405
|
+
items: scheduled,
|
|
406
|
+
limit: concurrency,
|
|
407
|
+
task: async (candidate) => {
|
|
408
|
+
if (signal?.aborted) return { stop: "aborted" };
|
|
409
|
+
try {
|
|
410
|
+
return { evaluation: await screen(candidate, "validation") };
|
|
411
|
+
} catch (err) {
|
|
412
|
+
if (err instanceof require_reporting.BudgetExhausted) return { stop: "budgetExhausted" };
|
|
413
|
+
if (signal?.aborted) return { stop: "aborted" };
|
|
414
|
+
throw err;
|
|
352
415
|
}
|
|
353
|
-
throw err;
|
|
354
416
|
}
|
|
355
|
-
|
|
417
|
+
});
|
|
418
|
+
for (const [index, outcome] of screened.entries()) {
|
|
419
|
+
if (outcome.stop !== void 0) {
|
|
420
|
+
roundStop = outcome.stop;
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
const candidate = scheduled[index];
|
|
424
|
+
const text = candidate[component];
|
|
425
|
+
const evaluation = outcome.evaluation;
|
|
426
|
+
const score = require_reporting.measuredMean(evaluation);
|
|
356
427
|
if (score === void 0) continue;
|
|
357
428
|
const accepted = score > bestSearchScore;
|
|
358
429
|
history.push({
|
|
@@ -366,7 +437,7 @@ async function runOpro(args) {
|
|
|
366
437
|
candidate,
|
|
367
438
|
score
|
|
368
439
|
});
|
|
369
|
-
|
|
440
|
+
emit({
|
|
370
441
|
type: "attempt",
|
|
371
442
|
round,
|
|
372
443
|
component,
|
|
@@ -381,6 +452,11 @@ async function runOpro(args) {
|
|
|
381
452
|
lastSwept = candidate;
|
|
382
453
|
bestScore = score;
|
|
383
454
|
bestOutputs = evaluation.outputs;
|
|
455
|
+
emitAccepted({
|
|
456
|
+
candidate,
|
|
457
|
+
evaluation,
|
|
458
|
+
score
|
|
459
|
+
});
|
|
384
460
|
}
|
|
385
461
|
const scaled = scaleScore(score, scoreScale);
|
|
386
462
|
for (const name of components) {
|
|
@@ -394,22 +470,22 @@ async function runOpro(args) {
|
|
|
394
470
|
}
|
|
395
471
|
}
|
|
396
472
|
round += 1;
|
|
473
|
+
let cadenceStop;
|
|
474
|
+
if (roundStop === void 0 && scoringSet !== void 0 && round % fullEvalInterval === 0 && await refreshIncumbent() === "stop") cadenceStop = signal?.aborted ? "aborted" : "budgetExhausted";
|
|
397
475
|
await checkpoint();
|
|
398
476
|
if (roundStop !== void 0) {
|
|
399
477
|
stopReason = roundStop;
|
|
400
478
|
break;
|
|
401
479
|
}
|
|
402
|
-
if (
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
break;
|
|
406
|
-
}
|
|
480
|
+
if (cadenceStop !== void 0) {
|
|
481
|
+
stopReason = cadenceStop;
|
|
482
|
+
break;
|
|
407
483
|
}
|
|
408
484
|
}
|
|
409
485
|
if (scoringSet !== void 0 && !signal?.aborted) await refreshIncumbent();
|
|
410
486
|
if (signal?.aborted) stopReason = "aborted";
|
|
411
|
-
const
|
|
412
|
-
candidate:
|
|
487
|
+
const heldOut = testSet === void 0 ? void 0 : await evaluator.evaluate({
|
|
488
|
+
candidate: reported,
|
|
413
489
|
batch: testSet,
|
|
414
490
|
ids: testIds,
|
|
415
491
|
split: "test",
|
|
@@ -417,13 +493,17 @@ async function runOpro(args) {
|
|
|
417
493
|
candidateId: null,
|
|
418
494
|
iteration: round,
|
|
419
495
|
charge: false
|
|
420
|
-
})
|
|
421
|
-
|
|
496
|
+
});
|
|
497
|
+
const testScore = heldOut === void 0 ? void 0 : require_reporting.measuredMean(heldOut);
|
|
498
|
+
emit({
|
|
422
499
|
type: "finish",
|
|
423
500
|
reason: stopReason,
|
|
501
|
+
bestCandidateId: acceptedCandidates,
|
|
424
502
|
bestScore,
|
|
425
503
|
metricCalls: budget.spent(),
|
|
426
|
-
...testScore === void 0 ? {} : { testScore }
|
|
504
|
+
...testScore === void 0 ? {} : { testScore },
|
|
505
|
+
...heldOut === void 0 ? {} : { testInstanceScores: require_reporting.instanceRow(heldOut) },
|
|
506
|
+
...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
|
|
427
507
|
});
|
|
428
508
|
return {
|
|
429
509
|
snapshot: takeSnapshot(),
|
|
@@ -434,7 +514,8 @@ async function runOpro(args) {
|
|
|
434
514
|
...trackBestOutputs ? { bestOutputs } : {},
|
|
435
515
|
...testScore === void 0 ? {} : {
|
|
436
516
|
testScore,
|
|
437
|
-
testMetricCalls: evaluator.unchargedCalls()
|
|
517
|
+
testMetricCalls: evaluator.unchargedCalls(),
|
|
518
|
+
testUsage: evaluator.unchargedUsage()
|
|
438
519
|
},
|
|
439
520
|
rounds: round,
|
|
440
521
|
trajectory,
|
|
@@ -478,10 +559,8 @@ function assertConfig(config) {
|
|
|
478
559
|
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
560
|
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
561
|
}
|
|
481
|
-
function defaultInstanceId(args) {
|
|
482
|
-
const hash = require_evaluation.stableHash(args.datum);
|
|
483
|
-
return hash === "" ? String(args.index) : hash;
|
|
484
|
-
}
|
|
485
562
|
//#endregion
|
|
486
563
|
exports.OproOptimizer = OproOptimizer;
|
|
487
564
|
exports.buildOproPrompt = buildOproPrompt;
|
|
565
|
+
exports.isCandidateAccepted = require_reporting.isCandidateAccepted;
|
|
566
|
+
exports.isRunFinished = require_reporting.isRunFinished;
|
package/dist/opro/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as TextModel, a as RunFinished, c as Adapter, i as Reporter, l as Candidate, n as OptimizerEvent, o as isCandidateAccepted, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, v as UsageTotals } from "../reporting-DQbAohc9.cjs";
|
|
2
2
|
import { n as EvaluationCache, t as CachedScore } from "../cache-CuSo0NJ8.cjs";
|
|
3
|
-
import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-
|
|
3
|
+
import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-Bh5DPRMH.cjs";
|
|
4
4
|
//#region src/opro/optimize.d.ts
|
|
5
5
|
/** One instruction that was tried, and what it scored. */
|
|
6
6
|
/** A history entry plus the system state its score was measured in. */
|
|
@@ -111,6 +111,13 @@ interface OproSnapshot {
|
|
|
111
111
|
reflectionCalls: number;
|
|
112
112
|
metricCalls: number;
|
|
113
113
|
cacheHits: number;
|
|
114
|
+
/** Usage already spent, so a resumed run reports totals and honours ceilings. */
|
|
115
|
+
usage?: UsageTotals;
|
|
116
|
+
/**
|
|
117
|
+
* Candidates accepted so far. Reporters key rows by this id, so restarting it
|
|
118
|
+
* at zero makes a resumed run collide with the run it continues.
|
|
119
|
+
*/
|
|
120
|
+
acceptedCandidates?: number;
|
|
114
121
|
rngState: number;
|
|
115
122
|
/** Component name -> every text tried for it, with what it scored. */
|
|
116
123
|
histories: Record<string, RecordedAttempt[]>;
|
|
@@ -133,7 +140,8 @@ interface OproTask<Datum, Trajectory = unknown, Output = unknown, K extends stri
|
|
|
133
140
|
}) => string;
|
|
134
141
|
/** Pass `false` to disable caching entirely. */
|
|
135
142
|
cache?: EvaluationCache | false;
|
|
136
|
-
|
|
143
|
+
/** Observers of the run. Every one sees every event; none can fail it. */
|
|
144
|
+
reporters?: readonly Reporter<OproEvent<NoInfer<K>>>[];
|
|
137
145
|
/**
|
|
138
146
|
* Called with a resumable snapshot after the seed is scored and after every
|
|
139
147
|
* round. Persist it and a killed run costs the last round, not all of them.
|
|
@@ -161,13 +169,13 @@ type OproEvent<K extends string = string> = {
|
|
|
161
169
|
score: number;
|
|
162
170
|
/** True when this attempt became the new incumbent. */
|
|
163
171
|
accepted: boolean;
|
|
164
|
-
} | {
|
|
172
|
+
} | ({
|
|
173
|
+
type: "candidateAccepted";
|
|
174
|
+
round: number;
|
|
175
|
+
} & CandidateAccepted<K>) | ({
|
|
165
176
|
type: "finish";
|
|
166
177
|
reason: OproStopReason;
|
|
167
|
-
|
|
168
|
-
metricCalls: number;
|
|
169
|
-
testScore?: number;
|
|
170
|
-
};
|
|
178
|
+
} & RunFinished);
|
|
171
179
|
interface OproAttempt<K extends string = string> {
|
|
172
180
|
round: number;
|
|
173
181
|
component: K;
|
|
@@ -227,4 +235,4 @@ declare function buildOproPrompt(args: {
|
|
|
227
235
|
exemplars: readonly string[];
|
|
228
236
|
}): string;
|
|
229
237
|
//#endregion
|
|
230
|
-
export { type OproAttempt, type OproConfig, type OproEvent, OproOptimizer, type OproPromptBuilder, type OproResult, type OproSnapshot, type OproStopReason, type OproTask, type ScoredAttempt, buildOproPrompt };
|
|
238
|
+
export { type CandidateAccepted, type OproAttempt, type OproConfig, type OproEvent, OproOptimizer, type OproPromptBuilder, type OproResult, type OproSnapshot, type OproStopReason, type OproTask, type OptimizerEvent, type ReportableEvent, type Reporter, type RunFinished, type ScoredAttempt, buildOproPrompt, isCandidateAccepted, isRunFinished };
|