textopt 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +24 -6
  2. package/dist/bootstrap-search/index.cjs +29 -23
  3. package/dist/bootstrap-search/index.d.cts +3 -3
  4. package/dist/bootstrap-search/index.d.mts +3 -3
  5. package/dist/bootstrap-search/index.mjs +9 -3
  6. package/dist/{demos-D2o0qSSo.cjs → demos-9v5ts7F3.cjs} +4 -4
  7. package/dist/{demos-1b7JiUue.d.mts → demos-ASsSXYXA.d.mts} +1 -1
  8. package/dist/{demos-DE2oxNWX.mjs → demos-Brobjfuc.mjs} +1 -1
  9. package/dist/{demos-CU9dy2oT.d.cts → demos-ByaLZy-Z.d.cts} +1 -1
  10. package/dist/file-cache.cjs +16 -5
  11. package/dist/file-cache.d.cts +13 -0
  12. package/dist/file-cache.d.mts +13 -0
  13. package/dist/file-cache.mjs +16 -5
  14. package/dist/gepa/index.cjs +87 -44
  15. package/dist/gepa/index.d.cts +8 -6
  16. package/dist/gepa/index.d.mts +8 -6
  17. package/dist/gepa/index.mjs +55 -12
  18. package/dist/index.cjs +44 -19
  19. package/dist/index.d.cts +37 -5
  20. package/dist/index.d.mts +37 -5
  21. package/dist/index.mjs +29 -6
  22. package/dist/mipro/index.cjs +31 -25
  23. package/dist/mipro/index.d.cts +3 -3
  24. package/dist/mipro/index.d.mts +3 -3
  25. package/dist/mipro/index.mjs +9 -3
  26. package/dist/opro/index.cjs +31 -25
  27. package/dist/opro/index.d.cts +2 -2
  28. package/dist/opro/index.d.mts +2 -2
  29. package/dist/opro/index.mjs +8 -2
  30. package/dist/{optimizer-Bh5DPRMH.d.cts → optimizer-4Zv-Zt2t.d.cts} +41 -2
  31. package/dist/{optimizer-Ck6-e_8o.d.mts → optimizer-Ds5mzYjz.d.mts} +41 -2
  32. package/dist/random-search/index.cjs +27 -21
  33. package/dist/random-search/index.d.cts +2 -2
  34. package/dist/random-search/index.d.mts +2 -2
  35. package/dist/random-search/index.mjs +8 -2
  36. package/dist/{reflection-LRaAZP4e.d.mts → reflection-CMezGu6u.d.mts} +32 -4
  37. package/dist/{reflection-Dt3QrXhM.d.cts → reflection-D0A7eahD.d.cts} +32 -4
  38. package/dist/{reporting-DQbAohc9.d.cts → reporting-bq007_2z.d.cts} +55 -1
  39. package/dist/{reporting-DQbAohc9.d.mts → reporting-bq007_2z.d.mts} +55 -1
  40. package/dist/simba/index.cjs +31 -25
  41. package/dist/simba/index.d.cts +24 -5
  42. package/dist/simba/index.d.mts +24 -5
  43. package/dist/simba/index.mjs +9 -3
  44. package/dist/testing.d.cts +2 -2
  45. package/dist/testing.d.mts +2 -2
  46. package/dist/{reporting-CNHzbJC-.cjs → warnings-CWRJF-jA.cjs} +63 -0
  47. package/dist/{reporting-DY-DC4HG.mjs → warnings-OxvDi9kN.mjs} +52 -1
  48. package/docs/adapters.md +169 -0
  49. package/docs/benchmark.md +90 -0
  50. package/docs/data-prep.md +113 -0
  51. package/docs/distillation.md +128 -0
  52. package/docs/evaluation.md +87 -0
  53. package/docs/metric-preflight.md +132 -0
  54. package/docs/optimizers.md +293 -0
  55. package/docs/tuning.md +130 -0
  56. package/package.json +3 -2
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_reporting = require("../reporting-CNHzbJC-.cjs");
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");
@@ -49,7 +49,7 @@ var OproOptimizer = class {
49
49
  task
50
50
  });
51
51
  } finally {
52
- await require_reporting.flushReporters(task.reporters ?? []);
52
+ await require_warnings.flushReporters(task.reporters ?? []);
53
53
  }
54
54
  }
55
55
  };
@@ -95,10 +95,14 @@ function buildOproPrompt(args) {
95
95
  async function runOpro(args) {
96
96
  const { config, task } = args;
97
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;
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);
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);
102
106
  if (trainingSet.length === 0) throw new Error("optimize requires a non-empty trainingSet");
103
107
  if (validationSet.length === 0) throw new Error("optimize requires a non-empty validationSet");
104
108
  if (components.length === 0) throw new Error("optimize requires a seed candidate with at least one component");
@@ -111,7 +115,7 @@ async function runOpro(args) {
111
115
  datum,
112
116
  index
113
117
  })) ?? [];
114
- const fingerprint = require_reporting.runFingerprint({
118
+ const fingerprint = require_warnings.runFingerprint({
115
119
  seedCandidate,
116
120
  trainingIds: trainingSet.map((datum, index) => instanceId({
117
121
  datum,
@@ -121,17 +125,17 @@ async function runOpro(args) {
121
125
  seed,
122
126
  ...cacheNamespace === void 0 ? {} : { cacheNamespace }
123
127
  });
124
- require_reporting.assertResumable({
128
+ require_warnings.assertResumable({
125
129
  fingerprint,
126
130
  ...resumeFrom === void 0 ? {} : { snapshot: resumeFrom }
127
131
  });
128
132
  const rng = require_rng.createSeededRng(seed, resumeFrom?.rngState);
129
- const budget = require_reporting.createBudget({
133
+ const budget = require_warnings.createBudget({
130
134
  maxMetricCalls,
131
135
  spent: resumeFrom?.metricCalls ?? 0
132
136
  });
133
- const evaluationCache = cache === false ? void 0 : cache ?? require_reporting.createMemoryCache();
134
- const evaluator = require_reporting.createEvaluator({
137
+ const evaluationCache = cache === false ? void 0 : cache ?? require_warnings.createMemoryCache();
138
+ const evaluator = require_warnings.createEvaluator({
135
139
  adapter,
136
140
  budget,
137
141
  ...retry === void 0 ? {} : { retry },
@@ -160,7 +164,7 @@ async function runOpro(args) {
160
164
  function contextOf(candidate, component) {
161
165
  const rest = {};
162
166
  for (const name of components) if (name !== component) rest[name] = candidate[name];
163
- return require_reporting.stableHash(rest);
167
+ return require_warnings.stableHash(rest);
164
168
  }
165
169
  const trajectory = [];
166
170
  let round = resumeFrom?.round ?? 0;
@@ -212,7 +216,7 @@ async function runOpro(args) {
212
216
  });
213
217
  }
214
218
  const seedEvaluation = resumeFrom === void 0 ? await sweep(seedCandidate, "seed") : void 0;
215
- const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore : require_reporting.requireMeasuredMean({
219
+ const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore : require_warnings.requireMeasuredMean({
216
220
  batch: seedEvaluation,
217
221
  phase: "seed"
218
222
  });
@@ -222,7 +226,7 @@ async function runOpro(args) {
222
226
  candidateId: 0,
223
227
  candidate: seedCandidate,
224
228
  aggregateScore: seedScore,
225
- instanceScores: require_reporting.instanceRow(seedEvaluation),
229
+ instanceScores: require_warnings.instanceRow(seedEvaluation),
226
230
  ...trackBestOutputs ? { outputs: seedEvaluation.outputs } : {}
227
231
  });
228
232
  let best = resumeFrom?.best ?? seedCandidate;
@@ -233,7 +237,7 @@ async function runOpro(args) {
233
237
  let reported = resumeFrom?.reported ?? seedCandidate;
234
238
  let lastSwept = resumeFrom === void 0 ? seedCandidate : resumeFrom.incumbentSwept ? best : {};
235
239
  let bestSearchScore = resumeFrom?.bestSearchScore ?? seedScore;
236
- if (resumeFrom === void 0 && scoringSet !== void 0) bestSearchScore = require_reporting.requireMeasuredMean({
240
+ if (resumeFrom === void 0 && scoringSet !== void 0) bestSearchScore = require_warnings.requireMeasuredMean({
237
241
  batch: await screen(seedCandidate, "seed"),
238
242
  phase: "seed"
239
243
  });
@@ -257,7 +261,7 @@ async function runOpro(args) {
257
261
  candidateId: acceptedCandidates,
258
262
  candidate: args.candidate,
259
263
  aggregateScore: args.score,
260
- instanceScores: require_reporting.instanceRow(args.evaluation),
264
+ instanceScores: require_warnings.instanceRow(args.evaluation),
261
265
  ...trackBestOutputs ? { outputs: args.evaluation.outputs } : {}
262
266
  });
263
267
  }
@@ -265,7 +269,7 @@ async function runOpro(args) {
265
269
  if (best === lastSwept || !budget.canAfford(validationSet.length)) return "ok";
266
270
  try {
267
271
  const evaluation = await sweep(best, "validation");
268
- const full = require_reporting.measuredMean(evaluation);
272
+ const full = require_warnings.measuredMean(evaluation);
269
273
  lastSwept = best;
270
274
  if (full !== void 0 && full > bestScore) {
271
275
  reported = best;
@@ -278,7 +282,7 @@ async function runOpro(args) {
278
282
  });
279
283
  }
280
284
  } catch (err) {
281
- if (err instanceof require_reporting.BudgetExhausted || signal?.aborted) return "stop";
285
+ if (err instanceof require_warnings.BudgetExhausted || signal?.aborted) return "stop";
282
286
  throw err;
283
287
  }
284
288
  return "ok";
@@ -334,7 +338,7 @@ async function runOpro(args) {
334
338
  stopReason = "proposalsExhausted";
335
339
  break;
336
340
  }
337
- if (require_reporting.costExhausted({
341
+ if (require_warnings.costExhausted({
338
342
  usage: evaluator.usage(),
339
343
  maxCostUsd
340
344
  })) {
@@ -409,7 +413,7 @@ async function runOpro(args) {
409
413
  try {
410
414
  return { evaluation: await screen(candidate, "validation") };
411
415
  } catch (err) {
412
- if (err instanceof require_reporting.BudgetExhausted) return { stop: "budgetExhausted" };
416
+ if (err instanceof require_warnings.BudgetExhausted) return { stop: "budgetExhausted" };
413
417
  if (signal?.aborted) return { stop: "aborted" };
414
418
  throw err;
415
419
  }
@@ -423,7 +427,7 @@ async function runOpro(args) {
423
427
  const candidate = scheduled[index];
424
428
  const text = candidate[component];
425
429
  const evaluation = outcome.evaluation;
426
- const score = require_reporting.measuredMean(evaluation);
430
+ const score = require_warnings.measuredMean(evaluation);
427
431
  if (score === void 0) continue;
428
432
  const accepted = score > bestSearchScore;
429
433
  history.push({
@@ -494,15 +498,16 @@ async function runOpro(args) {
494
498
  iteration: round,
495
499
  charge: false
496
500
  });
497
- const testScore = heldOut === void 0 ? void 0 : require_reporting.measuredMean(heldOut);
501
+ const testScore = heldOut === void 0 ? void 0 : require_warnings.measuredMean(heldOut);
498
502
  emit({
499
503
  type: "finish",
500
504
  reason: stopReason,
505
+ warnings,
501
506
  bestCandidateId: acceptedCandidates,
502
507
  bestScore,
503
508
  metricCalls: budget.spent(),
504
509
  ...testScore === void 0 ? {} : { testScore },
505
- ...heldOut === void 0 ? {} : { testInstanceScores: require_reporting.instanceRow(heldOut) },
510
+ ...heldOut === void 0 ? {} : { testInstanceScores: require_warnings.instanceRow(heldOut) },
506
511
  ...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
507
512
  });
508
513
  return {
@@ -522,6 +527,7 @@ async function runOpro(args) {
522
527
  metricCalls: budget.spent(),
523
528
  reflectionCalls,
524
529
  cacheHits: evaluator.cacheHits(),
530
+ warnings,
525
531
  stopReason
526
532
  };
527
533
  }
@@ -562,5 +568,5 @@ function assertConfig(config) {
562
568
  //#endregion
563
569
  exports.OproOptimizer = OproOptimizer;
564
570
  exports.buildOproPrompt = buildOproPrompt;
565
- exports.isCandidateAccepted = require_reporting.isCandidateAccepted;
566
- exports.isRunFinished = require_reporting.isRunFinished;
571
+ exports.isCandidateAccepted = require_warnings.isCandidateAccepted;
572
+ exports.isRunFinished = require_warnings.isRunFinished;
@@ -1,6 +1,6 @@
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";
1
+ import { S as UsageTotals, a as RunFinished, f as Adapter, i as Reporter, n as OptimizerEvent, o as isCandidateAccepted, p as Candidate, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, x as TextModel } from "../reporting-bq007_2z.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-Bh5DPRMH.cjs";
3
+ import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-4Zv-Zt2t.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. */
@@ -1,6 +1,6 @@
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.mjs";
1
+ import { S as UsageTotals, a as RunFinished, f as Adapter, i as Reporter, n as OptimizerEvent, o as isCandidateAccepted, p as Candidate, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, x as TextModel } from "../reporting-bq007_2z.mjs";
2
2
  import { n as EvaluationCache, t as CachedScore } from "../cache-CuSo0NJ8.mjs";
3
- import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-Ck6-e_8o.mjs";
3
+ import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-Ds5mzYjz.mjs";
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. */
@@ -1,4 +1,4 @@
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, y as stableHash } from "../reporting-DY-DC4HG.mjs";
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, x as stableHash, y as createMemoryCache } from "../warnings-OxvDi9kN.mjs";
2
2
  import { t as mapWithConcurrency } from "../concurrency-D58PWeSk.mjs";
3
3
  import { t as parseProposedText } from "../text--v4Ffbus.mjs";
4
4
  import { t as createSeededRng } from "../rng-Dtc5eZ_W.mjs";
@@ -94,7 +94,11 @@ function buildOproPrompt(args) {
94
94
  async function runOpro(args) {
95
95
  const { config, task } = args;
96
96
  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;
97
- const { seedCandidate, trainingSet, validationSet = trainingSet, testSet, adapter, reflect, maxMetricCalls, renderDatum = renderDefault, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
97
+ const { seedCandidate, trainingSet, validationSet: requestedValidationSet, testSet, adapter, reflect, maxMetricCalls, renderDatum = renderDefault, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
98
+ const { validationSet, warnings } = resolveValidationSet({
99
+ validationSet: requestedValidationSet,
100
+ trainingSet
101
+ });
98
102
  const emit = createEmitter(reporters);
99
103
  const deadline = createDeadline({ maxWallClockMs });
100
104
  const components = componentNames(seedCandidate);
@@ -497,6 +501,7 @@ async function runOpro(args) {
497
501
  emit({
498
502
  type: "finish",
499
503
  reason: stopReason,
504
+ warnings,
500
505
  bestCandidateId: acceptedCandidates,
501
506
  bestScore,
502
507
  metricCalls: budget.spent(),
@@ -521,6 +526,7 @@ async function runOpro(args) {
521
526
  metricCalls: budget.spent(),
522
527
  reflectionCalls,
523
528
  cacheHits: evaluator.cacheHits(),
529
+ warnings,
524
530
  stopReason
525
531
  };
526
532
  }
@@ -1,4 +1,4 @@
1
- import { c as Adapter, d as EvaluationBatch, l as Candidate, m as EvaluationSplit, p as EvaluationPhase, v as UsageTotals } from "./reporting-DQbAohc9.cjs";
1
+ import { S as UsageTotals, _ as EvaluationPhase, c as RunWarning, f as Adapter, h as EvaluationBatch, p as Candidate, v as EvaluationSplit } from "./reporting-bq007_2z.cjs";
2
2
  import { n as EvaluationCache, t as CachedScore } from "./cache-CuSo0NJ8.cjs";
3
3
  //#region src/budget.d.ts
4
4
  interface Budget {
@@ -214,8 +214,28 @@ declare function requireMeasuredMean(args: {
214
214
  */
215
215
  interface OptimizerTask<Datum, Trajectory = unknown, Output = unknown, K extends string = string> {
216
216
  seedCandidate: Candidate<K>;
217
+ /**
218
+ * Instances the search draws evidence from. Reflective optimizers mine these
219
+ * for what a candidate got wrong, so a training row earns its place by being
220
+ * diagnostic — a row every candidate already passes teaches the rewriter
221
+ * nothing.
222
+ *
223
+ * @see docs/data-prep.md
224
+ */
217
225
  trainingSet: readonly Datum[];
218
- validationSet?: readonly Datum[];
226
+ /**
227
+ * Instances the search selects candidates against. Defaults to
228
+ * `trainingSet`, which is the right default for a first run and the wrong
229
+ * number to report from one — the result carries a warning saying so.
230
+ * `"reuseTraining"` is that same default with the caller's name on it, and
231
+ * carries no warning.
232
+ *
233
+ * Split by group rather than by row: near-duplicate instances that straddle
234
+ * the boundary leak, and the run reports a score nothing earned.
235
+ *
236
+ * @see docs/data-prep.md
237
+ */
238
+ validationSet?: readonly Datum[] | "reuseTraining";
219
239
  /**
220
240
  * `NoInfer` keeps the adapter out of `K`'s inference: an adapter built by a
221
241
  * factory knows nothing about component names, and one inference candidate of
@@ -229,6 +249,18 @@ interface OptimizerTask<Datum, Trajectory = unknown, Output = unknown, K extends
229
249
  * number in a result that no candidate was ever selected against.
230
250
  */
231
251
  testSet?: readonly Datum[];
252
+ /**
253
+ * Scored rollouts the search may spend. Cache hits do not count, and test
254
+ * rollouts are outside it entirely.
255
+ *
256
+ * Spending it is only worth anything if the metric separates candidates
257
+ * first: a metric that scores every candidate alike turns the whole budget
258
+ * into ranked ties, and the run reports a stop reason that looks like any
259
+ * other.
260
+ *
261
+ * @see docs/metric-preflight.md
262
+ * @see docs/tuning.md
263
+ */
232
264
  maxMetricCalls: number;
233
265
  /**
234
266
  * Dollars the run may spend, as reported by the adapter's usage. Checked
@@ -314,6 +346,13 @@ interface OptimizerResult<K extends string, Stop extends string, Output = unknow
314
346
  */
315
347
  testUsage?: UsageTotals;
316
348
  stopReason: Stop;
349
+ /**
350
+ * What this run cannot say about itself from its own numbers — selection
351
+ * that reused the training instances, a seed the metric could not separate.
352
+ * Empty when there is nothing to say. Never fatal, and repeated on the
353
+ * `finish` event so a reporter sees them next to the score.
354
+ */
355
+ warnings: RunWarning[];
317
356
  }
318
357
  /**
319
358
  * An optimizer: a task in, the best candidate it found out. Exactly one method.
@@ -1,4 +1,4 @@
1
- import { c as Adapter, d as EvaluationBatch, l as Candidate, m as EvaluationSplit, p as EvaluationPhase, v as UsageTotals } from "./reporting-DQbAohc9.mjs";
1
+ import { S as UsageTotals, _ as EvaluationPhase, c as RunWarning, f as Adapter, h as EvaluationBatch, p as Candidate, v as EvaluationSplit } from "./reporting-bq007_2z.mjs";
2
2
  import { n as EvaluationCache, t as CachedScore } from "./cache-CuSo0NJ8.mjs";
3
3
  //#region src/budget.d.ts
4
4
  interface Budget {
@@ -214,8 +214,28 @@ declare function requireMeasuredMean(args: {
214
214
  */
215
215
  interface OptimizerTask<Datum, Trajectory = unknown, Output = unknown, K extends string = string> {
216
216
  seedCandidate: Candidate<K>;
217
+ /**
218
+ * Instances the search draws evidence from. Reflective optimizers mine these
219
+ * for what a candidate got wrong, so a training row earns its place by being
220
+ * diagnostic — a row every candidate already passes teaches the rewriter
221
+ * nothing.
222
+ *
223
+ * @see docs/data-prep.md
224
+ */
217
225
  trainingSet: readonly Datum[];
218
- validationSet?: readonly Datum[];
226
+ /**
227
+ * Instances the search selects candidates against. Defaults to
228
+ * `trainingSet`, which is the right default for a first run and the wrong
229
+ * number to report from one — the result carries a warning saying so.
230
+ * `"reuseTraining"` is that same default with the caller's name on it, and
231
+ * carries no warning.
232
+ *
233
+ * Split by group rather than by row: near-duplicate instances that straddle
234
+ * the boundary leak, and the run reports a score nothing earned.
235
+ *
236
+ * @see docs/data-prep.md
237
+ */
238
+ validationSet?: readonly Datum[] | "reuseTraining";
219
239
  /**
220
240
  * `NoInfer` keeps the adapter out of `K`'s inference: an adapter built by a
221
241
  * factory knows nothing about component names, and one inference candidate of
@@ -229,6 +249,18 @@ interface OptimizerTask<Datum, Trajectory = unknown, Output = unknown, K extends
229
249
  * number in a result that no candidate was ever selected against.
230
250
  */
231
251
  testSet?: readonly Datum[];
252
+ /**
253
+ * Scored rollouts the search may spend. Cache hits do not count, and test
254
+ * rollouts are outside it entirely.
255
+ *
256
+ * Spending it is only worth anything if the metric separates candidates
257
+ * first: a metric that scores every candidate alike turns the whole budget
258
+ * into ranked ties, and the run reports a stop reason that looks like any
259
+ * other.
260
+ *
261
+ * @see docs/metric-preflight.md
262
+ * @see docs/tuning.md
263
+ */
232
264
  maxMetricCalls: number;
233
265
  /**
234
266
  * Dollars the run may spend, as reported by the adapter's usage. Checked
@@ -314,6 +346,13 @@ interface OptimizerResult<K extends string, Stop extends string, Output = unknow
314
346
  */
315
347
  testUsage?: UsageTotals;
316
348
  stopReason: Stop;
349
+ /**
350
+ * What this run cannot say about itself from its own numbers — selection
351
+ * that reused the training instances, a seed the metric could not separate.
352
+ * Empty when there is nothing to say. Never fatal, and repeated on the
353
+ * `finish` event so a reporter sees them next to the score.
354
+ */
355
+ warnings: RunWarning[];
317
356
  }
318
357
  /**
319
358
  * An optimizer: a task in, the best candidate it found out. Exactly one method.
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_reporting = require("../reporting-CNHzbJC-.cjs");
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
  //#region src/random-search/optimize.ts
@@ -39,7 +39,7 @@ var RandomSearchOptimizer = class {
39
39
  task
40
40
  });
41
41
  } finally {
42
- await require_reporting.flushReporters(task.reporters ?? []);
42
+ await require_warnings.flushReporters(task.reporters ?? []);
43
43
  }
44
44
  }
45
45
  };
@@ -67,10 +67,14 @@ function buildParaphrasePrompt(args) {
67
67
  async function runRandomSearch(args) {
68
68
  const { config, task } = args;
69
69
  const { variants = DEFAULT_VARIANTS, concurrency = 1, maxRounds = Number.POSITIVE_INFINITY, buildPrompt = buildParaphrasePrompt, trackBestOutputs = false, checkpointCache = true } = config;
70
- const { seedCandidate, trainingSet, validationSet = trainingSet, testSet, adapter, reflect, maxMetricCalls, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = require_reporting.defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
71
- const emit = require_reporting.createEmitter(reporters);
72
- const deadline = require_reporting.createDeadline({ maxWallClockMs });
73
- const components = require_reporting.componentNames(seedCandidate);
70
+ const { seedCandidate, trainingSet, validationSet: requestedValidationSet, testSet, adapter, reflect, maxMetricCalls, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = require_warnings.defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
71
+ const { validationSet, warnings } = require_warnings.resolveValidationSet({
72
+ validationSet: requestedValidationSet,
73
+ trainingSet
74
+ });
75
+ const emit = require_warnings.createEmitter(reporters);
76
+ const deadline = require_warnings.createDeadline({ maxWallClockMs });
77
+ const components = require_warnings.componentNames(seedCandidate);
74
78
  if (trainingSet.length === 0) throw new Error("optimize requires a non-empty trainingSet");
75
79
  if (validationSet.length === 0) throw new Error("optimize requires a non-empty validationSet");
76
80
  if (components.length === 0) throw new Error("optimize requires a seed candidate with at least one component");
@@ -83,7 +87,7 @@ async function runRandomSearch(args) {
83
87
  datum,
84
88
  index
85
89
  })) ?? [];
86
- const fingerprint = require_reporting.runFingerprint({
90
+ const fingerprint = require_warnings.runFingerprint({
87
91
  seedCandidate,
88
92
  trainingIds: trainingSet.map((datum, index) => instanceId({
89
93
  datum,
@@ -92,16 +96,16 @@ async function runRandomSearch(args) {
92
96
  validationIds,
93
97
  ...cacheNamespace === void 0 ? {} : { cacheNamespace }
94
98
  });
95
- require_reporting.assertResumable({
99
+ require_warnings.assertResumable({
96
100
  fingerprint,
97
101
  ...resumeFrom === void 0 ? {} : { snapshot: resumeFrom }
98
102
  });
99
- const budget = require_reporting.createBudget({
103
+ const budget = require_warnings.createBudget({
100
104
  maxMetricCalls,
101
105
  spent: resumeFrom?.metricCalls ?? 0
102
106
  });
103
- const evaluationCache = cache === false ? void 0 : cache ?? require_reporting.createMemoryCache();
104
- const evaluator = require_reporting.createEvaluator({
107
+ const evaluationCache = cache === false ? void 0 : cache ?? require_warnings.createMemoryCache();
108
+ const evaluator = require_warnings.createEvaluator({
105
109
  adapter,
106
110
  budget,
107
111
  ...retry === void 0 ? {} : { retry },
@@ -171,7 +175,7 @@ async function runRandomSearch(args) {
171
175
  candidate: seedCandidate,
172
176
  phase: "seed"
173
177
  }) : void 0;
174
- const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore : require_reporting.requireMeasuredMean({
178
+ const seedScore = seedEvaluation === void 0 ? resumeFrom.seedScore : require_warnings.requireMeasuredMean({
175
179
  batch: seedEvaluation,
176
180
  phase: "seed"
177
181
  });
@@ -181,7 +185,7 @@ async function runRandomSearch(args) {
181
185
  candidateId: 0,
182
186
  candidate: seedCandidate,
183
187
  aggregateScore: seedScore,
184
- instanceScores: require_reporting.instanceRow(seedEvaluation),
188
+ instanceScores: require_warnings.instanceRow(seedEvaluation),
185
189
  ...trackBestOutputs ? { outputs: seedEvaluation.outputs } : {}
186
190
  });
187
191
  let best = resumeFrom?.best ?? seedCandidate;
@@ -195,7 +199,7 @@ async function runRandomSearch(args) {
195
199
  stopReason = "aborted";
196
200
  break;
197
201
  }
198
- if (require_reporting.costExhausted({
202
+ if (require_warnings.costExhausted({
199
203
  usage: evaluator.usage(),
200
204
  maxCostUsd
201
205
  })) {
@@ -268,7 +272,7 @@ async function runRandomSearch(args) {
268
272
  phase: "validation"
269
273
  }) };
270
274
  } catch (err) {
271
- if (err instanceof require_reporting.BudgetExhausted) return { stop: "budgetExhausted" };
275
+ if (err instanceof require_warnings.BudgetExhausted) return { stop: "budgetExhausted" };
272
276
  if (signal?.aborted) return { stop: "aborted" };
273
277
  throw err;
274
278
  }
@@ -280,7 +284,7 @@ async function runRandomSearch(args) {
280
284
  break;
281
285
  }
282
286
  variantsEvaluated += 1;
283
- const score = require_reporting.measuredMean(outcome.evaluation);
287
+ const score = require_warnings.measuredMean(outcome.evaluation);
284
288
  if (score !== void 0 && score > bestScore) {
285
289
  const candidate = scheduled[index];
286
290
  acceptedCandidates += 1;
@@ -290,7 +294,7 @@ async function runRandomSearch(args) {
290
294
  candidateId: acceptedCandidates,
291
295
  candidate,
292
296
  aggregateScore: score,
293
- instanceScores: require_reporting.instanceRow(outcome.evaluation),
297
+ instanceScores: require_warnings.instanceRow(outcome.evaluation),
294
298
  ...trackBestOutputs ? { outputs: outcome.evaluation.outputs } : {}
295
299
  });
296
300
  best = candidate;
@@ -321,15 +325,16 @@ async function runRandomSearch(args) {
321
325
  iteration: round,
322
326
  charge: false
323
327
  });
324
- const testScore = heldOut === void 0 ? void 0 : require_reporting.measuredMean(heldOut);
328
+ const testScore = heldOut === void 0 ? void 0 : require_warnings.measuredMean(heldOut);
325
329
  emit({
326
330
  type: "finish",
327
331
  reason: stopReason,
332
+ warnings,
328
333
  bestCandidateId: acceptedCandidates,
329
334
  bestScore,
330
335
  metricCalls: budget.spent(),
331
336
  ...testScore === void 0 ? {} : { testScore },
332
- ...heldOut === void 0 ? {} : { testInstanceScores: require_reporting.instanceRow(heldOut) },
337
+ ...heldOut === void 0 ? {} : { testInstanceScores: require_warnings.instanceRow(heldOut) },
333
338
  ...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
334
339
  });
335
340
  return {
@@ -349,6 +354,7 @@ async function runRandomSearch(args) {
349
354
  metricCalls: budget.spent(),
350
355
  reflectionCalls,
351
356
  cacheHits: evaluator.cacheHits(),
357
+ warnings,
352
358
  stopReason
353
359
  };
354
360
  }
@@ -361,5 +367,5 @@ function assertConfig(config) {
361
367
  //#endregion
362
368
  exports.RandomSearchOptimizer = RandomSearchOptimizer;
363
369
  exports.buildParaphrasePrompt = buildParaphrasePrompt;
364
- exports.isCandidateAccepted = require_reporting.isCandidateAccepted;
365
- exports.isRunFinished = require_reporting.isRunFinished;
370
+ exports.isCandidateAccepted = require_warnings.isCandidateAccepted;
371
+ exports.isRunFinished = require_warnings.isRunFinished;
@@ -1,6 +1,6 @@
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";
1
+ import { S as UsageTotals, a as RunFinished, f as Adapter, i as Reporter, n as OptimizerEvent, o as isCandidateAccepted, p as Candidate, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, x as TextModel } from "../reporting-bq007_2z.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-Bh5DPRMH.cjs";
3
+ import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-4Zv-Zt2t.cjs";
4
4
  //#region src/random-search/optimize.d.ts
5
5
  /** Builds the prompt one variant is drawn from. */
6
6
  type ParaphrasePromptBuilder = (args: {
@@ -1,6 +1,6 @@
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.mjs";
1
+ import { S as UsageTotals, a as RunFinished, f as Adapter, i as Reporter, n as OptimizerEvent, o as isCandidateAccepted, p as Candidate, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, x as TextModel } from "../reporting-bq007_2z.mjs";
2
2
  import { n as EvaluationCache, t as CachedScore } from "../cache-CuSo0NJ8.mjs";
3
- import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-Ck6-e_8o.mjs";
3
+ import { n as OptimizerResult, r as OptimizerTask, s as EvaluationEvent, t as Optimizer } from "../optimizer-Ds5mzYjz.mjs";
4
4
  //#region src/random-search/optimize.d.ts
5
5
  /** Builds the prompt one variant is drawn from. */
6
6
  type ParaphrasePromptBuilder = (args: {
@@ -1,4 +1,4 @@
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";
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
3
  import { t as parseProposedText } from "../text--v4Ffbus.mjs";
4
4
  //#region src/random-search/optimize.ts
@@ -66,7 +66,11 @@ function buildParaphrasePrompt(args) {
66
66
  async function runRandomSearch(args) {
67
67
  const { config, task } = args;
68
68
  const { variants = DEFAULT_VARIANTS, concurrency = 1, maxRounds = Number.POSITIVE_INFINITY, buildPrompt = buildParaphrasePrompt, trackBestOutputs = false, checkpointCache = true } = config;
69
- const { seedCandidate, trainingSet, validationSet = trainingSet, testSet, adapter, reflect, maxMetricCalls, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
69
+ const { seedCandidate, trainingSet, validationSet: requestedValidationSet, testSet, adapter, reflect, maxMetricCalls, cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
70
+ const { validationSet, warnings } = resolveValidationSet({
71
+ validationSet: requestedValidationSet,
72
+ trainingSet
73
+ });
70
74
  const emit = createEmitter(reporters);
71
75
  const deadline = createDeadline({ maxWallClockMs });
72
76
  const components = componentNames(seedCandidate);
@@ -324,6 +328,7 @@ async function runRandomSearch(args) {
324
328
  emit({
325
329
  type: "finish",
326
330
  reason: stopReason,
331
+ warnings,
327
332
  bestCandidateId: acceptedCandidates,
328
333
  bestScore,
329
334
  metricCalls: budget.spent(),
@@ -348,6 +353,7 @@ async function runRandomSearch(args) {
348
353
  metricCalls: budget.spent(),
349
354
  reflectionCalls,
350
355
  cacheHits: evaluator.cacheHits(),
356
+ warnings,
351
357
  stopReason
352
358
  };
353
359
  }