textopt 0.0.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/LICENSE +21 -0
- package/README.md +509 -0
- package/dist/bootstrap-search/index.cjs +308 -0
- package/dist/bootstrap-search/index.d.cts +162 -0
- package/dist/bootstrap-search/index.d.mts +162 -0
- package/dist/bootstrap-search/index.mjs +307 -0
- package/dist/cache-CuSo0NJ8.d.cts +24 -0
- package/dist/cache-CuSo0NJ8.d.mts +24 -0
- package/dist/concurrency-C-cFzWW2.cjs +44 -0
- package/dist/concurrency-D58PWeSk.mjs +39 -0
- package/dist/demos-B0pVQjYC.d.mts +88 -0
- package/dist/demos-B9BJiNKz.cjs +143 -0
- package/dist/demos-BTuzFNsp.d.cts +88 -0
- package/dist/demos-Degx6UmP.mjs +126 -0
- package/dist/evaluation-BV0nSZVx.mjs +521 -0
- package/dist/evaluation-OZOp6TB7.cjs +598 -0
- package/dist/file-cache.cjs +70 -0
- package/dist/file-cache.d.cts +21 -0
- package/dist/file-cache.d.mts +21 -0
- package/dist/file-cache.mjs +69 -0
- package/dist/gepa/index.cjs +1671 -0
- package/dist/gepa/index.d.cts +385 -0
- package/dist/gepa/index.d.mts +385 -0
- package/dist/gepa/index.mjs +1652 -0
- package/dist/index.cjs +266 -0
- package/dist/index.d.cts +221 -0
- package/dist/index.d.mts +221 -0
- package/dist/index.mjs +245 -0
- package/dist/math-COOofUyv.cjs +101 -0
- package/dist/math-DhrDmpFS.mjs +78 -0
- package/dist/mipro/index.cjs +739 -0
- package/dist/mipro/index.d.cts +372 -0
- package/dist/mipro/index.d.mts +372 -0
- package/dist/mipro/index.mjs +736 -0
- package/dist/opro/index.cjs +487 -0
- package/dist/opro/index.d.cts +230 -0
- package/dist/opro/index.d.mts +230 -0
- package/dist/opro/index.mjs +485 -0
- package/dist/optimizer-B7SpRwl7.d.cts +288 -0
- package/dist/optimizer-DqCoth_w.d.mts +288 -0
- package/dist/random-search/index.cjs +321 -0
- package/dist/random-search/index.d.cts +156 -0
- package/dist/random-search/index.d.mts +156 -0
- package/dist/random-search/index.mjs +319 -0
- package/dist/reflection-CQToe-5B.d.cts +283 -0
- package/dist/reflection-Cr_upzU0.d.mts +283 -0
- package/dist/reflection-DRfbk6hu.cjs +249 -0
- package/dist/reflection-mwMhrjs_.mjs +214 -0
- package/dist/rng-BR5MOedA.d.cts +22 -0
- package/dist/rng-BR5MOedA.d.mts +22 -0
- package/dist/rng-DbA_rPIo.cjs +67 -0
- package/dist/rng-Dtc5eZ_W.mjs +62 -0
- package/dist/sampling-CfHt7Gue.mjs +59 -0
- package/dist/sampling-DFo_7RNJ.d.mts +23 -0
- package/dist/sampling-Dars7ctR.cjs +64 -0
- package/dist/sampling-axOwfZf5.d.cts +23 -0
- package/dist/simba/index.cjs +709 -0
- package/dist/simba/index.d.cts +289 -0
- package/dist/simba/index.d.mts +289 -0
- package/dist/simba/index.mjs +700 -0
- package/dist/testing.cjs +155 -0
- package/dist/testing.d.cts +53 -0
- package/dist/testing.d.mts +53 -0
- package/dist/testing.mjs +148 -0
- package/dist/text--v4Ffbus.mjs +21 -0
- package/dist/text-CK_HB3su.cjs +26 -0
- package/dist/types-CWv4IQFF.d.cts +129 -0
- package/dist/types-CWv4IQFF.d.mts +129 -0
- package/package.json +135 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { n as Candidate, t as Adapter, u as TextModel } from "../types-CWv4IQFF.cjs";
|
|
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-B7SpRwl7.cjs";
|
|
4
|
+
//#region src/opro/optimize.d.ts
|
|
5
|
+
/** One instruction that was tried, and what it scored. */
|
|
6
|
+
/** A history entry plus the system state its score was measured in. */
|
|
7
|
+
interface RecordedAttempt extends ScoredAttempt {
|
|
8
|
+
context: string;
|
|
9
|
+
}
|
|
10
|
+
interface ScoredAttempt {
|
|
11
|
+
text: string;
|
|
12
|
+
score: number;
|
|
13
|
+
}
|
|
14
|
+
type OproPromptBuilder = (args: {
|
|
15
|
+
componentName: string;
|
|
16
|
+
/** Attempts so far, ascending by score — the weakest first. */
|
|
17
|
+
history: readonly ScoredAttempt[];
|
|
18
|
+
/** Rendered task inputs, for grounding. Empty when none were requested. */
|
|
19
|
+
exemplars: readonly string[];
|
|
20
|
+
}) => string;
|
|
21
|
+
interface OproConfig {
|
|
22
|
+
/**
|
|
23
|
+
* Instructions drawn per round. Default 8, as in the paper.
|
|
24
|
+
*
|
|
25
|
+
* All eight come from one prompt, so they differ only by the sampling
|
|
26
|
+
* temperature of `reflect`. The paper runs its optimizer at 1.0 and finds
|
|
27
|
+
* below 0.5 explores too little to escape a plateau. At temperature 0 the
|
|
28
|
+
* eight drafts are identical, dedup collapses them to one, and the round
|
|
29
|
+
* costs eight reflection calls to try a single instruction — set a
|
|
30
|
+
* temperature on the model before raising this.
|
|
31
|
+
*/
|
|
32
|
+
proposalsPerRound?: number;
|
|
33
|
+
/** How many of them may be in flight at once. Default 1. */
|
|
34
|
+
concurrency?: number;
|
|
35
|
+
maxRounds?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Reflection is the expensive half of this search and no metric budget
|
|
38
|
+
* covers it, so it is bounded separately.
|
|
39
|
+
*/
|
|
40
|
+
maxReflectionCalls?: number;
|
|
41
|
+
seed?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Scored attempts the prompt carries, strongest kept. Default 20, matching
|
|
44
|
+
* the paper's `max_num_instructions`.
|
|
45
|
+
*
|
|
46
|
+
* The reference also drops attempts below an absolute score threshold
|
|
47
|
+
* (`old_instruction_score_threshold`, 0.3 for its GPT scorers) before this
|
|
48
|
+
* cut. Nothing here does: the weak tail is what marks the bottom of the
|
|
49
|
+
* range the model is reading a gradient across, and once twenty decent
|
|
50
|
+
* attempts exist the strongest-kept rule has retired it anyway.
|
|
51
|
+
*/
|
|
52
|
+
historySize?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Task inputs shown for grounding, redrawn each round. Default 3, the
|
|
55
|
+
* reference's `num_few_shot_questions_for_instruction_refinement`, which
|
|
56
|
+
* resamples them per step under its default `random` selection.
|
|
57
|
+
*/
|
|
58
|
+
exemplars?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Instances drawn once from the training set to screen proposals on. Unset means
|
|
61
|
+
* every proposal is measured on the whole validation set, which is the reliable
|
|
62
|
+
* reading and the expensive one: a round of eight proposals against a
|
|
63
|
+
* 500-instance validation set costs 4000 rollouts before anything is learned.
|
|
64
|
+
*
|
|
65
|
+
* The paper screens on a small fixed slice of the training set and checks the
|
|
66
|
+
* full set periodically, which is what lets the validation set be large enough to
|
|
67
|
+
* trust. The slice is drawn once and never resampled — the meta-prompt ranks
|
|
68
|
+
* attempts against each other, so they have to be measured on the same
|
|
69
|
+
* instances or the ranking is noise.
|
|
70
|
+
*/
|
|
71
|
+
scoringSetSize?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Rounds between full validation set sweeps of the incumbent. Default 3, the paper's
|
|
74
|
+
* `eval_interval`. Only used when `scoringSetSize` is set; without it every
|
|
75
|
+
* proposal is already a full sweep.
|
|
76
|
+
*/
|
|
77
|
+
fullEvalInterval?: number;
|
|
78
|
+
/**
|
|
79
|
+
* What scores are multiplied by before being shown. Models discriminate
|
|
80
|
+
* between 41 and 68 far more reliably than between 0.41 and 0.68, which is
|
|
81
|
+
* the whole mechanism this search runs on. Default 100.
|
|
82
|
+
*/
|
|
83
|
+
scoreScale?: number;
|
|
84
|
+
buildPrompt?: OproPromptBuilder;
|
|
85
|
+
trackBestOutputs?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Include cached instance scores in every checkpoint. Leaving them out keeps
|
|
88
|
+
* snapshots small at the cost of a resumed run re-paying for rollouts it
|
|
89
|
+
* cannot look up. Default true.
|
|
90
|
+
*/
|
|
91
|
+
checkpointCache?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Everything needed to continue a run: the per-component score histories the
|
|
95
|
+
* meta-prompt is written from, the incumbent, the budget already spent, the
|
|
96
|
+
* position of the random stream, and the screening slice — which is drawn once
|
|
97
|
+
* and must survive a resume, since attempts screened on different instances
|
|
98
|
+
* are not the gradient this search reads.
|
|
99
|
+
*/
|
|
100
|
+
interface OproSnapshot {
|
|
101
|
+
version: 1;
|
|
102
|
+
fingerprint: string;
|
|
103
|
+
best: Candidate;
|
|
104
|
+
reported: Candidate;
|
|
105
|
+
/** Whether the incumbent has already been confirmed by a full sweep. */
|
|
106
|
+
incumbentSwept: boolean;
|
|
107
|
+
bestScore: number;
|
|
108
|
+
bestSearchScore: number;
|
|
109
|
+
seedScore: number;
|
|
110
|
+
round: number;
|
|
111
|
+
reflectionCalls: number;
|
|
112
|
+
metricCalls: number;
|
|
113
|
+
cacheHits: number;
|
|
114
|
+
rngState: number;
|
|
115
|
+
/** Component name -> every text tried for it, with what it scored. */
|
|
116
|
+
histories: Record<string, RecordedAttempt[]>;
|
|
117
|
+
/** Training set positions the screening slice was drawn from. */
|
|
118
|
+
scoringIndices?: number[];
|
|
119
|
+
cache?: [string, CachedScore][];
|
|
120
|
+
}
|
|
121
|
+
interface OproTask<Datum, Trajectory = unknown, Output = unknown, K extends string = string> extends OptimizerTask<Datum, Trajectory, Output, K> {
|
|
122
|
+
/**
|
|
123
|
+
* The base adapter, not `GepaAdapter`: this search reads scores only, so it
|
|
124
|
+
* never asks for traces or a reflective dataset.
|
|
125
|
+
*/
|
|
126
|
+
adapter: Adapter<Datum, Trajectory, Output, NoInfer<K>>;
|
|
127
|
+
reflect: TextModel;
|
|
128
|
+
/** Renders a task input for the prompt. Defaults to JSON. */
|
|
129
|
+
renderDatum?: (datum: NoInfer<Datum>) => string;
|
|
130
|
+
instanceId?: (args: {
|
|
131
|
+
datum: NoInfer<Datum>;
|
|
132
|
+
index: number;
|
|
133
|
+
}) => string;
|
|
134
|
+
/** Pass `false` to disable caching entirely. */
|
|
135
|
+
cache?: EvaluationCache | false;
|
|
136
|
+
onEvent?: (event: OproEvent<NoInfer<K>>) => void;
|
|
137
|
+
/**
|
|
138
|
+
* Called with a resumable snapshot after the seed is scored and after every
|
|
139
|
+
* round. Persist it and a killed run costs the last round, not all of them.
|
|
140
|
+
*/
|
|
141
|
+
onCheckpoint?: (snapshot: OproSnapshot) => void | Promise<void>;
|
|
142
|
+
/** Snapshot to continue from, instead of starting at the seed candidate. */
|
|
143
|
+
resumeFrom?: OproSnapshot;
|
|
144
|
+
}
|
|
145
|
+
type OproStopReason = "budgetExhausted" | "costExhausted" | "deadlineReached" | "reflectionBudgetExhausted" | "proposalsExhausted" | "maxRounds" | "aborted";
|
|
146
|
+
type OproEvent<K extends string = string> = {
|
|
147
|
+
type: "start";
|
|
148
|
+
components: K[];
|
|
149
|
+
validationSetSize: number;
|
|
150
|
+
} | {
|
|
151
|
+
type: "roundStart";
|
|
152
|
+
round: number;
|
|
153
|
+
component: K;
|
|
154
|
+
historySize: number;
|
|
155
|
+
} | ({
|
|
156
|
+
type: "evaluation";
|
|
157
|
+
} & EvaluationEvent) | {
|
|
158
|
+
type: "attempt";
|
|
159
|
+
round: number;
|
|
160
|
+
component: K;
|
|
161
|
+
score: number;
|
|
162
|
+
/** True when this attempt became the new incumbent. */
|
|
163
|
+
accepted: boolean;
|
|
164
|
+
} | {
|
|
165
|
+
type: "finish";
|
|
166
|
+
reason: OproStopReason;
|
|
167
|
+
bestScore: number;
|
|
168
|
+
metricCalls: number;
|
|
169
|
+
testScore?: number;
|
|
170
|
+
};
|
|
171
|
+
interface OproAttempt<K extends string = string> {
|
|
172
|
+
round: number;
|
|
173
|
+
component: K;
|
|
174
|
+
candidate: Candidate<K>;
|
|
175
|
+
score: number;
|
|
176
|
+
}
|
|
177
|
+
interface OproResult<K extends string = string, Output = unknown> extends OptimizerResult<K, OproStopReason, Output> {
|
|
178
|
+
/** The seed's score, so the lift the search bought is readable directly. */
|
|
179
|
+
seedScore: number;
|
|
180
|
+
rounds: number;
|
|
181
|
+
/** Every candidate scored, in the order it was tried. */
|
|
182
|
+
trajectory: OproAttempt<K>[];
|
|
183
|
+
reflectionCalls: number;
|
|
184
|
+
cacheHits: number;
|
|
185
|
+
/** State as of the last round, ready to hand back as `resumeFrom`. */
|
|
186
|
+
snapshot: OproSnapshot;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Optimization by prompting: show the model what has been tried and what each
|
|
190
|
+
* attempt scored, and ask for something better.
|
|
191
|
+
*
|
|
192
|
+
* The regime this is for is the one GEPA cannot serve. GEPA's advantage over
|
|
193
|
+
* blind search is the per-instance feedback string — a diagnosis of *why* a
|
|
194
|
+
* rollout failed. Plenty of metrics cannot produce one: a reward model, a
|
|
195
|
+
* preference score, a classifier's accuracy over a closed label set. Handed
|
|
196
|
+
* those, reflection is asked to diagnose a failure it has no evidence about,
|
|
197
|
+
* and pays a frontier-model call to guess.
|
|
198
|
+
*
|
|
199
|
+
* This search asks for less and needs less. One scalar per candidate is the
|
|
200
|
+
* entire signal, and the model reasons over the *trajectory* of scores rather
|
|
201
|
+
* than the anatomy of a single failure. Where feedback does exist, use GEPA:
|
|
202
|
+
* a score history is a much thinner channel than a paragraph saying what broke.
|
|
203
|
+
*/
|
|
204
|
+
declare class OproOptimizer implements Optimizer<OproStopReason> {
|
|
205
|
+
#private;
|
|
206
|
+
constructor(config?: OproConfig);
|
|
207
|
+
optimize<Datum, Trajectory = unknown, Output = unknown, const K extends string = string>(task: OproTask<Datum, Trajectory, Output, K>): Promise<OproResult<K, Output>>;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Adapted from the meta-prompt in *Large Language Models as Optimizers* (Yang
|
|
211
|
+
* et al., 2023). Ascending order is load-bearing: the paper finds the model
|
|
212
|
+
* attends most to what is nearest the end of the prompt, so the best attempt
|
|
213
|
+
* has to be last.
|
|
214
|
+
*
|
|
215
|
+
* Exemplars carry an `<INS>` marker for the same reason the paper's do: an
|
|
216
|
+
* instruction written against the task in the abstract reads differently from
|
|
217
|
+
* one written to sit in a particular slot. The marker is placed ahead of the
|
|
218
|
+
* input, which is where a component's text usually goes but which this
|
|
219
|
+
* optimizer cannot actually know — only the adapter composes the real prompt.
|
|
220
|
+
* The paper also shows each exemplar's gold answer. Nothing here needs to know
|
|
221
|
+
* what that is: `renderDatum` is handed the whole datum, so a caller holding
|
|
222
|
+
* labels can render them alongside the input.
|
|
223
|
+
*/
|
|
224
|
+
declare function buildOproPrompt(args: {
|
|
225
|
+
componentName: string;
|
|
226
|
+
history: readonly ScoredAttempt[];
|
|
227
|
+
exemplars: readonly string[];
|
|
228
|
+
}): string;
|
|
229
|
+
//#endregion
|
|
230
|
+
export { type OproAttempt, type OproConfig, type OproEvent, OproOptimizer, type OproPromptBuilder, type OproResult, type OproSnapshot, type OproStopReason, type OproTask, type ScoredAttempt, buildOproPrompt };
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { n as Candidate, t as Adapter, u as TextModel } from "../types-CWv4IQFF.mjs";
|
|
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-DqCoth_w.mjs";
|
|
4
|
+
//#region src/opro/optimize.d.ts
|
|
5
|
+
/** One instruction that was tried, and what it scored. */
|
|
6
|
+
/** A history entry plus the system state its score was measured in. */
|
|
7
|
+
interface RecordedAttempt extends ScoredAttempt {
|
|
8
|
+
context: string;
|
|
9
|
+
}
|
|
10
|
+
interface ScoredAttempt {
|
|
11
|
+
text: string;
|
|
12
|
+
score: number;
|
|
13
|
+
}
|
|
14
|
+
type OproPromptBuilder = (args: {
|
|
15
|
+
componentName: string;
|
|
16
|
+
/** Attempts so far, ascending by score — the weakest first. */
|
|
17
|
+
history: readonly ScoredAttempt[];
|
|
18
|
+
/** Rendered task inputs, for grounding. Empty when none were requested. */
|
|
19
|
+
exemplars: readonly string[];
|
|
20
|
+
}) => string;
|
|
21
|
+
interface OproConfig {
|
|
22
|
+
/**
|
|
23
|
+
* Instructions drawn per round. Default 8, as in the paper.
|
|
24
|
+
*
|
|
25
|
+
* All eight come from one prompt, so they differ only by the sampling
|
|
26
|
+
* temperature of `reflect`. The paper runs its optimizer at 1.0 and finds
|
|
27
|
+
* below 0.5 explores too little to escape a plateau. At temperature 0 the
|
|
28
|
+
* eight drafts are identical, dedup collapses them to one, and the round
|
|
29
|
+
* costs eight reflection calls to try a single instruction — set a
|
|
30
|
+
* temperature on the model before raising this.
|
|
31
|
+
*/
|
|
32
|
+
proposalsPerRound?: number;
|
|
33
|
+
/** How many of them may be in flight at once. Default 1. */
|
|
34
|
+
concurrency?: number;
|
|
35
|
+
maxRounds?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Reflection is the expensive half of this search and no metric budget
|
|
38
|
+
* covers it, so it is bounded separately.
|
|
39
|
+
*/
|
|
40
|
+
maxReflectionCalls?: number;
|
|
41
|
+
seed?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Scored attempts the prompt carries, strongest kept. Default 20, matching
|
|
44
|
+
* the paper's `max_num_instructions`.
|
|
45
|
+
*
|
|
46
|
+
* The reference also drops attempts below an absolute score threshold
|
|
47
|
+
* (`old_instruction_score_threshold`, 0.3 for its GPT scorers) before this
|
|
48
|
+
* cut. Nothing here does: the weak tail is what marks the bottom of the
|
|
49
|
+
* range the model is reading a gradient across, and once twenty decent
|
|
50
|
+
* attempts exist the strongest-kept rule has retired it anyway.
|
|
51
|
+
*/
|
|
52
|
+
historySize?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Task inputs shown for grounding, redrawn each round. Default 3, the
|
|
55
|
+
* reference's `num_few_shot_questions_for_instruction_refinement`, which
|
|
56
|
+
* resamples them per step under its default `random` selection.
|
|
57
|
+
*/
|
|
58
|
+
exemplars?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Instances drawn once from the training set to screen proposals on. Unset means
|
|
61
|
+
* every proposal is measured on the whole validation set, which is the reliable
|
|
62
|
+
* reading and the expensive one: a round of eight proposals against a
|
|
63
|
+
* 500-instance validation set costs 4000 rollouts before anything is learned.
|
|
64
|
+
*
|
|
65
|
+
* The paper screens on a small fixed slice of the training set and checks the
|
|
66
|
+
* full set periodically, which is what lets the validation set be large enough to
|
|
67
|
+
* trust. The slice is drawn once and never resampled — the meta-prompt ranks
|
|
68
|
+
* attempts against each other, so they have to be measured on the same
|
|
69
|
+
* instances or the ranking is noise.
|
|
70
|
+
*/
|
|
71
|
+
scoringSetSize?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Rounds between full validation set sweeps of the incumbent. Default 3, the paper's
|
|
74
|
+
* `eval_interval`. Only used when `scoringSetSize` is set; without it every
|
|
75
|
+
* proposal is already a full sweep.
|
|
76
|
+
*/
|
|
77
|
+
fullEvalInterval?: number;
|
|
78
|
+
/**
|
|
79
|
+
* What scores are multiplied by before being shown. Models discriminate
|
|
80
|
+
* between 41 and 68 far more reliably than between 0.41 and 0.68, which is
|
|
81
|
+
* the whole mechanism this search runs on. Default 100.
|
|
82
|
+
*/
|
|
83
|
+
scoreScale?: number;
|
|
84
|
+
buildPrompt?: OproPromptBuilder;
|
|
85
|
+
trackBestOutputs?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Include cached instance scores in every checkpoint. Leaving them out keeps
|
|
88
|
+
* snapshots small at the cost of a resumed run re-paying for rollouts it
|
|
89
|
+
* cannot look up. Default true.
|
|
90
|
+
*/
|
|
91
|
+
checkpointCache?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Everything needed to continue a run: the per-component score histories the
|
|
95
|
+
* meta-prompt is written from, the incumbent, the budget already spent, the
|
|
96
|
+
* position of the random stream, and the screening slice — which is drawn once
|
|
97
|
+
* and must survive a resume, since attempts screened on different instances
|
|
98
|
+
* are not the gradient this search reads.
|
|
99
|
+
*/
|
|
100
|
+
interface OproSnapshot {
|
|
101
|
+
version: 1;
|
|
102
|
+
fingerprint: string;
|
|
103
|
+
best: Candidate;
|
|
104
|
+
reported: Candidate;
|
|
105
|
+
/** Whether the incumbent has already been confirmed by a full sweep. */
|
|
106
|
+
incumbentSwept: boolean;
|
|
107
|
+
bestScore: number;
|
|
108
|
+
bestSearchScore: number;
|
|
109
|
+
seedScore: number;
|
|
110
|
+
round: number;
|
|
111
|
+
reflectionCalls: number;
|
|
112
|
+
metricCalls: number;
|
|
113
|
+
cacheHits: number;
|
|
114
|
+
rngState: number;
|
|
115
|
+
/** Component name -> every text tried for it, with what it scored. */
|
|
116
|
+
histories: Record<string, RecordedAttempt[]>;
|
|
117
|
+
/** Training set positions the screening slice was drawn from. */
|
|
118
|
+
scoringIndices?: number[];
|
|
119
|
+
cache?: [string, CachedScore][];
|
|
120
|
+
}
|
|
121
|
+
interface OproTask<Datum, Trajectory = unknown, Output = unknown, K extends string = string> extends OptimizerTask<Datum, Trajectory, Output, K> {
|
|
122
|
+
/**
|
|
123
|
+
* The base adapter, not `GepaAdapter`: this search reads scores only, so it
|
|
124
|
+
* never asks for traces or a reflective dataset.
|
|
125
|
+
*/
|
|
126
|
+
adapter: Adapter<Datum, Trajectory, Output, NoInfer<K>>;
|
|
127
|
+
reflect: TextModel;
|
|
128
|
+
/** Renders a task input for the prompt. Defaults to JSON. */
|
|
129
|
+
renderDatum?: (datum: NoInfer<Datum>) => string;
|
|
130
|
+
instanceId?: (args: {
|
|
131
|
+
datum: NoInfer<Datum>;
|
|
132
|
+
index: number;
|
|
133
|
+
}) => string;
|
|
134
|
+
/** Pass `false` to disable caching entirely. */
|
|
135
|
+
cache?: EvaluationCache | false;
|
|
136
|
+
onEvent?: (event: OproEvent<NoInfer<K>>) => void;
|
|
137
|
+
/**
|
|
138
|
+
* Called with a resumable snapshot after the seed is scored and after every
|
|
139
|
+
* round. Persist it and a killed run costs the last round, not all of them.
|
|
140
|
+
*/
|
|
141
|
+
onCheckpoint?: (snapshot: OproSnapshot) => void | Promise<void>;
|
|
142
|
+
/** Snapshot to continue from, instead of starting at the seed candidate. */
|
|
143
|
+
resumeFrom?: OproSnapshot;
|
|
144
|
+
}
|
|
145
|
+
type OproStopReason = "budgetExhausted" | "costExhausted" | "deadlineReached" | "reflectionBudgetExhausted" | "proposalsExhausted" | "maxRounds" | "aborted";
|
|
146
|
+
type OproEvent<K extends string = string> = {
|
|
147
|
+
type: "start";
|
|
148
|
+
components: K[];
|
|
149
|
+
validationSetSize: number;
|
|
150
|
+
} | {
|
|
151
|
+
type: "roundStart";
|
|
152
|
+
round: number;
|
|
153
|
+
component: K;
|
|
154
|
+
historySize: number;
|
|
155
|
+
} | ({
|
|
156
|
+
type: "evaluation";
|
|
157
|
+
} & EvaluationEvent) | {
|
|
158
|
+
type: "attempt";
|
|
159
|
+
round: number;
|
|
160
|
+
component: K;
|
|
161
|
+
score: number;
|
|
162
|
+
/** True when this attempt became the new incumbent. */
|
|
163
|
+
accepted: boolean;
|
|
164
|
+
} | {
|
|
165
|
+
type: "finish";
|
|
166
|
+
reason: OproStopReason;
|
|
167
|
+
bestScore: number;
|
|
168
|
+
metricCalls: number;
|
|
169
|
+
testScore?: number;
|
|
170
|
+
};
|
|
171
|
+
interface OproAttempt<K extends string = string> {
|
|
172
|
+
round: number;
|
|
173
|
+
component: K;
|
|
174
|
+
candidate: Candidate<K>;
|
|
175
|
+
score: number;
|
|
176
|
+
}
|
|
177
|
+
interface OproResult<K extends string = string, Output = unknown> extends OptimizerResult<K, OproStopReason, Output> {
|
|
178
|
+
/** The seed's score, so the lift the search bought is readable directly. */
|
|
179
|
+
seedScore: number;
|
|
180
|
+
rounds: number;
|
|
181
|
+
/** Every candidate scored, in the order it was tried. */
|
|
182
|
+
trajectory: OproAttempt<K>[];
|
|
183
|
+
reflectionCalls: number;
|
|
184
|
+
cacheHits: number;
|
|
185
|
+
/** State as of the last round, ready to hand back as `resumeFrom`. */
|
|
186
|
+
snapshot: OproSnapshot;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Optimization by prompting: show the model what has been tried and what each
|
|
190
|
+
* attempt scored, and ask for something better.
|
|
191
|
+
*
|
|
192
|
+
* The regime this is for is the one GEPA cannot serve. GEPA's advantage over
|
|
193
|
+
* blind search is the per-instance feedback string — a diagnosis of *why* a
|
|
194
|
+
* rollout failed. Plenty of metrics cannot produce one: a reward model, a
|
|
195
|
+
* preference score, a classifier's accuracy over a closed label set. Handed
|
|
196
|
+
* those, reflection is asked to diagnose a failure it has no evidence about,
|
|
197
|
+
* and pays a frontier-model call to guess.
|
|
198
|
+
*
|
|
199
|
+
* This search asks for less and needs less. One scalar per candidate is the
|
|
200
|
+
* entire signal, and the model reasons over the *trajectory* of scores rather
|
|
201
|
+
* than the anatomy of a single failure. Where feedback does exist, use GEPA:
|
|
202
|
+
* a score history is a much thinner channel than a paragraph saying what broke.
|
|
203
|
+
*/
|
|
204
|
+
declare class OproOptimizer implements Optimizer<OproStopReason> {
|
|
205
|
+
#private;
|
|
206
|
+
constructor(config?: OproConfig);
|
|
207
|
+
optimize<Datum, Trajectory = unknown, Output = unknown, const K extends string = string>(task: OproTask<Datum, Trajectory, Output, K>): Promise<OproResult<K, Output>>;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Adapted from the meta-prompt in *Large Language Models as Optimizers* (Yang
|
|
211
|
+
* et al., 2023). Ascending order is load-bearing: the paper finds the model
|
|
212
|
+
* attends most to what is nearest the end of the prompt, so the best attempt
|
|
213
|
+
* has to be last.
|
|
214
|
+
*
|
|
215
|
+
* Exemplars carry an `<INS>` marker for the same reason the paper's do: an
|
|
216
|
+
* instruction written against the task in the abstract reads differently from
|
|
217
|
+
* one written to sit in a particular slot. The marker is placed ahead of the
|
|
218
|
+
* input, which is where a component's text usually goes but which this
|
|
219
|
+
* optimizer cannot actually know — only the adapter composes the real prompt.
|
|
220
|
+
* The paper also shows each exemplar's gold answer. Nothing here needs to know
|
|
221
|
+
* what that is: `renderDatum` is handed the whole datum, so a caller holding
|
|
222
|
+
* labels can render them alongside the input.
|
|
223
|
+
*/
|
|
224
|
+
declare function buildOproPrompt(args: {
|
|
225
|
+
componentName: string;
|
|
226
|
+
history: readonly ScoredAttempt[];
|
|
227
|
+
exemplars: readonly string[];
|
|
228
|
+
}): string;
|
|
229
|
+
//#endregion
|
|
230
|
+
export { type OproAttempt, type OproConfig, type OproEvent, OproOptimizer, type OproPromptBuilder, type OproResult, type OproSnapshot, type OproStopReason, type OproTask, type ScoredAttempt, buildOproPrompt };
|