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
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { 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.mjs";
|
|
2
2
|
import { n as EvaluationCache, t as CachedScore } from "../cache-CuSo0NJ8.mjs";
|
|
3
|
-
import { r as DemoRenderer } from "../demos-
|
|
4
|
-
import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-
|
|
3
|
+
import { r as DemoRenderer } from "../demos-1b7JiUue.mjs";
|
|
4
|
+
import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-Ck6-e_8o.mjs";
|
|
5
5
|
//#region src/bootstrap-search/optimize.d.ts
|
|
6
6
|
/**
|
|
7
7
|
* Where a candidate's demo block came from. `zeroShot` holds no demos at all,
|
|
@@ -35,6 +35,18 @@ interface BootstrapSearchConfig {
|
|
|
35
35
|
* every candidate, which is the reliable reading and the expensive one.
|
|
36
36
|
*/
|
|
37
37
|
stopAtScore?: number;
|
|
38
|
+
/**
|
|
39
|
+
* How many candidates may be swept at once. Default 1.
|
|
40
|
+
*
|
|
41
|
+
* Harvesting stays in plan order however this is set — every harvest draws
|
|
42
|
+
* from the same random stream, and reordering them would make a seeded run
|
|
43
|
+
* unreproducible — so what overlaps is a sweep with the harvest of the
|
|
44
|
+
* candidates behind it. Two costs come with raising it: a checkpoint is
|
|
45
|
+
* taken per wave rather than per candidate, so a killed run loses up to this
|
|
46
|
+
* many candidates instead of one, and `stopAtScore` is honoured by sweeping
|
|
47
|
+
* one at a time, since a wave cannot know it has already passed the target.
|
|
48
|
+
*/
|
|
49
|
+
concurrency?: number;
|
|
38
50
|
seed?: number;
|
|
39
51
|
trackBestOutputs?: boolean;
|
|
40
52
|
/**
|
|
@@ -61,6 +73,13 @@ interface BootstrapSearchSnapshot {
|
|
|
61
73
|
metricCalls: number;
|
|
62
74
|
bootstrapMetricCalls: number;
|
|
63
75
|
cacheHits: number;
|
|
76
|
+
/** Usage already spent, so a resumed run reports totals and honours ceilings. */
|
|
77
|
+
usage?: UsageTotals;
|
|
78
|
+
/**
|
|
79
|
+
* Candidates accepted so far. Reporters key rows by this id, so restarting it
|
|
80
|
+
* at zero makes a resumed run collide with the run it continues.
|
|
81
|
+
*/
|
|
82
|
+
acceptedCandidates?: number;
|
|
64
83
|
rngState: number;
|
|
65
84
|
cache?: [string, CachedScore][];
|
|
66
85
|
}
|
|
@@ -92,7 +111,8 @@ interface BootstrapSearchTask<Datum, Trajectory = unknown, Output = unknown, K e
|
|
|
92
111
|
}) => string;
|
|
93
112
|
/** Pass `false` to disable caching entirely. */
|
|
94
113
|
cache?: EvaluationCache | false;
|
|
95
|
-
|
|
114
|
+
/** Observers of the run. Every one sees every event; none can fail it. */
|
|
115
|
+
reporters?: readonly Reporter<BootstrapSearchEvent<NoInfer<K>>>[];
|
|
96
116
|
/** Called with a resumable snapshot after every candidate is scored. */
|
|
97
117
|
onCheckpoint?: (snapshot: BootstrapSearchSnapshot) => void | Promise<void>;
|
|
98
118
|
/** Snapshot to continue from. */
|
|
@@ -112,13 +132,15 @@ type BootstrapSearchEvent<K extends string = string> = {
|
|
|
112
132
|
demos: number;
|
|
113
133
|
score: number;
|
|
114
134
|
accepted: boolean;
|
|
115
|
-
} | {
|
|
135
|
+
} | ({
|
|
136
|
+
type: "candidateAccepted";
|
|
137
|
+
/** Which construction produced the demo block that won. */
|
|
138
|
+
source: DemoSource;
|
|
139
|
+
demos: number;
|
|
140
|
+
} & CandidateAccepted<K>) | ({
|
|
116
141
|
type: "finish";
|
|
117
142
|
reason: BootstrapSearchStopReason;
|
|
118
|
-
|
|
119
|
-
metricCalls: number;
|
|
120
|
-
testScore?: number;
|
|
121
|
-
};
|
|
143
|
+
} & RunFinished);
|
|
122
144
|
interface BootstrapSearchResult<K extends string = string, Output = unknown> extends OptimizerResult<K, BootstrapSearchStopReason, Output> {
|
|
123
145
|
/** The seed's score, so the lift the demos bought is readable directly. */
|
|
124
146
|
seedScore: number;
|
|
@@ -159,4 +181,4 @@ declare class BootstrapSearchOptimizer implements Optimizer<BootstrapSearchStopR
|
|
|
159
181
|
optimize<Datum, Trajectory = unknown, Output = unknown, const K extends string = string>(task: BootstrapSearchTask<Datum, Trajectory, Output, K>): Promise<BootstrapSearchResult<K, Output>>;
|
|
160
182
|
}
|
|
161
183
|
//#endregion
|
|
162
|
-
export { type BootstrapCandidate, type BootstrapSearchConfig, type BootstrapSearchEvent, BootstrapSearchOptimizer, type BootstrapSearchResult, type BootstrapSearchSnapshot, type BootstrapSearchStopReason, type BootstrapSearchTask, type DemoSource };
|
|
184
|
+
export { type BootstrapCandidate, type BootstrapSearchConfig, type BootstrapSearchEvent, BootstrapSearchOptimizer, type BootstrapSearchResult, type BootstrapSearchSnapshot, type BootstrapSearchStopReason, type BootstrapSearchTask, type CandidateAccepted, type DemoSource, type OptimizerEvent, type ReportableEvent, type Reporter, type RunFinished, isCandidateAccepted, isRunFinished };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { n as
|
|
1
|
+
import { _ as createMemoryCache, a as isRunFinished, b as createBudget, c as createEvaluator, d as createDeadline, f as assertResumable, g as candidateHash, 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
|
+
import { n as harvestFewShotExamples, t as formatDemos } from "../demos-DE2oxNWX.mjs";
|
|
3
3
|
import { t as createSeededRng } from "../rng-Dtc5eZ_W.mjs";
|
|
4
4
|
//#region src/bootstrap-search/optimize.ts
|
|
5
5
|
const DEFAULT_CANDIDATES = 16;
|
|
@@ -33,19 +33,25 @@ const DEFAULT_MAX_LABELED_DEMOS = 16;
|
|
|
33
33
|
var BootstrapSearchOptimizer = class {
|
|
34
34
|
#config;
|
|
35
35
|
constructor(config = {}) {
|
|
36
|
+
assertBootstrapSearchConfig(config);
|
|
36
37
|
this.#config = config;
|
|
37
38
|
}
|
|
38
|
-
optimize(task) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
async optimize(task) {
|
|
40
|
+
try {
|
|
41
|
+
return await run({
|
|
42
|
+
config: this.#config,
|
|
43
|
+
task
|
|
44
|
+
});
|
|
45
|
+
} finally {
|
|
46
|
+
await flushReporters(task.reporters ?? []);
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
};
|
|
45
50
|
async function run(args) {
|
|
46
51
|
const { config, task } = args;
|
|
47
|
-
const { candidates: shuffledHarvests = DEFAULT_CANDIDATES, maxDemos = DEFAULT_MAX_DEMOS, minDemos = DEFAULT_MIN_DEMOS, maxLabeledDemos = DEFAULT_MAX_LABELED_DEMOS, demoMinScore, stopAtScore, seed = 0, trackBestOutputs = false, checkpointCache = true } = config;
|
|
48
|
-
const { seedCandidate, trainingSet, validationSet = trainingSet, testSet, adapter, demoComponents, renderDemo, goldOutput, maxMetricCalls, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId,
|
|
52
|
+
const { candidates: shuffledHarvests = DEFAULT_CANDIDATES, maxDemos = DEFAULT_MAX_DEMOS, minDemos = DEFAULT_MIN_DEMOS, maxLabeledDemos = DEFAULT_MAX_LABELED_DEMOS, demoMinScore, stopAtScore, concurrency = 1, seed = 0, trackBestOutputs = false, checkpointCache = true } = config;
|
|
53
|
+
const { seedCandidate, trainingSet, validationSet = trainingSet, testSet, adapter, demoComponents, renderDemo, goldOutput, maxMetricCalls, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
|
|
54
|
+
const emit = createEmitter(reporters);
|
|
49
55
|
const deadline = createDeadline({ maxWallClockMs });
|
|
50
56
|
const components = componentNames(seedCandidate);
|
|
51
57
|
if (trainingSet.length === 0) throw new Error("optimize requires a non-empty trainingSet");
|
|
@@ -88,8 +94,9 @@ async function run(args) {
|
|
|
88
94
|
...evaluationCache === void 0 ? {} : { cache: evaluationCache },
|
|
89
95
|
trackOutputs: trackBestOutputs,
|
|
90
96
|
cacheHits: resumeFrom?.cacheHits ?? 0,
|
|
97
|
+
...resumeFrom?.usage === void 0 ? {} : { usage: resumeFrom.usage },
|
|
91
98
|
...signal === void 0 ? {} : { signal },
|
|
92
|
-
onEvaluation: (event) =>
|
|
99
|
+
onEvaluation: (event) => emit({
|
|
93
100
|
type: "evaluation",
|
|
94
101
|
...event
|
|
95
102
|
})
|
|
@@ -99,7 +106,7 @@ async function run(args) {
|
|
|
99
106
|
let drawn = resumeFrom?.drawn ?? 0;
|
|
100
107
|
let bootstrapMetricCalls = resumeFrom?.bootstrapMetricCalls ?? 0;
|
|
101
108
|
let stopReason = "candidatesExhausted";
|
|
102
|
-
|
|
109
|
+
emit({
|
|
103
110
|
type: "start",
|
|
104
111
|
components,
|
|
105
112
|
validationSetSize: validationSet.length
|
|
@@ -115,13 +122,25 @@ async function run(args) {
|
|
|
115
122
|
iteration: evaluated.length
|
|
116
123
|
});
|
|
117
124
|
}
|
|
118
|
-
const
|
|
119
|
-
|
|
125
|
+
const seedEvaluation = resumeFrom === void 0 ? await sweep(seedCandidate, "seed") : void 0;
|
|
126
|
+
const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore : requireMeasuredMean({
|
|
127
|
+
batch: seedEvaluation,
|
|
120
128
|
phase: "seed"
|
|
121
129
|
});
|
|
122
130
|
let best = resumeFrom?.best ?? seedCandidate;
|
|
123
131
|
let bestScore = resumeFrom?.bestScore ?? seedScore;
|
|
124
132
|
let bestOutputs;
|
|
133
|
+
let acceptedCandidates = resumeFrom?.acceptedCandidates ?? 0;
|
|
134
|
+
if (seedEvaluation !== void 0) emit({
|
|
135
|
+
type: "candidateAccepted",
|
|
136
|
+
source: "zeroShot",
|
|
137
|
+
demos: 0,
|
|
138
|
+
candidateId: 0,
|
|
139
|
+
candidate: seedCandidate,
|
|
140
|
+
aggregateScore: seedScore,
|
|
141
|
+
instanceScores: instanceRow(seedEvaluation),
|
|
142
|
+
...trackBestOutputs ? { outputs: seedEvaluation.outputs } : {}
|
|
143
|
+
});
|
|
125
144
|
function takeSnapshot() {
|
|
126
145
|
const cached = checkpointCache ? evaluationCache?.entries?.() : void 0;
|
|
127
146
|
return {
|
|
@@ -135,6 +154,8 @@ async function run(args) {
|
|
|
135
154
|
metricCalls: budget.spent(),
|
|
136
155
|
bootstrapMetricCalls,
|
|
137
156
|
cacheHits: evaluator.cacheHits(),
|
|
157
|
+
usage: evaluator.usage(),
|
|
158
|
+
acceptedCandidates,
|
|
138
159
|
rngState: rng.state(),
|
|
139
160
|
...cached === void 0 ? {} : { cache: cached }
|
|
140
161
|
};
|
|
@@ -147,7 +168,8 @@ async function run(args) {
|
|
|
147
168
|
shuffledHarvests,
|
|
148
169
|
labeled: goldOutput !== void 0
|
|
149
170
|
});
|
|
150
|
-
|
|
171
|
+
const waveSize = stopAtScore === void 0 ? concurrency : 1;
|
|
172
|
+
while (drawn < plan.length) {
|
|
151
173
|
if (signal?.aborted) {
|
|
152
174
|
stopReason = "aborted";
|
|
153
175
|
break;
|
|
@@ -163,58 +185,95 @@ async function run(args) {
|
|
|
163
185
|
stopReason = "deadlineReached";
|
|
164
186
|
break;
|
|
165
187
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const candidate = withDemos(block);
|
|
173
|
-
let evaluation;
|
|
174
|
-
try {
|
|
175
|
-
evaluation = await sweep(candidate, "validation");
|
|
176
|
-
} catch (err) {
|
|
177
|
-
if (err instanceof BudgetExhausted) {
|
|
178
|
-
stopReason = "budgetExhausted";
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
if (signal?.aborted) {
|
|
182
|
-
stopReason = "aborted";
|
|
188
|
+
const wave = [];
|
|
189
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
190
|
+
let waveStop;
|
|
191
|
+
while (wave.length < waveSize && drawn + wave.length < plan.length) {
|
|
192
|
+
if (!budget.canAfford(validationSet.length + 1)) {
|
|
193
|
+
waveStop = "budgetExhausted";
|
|
183
194
|
break;
|
|
184
195
|
}
|
|
185
|
-
|
|
196
|
+
const source = plan[drawn + wave.length];
|
|
197
|
+
const block = await buildBlock(source);
|
|
198
|
+
const candidate = withDemos(block);
|
|
199
|
+
const key = candidateHash(candidate);
|
|
200
|
+
const prior = inFlight.get(key);
|
|
201
|
+
const sweeping = prior === void 0 ? settled(sweep(candidate, "validation")) : prior.then(() => settled(sweep(candidate, "validation")));
|
|
202
|
+
inFlight.set(key, sweeping);
|
|
203
|
+
wave.push({
|
|
204
|
+
source,
|
|
205
|
+
candidate,
|
|
206
|
+
block,
|
|
207
|
+
sweep: sweeping
|
|
208
|
+
});
|
|
186
209
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
210
|
+
let waveError;
|
|
211
|
+
let draining = false;
|
|
212
|
+
for (const entry of wave) {
|
|
213
|
+
const outcome = await entry.sweep;
|
|
214
|
+
if (draining) continue;
|
|
215
|
+
drawn += 1;
|
|
216
|
+
if (outcome.failed === true) {
|
|
217
|
+
draining = true;
|
|
218
|
+
if (outcome.err instanceof BudgetExhausted) {
|
|
219
|
+
waveStop = "budgetExhausted";
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (signal?.aborted) {
|
|
223
|
+
waveStop = "aborted";
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
waveError = outcome.err;
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const evaluation = outcome.evaluation;
|
|
230
|
+
const score = measuredMean(evaluation);
|
|
231
|
+
if (score === void 0) continue;
|
|
232
|
+
const accepted = score > bestScore;
|
|
233
|
+
evaluated.push({
|
|
234
|
+
candidate: entry.candidate,
|
|
235
|
+
source: entry.source,
|
|
236
|
+
demos: countDemos(entry.block),
|
|
237
|
+
score
|
|
238
|
+
});
|
|
239
|
+
emit({
|
|
240
|
+
type: "candidate",
|
|
241
|
+
index: evaluated.length - 1,
|
|
242
|
+
source: entry.source,
|
|
243
|
+
demos: countDemos(entry.block),
|
|
244
|
+
score,
|
|
245
|
+
accepted
|
|
246
|
+
});
|
|
247
|
+
if (accepted) {
|
|
248
|
+
acceptedCandidates += 1;
|
|
249
|
+
emit({
|
|
250
|
+
type: "candidateAccepted",
|
|
251
|
+
source: entry.source,
|
|
252
|
+
demos: countDemos(entry.block),
|
|
253
|
+
candidateId: acceptedCandidates,
|
|
254
|
+
candidate: entry.candidate,
|
|
255
|
+
aggregateScore: score,
|
|
256
|
+
instanceScores: instanceRow(evaluation),
|
|
257
|
+
...trackBestOutputs ? { outputs: evaluation.outputs } : {}
|
|
258
|
+
});
|
|
259
|
+
best = entry.candidate;
|
|
260
|
+
bestScore = score;
|
|
261
|
+
bestOutputs = evaluation.outputs;
|
|
262
|
+
}
|
|
263
|
+
if (stopAtScore !== void 0 && score >= stopAtScore) {
|
|
264
|
+
waveStop = "scoreReached";
|
|
265
|
+
draining = true;
|
|
266
|
+
}
|
|
208
267
|
}
|
|
268
|
+
if (waveError !== void 0) throw waveError;
|
|
209
269
|
await checkpoint();
|
|
210
|
-
if (
|
|
211
|
-
stopReason =
|
|
212
|
-
drawn += 1;
|
|
270
|
+
if (waveStop !== void 0) {
|
|
271
|
+
stopReason = waveStop;
|
|
213
272
|
break;
|
|
214
273
|
}
|
|
215
274
|
}
|
|
216
275
|
if (signal?.aborted) stopReason = "aborted";
|
|
217
|
-
const
|
|
276
|
+
const heldOut = testSet === void 0 ? void 0 : await evaluator.evaluate({
|
|
218
277
|
candidate: best,
|
|
219
278
|
batch: testSet,
|
|
220
279
|
ids: testIds,
|
|
@@ -223,13 +282,17 @@ async function run(args) {
|
|
|
223
282
|
candidateId: null,
|
|
224
283
|
iteration: evaluated.length,
|
|
225
284
|
charge: false
|
|
226
|
-
})
|
|
227
|
-
|
|
285
|
+
});
|
|
286
|
+
const testScore = heldOut === void 0 ? void 0 : measuredMean(heldOut);
|
|
287
|
+
emit({
|
|
228
288
|
type: "finish",
|
|
229
289
|
reason: stopReason,
|
|
290
|
+
bestCandidateId: acceptedCandidates,
|
|
230
291
|
bestScore,
|
|
231
292
|
metricCalls: budget.spent(),
|
|
232
|
-
...testScore === void 0 ? {} : { testScore }
|
|
293
|
+
...testScore === void 0 ? {} : { testScore },
|
|
294
|
+
...heldOut === void 0 ? {} : { testInstanceScores: instanceRow(heldOut) },
|
|
295
|
+
...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
|
|
233
296
|
});
|
|
234
297
|
return {
|
|
235
298
|
bestCandidate: best,
|
|
@@ -244,7 +307,8 @@ async function run(args) {
|
|
|
244
307
|
...trackBestOutputs && bestOutputs !== void 0 ? { bestOutputs } : {},
|
|
245
308
|
...testScore === void 0 ? {} : {
|
|
246
309
|
testScore,
|
|
247
|
-
testMetricCalls:
|
|
310
|
+
testMetricCalls: evaluator.unchargedCalls(),
|
|
311
|
+
testUsage: evaluator.unchargedUsage()
|
|
248
312
|
},
|
|
249
313
|
stopReason
|
|
250
314
|
};
|
|
@@ -259,19 +323,21 @@ async function run(args) {
|
|
|
259
323
|
const requested = source === "unshuffled" ? maxDemos : minDemos + rng.nextInt(Math.max(1, maxDemos - minDemos + 1));
|
|
260
324
|
const affordable = Math.min(trainingSet.length, budget.remaining() - validationSet.length);
|
|
261
325
|
if (affordable < 1) return "";
|
|
262
|
-
const harvest = await
|
|
326
|
+
const harvest = await harvestFewShotExamples({
|
|
263
327
|
adapter,
|
|
264
328
|
candidate: seedCandidate,
|
|
265
329
|
trainingSet,
|
|
266
330
|
...demoMinScore === void 0 ? {} : { minScore: demoMinScore },
|
|
267
331
|
maxDemos: requested,
|
|
268
332
|
maxMetricCalls: affordable,
|
|
333
|
+
...maxCostUsd === void 0 ? {} : { maxCostUsd: maxCostUsd - evaluator.usage().costUsd },
|
|
269
334
|
...source === "unshuffled" ? {} : { rng },
|
|
270
335
|
...renderDemo === void 0 ? {} : { renderDemo },
|
|
271
336
|
...signal === void 0 ? {} : { signal }
|
|
272
337
|
});
|
|
273
338
|
bootstrapMetricCalls += harvest.metricCalls;
|
|
274
339
|
budget.reserve(harvest.metricCalls);
|
|
340
|
+
evaluator.absorbUsage(harvest.usage);
|
|
275
341
|
return harvest.block;
|
|
276
342
|
}
|
|
277
343
|
function labeledBlock() {
|
|
@@ -297,11 +363,23 @@ function candidatePlan(args) {
|
|
|
297
363
|
...Array.from({ length: shuffledHarvests }, () => "bootstrapped")
|
|
298
364
|
];
|
|
299
365
|
}
|
|
366
|
+
/** Turns a sweep into a value, so a dispatched one never rejects unobserved. */
|
|
367
|
+
function settled(sweeping) {
|
|
368
|
+
return sweeping.then((evaluation) => ({ evaluation }), (err) => ({
|
|
369
|
+
failed: true,
|
|
370
|
+
err
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Range checks on the search knobs, run at construction so a configuration
|
|
375
|
+
* that could never terminate is refused before a task is ever handed to it.
|
|
376
|
+
*/
|
|
377
|
+
function assertBootstrapSearchConfig(config) {
|
|
378
|
+
const { concurrency = 1 } = config;
|
|
379
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) throw new Error(`concurrency must be a positive integer, received ${concurrency}`);
|
|
380
|
+
}
|
|
300
381
|
function countDemos(block) {
|
|
301
382
|
return block.split("<demo>").length - 1;
|
|
302
383
|
}
|
|
303
|
-
function defaultInstanceId(args) {
|
|
304
|
-
return String(args.index);
|
|
305
|
-
}
|
|
306
384
|
//#endregion
|
|
307
|
-
export { BootstrapSearchOptimizer };
|
|
385
|
+
export { BootstrapSearchOptimizer, isCandidateAccepted, isRunFinished };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as Adapter, l as Candidate, v as UsageTotals } from "./reporting-DQbAohc9.mjs";
|
|
2
2
|
import { t as Rng } from "./rng-BR5MOedA.mjs";
|
|
3
3
|
//#region src/demos.d.ts
|
|
4
4
|
/**
|
|
@@ -23,6 +23,8 @@ interface BootstrapResult<Datum, Output> {
|
|
|
23
23
|
block: string;
|
|
24
24
|
/** Rollouts this cost. Bootstrapping is cheap, not free. */
|
|
25
25
|
metricCalls: number;
|
|
26
|
+
/** Tokens and dollars this cost, for a caller that bounds spend. */
|
|
27
|
+
usage: UsageTotals;
|
|
26
28
|
attempted: number;
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
@@ -36,7 +38,7 @@ interface BootstrapResult<Datum, Output> {
|
|
|
36
38
|
* examples on what the output should look like — so a seed carrying both
|
|
37
39
|
* starts somewhere neither reaches alone.
|
|
38
40
|
*/
|
|
39
|
-
declare function
|
|
41
|
+
declare function harvestFewShotExamples<Datum, Trajectory, Output, K extends string = string>(args: {
|
|
40
42
|
adapter: Adapter<Datum, Trajectory, Output, K>;
|
|
41
43
|
/** The candidate to run. Usually the seed, sometimes a run's winner. */
|
|
42
44
|
candidate: Candidate<K>;
|
|
@@ -61,6 +63,11 @@ declare function bootstrapDemos<Datum, Trajectory, Output, K extends string = st
|
|
|
61
63
|
batchSize?: number;
|
|
62
64
|
/** Ceiling on rollouts. Defaults to one pass over the trainingSet. */
|
|
63
65
|
maxMetricCalls?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Ceiling on dollars this pass may spend, checked between batches. Harvesting
|
|
68
|
+
* runs on its own evaluator, so a caller bounding spend has to say so here.
|
|
69
|
+
*/
|
|
70
|
+
maxCostUsd?: number;
|
|
64
71
|
/** Shuffles the trainingSet first, so demos are not all drawn from its head. */
|
|
65
72
|
rng?: Rng;
|
|
66
73
|
renderDemo?: DemoRenderer<Datum, Output>;
|
|
@@ -85,4 +92,4 @@ declare function formatDemos<Datum, Output>(demos: readonly Demo<Datum, Output>[
|
|
|
85
92
|
*/
|
|
86
93
|
declare function parseDemos(text: string): Demo[];
|
|
87
94
|
//#endregion
|
|
88
|
-
export {
|
|
95
|
+
export { harvestFewShotExamples as a, formatDemos as i, Demo as n, parseDemos as o, DemoRenderer as r, BootstrapResult as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as Adapter, l as Candidate, v as UsageTotals } from "./reporting-DQbAohc9.cjs";
|
|
2
2
|
import { t as Rng } from "./rng-BR5MOedA.cjs";
|
|
3
3
|
//#region src/demos.d.ts
|
|
4
4
|
/**
|
|
@@ -23,6 +23,8 @@ interface BootstrapResult<Datum, Output> {
|
|
|
23
23
|
block: string;
|
|
24
24
|
/** Rollouts this cost. Bootstrapping is cheap, not free. */
|
|
25
25
|
metricCalls: number;
|
|
26
|
+
/** Tokens and dollars this cost, for a caller that bounds spend. */
|
|
27
|
+
usage: UsageTotals;
|
|
26
28
|
attempted: number;
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
@@ -36,7 +38,7 @@ interface BootstrapResult<Datum, Output> {
|
|
|
36
38
|
* examples on what the output should look like — so a seed carrying both
|
|
37
39
|
* starts somewhere neither reaches alone.
|
|
38
40
|
*/
|
|
39
|
-
declare function
|
|
41
|
+
declare function harvestFewShotExamples<Datum, Trajectory, Output, K extends string = string>(args: {
|
|
40
42
|
adapter: Adapter<Datum, Trajectory, Output, K>;
|
|
41
43
|
/** The candidate to run. Usually the seed, sometimes a run's winner. */
|
|
42
44
|
candidate: Candidate<K>;
|
|
@@ -61,6 +63,11 @@ declare function bootstrapDemos<Datum, Trajectory, Output, K extends string = st
|
|
|
61
63
|
batchSize?: number;
|
|
62
64
|
/** Ceiling on rollouts. Defaults to one pass over the trainingSet. */
|
|
63
65
|
maxMetricCalls?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Ceiling on dollars this pass may spend, checked between batches. Harvesting
|
|
68
|
+
* runs on its own evaluator, so a caller bounding spend has to say so here.
|
|
69
|
+
*/
|
|
70
|
+
maxCostUsd?: number;
|
|
64
71
|
/** Shuffles the trainingSet first, so demos are not all drawn from its head. */
|
|
65
72
|
rng?: Rng;
|
|
66
73
|
renderDemo?: DemoRenderer<Datum, Output>;
|
|
@@ -85,4 +92,4 @@ declare function formatDemos<Datum, Output>(demos: readonly Demo<Datum, Output>[
|
|
|
85
92
|
*/
|
|
86
93
|
declare function parseDemos(text: string): Demo[];
|
|
87
94
|
//#endregion
|
|
88
|
-
export {
|
|
95
|
+
export { harvestFewShotExamples as a, formatDemos as i, Demo as n, parseDemos as o, DemoRenderer as r, BootstrapResult as t };
|