@ax-llm/ax 11.0.27 → 11.0.28
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/index.cjs +845 -42
- package/index.cjs.map +1 -1
- package/index.d.cts +148 -2
- package/index.d.ts +148 -2
- package/index.js +848 -46
- package/index.js.map +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -58,7 +58,7 @@ var AxSpanKindValues = /* @__PURE__ */ ((AxSpanKindValues2) => {
|
|
|
58
58
|
|
|
59
59
|
// util/apicall.ts
|
|
60
60
|
import {
|
|
61
|
-
ReadableStream,
|
|
61
|
+
ReadableStream as ReadableStream2,
|
|
62
62
|
TextDecoderStream as TextDecoderStreamNative,
|
|
63
63
|
TransformStream as TransformStream3
|
|
64
64
|
} from "stream/web";
|
|
@@ -427,7 +427,7 @@ var apiCall = async (api, json) => {
|
|
|
427
427
|
}
|
|
428
428
|
});
|
|
429
429
|
let closed = false;
|
|
430
|
-
return new
|
|
430
|
+
return new ReadableStream2({
|
|
431
431
|
start(controller2) {
|
|
432
432
|
const reader = res.body.pipeThrough(new textDecoderStream()).pipeThrough(new SSEParser()).pipeThrough(trackingStream).getReader();
|
|
433
433
|
async function read() {
|
|
@@ -3733,7 +3733,7 @@ var AxAI = class {
|
|
|
3733
3733
|
};
|
|
3734
3734
|
|
|
3735
3735
|
// dsp/generate.ts
|
|
3736
|
-
import { ReadableStream as
|
|
3736
|
+
import { ReadableStream as ReadableStream3 } from "node:stream/web";
|
|
3737
3737
|
import { SpanKind as SpanKind2 } from "@opentelemetry/api";
|
|
3738
3738
|
|
|
3739
3739
|
// ai/util.ts
|
|
@@ -4637,16 +4637,19 @@ var validateValue = (field, value) => {
|
|
|
4637
4637
|
};
|
|
4638
4638
|
function mergeProgramUsage(usages) {
|
|
4639
4639
|
const usageMap = {};
|
|
4640
|
-
|
|
4640
|
+
for (const usage of usages) {
|
|
4641
4641
|
const key = `${usage.ai}:${usage.model}`;
|
|
4642
4642
|
if (!usageMap[key]) {
|
|
4643
4643
|
usageMap[key] = { ...usage };
|
|
4644
|
-
|
|
4644
|
+
continue;
|
|
4645
4645
|
}
|
|
4646
|
-
usageMap[key]
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4646
|
+
const currentUsage = usageMap[key];
|
|
4647
|
+
if (currentUsage) {
|
|
4648
|
+
currentUsage.promptTokens += usage.promptTokens;
|
|
4649
|
+
currentUsage.completionTokens += usage.completionTokens;
|
|
4650
|
+
currentUsage.totalTokens += usage.totalTokens;
|
|
4651
|
+
}
|
|
4652
|
+
}
|
|
4650
4653
|
return Object.values(usageMap);
|
|
4651
4654
|
}
|
|
4652
4655
|
var parseMarkdownList = (input) => {
|
|
@@ -4667,7 +4670,6 @@ var parseMarkdownList = (input) => {
|
|
|
4667
4670
|
} else if (numberedListRegex.test(trimmedLine)) {
|
|
4668
4671
|
list.push(trimmedLine.replace(numberedListRegex, "").trim());
|
|
4669
4672
|
} else if (list.length === 0) {
|
|
4670
|
-
continue;
|
|
4671
4673
|
} else {
|
|
4672
4674
|
throw new Error("Could not parse markdown list: mixed content detected");
|
|
4673
4675
|
}
|
|
@@ -4740,12 +4742,72 @@ function matchesContent(content, prefix, startIndex = 0, prefixCache = globalPre
|
|
|
4740
4742
|
);
|
|
4741
4743
|
for (let i = 0; i < prefixes.length - 1; i++) {
|
|
4742
4744
|
const partialPrefix = prefixes[i];
|
|
4743
|
-
if (contentEnd.endsWith(partialPrefix)) {
|
|
4745
|
+
if (partialPrefix && contentEnd.endsWith(partialPrefix)) {
|
|
4744
4746
|
return -2;
|
|
4745
4747
|
}
|
|
4746
4748
|
}
|
|
4747
4749
|
return -1;
|
|
4748
4750
|
}
|
|
4751
|
+
var formatTime = (ms) => {
|
|
4752
|
+
const seconds = Math.floor(ms / 1e3);
|
|
4753
|
+
if (seconds < 60) return `${seconds}s`;
|
|
4754
|
+
const minutes = Math.floor(seconds / 60);
|
|
4755
|
+
const remainingSeconds = seconds % 60;
|
|
4756
|
+
if (minutes < 60) return `${minutes}m ${remainingSeconds}s`;
|
|
4757
|
+
const hours = Math.floor(minutes / 60);
|
|
4758
|
+
const remainingMinutes = minutes % 60;
|
|
4759
|
+
return `${hours}h ${remainingMinutes}m ${remainingSeconds}s`;
|
|
4760
|
+
};
|
|
4761
|
+
var calculateETA = (current, total, elapsedMs) => {
|
|
4762
|
+
if (current === 0) return "calculating...";
|
|
4763
|
+
const msPerItem = elapsedMs / current;
|
|
4764
|
+
const remainingItems = total - current;
|
|
4765
|
+
const etaMs = msPerItem * remainingItems;
|
|
4766
|
+
return formatTime(etaMs);
|
|
4767
|
+
};
|
|
4768
|
+
var updateDetailedProgress = (roundIndex, current, total, elapsedTime, example, stats, configInfo, result, error) => {
|
|
4769
|
+
process.stdout.write("\r\x1B[K");
|
|
4770
|
+
const percentage = (current / total * 100).toFixed(1);
|
|
4771
|
+
const formattedTime = formatTime(elapsedTime);
|
|
4772
|
+
const itemsPerSecond = elapsedTime > 0 ? (current / elapsedTime * 1e3).toFixed(2) : "0.00";
|
|
4773
|
+
const eta = calculateETA(current, total, elapsedTime);
|
|
4774
|
+
let output = `Round ${roundIndex + 1}/${configInfo.maxRounds}: ${current}/${total} (${percentage}%) [${formattedTime}, ${itemsPerSecond} it/s, ETA: ${eta}]`;
|
|
4775
|
+
const successRate = stats.totalCalls > 0 ? stats.successfulDemos / stats.totalCalls * 100 : 0;
|
|
4776
|
+
output += ` | Success: ${stats.successfulDemos}/${stats.totalCalls} (${successRate.toFixed(1)}%)`;
|
|
4777
|
+
if (configInfo.verboseMode || configInfo.debugMode) {
|
|
4778
|
+
if (configInfo.costMonitoring) {
|
|
4779
|
+
output += `
|
|
4780
|
+
Tokens: ~${stats.estimatedTokenUsage.toLocaleString()} total`;
|
|
4781
|
+
}
|
|
4782
|
+
output += `
|
|
4783
|
+
Batch: ${Math.floor(current / configInfo.batchSize) + 1}/${Math.ceil(total / configInfo.batchSize)}`;
|
|
4784
|
+
if (configInfo.earlyStoppingPatience > 0 && stats.earlyStopping) {
|
|
4785
|
+
output += `
|
|
4786
|
+
Best round: ${stats.earlyStopping.bestScoreRound + 1}, Patience: ${configInfo.earlyStoppingPatience}`;
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
if (configInfo.debugMode) {
|
|
4790
|
+
const exampleKeys = Object.keys(example).map((k) => {
|
|
4791
|
+
const valueStr = JSON.stringify(example[k]);
|
|
4792
|
+
const truncated = valueStr.length > 30 ? `${valueStr.substring(0, 30)}...` : valueStr;
|
|
4793
|
+
return `${k}: ${truncated}`;
|
|
4794
|
+
}).join(", ");
|
|
4795
|
+
output += `
|
|
4796
|
+
Example: {${exampleKeys}}`;
|
|
4797
|
+
if (error) {
|
|
4798
|
+
output += `
|
|
4799
|
+
ERROR: ${error.message}`;
|
|
4800
|
+
} else if (result) {
|
|
4801
|
+
const resultStr = JSON.stringify(result);
|
|
4802
|
+
const truncatedResult = resultStr.length > 50 ? `${resultStr.substring(0, 50)}...` : resultStr;
|
|
4803
|
+
output += `
|
|
4804
|
+
Result: ${truncatedResult}`;
|
|
4805
|
+
}
|
|
4806
|
+
output += `
|
|
4807
|
+
Temperature: ${(0.7 + 1e-3 * current).toFixed(3)}`;
|
|
4808
|
+
}
|
|
4809
|
+
console.log(output);
|
|
4810
|
+
};
|
|
4749
4811
|
|
|
4750
4812
|
// dsp/program.ts
|
|
4751
4813
|
var AxProgramWithSignature = class {
|
|
@@ -4987,7 +5049,7 @@ ${outputFields}`);
|
|
|
4987
5049
|
demos
|
|
4988
5050
|
}) => {
|
|
4989
5051
|
const renderedExamples = examples ? [
|
|
4990
|
-
{ type: "text", text: "## Examples
|
|
5052
|
+
{ type: "text", text: "\n\n## Examples\n" },
|
|
4991
5053
|
...this.renderExamples(examples)
|
|
4992
5054
|
] : [];
|
|
4993
5055
|
const renderedDemos = demos ? this.renderDemos(demos) : [];
|
|
@@ -5070,6 +5132,9 @@ ${outputFields}`);
|
|
|
5070
5132
|
);
|
|
5071
5133
|
}
|
|
5072
5134
|
const renderedItem = [...renderedInputItem, ...renderedOutputItem];
|
|
5135
|
+
if (index > 0 && renderedItem.length > 0 && renderedItem[0]?.type === "text") {
|
|
5136
|
+
list.push({ type: "text", text: "---\n\n" });
|
|
5137
|
+
}
|
|
5073
5138
|
renderedItem.forEach((v) => {
|
|
5074
5139
|
if ("text" in v) {
|
|
5075
5140
|
v.text = v.text + "\n";
|
|
@@ -5253,10 +5318,7 @@ var processValue = (field, value) => {
|
|
|
5253
5318
|
if (typeof value === "string") {
|
|
5254
5319
|
return value;
|
|
5255
5320
|
}
|
|
5256
|
-
|
|
5257
|
-
return value;
|
|
5258
|
-
}
|
|
5259
|
-
return JSON.stringify(value);
|
|
5321
|
+
return JSON.stringify(value, null, 2);
|
|
5260
5322
|
};
|
|
5261
5323
|
var toFieldType = (type) => {
|
|
5262
5324
|
const baseType = (() => {
|
|
@@ -6062,7 +6124,7 @@ var AxGen = class extends AxProgramWithSignature {
|
|
|
6062
6124
|
mem,
|
|
6063
6125
|
options
|
|
6064
6126
|
});
|
|
6065
|
-
if (res instanceof
|
|
6127
|
+
if (res instanceof ReadableStream3) {
|
|
6066
6128
|
yield* this.processStreamingResponse({
|
|
6067
6129
|
ai,
|
|
6068
6130
|
model,
|
|
@@ -6997,60 +7059,147 @@ function validateModels2(services) {
|
|
|
6997
7059
|
// dsp/optimize.ts
|
|
6998
7060
|
var AxBootstrapFewShot = class {
|
|
6999
7061
|
ai;
|
|
7062
|
+
teacherAI;
|
|
7000
7063
|
program;
|
|
7001
7064
|
examples;
|
|
7002
7065
|
maxRounds;
|
|
7003
7066
|
maxDemos;
|
|
7004
7067
|
maxExamples;
|
|
7068
|
+
batchSize;
|
|
7069
|
+
earlyStoppingPatience;
|
|
7070
|
+
costMonitoring;
|
|
7071
|
+
maxTokensPerGeneration;
|
|
7072
|
+
verboseMode;
|
|
7073
|
+
debugMode;
|
|
7005
7074
|
traces = [];
|
|
7075
|
+
stats = {
|
|
7076
|
+
totalCalls: 0,
|
|
7077
|
+
successfulDemos: 0,
|
|
7078
|
+
estimatedTokenUsage: 0,
|
|
7079
|
+
earlyStopped: false
|
|
7080
|
+
};
|
|
7006
7081
|
constructor({
|
|
7007
7082
|
ai,
|
|
7008
7083
|
program,
|
|
7009
7084
|
examples = [],
|
|
7010
7085
|
options
|
|
7011
7086
|
}) {
|
|
7012
|
-
if (examples.length
|
|
7087
|
+
if (examples.length === 0) {
|
|
7013
7088
|
throw new Error("No examples found");
|
|
7014
7089
|
}
|
|
7015
7090
|
this.maxRounds = options?.maxRounds ?? 3;
|
|
7016
7091
|
this.maxDemos = options?.maxDemos ?? 4;
|
|
7017
7092
|
this.maxExamples = options?.maxExamples ?? 16;
|
|
7093
|
+
this.batchSize = options?.batchSize ?? 1;
|
|
7094
|
+
this.earlyStoppingPatience = options?.earlyStoppingPatience ?? 0;
|
|
7095
|
+
this.costMonitoring = options?.costMonitoring ?? false;
|
|
7096
|
+
this.maxTokensPerGeneration = options?.maxTokensPerGeneration ?? 0;
|
|
7097
|
+
this.verboseMode = options?.verboseMode ?? true;
|
|
7098
|
+
this.debugMode = options?.debugMode ?? false;
|
|
7018
7099
|
this.ai = ai;
|
|
7100
|
+
this.teacherAI = options?.teacherAI;
|
|
7019
7101
|
this.program = program;
|
|
7020
7102
|
this.examples = examples;
|
|
7021
7103
|
}
|
|
7022
7104
|
async compileRound(roundIndex, metricFn, options) {
|
|
7023
7105
|
const st = (/* @__PURE__ */ new Date()).getTime();
|
|
7024
7106
|
const maxDemos = options?.maxDemos ?? this.maxDemos;
|
|
7025
|
-
const aiOpt = {
|
|
7107
|
+
const aiOpt = {
|
|
7108
|
+
modelConfig: {
|
|
7109
|
+
temperature: 0.7
|
|
7110
|
+
}
|
|
7111
|
+
};
|
|
7112
|
+
if (this.maxTokensPerGeneration > 0) {
|
|
7113
|
+
aiOpt.modelConfig.max_tokens = this.maxTokensPerGeneration;
|
|
7114
|
+
}
|
|
7026
7115
|
const examples = randomSample(this.examples, this.maxExamples);
|
|
7027
|
-
|
|
7116
|
+
const previousSuccessCount = this.traces.length;
|
|
7117
|
+
for (let i = 0; i < examples.length; i += this.batchSize) {
|
|
7028
7118
|
if (i > 0) {
|
|
7029
7119
|
aiOpt.modelConfig.temperature = 0.7 + 1e-3 * i;
|
|
7030
7120
|
}
|
|
7031
|
-
const
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7121
|
+
const batch = examples.slice(i, i + this.batchSize);
|
|
7122
|
+
for (const ex of batch) {
|
|
7123
|
+
if (!ex) {
|
|
7124
|
+
continue;
|
|
7125
|
+
}
|
|
7126
|
+
const exList = examples.filter((e) => e !== ex);
|
|
7127
|
+
this.program.setExamples(exList);
|
|
7128
|
+
const aiService = this.teacherAI || this.ai;
|
|
7129
|
+
this.stats.totalCalls++;
|
|
7130
|
+
let res;
|
|
7131
|
+
let error;
|
|
7132
|
+
try {
|
|
7133
|
+
res = await this.program.forward(aiService, ex, aiOpt);
|
|
7134
|
+
if (this.costMonitoring) {
|
|
7135
|
+
this.stats.estimatedTokenUsage += JSON.stringify(ex).length / 4 + JSON.stringify(res).length / 4;
|
|
7136
|
+
}
|
|
7137
|
+
const success = metricFn({ prediction: res, example: ex });
|
|
7138
|
+
if (success) {
|
|
7139
|
+
this.traces = [...this.traces, ...this.program.getTraces()];
|
|
7140
|
+
this.stats.successfulDemos++;
|
|
7141
|
+
}
|
|
7142
|
+
} catch (err) {
|
|
7143
|
+
error = err;
|
|
7144
|
+
res = {};
|
|
7145
|
+
}
|
|
7146
|
+
const current = i + examples.length * roundIndex + (batch.indexOf(ex) + 1);
|
|
7147
|
+
const total = examples.length * this.maxRounds;
|
|
7148
|
+
const et = (/* @__PURE__ */ new Date()).getTime() - st;
|
|
7149
|
+
if (this.verboseMode || this.debugMode) {
|
|
7150
|
+
const configInfo = {
|
|
7151
|
+
maxRounds: this.maxRounds,
|
|
7152
|
+
batchSize: this.batchSize,
|
|
7153
|
+
earlyStoppingPatience: this.earlyStoppingPatience,
|
|
7154
|
+
costMonitoring: this.costMonitoring,
|
|
7155
|
+
verboseMode: this.verboseMode,
|
|
7156
|
+
debugMode: this.debugMode
|
|
7157
|
+
};
|
|
7158
|
+
updateDetailedProgress(
|
|
7159
|
+
roundIndex,
|
|
7160
|
+
current,
|
|
7161
|
+
total,
|
|
7162
|
+
et,
|
|
7163
|
+
ex,
|
|
7164
|
+
this.stats,
|
|
7165
|
+
configInfo,
|
|
7166
|
+
res,
|
|
7167
|
+
error
|
|
7168
|
+
);
|
|
7169
|
+
} else {
|
|
7170
|
+
updateProgressBar(
|
|
7171
|
+
current,
|
|
7172
|
+
total,
|
|
7173
|
+
this.traces.length,
|
|
7174
|
+
et,
|
|
7175
|
+
"Tuning Prompt",
|
|
7176
|
+
30
|
|
7177
|
+
);
|
|
7178
|
+
}
|
|
7179
|
+
if (this.traces.length >= maxDemos) {
|
|
7180
|
+
return;
|
|
7181
|
+
}
|
|
7041
7182
|
}
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
const
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
if (this.
|
|
7183
|
+
}
|
|
7184
|
+
if (this.earlyStoppingPatience > 0) {
|
|
7185
|
+
const newSuccessCount = this.traces.length;
|
|
7186
|
+
const improvement = newSuccessCount - previousSuccessCount;
|
|
7187
|
+
if (!this.stats.earlyStopping) {
|
|
7188
|
+
this.stats.earlyStopping = {
|
|
7189
|
+
bestScoreRound: improvement > 0 ? roundIndex : 0,
|
|
7190
|
+
patienceExhausted: false
|
|
7191
|
+
};
|
|
7192
|
+
} else if (improvement > 0) {
|
|
7193
|
+
this.stats.earlyStopping.bestScoreRound = roundIndex;
|
|
7194
|
+
} else if (roundIndex - this.stats.earlyStopping.bestScoreRound >= this.earlyStoppingPatience) {
|
|
7195
|
+
this.stats.earlyStopping.patienceExhausted = true;
|
|
7196
|
+
this.stats.earlyStopped = true;
|
|
7197
|
+
if (this.verboseMode || this.debugMode) {
|
|
7198
|
+
console.log(
|
|
7199
|
+
`
|
|
7200
|
+
Early stopping triggered after ${roundIndex + 1} rounds. No improvement for ${this.earlyStoppingPatience} rounds.`
|
|
7201
|
+
);
|
|
7202
|
+
}
|
|
7054
7203
|
return;
|
|
7055
7204
|
}
|
|
7056
7205
|
}
|
|
@@ -7058,8 +7207,17 @@ var AxBootstrapFewShot = class {
|
|
|
7058
7207
|
async compile(metricFn, options) {
|
|
7059
7208
|
const maxRounds = options?.maxRounds ?? this.maxRounds;
|
|
7060
7209
|
this.traces = [];
|
|
7210
|
+
this.stats = {
|
|
7211
|
+
totalCalls: 0,
|
|
7212
|
+
successfulDemos: 0,
|
|
7213
|
+
estimatedTokenUsage: 0,
|
|
7214
|
+
earlyStopped: false
|
|
7215
|
+
};
|
|
7061
7216
|
for (let i = 0; i < maxRounds; i++) {
|
|
7062
7217
|
await this.compileRound(i, metricFn, options);
|
|
7218
|
+
if (this.stats.earlyStopped) {
|
|
7219
|
+
break;
|
|
7220
|
+
}
|
|
7063
7221
|
}
|
|
7064
7222
|
if (this.traces.length === 0) {
|
|
7065
7223
|
throw new Error(
|
|
@@ -7067,22 +7225,32 @@ var AxBootstrapFewShot = class {
|
|
|
7067
7225
|
);
|
|
7068
7226
|
}
|
|
7069
7227
|
const demos = groupTracesByKeys(this.traces);
|
|
7070
|
-
return
|
|
7228
|
+
return {
|
|
7229
|
+
demos,
|
|
7230
|
+
stats: this.stats
|
|
7231
|
+
};
|
|
7232
|
+
}
|
|
7233
|
+
// Get optimization statistics
|
|
7234
|
+
getStats() {
|
|
7235
|
+
return this.stats;
|
|
7071
7236
|
}
|
|
7072
7237
|
};
|
|
7073
7238
|
function groupTracesByKeys(programTraces) {
|
|
7074
7239
|
const groupedTraces = /* @__PURE__ */ new Map();
|
|
7075
7240
|
for (const programTrace of programTraces) {
|
|
7076
7241
|
if (groupedTraces.has(programTrace.programId)) {
|
|
7077
|
-
groupedTraces.get(programTrace.programId)
|
|
7242
|
+
const traces = groupedTraces.get(programTrace.programId);
|
|
7243
|
+
if (traces) {
|
|
7244
|
+
traces.push(programTrace.trace);
|
|
7245
|
+
}
|
|
7078
7246
|
} else {
|
|
7079
7247
|
groupedTraces.set(programTrace.programId, [programTrace.trace]);
|
|
7080
7248
|
}
|
|
7081
7249
|
}
|
|
7082
7250
|
const programDemosArray = [];
|
|
7083
|
-
groupedTraces.
|
|
7251
|
+
for (const [programId, traces] of groupedTraces.entries()) {
|
|
7084
7252
|
programDemosArray.push({ traces, programId });
|
|
7085
|
-
}
|
|
7253
|
+
}
|
|
7086
7254
|
return programDemosArray;
|
|
7087
7255
|
}
|
|
7088
7256
|
var randomSample = (array, n) => {
|
|
@@ -8202,6 +8370,639 @@ var AxJSInterpreter = class {
|
|
|
8202
8370
|
}
|
|
8203
8371
|
};
|
|
8204
8372
|
|
|
8373
|
+
// dsp/mipro.ts
|
|
8374
|
+
var AxMiPRO = class {
|
|
8375
|
+
ai;
|
|
8376
|
+
program;
|
|
8377
|
+
examples;
|
|
8378
|
+
maxBootstrappedDemos;
|
|
8379
|
+
maxLabeledDemos;
|
|
8380
|
+
numCandidates;
|
|
8381
|
+
initTemperature;
|
|
8382
|
+
numTrials;
|
|
8383
|
+
minibatch;
|
|
8384
|
+
minibatchSize;
|
|
8385
|
+
minibatchFullEvalSteps;
|
|
8386
|
+
programAwareProposer;
|
|
8387
|
+
dataAwareProposer;
|
|
8388
|
+
viewDataBatchSize;
|
|
8389
|
+
tipAwareProposer;
|
|
8390
|
+
fewshotAwareProposer;
|
|
8391
|
+
seed;
|
|
8392
|
+
verbose;
|
|
8393
|
+
bootstrapper;
|
|
8394
|
+
earlyStoppingTrials;
|
|
8395
|
+
minImprovementThreshold;
|
|
8396
|
+
constructor({
|
|
8397
|
+
ai,
|
|
8398
|
+
program,
|
|
8399
|
+
examples = [],
|
|
8400
|
+
options
|
|
8401
|
+
}) {
|
|
8402
|
+
if (examples.length === 0) {
|
|
8403
|
+
throw new Error("No examples found");
|
|
8404
|
+
}
|
|
8405
|
+
const miproOptions = options || {};
|
|
8406
|
+
this.numCandidates = miproOptions.numCandidates ?? 5;
|
|
8407
|
+
this.initTemperature = miproOptions.initTemperature ?? 0.7;
|
|
8408
|
+
this.maxBootstrappedDemos = miproOptions.maxBootstrappedDemos ?? 3;
|
|
8409
|
+
this.maxLabeledDemos = miproOptions.maxLabeledDemos ?? 4;
|
|
8410
|
+
this.numTrials = miproOptions.numTrials ?? 30;
|
|
8411
|
+
this.minibatch = miproOptions.minibatch ?? true;
|
|
8412
|
+
this.minibatchSize = miproOptions.minibatchSize ?? 25;
|
|
8413
|
+
this.minibatchFullEvalSteps = miproOptions.minibatchFullEvalSteps ?? 10;
|
|
8414
|
+
this.programAwareProposer = miproOptions.programAwareProposer ?? true;
|
|
8415
|
+
this.dataAwareProposer = miproOptions.dataAwareProposer ?? true;
|
|
8416
|
+
this.viewDataBatchSize = miproOptions.viewDataBatchSize ?? 10;
|
|
8417
|
+
this.tipAwareProposer = miproOptions.tipAwareProposer ?? true;
|
|
8418
|
+
this.fewshotAwareProposer = miproOptions.fewshotAwareProposer ?? true;
|
|
8419
|
+
this.seed = miproOptions.seed;
|
|
8420
|
+
this.verbose = miproOptions.verbose ?? false;
|
|
8421
|
+
this.earlyStoppingTrials = miproOptions.earlyStoppingTrials ?? 5;
|
|
8422
|
+
this.minImprovementThreshold = miproOptions.minImprovementThreshold ?? 0.01;
|
|
8423
|
+
this.ai = ai;
|
|
8424
|
+
this.program = program;
|
|
8425
|
+
this.examples = examples;
|
|
8426
|
+
this.bootstrapper = new AxBootstrapFewShot({
|
|
8427
|
+
ai,
|
|
8428
|
+
program,
|
|
8429
|
+
examples,
|
|
8430
|
+
options: {
|
|
8431
|
+
maxDemos: this.maxBootstrappedDemos,
|
|
8432
|
+
maxRounds: 3,
|
|
8433
|
+
// Default, or adjust based on your needs
|
|
8434
|
+
verboseMode: this.verbose
|
|
8435
|
+
}
|
|
8436
|
+
});
|
|
8437
|
+
}
|
|
8438
|
+
/**
|
|
8439
|
+
* Configures the optimizer for light, medium, or heavy optimization
|
|
8440
|
+
* @param level The optimization level: "light", "medium", or "heavy"
|
|
8441
|
+
*/
|
|
8442
|
+
configureAuto(level) {
|
|
8443
|
+
switch (level) {
|
|
8444
|
+
case "light":
|
|
8445
|
+
this.numCandidates = 3;
|
|
8446
|
+
this.numTrials = 10;
|
|
8447
|
+
this.minibatch = true;
|
|
8448
|
+
this.minibatchSize = 20;
|
|
8449
|
+
break;
|
|
8450
|
+
case "medium":
|
|
8451
|
+
this.numCandidates = 5;
|
|
8452
|
+
this.numTrials = 20;
|
|
8453
|
+
this.minibatch = true;
|
|
8454
|
+
this.minibatchSize = 25;
|
|
8455
|
+
break;
|
|
8456
|
+
case "heavy":
|
|
8457
|
+
this.numCandidates = 7;
|
|
8458
|
+
this.numTrials = 30;
|
|
8459
|
+
this.minibatch = true;
|
|
8460
|
+
this.minibatchSize = 30;
|
|
8461
|
+
break;
|
|
8462
|
+
}
|
|
8463
|
+
}
|
|
8464
|
+
/**
|
|
8465
|
+
* Generates creative tips for instruction generation
|
|
8466
|
+
*/
|
|
8467
|
+
generateTips() {
|
|
8468
|
+
return [
|
|
8469
|
+
"Be very specific and detailed in your instructions.",
|
|
8470
|
+
"Focus on step-by-step reasoning in your instructions.",
|
|
8471
|
+
"Provide clear constraints and guidelines in your instructions.",
|
|
8472
|
+
"Keep your instructions concise and to the point.",
|
|
8473
|
+
"Emphasize accuracy and precision in your instructions.",
|
|
8474
|
+
"Include examples of good outputs in your instructions.",
|
|
8475
|
+
"Focus on handling edge cases in your instructions.",
|
|
8476
|
+
"Explicitly outline the reasoning process in your instructions."
|
|
8477
|
+
];
|
|
8478
|
+
}
|
|
8479
|
+
/**
|
|
8480
|
+
* Generates instruction candidates for each predictor in the program
|
|
8481
|
+
* @returns Array of generated instruction candidates
|
|
8482
|
+
*/
|
|
8483
|
+
async proposeInstructionCandidates() {
|
|
8484
|
+
const instructions = [];
|
|
8485
|
+
let programContext = "";
|
|
8486
|
+
if (this.programAwareProposer) {
|
|
8487
|
+
programContext = await this.generateProgramSummary();
|
|
8488
|
+
}
|
|
8489
|
+
let dataContext = "";
|
|
8490
|
+
if (this.dataAwareProposer) {
|
|
8491
|
+
dataContext = await this.generateDataSummary();
|
|
8492
|
+
}
|
|
8493
|
+
const tips = this.tipAwareProposer ? this.generateTips() : [];
|
|
8494
|
+
for (let i = 0; i < this.numCandidates; i++) {
|
|
8495
|
+
const tipIndex = tips.length > 0 ? i % tips.length : -1;
|
|
8496
|
+
const tipToUse = tipIndex >= 0 ? tips[tipIndex] : "";
|
|
8497
|
+
const instruction = await this.generateInstruction({
|
|
8498
|
+
programContext,
|
|
8499
|
+
dataContext,
|
|
8500
|
+
tip: tipToUse,
|
|
8501
|
+
candidateIndex: i
|
|
8502
|
+
});
|
|
8503
|
+
instructions.push(instruction);
|
|
8504
|
+
}
|
|
8505
|
+
return instructions;
|
|
8506
|
+
}
|
|
8507
|
+
/**
|
|
8508
|
+
* Generates a summary of the program structure for instruction proposal
|
|
8509
|
+
*/
|
|
8510
|
+
async generateProgramSummary() {
|
|
8511
|
+
const prompt = `Summarize the following program structure. Focus on the signatures,
|
|
8512
|
+
input/output fields, and the purpose of each component. Identify key components
|
|
8513
|
+
that might benefit from better instructions.`;
|
|
8514
|
+
const programStr = JSON.stringify(this.program);
|
|
8515
|
+
const response = await this.ai.chat({
|
|
8516
|
+
chatPrompt: [
|
|
8517
|
+
{ role: "system", content: prompt },
|
|
8518
|
+
{ role: "user", content: programStr }
|
|
8519
|
+
],
|
|
8520
|
+
modelConfig: { temperature: 0.2 }
|
|
8521
|
+
});
|
|
8522
|
+
if (response instanceof ReadableStream) {
|
|
8523
|
+
return "";
|
|
8524
|
+
}
|
|
8525
|
+
return response.results[0]?.content || "";
|
|
8526
|
+
}
|
|
8527
|
+
/**
|
|
8528
|
+
* Generates a summary of the dataset for instruction proposal
|
|
8529
|
+
*/
|
|
8530
|
+
async generateDataSummary() {
|
|
8531
|
+
const sampleSize = Math.min(this.viewDataBatchSize, this.examples.length);
|
|
8532
|
+
const sample = this.examples.slice(0, sampleSize);
|
|
8533
|
+
const prompt = `Analyze the following dataset examples and provide a summary
|
|
8534
|
+
of key patterns, input-output relationships, and any specific challenges
|
|
8535
|
+
the data presents. Focus on what makes a good answer and what patterns should
|
|
8536
|
+
be followed.`;
|
|
8537
|
+
const dataStr = JSON.stringify(sample);
|
|
8538
|
+
const response = await this.ai.chat({
|
|
8539
|
+
chatPrompt: [
|
|
8540
|
+
{ role: "system", content: prompt },
|
|
8541
|
+
{ role: "user", content: dataStr }
|
|
8542
|
+
],
|
|
8543
|
+
modelConfig: { temperature: 0.2 }
|
|
8544
|
+
});
|
|
8545
|
+
if (response instanceof ReadableStream) {
|
|
8546
|
+
return "";
|
|
8547
|
+
}
|
|
8548
|
+
return response.results[0]?.content || "";
|
|
8549
|
+
}
|
|
8550
|
+
/**
|
|
8551
|
+
* Generates a specific instruction candidate
|
|
8552
|
+
*/
|
|
8553
|
+
async generateInstruction({
|
|
8554
|
+
programContext,
|
|
8555
|
+
dataContext,
|
|
8556
|
+
tip,
|
|
8557
|
+
candidateIndex
|
|
8558
|
+
}) {
|
|
8559
|
+
const prompt = `Create a high-quality instruction for an AI model performing the task described below.
|
|
8560
|
+
|
|
8561
|
+
${programContext ? `PROGRAM CONTEXT:
|
|
8562
|
+
${programContext}
|
|
8563
|
+
|
|
8564
|
+
` : ""}
|
|
8565
|
+
${dataContext ? `DATA CONTEXT:
|
|
8566
|
+
${dataContext}
|
|
8567
|
+
|
|
8568
|
+
` : ""}
|
|
8569
|
+
${tip ? `STYLE TIP: ${tip}
|
|
8570
|
+
|
|
8571
|
+
` : ""}
|
|
8572
|
+
|
|
8573
|
+
Your task is to craft a clear, effective instruction that will help the AI model generate
|
|
8574
|
+
accurate outputs for this task. Instruction #${candidateIndex + 1}/${this.numCandidates}.
|
|
8575
|
+
|
|
8576
|
+
The instruction should be detailed enough to guide the model but not overly prescriptive
|
|
8577
|
+
or restrictive. Focus on what makes a good response rather than listing exact steps.
|
|
8578
|
+
|
|
8579
|
+
INSTRUCTION:`;
|
|
8580
|
+
const response = await this.ai.chat({
|
|
8581
|
+
chatPrompt: [{ role: "user", content: prompt }],
|
|
8582
|
+
modelConfig: { temperature: 0.7 + 0.1 * candidateIndex }
|
|
8583
|
+
});
|
|
8584
|
+
if (response instanceof ReadableStream) {
|
|
8585
|
+
return "";
|
|
8586
|
+
}
|
|
8587
|
+
return response.results[0]?.content || "";
|
|
8588
|
+
}
|
|
8589
|
+
/**
|
|
8590
|
+
* Bootstraps few-shot examples for the program
|
|
8591
|
+
*/
|
|
8592
|
+
async bootstrapFewShotExamples(metricFn) {
|
|
8593
|
+
if (this.verbose) {
|
|
8594
|
+
console.log("Bootstrapping few-shot examples...");
|
|
8595
|
+
}
|
|
8596
|
+
const result = await this.bootstrapper.compile(metricFn, {
|
|
8597
|
+
maxDemos: this.maxBootstrappedDemos
|
|
8598
|
+
});
|
|
8599
|
+
return result.demos;
|
|
8600
|
+
}
|
|
8601
|
+
/**
|
|
8602
|
+
* Selects labeled examples directly from the training set
|
|
8603
|
+
*/
|
|
8604
|
+
selectLabeledExamples() {
|
|
8605
|
+
const selectedExamples = [];
|
|
8606
|
+
const indices = /* @__PURE__ */ new Set();
|
|
8607
|
+
while (indices.size < this.maxLabeledDemos && indices.size < this.examples.length) {
|
|
8608
|
+
const idx = Math.floor(Math.random() * this.examples.length);
|
|
8609
|
+
if (!indices.has(idx)) {
|
|
8610
|
+
indices.add(idx);
|
|
8611
|
+
const example = this.examples[idx];
|
|
8612
|
+
if (example) {
|
|
8613
|
+
selectedExamples.push(example);
|
|
8614
|
+
}
|
|
8615
|
+
}
|
|
8616
|
+
}
|
|
8617
|
+
return selectedExamples;
|
|
8618
|
+
}
|
|
8619
|
+
/**
|
|
8620
|
+
* Runs Bayesian optimization to find the best combination of few-shot examples and instructions
|
|
8621
|
+
*/
|
|
8622
|
+
async runBayesianOptimization(bootstrappedDemos, labeledExamples, instructions, valset, metricFn) {
|
|
8623
|
+
let bestConfig = null;
|
|
8624
|
+
let bestScore = Number.NEGATIVE_INFINITY;
|
|
8625
|
+
const evaluatedConfigs = [];
|
|
8626
|
+
const defaultConfig = {
|
|
8627
|
+
instruction: instructions[0] || "",
|
|
8628
|
+
bootstrappedDemos: Math.min(1, bootstrappedDemos.length),
|
|
8629
|
+
labeledExamples: Math.min(1, labeledExamples.length)
|
|
8630
|
+
};
|
|
8631
|
+
let trialsWithoutImprovement = 0;
|
|
8632
|
+
let lastBestScore = Number.NEGATIVE_INFINITY;
|
|
8633
|
+
const initialExplorationTrials = Math.min(
|
|
8634
|
+
10,
|
|
8635
|
+
Math.floor(this.numTrials / 3)
|
|
8636
|
+
);
|
|
8637
|
+
const configs = [];
|
|
8638
|
+
for (let i = 0; i < initialExplorationTrials; i++) {
|
|
8639
|
+
const instructionIndex = Math.floor(Math.random() * instructions.length);
|
|
8640
|
+
const instructionValue = instructions[instructionIndex] || "";
|
|
8641
|
+
const config = {
|
|
8642
|
+
instruction: instructionValue,
|
|
8643
|
+
bootstrappedDemos: Math.floor(
|
|
8644
|
+
Math.random() * (bootstrappedDemos.length + 1)
|
|
8645
|
+
),
|
|
8646
|
+
labeledExamples: Math.floor(
|
|
8647
|
+
Math.random() * (labeledExamples.length + 1)
|
|
8648
|
+
)
|
|
8649
|
+
};
|
|
8650
|
+
configs.push(config);
|
|
8651
|
+
}
|
|
8652
|
+
for (let i = 0; i < configs.length; i++) {
|
|
8653
|
+
const config = configs[i];
|
|
8654
|
+
if (!config) continue;
|
|
8655
|
+
const score = await this.evaluateConfig(
|
|
8656
|
+
config,
|
|
8657
|
+
bootstrappedDemos,
|
|
8658
|
+
labeledExamples,
|
|
8659
|
+
valset,
|
|
8660
|
+
metricFn,
|
|
8661
|
+
i
|
|
8662
|
+
);
|
|
8663
|
+
evaluatedConfigs.push({ config, score });
|
|
8664
|
+
if (score > bestScore) {
|
|
8665
|
+
bestScore = score;
|
|
8666
|
+
bestConfig = config;
|
|
8667
|
+
if (this.verbose) {
|
|
8668
|
+
console.log(
|
|
8669
|
+
`New best configuration found with score ${bestScore} (exploration phase)`
|
|
8670
|
+
);
|
|
8671
|
+
}
|
|
8672
|
+
}
|
|
8673
|
+
updateProgressBar(
|
|
8674
|
+
i + 1,
|
|
8675
|
+
this.numTrials,
|
|
8676
|
+
Math.round(bestScore * 100),
|
|
8677
|
+
0,
|
|
8678
|
+
"Running MIPROv2 optimization",
|
|
8679
|
+
30
|
|
8680
|
+
);
|
|
8681
|
+
}
|
|
8682
|
+
for (let i = configs.length; i < this.numTrials; i++) {
|
|
8683
|
+
const nextConfig = this.selectNextConfiguration(
|
|
8684
|
+
evaluatedConfigs,
|
|
8685
|
+
bootstrappedDemos.length,
|
|
8686
|
+
labeledExamples.length,
|
|
8687
|
+
instructions
|
|
8688
|
+
);
|
|
8689
|
+
const score = await this.evaluateConfig(
|
|
8690
|
+
nextConfig,
|
|
8691
|
+
bootstrappedDemos,
|
|
8692
|
+
labeledExamples,
|
|
8693
|
+
valset,
|
|
8694
|
+
metricFn,
|
|
8695
|
+
i
|
|
8696
|
+
);
|
|
8697
|
+
evaluatedConfigs.push({ config: nextConfig, score });
|
|
8698
|
+
if (score > bestScore) {
|
|
8699
|
+
bestScore = score;
|
|
8700
|
+
bestConfig = nextConfig;
|
|
8701
|
+
if (this.verbose) {
|
|
8702
|
+
console.log(
|
|
8703
|
+
`New best configuration found with score ${bestScore} (exploitation phase)`
|
|
8704
|
+
);
|
|
8705
|
+
}
|
|
8706
|
+
trialsWithoutImprovement = 0;
|
|
8707
|
+
lastBestScore = bestScore;
|
|
8708
|
+
} else {
|
|
8709
|
+
if (bestScore - lastBestScore < this.minImprovementThreshold) {
|
|
8710
|
+
trialsWithoutImprovement++;
|
|
8711
|
+
if (trialsWithoutImprovement >= this.earlyStoppingTrials) {
|
|
8712
|
+
if (this.verbose) {
|
|
8713
|
+
console.log(
|
|
8714
|
+
`Early stopping triggered after ${i + 1} trials. No improvement for ${trialsWithoutImprovement} trials.`
|
|
8715
|
+
);
|
|
8716
|
+
}
|
|
8717
|
+
break;
|
|
8718
|
+
}
|
|
8719
|
+
} else {
|
|
8720
|
+
lastBestScore = bestScore;
|
|
8721
|
+
trialsWithoutImprovement = 0;
|
|
8722
|
+
}
|
|
8723
|
+
}
|
|
8724
|
+
updateProgressBar(
|
|
8725
|
+
i + 1,
|
|
8726
|
+
this.numTrials,
|
|
8727
|
+
Math.round(bestScore * 100),
|
|
8728
|
+
0,
|
|
8729
|
+
"Running MIPROv2 optimization",
|
|
8730
|
+
30
|
|
8731
|
+
);
|
|
8732
|
+
if (this.minibatch && i > 0 && (i + 1) % this.minibatchFullEvalSteps === 0 && bestConfig) {
|
|
8733
|
+
if (this.verbose) {
|
|
8734
|
+
console.log(
|
|
8735
|
+
`Running full evaluation on best configuration at trial ${i + 1}`
|
|
8736
|
+
);
|
|
8737
|
+
}
|
|
8738
|
+
const fullScore = await this.fullEvaluation(
|
|
8739
|
+
bestConfig,
|
|
8740
|
+
bootstrappedDemos,
|
|
8741
|
+
labeledExamples,
|
|
8742
|
+
valset,
|
|
8743
|
+
metricFn
|
|
8744
|
+
);
|
|
8745
|
+
if (this.verbose) {
|
|
8746
|
+
console.log(`Full evaluation score: ${fullScore}`);
|
|
8747
|
+
}
|
|
8748
|
+
bestScore = fullScore;
|
|
8749
|
+
}
|
|
8750
|
+
}
|
|
8751
|
+
if (!bestConfig) {
|
|
8752
|
+
if (this.verbose) {
|
|
8753
|
+
console.warn(
|
|
8754
|
+
"Optimization failed to find any valid configurations, using default fallback configuration"
|
|
8755
|
+
);
|
|
8756
|
+
}
|
|
8757
|
+
bestConfig = defaultConfig;
|
|
8758
|
+
try {
|
|
8759
|
+
bestScore = await this.evaluateConfig(
|
|
8760
|
+
bestConfig,
|
|
8761
|
+
bootstrappedDemos,
|
|
8762
|
+
labeledExamples,
|
|
8763
|
+
valset,
|
|
8764
|
+
metricFn,
|
|
8765
|
+
this.numTrials - 1
|
|
8766
|
+
);
|
|
8767
|
+
} catch (err) {
|
|
8768
|
+
if (this.verbose) {
|
|
8769
|
+
console.error("Error evaluating default configuration:", err);
|
|
8770
|
+
}
|
|
8771
|
+
bestScore = 0;
|
|
8772
|
+
}
|
|
8773
|
+
}
|
|
8774
|
+
return { bestConfig, bestScore };
|
|
8775
|
+
}
|
|
8776
|
+
/**
|
|
8777
|
+
* Evaluates a configuration on the validation set
|
|
8778
|
+
*/
|
|
8779
|
+
async evaluateConfig(config, bootstrappedDemos, labeledExamples, valset, metricFn, trialIndex) {
|
|
8780
|
+
this.applyConfigToProgram(
|
|
8781
|
+
this.program,
|
|
8782
|
+
config,
|
|
8783
|
+
bootstrappedDemos,
|
|
8784
|
+
labeledExamples
|
|
8785
|
+
);
|
|
8786
|
+
let evalSet = valset;
|
|
8787
|
+
if (this.minibatch) {
|
|
8788
|
+
const startIdx = trialIndex * this.minibatchSize % valset.length;
|
|
8789
|
+
const minibatchEvalSet = [];
|
|
8790
|
+
for (let j = 0; j < this.minibatchSize; j++) {
|
|
8791
|
+
const idx = (startIdx + j) % valset.length;
|
|
8792
|
+
const example = valset[idx];
|
|
8793
|
+
if (example) {
|
|
8794
|
+
minibatchEvalSet.push(example);
|
|
8795
|
+
}
|
|
8796
|
+
}
|
|
8797
|
+
evalSet = minibatchEvalSet;
|
|
8798
|
+
}
|
|
8799
|
+
let correctCount = 0;
|
|
8800
|
+
for (const example of evalSet) {
|
|
8801
|
+
try {
|
|
8802
|
+
const prediction = await this.program.forward(this.ai, example);
|
|
8803
|
+
const correct = metricFn({ prediction, example });
|
|
8804
|
+
if (correct) correctCount++;
|
|
8805
|
+
} catch (err) {
|
|
8806
|
+
if (this.verbose) {
|
|
8807
|
+
console.error("Error evaluating example:", err);
|
|
8808
|
+
}
|
|
8809
|
+
}
|
|
8810
|
+
}
|
|
8811
|
+
return correctCount / evalSet.length;
|
|
8812
|
+
}
|
|
8813
|
+
/**
|
|
8814
|
+
* Run full evaluation on the entire validation set
|
|
8815
|
+
*/
|
|
8816
|
+
async fullEvaluation(config, bootstrappedDemos, labeledExamples, valset, metricFn) {
|
|
8817
|
+
this.applyConfigToProgram(
|
|
8818
|
+
this.program,
|
|
8819
|
+
config,
|
|
8820
|
+
bootstrappedDemos,
|
|
8821
|
+
labeledExamples
|
|
8822
|
+
);
|
|
8823
|
+
let fullCorrectCount = 0;
|
|
8824
|
+
for (const example of valset) {
|
|
8825
|
+
try {
|
|
8826
|
+
const prediction = await this.program.forward(this.ai, example);
|
|
8827
|
+
const correct = metricFn({ prediction, example });
|
|
8828
|
+
if (correct) fullCorrectCount++;
|
|
8829
|
+
} catch (err) {
|
|
8830
|
+
if (this.verbose) {
|
|
8831
|
+
console.error("Error evaluating example:", err);
|
|
8832
|
+
}
|
|
8833
|
+
}
|
|
8834
|
+
}
|
|
8835
|
+
return fullCorrectCount / valset.length;
|
|
8836
|
+
}
|
|
8837
|
+
/**
|
|
8838
|
+
* Implements a Bayesian-inspired selection of the next configuration to try
|
|
8839
|
+
* This is a simplified version using Upper Confidence Bound (UCB) strategy
|
|
8840
|
+
*/
|
|
8841
|
+
selectNextConfiguration(evaluatedConfigs, maxBootstrappedDemos, maxLabeledExamples, instructions) {
|
|
8842
|
+
if (evaluatedConfigs.length < 5) {
|
|
8843
|
+
const instructionIndex = Math.floor(Math.random() * instructions.length);
|
|
8844
|
+
return {
|
|
8845
|
+
instruction: instructions[instructionIndex] || "",
|
|
8846
|
+
bootstrappedDemos: Math.floor(
|
|
8847
|
+
Math.random() * (maxBootstrappedDemos + 1)
|
|
8848
|
+
),
|
|
8849
|
+
labeledExamples: Math.floor(Math.random() * (maxLabeledExamples + 1))
|
|
8850
|
+
};
|
|
8851
|
+
}
|
|
8852
|
+
const sortedConfigs = [...evaluatedConfigs].sort(
|
|
8853
|
+
(a, b) => b.score - a.score
|
|
8854
|
+
);
|
|
8855
|
+
const topConfigs = sortedConfigs.slice(0, Math.min(3, sortedConfigs.length));
|
|
8856
|
+
const meanBootstrappedDemos = topConfigs.reduce((sum, c) => sum + c.config.bootstrappedDemos, 0) / topConfigs.length;
|
|
8857
|
+
const meanLabeledExamples = topConfigs.reduce((sum, c) => sum + c.config.labeledExamples, 0) / topConfigs.length;
|
|
8858
|
+
const popularInstructions = topConfigs.map((c) => c.config.instruction);
|
|
8859
|
+
const explorationFactor = Math.max(
|
|
8860
|
+
0.2,
|
|
8861
|
+
1 - evaluatedConfigs.length / this.numTrials
|
|
8862
|
+
);
|
|
8863
|
+
let newBootstrappedDemos;
|
|
8864
|
+
let newLabeledExamples;
|
|
8865
|
+
let newInstruction;
|
|
8866
|
+
if (Math.random() < 0.7) {
|
|
8867
|
+
newBootstrappedDemos = Math.min(
|
|
8868
|
+
maxBootstrappedDemos,
|
|
8869
|
+
Math.max(
|
|
8870
|
+
0,
|
|
8871
|
+
Math.round(
|
|
8872
|
+
meanBootstrappedDemos + (Math.random() * 2 - 1) * explorationFactor * 2
|
|
8873
|
+
)
|
|
8874
|
+
)
|
|
8875
|
+
);
|
|
8876
|
+
} else {
|
|
8877
|
+
newBootstrappedDemos = Math.floor(
|
|
8878
|
+
Math.random() * (maxBootstrappedDemos + 1)
|
|
8879
|
+
);
|
|
8880
|
+
}
|
|
8881
|
+
if (Math.random() < 0.7) {
|
|
8882
|
+
newLabeledExamples = Math.min(
|
|
8883
|
+
maxLabeledExamples,
|
|
8884
|
+
Math.max(
|
|
8885
|
+
0,
|
|
8886
|
+
Math.round(
|
|
8887
|
+
meanLabeledExamples + (Math.random() * 2 - 1) * explorationFactor * 2
|
|
8888
|
+
)
|
|
8889
|
+
)
|
|
8890
|
+
);
|
|
8891
|
+
} else {
|
|
8892
|
+
newLabeledExamples = Math.floor(Math.random() * (maxLabeledExamples + 1));
|
|
8893
|
+
}
|
|
8894
|
+
if (Math.random() < 0.7 && popularInstructions.length > 0) {
|
|
8895
|
+
const idx = Math.floor(Math.random() * popularInstructions.length);
|
|
8896
|
+
newInstruction = popularInstructions[idx] || "";
|
|
8897
|
+
} else {
|
|
8898
|
+
const idx = Math.floor(Math.random() * instructions.length);
|
|
8899
|
+
newInstruction = instructions[idx] || "";
|
|
8900
|
+
}
|
|
8901
|
+
return {
|
|
8902
|
+
instruction: newInstruction,
|
|
8903
|
+
bootstrappedDemos: newBootstrappedDemos,
|
|
8904
|
+
labeledExamples: newLabeledExamples
|
|
8905
|
+
};
|
|
8906
|
+
}
|
|
8907
|
+
/**
|
|
8908
|
+
* Applies a configuration to a program instance
|
|
8909
|
+
*/
|
|
8910
|
+
applyConfigToProgram(program, config, bootstrappedDemos, labeledExamples) {
|
|
8911
|
+
this.setInstructionToProgram(program, config.instruction);
|
|
8912
|
+
if (config.bootstrappedDemos > 0) {
|
|
8913
|
+
program.setDemos(bootstrappedDemos.slice(0, config.bootstrappedDemos));
|
|
8914
|
+
}
|
|
8915
|
+
if (config.labeledExamples > 0) {
|
|
8916
|
+
program.setExamples(labeledExamples.slice(0, config.labeledExamples));
|
|
8917
|
+
}
|
|
8918
|
+
}
|
|
8919
|
+
/**
|
|
8920
|
+
* Sets instruction to a program
|
|
8921
|
+
* Note: Workaround since setInstruction may not be available directly
|
|
8922
|
+
*/
|
|
8923
|
+
setInstructionToProgram(program, instruction) {
|
|
8924
|
+
const programWithInstruction = program;
|
|
8925
|
+
programWithInstruction.setInstruction?.(instruction);
|
|
8926
|
+
}
|
|
8927
|
+
/**
|
|
8928
|
+
* The main compile method to run MIPROv2 optimization
|
|
8929
|
+
* @param metricFn Evaluation metric function
|
|
8930
|
+
* @param options Optional configuration options
|
|
8931
|
+
* @returns The optimized program
|
|
8932
|
+
*/
|
|
8933
|
+
async compile(metricFn, options) {
|
|
8934
|
+
if (options?.auto) {
|
|
8935
|
+
this.configureAuto(options.auto);
|
|
8936
|
+
}
|
|
8937
|
+
const trainset = this.examples;
|
|
8938
|
+
const valset = options?.valset || this.examples.slice(0, Math.floor(this.examples.length * 0.8));
|
|
8939
|
+
if (this.verbose) {
|
|
8940
|
+
console.log(`Starting MIPROv2 optimization with ${this.numTrials} trials`);
|
|
8941
|
+
console.log(
|
|
8942
|
+
`Using ${trainset.length} examples for training and ${valset.length} for validation`
|
|
8943
|
+
);
|
|
8944
|
+
}
|
|
8945
|
+
if (options?.teacher) {
|
|
8946
|
+
if (this.verbose) {
|
|
8947
|
+
console.log("Using provided teacher to assist with bootstrapping");
|
|
8948
|
+
}
|
|
8949
|
+
const bootstrapperWithTeacher = new AxBootstrapFewShot({
|
|
8950
|
+
ai: this.ai,
|
|
8951
|
+
program: this.program,
|
|
8952
|
+
examples: this.examples,
|
|
8953
|
+
options: {
|
|
8954
|
+
maxDemos: this.maxBootstrappedDemos,
|
|
8955
|
+
maxRounds: 3,
|
|
8956
|
+
verboseMode: this.verbose,
|
|
8957
|
+
teacherAI: this.ai
|
|
8958
|
+
// Use the same AI but with the teacher program
|
|
8959
|
+
}
|
|
8960
|
+
});
|
|
8961
|
+
this.bootstrapper = bootstrapperWithTeacher;
|
|
8962
|
+
}
|
|
8963
|
+
let bootstrappedDemos = [];
|
|
8964
|
+
if (this.maxBootstrappedDemos > 0) {
|
|
8965
|
+
bootstrappedDemos = await this.bootstrapFewShotExamples(metricFn);
|
|
8966
|
+
if (this.verbose) {
|
|
8967
|
+
console.log(
|
|
8968
|
+
`Generated ${bootstrappedDemos.length} bootstrapped demonstrations`
|
|
8969
|
+
);
|
|
8970
|
+
}
|
|
8971
|
+
}
|
|
8972
|
+
let labeledExamples = [];
|
|
8973
|
+
if (this.maxLabeledDemos > 0) {
|
|
8974
|
+
labeledExamples = this.selectLabeledExamples();
|
|
8975
|
+
if (this.verbose) {
|
|
8976
|
+
console.log(
|
|
8977
|
+
`Selected ${labeledExamples.length} labeled examples from training set`
|
|
8978
|
+
);
|
|
8979
|
+
}
|
|
8980
|
+
}
|
|
8981
|
+
const instructions = await this.proposeInstructionCandidates();
|
|
8982
|
+
if (this.verbose) {
|
|
8983
|
+
console.log(`Generated ${instructions.length} instruction candidates`);
|
|
8984
|
+
}
|
|
8985
|
+
const { bestConfig, bestScore } = await this.runBayesianOptimization(
|
|
8986
|
+
bootstrappedDemos,
|
|
8987
|
+
labeledExamples,
|
|
8988
|
+
instructions,
|
|
8989
|
+
valset,
|
|
8990
|
+
metricFn
|
|
8991
|
+
);
|
|
8992
|
+
if (this.verbose) {
|
|
8993
|
+
console.log(`Optimization complete. Best score: ${bestScore}`);
|
|
8994
|
+
console.log(`Best configuration: ${JSON.stringify(bestConfig)}`);
|
|
8995
|
+
}
|
|
8996
|
+
this.applyConfigToProgram(
|
|
8997
|
+
this.program,
|
|
8998
|
+
bestConfig,
|
|
8999
|
+
bootstrappedDemos,
|
|
9000
|
+
labeledExamples
|
|
9001
|
+
);
|
|
9002
|
+
return this.program;
|
|
9003
|
+
}
|
|
9004
|
+
};
|
|
9005
|
+
|
|
8205
9006
|
// ai/mock/api.ts
|
|
8206
9007
|
var AxMockAIService = class {
|
|
8207
9008
|
constructor(config = {}) {
|
|
@@ -10378,6 +11179,7 @@ export {
|
|
|
10378
11179
|
AxMCPHTTPTransport,
|
|
10379
11180
|
AxMCPStdioTransport,
|
|
10380
11181
|
AxMemory,
|
|
11182
|
+
AxMiPRO,
|
|
10381
11183
|
AxMockAIService,
|
|
10382
11184
|
AxMultiServiceRouter,
|
|
10383
11185
|
AxProgram,
|