@ax-llm/ax 11.0.50 → 11.0.51

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.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // ai/base.ts
2
+ import crypto2 from "crypto";
2
3
  import { context, SpanKind } from "@opentelemetry/api";
3
4
 
4
5
  // trace/trace.ts
@@ -66,6 +67,7 @@ var AxSpanKindValues = /* @__PURE__ */ ((AxSpanKindValues2) => {
66
67
  })(AxSpanKindValues || {});
67
68
 
68
69
  // util/apicall.ts
70
+ import crypto from "crypto";
69
71
  import {
70
72
  ReadableStream as ReadableStream2,
71
73
  TextDecoderStream as TextDecoderStreamNative,
@@ -748,7 +750,7 @@ var AxBaseAI = class {
748
750
  this.tracer = options.tracer;
749
751
  this.modelInfo = modelInfo;
750
752
  this.models = models;
751
- this.id = crypto.randomUUID();
753
+ this.id = crypto2.randomUUID();
752
754
  const model = this.getModel(defaults.model) ?? defaults.model;
753
755
  const embedModel = this.getEmbedModel(defaults.embedModel) ?? defaults.embedModel;
754
756
  this.defaults = { model, embedModel };
@@ -2097,6 +2099,9 @@ var AxAIOpenAIImpl = class {
2097
2099
  }
2098
2100
  if (config.thinkingTokenBudget) {
2099
2101
  switch (config.thinkingTokenBudget) {
2102
+ case "none":
2103
+ reqValue.reasoning_effort = void 0;
2104
+ break;
2100
2105
  case "minimal":
2101
2106
  reqValue.reasoning_effort = "low";
2102
2107
  break;
@@ -3158,6 +3163,9 @@ var AxAIGoogleGeminiImpl = class {
3158
3163
  }
3159
3164
  if (config.thinkingTokenBudget) {
3160
3165
  switch (config.thinkingTokenBudget) {
3166
+ case "none":
3167
+ thinkingConfig.thinkingBudget = 0;
3168
+ break;
3161
3169
  case "minimal":
3162
3170
  thinkingConfig.thinkingBudget = 200;
3163
3171
  break;
@@ -5753,16 +5761,20 @@ var AxPromptTemplate = class {
5753
5761
  sig;
5754
5762
  fieldTemplates;
5755
5763
  task;
5756
- constructor(sig, functions, fieldTemplates) {
5764
+ thoughtFieldName;
5765
+ functions;
5766
+ constructor(sig, options, fieldTemplates) {
5757
5767
  this.sig = sig;
5758
5768
  this.fieldTemplates = fieldTemplates;
5769
+ this.thoughtFieldName = options?.thoughtFieldName ?? "thought";
5770
+ this.functions = options?.functions;
5759
5771
  const task = [];
5760
5772
  const inArgs = renderDescFields(this.sig.getInputFields());
5761
5773
  const outArgs = renderDescFields(this.sig.getOutputFields());
5762
5774
  task.push(
5763
5775
  `You will be provided with the following fields: ${inArgs}. Your task is to generate new fields: ${outArgs}.`
5764
5776
  );
5765
- const funcs = functions?.map((f) => "toFunction" in f ? f.toFunction() : f)?.flat();
5777
+ const funcs = this.functions?.map((f) => "toFunction" in f ? f.toFunction() : f)?.flat();
5766
5778
  const funcList = funcs?.map((fn) => `- \`${fn.name}\`: ${formatDescription(fn.description)}`).join("\n");
5767
5779
  if (funcList && funcList.length > 0) {
5768
5780
  task.push(`## Available Functions
@@ -5797,7 +5809,6 @@ ${outputFields}`);
5797
5809
  ...this.renderExamples(examples)
5798
5810
  ] : [];
5799
5811
  const renderedDemos = demos ? this.renderDemos(demos) : [];
5800
- const completion = this.renderInputFields(values);
5801
5812
  const allTextExamples = renderedExamples.every((v) => v.type === "text");
5802
5813
  const allTextDemos = renderedDemos.every((v) => v.type === "text");
5803
5814
  const examplesInSystemPrompt = allTextExamples && allTextDemos;
@@ -5817,14 +5828,73 @@ ${outputFields}`);
5817
5828
  role: "system",
5818
5829
  content: systemContent
5819
5830
  };
5820
- const promptList = examplesInSystemPrompt ? completion : [...renderedExamples, ...renderedDemos, ...completion];
5821
- const prompt = promptList.filter((v) => v !== void 0);
5822
- const userContent = prompt.every((v) => v.type === "text") ? prompt.map((v) => v.text).join("\n") : prompt.reduce(combineConsecutiveStrings("\n"), []);
5823
- const userPrompt = {
5824
- role: "user",
5825
- content: userContent
5826
- };
5827
- return [systemPrompt, userPrompt];
5831
+ let userMessages = [];
5832
+ if (Array.isArray(values)) {
5833
+ const history = values;
5834
+ let lastRole = void 0;
5835
+ for (const message of history) {
5836
+ let messageContent = "";
5837
+ if (message.role === "user") {
5838
+ const userMsgParts = this.renderInputFields(
5839
+ message.values
5840
+ // Cast message.values (AxGenIn) to T (which extends AxGenIn)
5841
+ );
5842
+ messageContent = userMsgParts.map((part) => part.type === "text" ? part.text : "").join("").trim();
5843
+ } else if (message.role === "assistant") {
5844
+ const assistantValues = message.values;
5845
+ let assistantContentParts = [];
5846
+ const outputFields = this.sig.getOutputFields();
5847
+ for (const field of outputFields) {
5848
+ const value = assistantValues[field.name];
5849
+ if (value !== void 0 && value !== null && (typeof value === "string" ? value !== "" : true)) {
5850
+ const renderedValue = processValue(field, value);
5851
+ assistantContentParts.push(`${field.name}: ${renderedValue}`);
5852
+ } else {
5853
+ const isThoughtField = field.name === this.thoughtFieldName;
5854
+ if (!field.isOptional && !field.isInternal && !isThoughtField) {
5855
+ throw new Error(
5856
+ `Value for output field '${field.name}' ('${field.title}') is required in assistant message history but was not found or was empty.`
5857
+ );
5858
+ }
5859
+ }
5860
+ }
5861
+ messageContent = assistantContentParts.join("\n");
5862
+ }
5863
+ if (messageContent) {
5864
+ if (lastRole === message.role && userMessages.length > 0) {
5865
+ const lastMessage = userMessages[userMessages.length - 1];
5866
+ if (lastMessage) {
5867
+ lastMessage.content += "\n" + messageContent;
5868
+ }
5869
+ } else {
5870
+ if (message.role === "user") {
5871
+ userMessages.push({ role: "user", content: messageContent });
5872
+ } else if (message.role === "assistant") {
5873
+ userMessages.push({ role: "assistant", content: messageContent });
5874
+ }
5875
+ }
5876
+ lastRole = message.role;
5877
+ }
5878
+ }
5879
+ } else {
5880
+ const currentValues = values;
5881
+ const completion = this.renderInputFields(currentValues);
5882
+ const promptList = examplesInSystemPrompt ? completion : [...renderedExamples, ...renderedDemos, ...completion];
5883
+ const promptFilter = promptList.filter((v) => v !== void 0);
5884
+ let userContent;
5885
+ if (promptFilter.every((v) => v.type === "text")) {
5886
+ userContent = promptFilter.map((v) => v.text).join("\n");
5887
+ } else {
5888
+ userContent = promptFilter.map((part) => {
5889
+ if (part.type === "text") return part.text;
5890
+ if (part.type === "image") return "[IMAGE]";
5891
+ if (part.type === "audio") return "[AUDIO]";
5892
+ return "";
5893
+ }).join("\n").trim();
5894
+ }
5895
+ userMessages.push({ role: "user", content: userContent });
5896
+ }
5897
+ return [systemPrompt, ...userMessages];
5828
5898
  };
5829
5899
  renderExtraFields = (extraFields) => {
5830
5900
  const prompt = [];
@@ -5868,8 +5938,8 @@ ${outputFields}`);
5868
5938
  renderExamples = (data) => {
5869
5939
  const list = [];
5870
5940
  for (const [index, item] of data.entries()) {
5871
- const renderedInputItem = this.sig.getInputFields().map((field) => this.renderInField(field, item, true)).filter((v) => v !== void 0).flat();
5872
- const renderedOutputItem = this.sig.getOutputFields().map((field) => this.renderInField(field, item, true)).filter((v) => v !== void 0).flat();
5941
+ const renderedInputItem = this.sig.getInputFields().map((field) => this.renderInField(field, item)).filter((v) => v !== void 0).flat();
5942
+ const renderedOutputItem = this.sig.getOutputFields().map((field) => this.renderInField(field, item)).filter((v) => v !== void 0).flat();
5873
5943
  if (renderedOutputItem.length === 0) {
5874
5944
  throw new Error(
5875
5945
  `Output fields are required in examples: index: ${index}, data: ${JSON.stringify(item)}`
@@ -5895,7 +5965,7 @@ ${outputFields}`);
5895
5965
  const list = [];
5896
5966
  const fields = [...this.sig.getInputFields(), ...this.sig.getOutputFields()];
5897
5967
  for (const item of data) {
5898
- const renderedItem = fields.map((field) => this.renderInField(field, item, true)).filter((v) => v !== void 0).flat();
5968
+ const renderedItem = fields.map((field) => this.renderInField(field, item)).filter((v) => v !== void 0).flat();
5899
5969
  renderedItem.slice(0, -1).forEach((v) => {
5900
5970
  if ("text" in v) {
5901
5971
  v.text = v.text + "\n";
@@ -5915,11 +5985,8 @@ ${outputFields}`);
5915
5985
  });
5916
5986
  return renderedItems;
5917
5987
  };
5918
- renderInField = (field, values, skipMissing) => {
5988
+ renderInField = (field, values) => {
5919
5989
  const value = values[field.name];
5920
- if (skipMissing && !value) {
5921
- return;
5922
- }
5923
5990
  if (isEmptyValue(field, value)) {
5924
5991
  return;
5925
5992
  }
@@ -5956,20 +6023,20 @@ ${outputFields}`);
5956
6023
  }
5957
6024
  result = result.concat(
5958
6025
  value.map((v) => {
5959
- v = validateImage(v);
6026
+ const validated = validateImage(v);
5960
6027
  return {
5961
6028
  type: "image",
5962
- mimeType: v.mimeType,
5963
- image: v.data
6029
+ mimeType: validated.mimeType,
6030
+ image: validated.data
5964
6031
  };
5965
6032
  })
5966
6033
  );
5967
6034
  } else {
5968
- const v = validateImage(value);
6035
+ const validated = validateImage(value);
5969
6036
  result.push({
5970
6037
  type: "image",
5971
- mimeType: v.mimeType,
5972
- image: v.data
6038
+ mimeType: validated.mimeType,
6039
+ image: validated.data
5973
6040
  });
5974
6041
  }
5975
6042
  return result;
@@ -5992,24 +6059,24 @@ ${outputFields}`);
5992
6059
  ];
5993
6060
  if (field.type.isArray) {
5994
6061
  if (!Array.isArray(value)) {
5995
- throw new Error("Image field value must be an array.");
6062
+ throw new Error("Audio field value must be an array.");
5996
6063
  }
5997
6064
  result = result.concat(
5998
6065
  value.map((v) => {
5999
- v = validateAudio(v);
6066
+ const validated = validateAudio(v);
6000
6067
  return {
6001
6068
  type: "audio",
6002
- format: v.format ?? "wav",
6003
- data: v.data
6069
+ format: validated.format ?? "wav",
6070
+ data: validated.data
6004
6071
  };
6005
6072
  })
6006
6073
  );
6007
6074
  } else {
6008
- const v = validateAudio(value);
6075
+ const validated = validateAudio(value);
6009
6076
  result.push({
6010
6077
  type: "audio",
6011
- format: v.format ?? "wav",
6012
- data: v.data
6078
+ format: validated.format ?? "wav",
6079
+ data: validated.data
6013
6080
  });
6014
6081
  }
6015
6082
  return result;
@@ -6109,7 +6176,7 @@ var isEmptyValue = (field, value) => {
6109
6176
  return false;
6110
6177
  }
6111
6178
  if (!value || (Array.isArray(value) || typeof value === "string") && value.length === 0) {
6112
- if (field.isOptional) {
6179
+ if (field.isOptional || field.isInternal) {
6113
6180
  return true;
6114
6181
  }
6115
6182
  throw new Error(`Value for input field '${field.name}' is required.`);
@@ -7563,12 +7630,18 @@ var AxGen = class extends AxProgramWithSignature {
7563
7630
  streamingFieldProcessors = [];
7564
7631
  values = {};
7565
7632
  excludeContentFromTrace = false;
7633
+ thoughtFieldName;
7566
7634
  constructor(signature, options) {
7567
7635
  super(signature, { description: options?.description });
7568
7636
  this.options = options;
7637
+ this.thoughtFieldName = options?.thoughtFieldName ?? "thought";
7638
+ const promptTemplateOptions = {
7639
+ functions: options?.functions,
7640
+ thoughtFieldName: this.thoughtFieldName
7641
+ };
7569
7642
  this.promptTemplate = new (options?.promptTemplate ?? AxPromptTemplate)(
7570
7643
  this.signature,
7571
- options?.functions
7644
+ promptTemplateOptions
7572
7645
  );
7573
7646
  this.asserts = this.options?.asserts ?? [];
7574
7647
  this.streamingAsserts = this.options?.streamingAsserts ?? [];
@@ -7740,7 +7813,9 @@ var AxGen = class extends AxProgramWithSignature {
7740
7813
  );
7741
7814
  } else if (result.content && result.content.length > 0) {
7742
7815
  if (result.thought && result.thought.length > 0) {
7743
- yield { thought: result.thought };
7816
+ yield {
7817
+ [this.thoughtFieldName]: result.thought
7818
+ };
7744
7819
  }
7745
7820
  content += result.content;
7746
7821
  mem.updateResult(
@@ -7782,8 +7857,10 @@ var AxGen = class extends AxProgramWithSignature {
7782
7857
  );
7783
7858
  await assertAssertions(this.asserts, this.values);
7784
7859
  } else if (result.thought && result.thought.length > 0) {
7785
- this.values.thought = this.values.thought ?? "" + result.thought;
7786
- yield { thought: result.thought };
7860
+ this.values[this.thoughtFieldName] = (this.values[this.thoughtFieldName] ?? "") + result.thought;
7861
+ yield {
7862
+ [this.thoughtFieldName]: result.thought
7863
+ };
7787
7864
  }
7788
7865
  if (result.finishReason === "length") {
7789
7866
  throw new Error(
@@ -7883,7 +7960,7 @@ Content: ${content}`
7883
7960
  }
7884
7961
  } else if (result.content) {
7885
7962
  if (result.thought && result.thought.length > 0) {
7886
- this.values.thought = result.thought;
7963
+ this.values[this.thoughtFieldName] = result.thought;
7887
7964
  }
7888
7965
  extractValues(this.signature, this.values, result.content);
7889
7966
  await assertAssertions(this.asserts, this.values);
@@ -7920,16 +7997,29 @@ Content: ${result.content}`
7920
7997
  const mem = options.mem ?? this.options?.mem ?? new AxMemory(1e4, memOptions);
7921
7998
  let err;
7922
7999
  if (options?.functions && options.functions.length > 0) {
7923
- const promptTemplate = this.options?.promptTemplate ?? AxPromptTemplate;
7924
- this.promptTemplate = new promptTemplate(
8000
+ const promptTemplateClass = this.options?.promptTemplate ?? AxPromptTemplate;
8001
+ const currentPromptTemplateOptions = {
8002
+ functions: options.functions,
8003
+ thoughtFieldName: this.thoughtFieldName
8004
+ };
8005
+ this.promptTemplate = new promptTemplateClass(
7925
8006
  this.signature,
7926
- options.functions
8007
+ currentPromptTemplateOptions
7927
8008
  );
7928
8009
  }
7929
- const prompt = this.promptTemplate.render(values, {
7930
- examples: this.examples,
7931
- demos: this.demos
7932
- });
8010
+ let prompt;
8011
+ if (Array.isArray(values)) {
8012
+ prompt = this.promptTemplate.render(values, {
8013
+ examples: this.examples,
8014
+ demos: this.demos
8015
+ });
8016
+ } else {
8017
+ prompt = this.promptTemplate.render(values, {
8018
+ // Cast if necessary
8019
+ examples: this.examples,
8020
+ demos: this.demos
8021
+ });
8022
+ }
7933
8023
  mem.add(prompt, options?.sessionId);
7934
8024
  multiStepLoop: for (let n = 0; n < maxSteps; n++) {
7935
8025
  const firstStep = n === 0;
@@ -8791,7 +8881,8 @@ var AxBootstrapFewShot = class {
8791
8881
  if (this.costMonitoring) {
8792
8882
  this.stats.estimatedTokenUsage += JSON.stringify(ex).length / 4 + JSON.stringify(res).length / 4;
8793
8883
  }
8794
- const success = metricFn({ prediction: res, example: ex });
8884
+ const score = metricFn({ prediction: res, example: ex });
8885
+ const success = score >= 0.5;
8795
8886
  if (success) {
8796
8887
  this.traces = [...this.traces, ...this.program.getTraces()];
8797
8888
  this.stats.successfulDemos++;
@@ -10779,19 +10870,20 @@ ${dataContext}
10779
10870
  }
10780
10871
  evalSet = minibatchEvalSet;
10781
10872
  }
10782
- let correctCount = 0;
10873
+ let sumOfScores = 0;
10783
10874
  for (const example of evalSet) {
10784
10875
  try {
10785
10876
  const prediction = await this.program.forward(this.ai, example);
10786
- const correct = metricFn({ prediction, example });
10787
- if (correct) correctCount++;
10877
+ const score = metricFn({ prediction, example });
10878
+ sumOfScores += score;
10788
10879
  } catch (err) {
10789
10880
  if (this.verbose) {
10790
10881
  console.error("Error evaluating example:", err);
10791
10882
  }
10792
10883
  }
10793
10884
  }
10794
- return correctCount / evalSet.length;
10885
+ if (evalSet.length === 0) return 0;
10886
+ return sumOfScores / evalSet.length;
10795
10887
  }
10796
10888
  /**
10797
10889
  * Run full evaluation on the entire validation set
@@ -10803,19 +10895,20 @@ ${dataContext}
10803
10895
  bootstrappedDemos,
10804
10896
  labeledExamples
10805
10897
  );
10806
- let fullCorrectCount = 0;
10898
+ let sumOfScores = 0;
10807
10899
  for (const example of valset) {
10808
10900
  try {
10809
10901
  const prediction = await this.program.forward(this.ai, example);
10810
- const correct = metricFn({ prediction, example });
10811
- if (correct) fullCorrectCount++;
10902
+ const score = metricFn({ prediction, example });
10903
+ sumOfScores += score;
10812
10904
  } catch (err) {
10813
10905
  if (this.verbose) {
10814
10906
  console.error("Error evaluating example:", err);
10815
10907
  }
10816
10908
  }
10817
10909
  }
10818
- return fullCorrectCount / valset.length;
10910
+ if (valset.length === 0) return 0;
10911
+ return sumOfScores / valset.length;
10819
10912
  }
10820
10913
  /**
10821
10914
  * Implements a Bayesian-inspired selection of the next configuration to try
@@ -10987,10 +11080,11 @@ ${dataContext}
10987
11080
  };
10988
11081
 
10989
11082
  // ai/mock/api.ts
11083
+ import crypto3 from "crypto";
10990
11084
  var AxMockAIService = class {
10991
11085
  constructor(config = {}) {
10992
11086
  this.config = config;
10993
- this.config.id = this.config.id ?? crypto.randomUUID();
11087
+ this.config.id = this.config.id ?? crypto3.randomUUID();
10994
11088
  }
10995
11089
  metrics = {
10996
11090
  latency: {
@@ -11201,27 +11295,26 @@ var AxTestPrompt = class {
11201
11295
  async run(metricFn) {
11202
11296
  const st = (/* @__PURE__ */ new Date()).getTime();
11203
11297
  const total = this.examples.length;
11204
- let successCount = 0;
11298
+ let sumOfScores = 0;
11205
11299
  for (let i = 0; i < total; i++) {
11206
11300
  const ex = this.examples[i];
11207
11301
  if (!ex) {
11208
11302
  throw new Error("Invalid example");
11209
11303
  }
11210
11304
  const res = await this.program.forward(this.ai, ex);
11211
- const success = metricFn({ prediction: res, example: ex });
11212
- if (success) {
11213
- successCount++;
11214
- }
11305
+ const score = metricFn({ prediction: res, example: ex });
11306
+ sumOfScores += score;
11215
11307
  const et = (/* @__PURE__ */ new Date()).getTime() - st;
11216
- updateProgressBar(i, total, successCount, et, "Testing Prompt", 30);
11308
+ updateProgressBar(i, total, sumOfScores, et, "Testing Prompt", 30);
11217
11309
  }
11310
+ const averageScore = total > 0 ? sumOfScores / total : 0;
11218
11311
  console.log(
11219
11312
  "\nPerformance: ",
11220
- successCount,
11313
+ sumOfScores,
11221
11314
  "/",
11222
11315
  total,
11223
- "Accuracy: ",
11224
- successCount / total,
11316
+ "Average Score: ",
11317
+ averageScore,
11225
11318
  "\n"
11226
11319
  );
11227
11320
  }
@@ -11235,7 +11328,8 @@ var AxChainOfThought = class extends AxGen {
11235
11328
  sig.setOutputFields([
11236
11329
  {
11237
11330
  name: "reason",
11238
- description
11331
+ description,
11332
+ isInternal: options?.setVisibleReasoning !== true
11239
11333
  },
11240
11334
  ...sig.getOutputFields()
11241
11335
  ]);
@@ -12564,7 +12658,7 @@ function normalizeText(s) {
12564
12658
  return s.toLowerCase();
12565
12659
  }
12566
12660
  function emScore(prediction, groundTruth) {
12567
- return normalizeText(prediction) === normalizeText(groundTruth);
12661
+ return normalizeText(prediction) === normalizeText(groundTruth) ? 1 : 0;
12568
12662
  }
12569
12663
  function f1Score(prediction, groundTruth) {
12570
12664
  const predictionTokens = normalizeText(prediction).split(" ");
@@ -12604,12 +12698,12 @@ var AxEvalUtil = {
12604
12698
  };
12605
12699
 
12606
12700
  // ../../node_modules/uuid/dist/esm-node/rng.js
12607
- import crypto2 from "crypto";
12701
+ import crypto4 from "crypto";
12608
12702
  var rnds8Pool = new Uint8Array(256);
12609
12703
  var poolPtr = rnds8Pool.length;
12610
12704
  function rng() {
12611
12705
  if (poolPtr > rnds8Pool.length - 16) {
12612
- crypto2.randomFillSync(rnds8Pool);
12706
+ crypto4.randomFillSync(rnds8Pool);
12613
12707
  poolPtr = 0;
12614
12708
  }
12615
12709
  return rnds8Pool.slice(poolPtr, poolPtr += 16);
@@ -12625,9 +12719,9 @@ function unsafeStringify(arr, offset = 0) {
12625
12719
  }
12626
12720
 
12627
12721
  // ../../node_modules/uuid/dist/esm-node/native.js
12628
- import crypto3 from "crypto";
12722
+ import crypto5 from "crypto";
12629
12723
  var native_default = {
12630
- randomUUID: crypto3.randomUUID
12724
+ randomUUID: crypto5.randomUUID
12631
12725
  };
12632
12726
 
12633
12727
  // ../../node_modules/uuid/dist/esm-node/v4.js