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,88 @@
|
|
|
1
|
+
import { n as Candidate, t as Adapter } from "./types-CWv4IQFF.cjs";
|
|
2
|
+
import { t as Rng } from "./rng-BR5MOedA.cjs";
|
|
3
|
+
//#region src/demos.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* One worked example: what went in, what a run of the system produced, and
|
|
6
|
+
* how that output scored. A demo is harvested, never written — its value is
|
|
7
|
+
* that the output is one the system actually produced and the metric actually
|
|
8
|
+
* rewarded.
|
|
9
|
+
*/
|
|
10
|
+
interface Demo<Datum = unknown, Output = unknown> {
|
|
11
|
+
input: Datum;
|
|
12
|
+
output: Output;
|
|
13
|
+
/** Present on harvested demos, absent on ones recovered from a block. */
|
|
14
|
+
score?: number;
|
|
15
|
+
}
|
|
16
|
+
type DemoRenderer<Datum = unknown, Output = unknown> = (args: {
|
|
17
|
+
demo: Demo<Datum, Output>;
|
|
18
|
+
index: number;
|
|
19
|
+
}) => string;
|
|
20
|
+
interface BootstrapResult<Datum, Output> {
|
|
21
|
+
demos: Demo<Datum, Output>[];
|
|
22
|
+
/** The demos as a candidate component, ready to seed a run with. */
|
|
23
|
+
block: string;
|
|
24
|
+
/** Rollouts this cost. Bootstrapping is cheap, not free. */
|
|
25
|
+
metricCalls: number;
|
|
26
|
+
attempted: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Harvest demonstrations by running a candidate over the training set and keeping
|
|
30
|
+
* the rollouts the metric rewarded.
|
|
31
|
+
*
|
|
32
|
+
* The cheapest signal in the whole library: a rollout that scored well is
|
|
33
|
+
* already paid for, and turning it into a few-shot block costs one pass over
|
|
34
|
+
* the data rather than a search. Instruction search and demonstrations pull on
|
|
35
|
+
* different parts of a model's behaviour — instructions on what to do,
|
|
36
|
+
* examples on what the output should look like — so a seed carrying both
|
|
37
|
+
* starts somewhere neither reaches alone.
|
|
38
|
+
*/
|
|
39
|
+
declare function bootstrapDemos<Datum, Trajectory, Output, K extends string = string>(args: {
|
|
40
|
+
adapter: Adapter<Datum, Trajectory, Output, K>;
|
|
41
|
+
/** The candidate to run. Usually the seed, sometimes a run's winner. */
|
|
42
|
+
candidate: Candidate<K>;
|
|
43
|
+
trainingSet: readonly Datum[];
|
|
44
|
+
/**
|
|
45
|
+
* Score a rollout must reach to be kept. Unset keeps every rollout the
|
|
46
|
+
* metric rewarded at all, which is what MIPROv2's bootstrapper does without
|
|
47
|
+
* a `metric_threshold`: it keeps a trace on any truthy score and only
|
|
48
|
+
* compares against a number once one is configured.
|
|
49
|
+
*
|
|
50
|
+
* Demanding a perfect score instead is the right call for a boolean metric
|
|
51
|
+
* and the wrong one for a graded metric, where it throws away every rollout
|
|
52
|
+
* that was most of the way there — which on a hard task is all of them.
|
|
53
|
+
*/
|
|
54
|
+
minScore?: number;
|
|
55
|
+
/** Demos to collect before stopping. Default 4. */
|
|
56
|
+
maxDemos?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Instances per rollout batch. Smaller batches stop closer to the moment
|
|
59
|
+
* enough demos exist, at the cost of less concurrency inside the adapter.
|
|
60
|
+
*/
|
|
61
|
+
batchSize?: number;
|
|
62
|
+
/** Ceiling on rollouts. Defaults to one pass over the trainingSet. */
|
|
63
|
+
maxMetricCalls?: number;
|
|
64
|
+
/** Shuffles the trainingSet first, so demos are not all drawn from its head. */
|
|
65
|
+
rng?: Rng;
|
|
66
|
+
renderDemo?: DemoRenderer<Datum, Output>;
|
|
67
|
+
signal?: AbortSignal;
|
|
68
|
+
}): Promise<BootstrapResult<Datum, Output>>;
|
|
69
|
+
/**
|
|
70
|
+
* Render demos as the text a candidate component holds.
|
|
71
|
+
*
|
|
72
|
+
* Delimited rather than free-form so `parseDemos` can read them back: a demo
|
|
73
|
+
* component is edited over the course of a run, and a block that cannot be
|
|
74
|
+
* parsed can only be replaced wholesale, throwing away every example found
|
|
75
|
+
* before it.
|
|
76
|
+
*/
|
|
77
|
+
declare function formatDemos<Datum, Output>(demos: readonly Demo<Datum, Output>[], options?: {
|
|
78
|
+
render?: DemoRenderer<Datum, Output>;
|
|
79
|
+
}): string;
|
|
80
|
+
/**
|
|
81
|
+
* Recover the demos from a formatted block, ignoring anything written around
|
|
82
|
+
* them. Text a model rewrote and mangled yields the demos it left intact
|
|
83
|
+
* rather than throwing: a malformed example is worth less than the rest of the
|
|
84
|
+
* block, not more than it.
|
|
85
|
+
*/
|
|
86
|
+
declare function parseDemos(text: string): Demo[];
|
|
87
|
+
//#endregion
|
|
88
|
+
export { formatDemos as a, bootstrapDemos as i, Demo as n, parseDemos as o, DemoRenderer as r, BootstrapResult as t };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { p as createBudget, r as createEvaluator } from "./evaluation-BV0nSZVx.mjs";
|
|
2
|
+
//#region src/demos.ts
|
|
3
|
+
const DEMO_OPEN = "<demo>";
|
|
4
|
+
const DEMO_CLOSE = "</demo>";
|
|
5
|
+
const DEMO_BLOCK = /<demo>\s*([\s\S]*?)\s*<\/demo>/g;
|
|
6
|
+
const DEMO_PARTS = /<input>\s*([\s\S]*?)\s*<\/input>\s*<output>\s*([\s\S]*?)\s*<\/output>/;
|
|
7
|
+
const DEFAULT_MAX_DEMOS = 4;
|
|
8
|
+
/**
|
|
9
|
+
* Harvest demonstrations by running a candidate over the training set and keeping
|
|
10
|
+
* the rollouts the metric rewarded.
|
|
11
|
+
*
|
|
12
|
+
* The cheapest signal in the whole library: a rollout that scored well is
|
|
13
|
+
* already paid for, and turning it into a few-shot block costs one pass over
|
|
14
|
+
* the data rather than a search. Instruction search and demonstrations pull on
|
|
15
|
+
* different parts of a model's behaviour — instructions on what to do,
|
|
16
|
+
* examples on what the output should look like — so a seed carrying both
|
|
17
|
+
* starts somewhere neither reaches alone.
|
|
18
|
+
*/
|
|
19
|
+
async function bootstrapDemos(args) {
|
|
20
|
+
const { adapter, candidate, trainingSet, minScore, maxDemos = DEFAULT_MAX_DEMOS, batchSize = maxDemos, maxMetricCalls = trainingSet.length, rng, renderDemo, signal } = args;
|
|
21
|
+
if (trainingSet.length === 0) throw new Error("bootstrapDemos requires a non-empty trainingSet");
|
|
22
|
+
const budget = createBudget({ maxMetricCalls });
|
|
23
|
+
const evaluator = createEvaluator({
|
|
24
|
+
adapter,
|
|
25
|
+
budget,
|
|
26
|
+
...signal === void 0 ? {} : { signal }
|
|
27
|
+
});
|
|
28
|
+
const order = rng === void 0 ? [...trainingSet] : rng.shuffle(trainingSet);
|
|
29
|
+
const demos = [];
|
|
30
|
+
let attempted = 0;
|
|
31
|
+
for (let start = 0; start < order.length; start += batchSize) {
|
|
32
|
+
if (demos.length >= maxDemos || signal?.aborted) break;
|
|
33
|
+
const batch = order.slice(start, start + Math.min(batchSize, budget.remaining()));
|
|
34
|
+
if (batch.length === 0) break;
|
|
35
|
+
const evaluation = await evaluator.evaluateTraced({
|
|
36
|
+
candidate,
|
|
37
|
+
batch,
|
|
38
|
+
split: "train",
|
|
39
|
+
phase: "seed",
|
|
40
|
+
candidateId: null,
|
|
41
|
+
iteration: 0
|
|
42
|
+
});
|
|
43
|
+
if (evaluation === null) break;
|
|
44
|
+
attempted += batch.length;
|
|
45
|
+
for (let index = 0; index < batch.length; index += 1) {
|
|
46
|
+
const score = evaluation.scores[index];
|
|
47
|
+
if (!(minScore === void 0 ? score > 0 : score >= minScore) || demos.length >= maxDemos) continue;
|
|
48
|
+
demos.push({
|
|
49
|
+
input: batch[index],
|
|
50
|
+
output: evaluation.outputs[index],
|
|
51
|
+
score
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
demos,
|
|
57
|
+
block: formatDemos(demos, renderDemo === void 0 ? {} : { render: renderDemo }),
|
|
58
|
+
metricCalls: budget.spent(),
|
|
59
|
+
attempted
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Render demos as the text a candidate component holds.
|
|
64
|
+
*
|
|
65
|
+
* Delimited rather than free-form so `parseDemos` can read them back: a demo
|
|
66
|
+
* component is edited over the course of a run, and a block that cannot be
|
|
67
|
+
* parsed can only be replaced wholesale, throwing away every example found
|
|
68
|
+
* before it.
|
|
69
|
+
*/
|
|
70
|
+
function formatDemos(demos, options = {}) {
|
|
71
|
+
const { render = renderDefault } = options;
|
|
72
|
+
if (demos.length === 0) return "";
|
|
73
|
+
return demos.map((demo, index) => `${DEMO_OPEN}\n${render({
|
|
74
|
+
demo,
|
|
75
|
+
index
|
|
76
|
+
})}\n${DEMO_CLOSE}`).join("\n");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Recover the demos from a formatted block, ignoring anything written around
|
|
80
|
+
* them. Text a model rewrote and mangled yields the demos it left intact
|
|
81
|
+
* rather than throwing: a malformed example is worth less than the rest of the
|
|
82
|
+
* block, not more than it.
|
|
83
|
+
*/
|
|
84
|
+
function parseDemos(text) {
|
|
85
|
+
const demos = [];
|
|
86
|
+
for (const match of text.matchAll(DEMO_BLOCK)) {
|
|
87
|
+
const parts = (match[1] ?? "").match(DEMO_PARTS);
|
|
88
|
+
if (parts === null) continue;
|
|
89
|
+
const input = parseValue(parts[1] ?? "");
|
|
90
|
+
const output = parseValue(parts[2] ?? "");
|
|
91
|
+
demos.push({
|
|
92
|
+
input,
|
|
93
|
+
output
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return demos;
|
|
97
|
+
}
|
|
98
|
+
function renderDefault(args) {
|
|
99
|
+
const { demo } = args;
|
|
100
|
+
return [
|
|
101
|
+
"<input>",
|
|
102
|
+
serialize(demo.input),
|
|
103
|
+
"</input>",
|
|
104
|
+
"<output>",
|
|
105
|
+
serialize(demo.output),
|
|
106
|
+
"</output>"
|
|
107
|
+
].join("\n");
|
|
108
|
+
}
|
|
109
|
+
/** Strings stay as they are; anything else is shown as JSON. */
|
|
110
|
+
function serialize(value) {
|
|
111
|
+
if (typeof value === "string") return value;
|
|
112
|
+
try {
|
|
113
|
+
return JSON.stringify(value, null, 2) ?? String(value);
|
|
114
|
+
} catch {
|
|
115
|
+
return String(value);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function parseValue(text) {
|
|
119
|
+
try {
|
|
120
|
+
return JSON.parse(text);
|
|
121
|
+
} catch {
|
|
122
|
+
return text;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
export { formatDemos as n, parseDemos as r, bootstrapDemos as t };
|