@ax-llm/ax 12.0.8 → 12.0.9

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
@@ -320,6 +320,17 @@ var AxAIServiceAuthenticationError = class extends AxAIServiceError {
320
320
  this.name = this.constructor.name;
321
321
  }
322
322
  };
323
+ async function safeReadResponseBody(response) {
324
+ try {
325
+ if (response.headers.get("content-type")?.includes("application/json")) {
326
+ return await response.json();
327
+ }
328
+ const clonedResponse = response.clone();
329
+ return await clonedResponse.text();
330
+ } catch (e) {
331
+ return `[ReadableStream - read failed: ${e.message}]`;
332
+ }
333
+ }
323
334
  function calculateRetryDelay(attempt, config) {
324
335
  const delay = Math.min(
325
336
  config.maxDelayMs,
@@ -413,9 +424,15 @@ var apiCall = async (api, json) => {
413
424
  });
414
425
  clearTimeout(timeoutId);
415
426
  if (res.status === 401 || res.status === 403) {
416
- throw new AxAIServiceAuthenticationError(apiUrl.href, json, res.body, {
417
- metrics
418
- });
427
+ const responseBody = await safeReadResponseBody(res);
428
+ throw new AxAIServiceAuthenticationError(
429
+ apiUrl.href,
430
+ json,
431
+ responseBody,
432
+ {
433
+ metrics
434
+ }
435
+ );
419
436
  }
420
437
  if (res.status >= 400 && shouldRetry(new Error(), res.status, attempt, retryConfig)) {
421
438
  const delay = calculateRetryDelay(attempt, retryConfig);
@@ -433,12 +450,13 @@ var apiCall = async (api, json) => {
433
450
  continue;
434
451
  }
435
452
  if (res.status >= 400) {
453
+ const responseBody = await safeReadResponseBody(res);
436
454
  throw new AxAIServiceStatusError(
437
455
  res.status,
438
456
  res.statusText,
439
457
  apiUrl.href,
440
458
  json,
441
- res.body,
459
+ responseBody,
442
460
  { metrics }
443
461
  );
444
462
  }
@@ -536,7 +554,7 @@ var apiCall = async (api, json) => {
536
554
  error,
537
555
  apiUrl.href,
538
556
  json,
539
- res.body,
557
+ "[ReadableStream - consumed during streaming]",
540
558
  {
541
559
  streamMetrics
542
560
  }
@@ -667,12 +685,12 @@ var ColorLog = class {
667
685
  }
668
686
  };
669
687
 
670
- // ai/debug.ts
688
+ // dsp/loggers.ts
671
689
  var colorLog = new ColorLog();
672
690
  var defaultOutput = (message) => {
673
691
  process.stdout.write(message);
674
692
  };
675
- var createDefaultLogger = (output = defaultOutput) => {
693
+ var axCreateDefaultLogger = (output = defaultOutput) => {
676
694
  return (message, options) => {
677
695
  const tags = options?.tags ?? [];
678
696
  let formattedMessage = message;
@@ -681,11 +699,18 @@ var createDefaultLogger = (output = defaultOutput) => {
681
699
  } else if (tags.includes("success") || tags.includes("responseContent")) {
682
700
  formattedMessage = colorLog.greenBright(formattedMessage);
683
701
  } else if (tags.includes("functionName")) {
684
- formattedMessage = colorLog.whiteBright(formattedMessage);
685
- } else if (tags.includes("functionArg") || tags.includes("systemContent") || tags.includes("assistantContent")) {
702
+ if (tags.includes("firstFunction")) {
703
+ formattedMessage = `
704
+ ${colorLog.whiteBright(formattedMessage)}`;
705
+ } else {
706
+ formattedMessage = `${colorLog.whiteBright(formattedMessage)}`;
707
+ }
708
+ } else if (tags.includes("systemContent") || tags.includes("assistantContent")) {
686
709
  formattedMessage = colorLog.blueBright(formattedMessage);
687
710
  } else if (tags.includes("warning") || tags.includes("discovery")) {
688
711
  formattedMessage = colorLog.yellow(formattedMessage);
712
+ } else if (tags.includes("functionArg")) {
713
+ formattedMessage = "";
689
714
  }
690
715
  if (tags.includes("responseStart") || tags.includes("systemStart") || tags.includes("userStart")) {
691
716
  formattedMessage = `
@@ -700,6 +725,31 @@ ${formattedMessage}
700
725
  } else if (tags.includes("error")) {
701
726
  formattedMessage = `
702
727
  ${formattedMessage}
728
+ `;
729
+ } else if (tags.includes("functionEnd")) {
730
+ formattedMessage = `
731
+ `;
732
+ }
733
+ output(formattedMessage);
734
+ };
735
+ };
736
+ var axCreateDefaultTextLogger = (output = defaultOutput) => {
737
+ return (message, options) => {
738
+ const tags = options?.tags ?? [];
739
+ let formattedMessage = message;
740
+ if (tags.includes("responseStart") || tags.includes("systemStart") || tags.includes("userStart")) {
741
+ formattedMessage = `
742
+ ${formattedMessage}`;
743
+ } else if (tags.includes("responseEnd") || tags.includes("systemEnd") || tags.includes("userEnd")) {
744
+ formattedMessage = `${formattedMessage}
745
+ `;
746
+ } else if (tags.includes("assistantStart")) {
747
+ formattedMessage = `
748
+ ${formattedMessage}
749
+ `;
750
+ } else if (tags.includes("error")) {
751
+ formattedMessage = `
752
+ ${formattedMessage}
703
753
  `;
704
754
  } else if (tags.includes("functionEnd")) {
705
755
  formattedMessage = `${formattedMessage}
@@ -708,7 +758,137 @@ ${formattedMessage}
708
758
  output(formattedMessage);
709
759
  };
710
760
  };
711
- var defaultLogger = createDefaultLogger();
761
+ var axCreateOptimizerLogger = (output = (msg) => process.stdout.write(msg)) => {
762
+ const baseLogger = axCreateDefaultLogger(output);
763
+ let isFirstPhase = true;
764
+ return (message, options) => {
765
+ const tags = options?.tags ?? [];
766
+ let formattedMessage = message;
767
+ if (tags.includes("optimizer")) {
768
+ if (tags.includes("start")) {
769
+ const trialsMatch = message.match(/with (\d+) trials?/) || message.match(/(\d+) trials?/);
770
+ const optimizerMatch = message.match(
771
+ /(MIPROv2|BootstrapFewshot|[A-Z][a-zA-Z]+)/
772
+ );
773
+ const optimizerName = optimizerMatch ? optimizerMatch[1] : "Optimizer";
774
+ if (trialsMatch && trialsMatch[1]) {
775
+ formattedMessage = `
776
+ \u250C\u2500 ${optimizerName} optimization (${trialsMatch[1]} trials)
777
+ `;
778
+ } else {
779
+ formattedMessage = `
780
+ \u250C\u2500 ${optimizerName} optimization
781
+ `;
782
+ }
783
+ isFirstPhase = true;
784
+ } else if (tags.includes("config")) {
785
+ if (message.includes("examples") && message.includes("training")) {
786
+ const match = message.match(
787
+ /(\d+) examples for training and (\d+) for validation/
788
+ ) || message.match(/(\d+) training.*?(\d+) validation/);
789
+ if (match && match[1] && match[2]) {
790
+ formattedMessage = `\u2502 Dataset: ${match[1]} training, ${match[2]} validation
791
+ `;
792
+ } else {
793
+ const simpleMatch = message.match(/(\d+) examples/);
794
+ if (simpleMatch && simpleMatch[1]) {
795
+ formattedMessage = `\u2502 Dataset: ${simpleMatch[1]} examples
796
+ `;
797
+ }
798
+ }
799
+ } else if (message.includes("teacher")) {
800
+ formattedMessage = `\u2502 Using teacher model
801
+ `;
802
+ } else {
803
+ formattedMessage = `\u2502 ${message}
804
+ `;
805
+ }
806
+ } else if (tags.includes("phase")) {
807
+ if (isFirstPhase) {
808
+ formattedMessage = `\u251C\u2500 ${message}
809
+ `;
810
+ isFirstPhase = false;
811
+ } else {
812
+ formattedMessage = `\u251C\u2500 ${message}
813
+ `;
814
+ }
815
+ } else if (tags.includes("result")) {
816
+ if (message.includes("Generated") || message.includes("Selected")) {
817
+ const match = message.match(/(\d+)/);
818
+ if (match && match[1]) {
819
+ formattedMessage = `\u2502 \u2713 ${message}
820
+ `;
821
+ } else {
822
+ formattedMessage = `\u2502 \u2713 ${message}
823
+ `;
824
+ }
825
+ } else if (message.includes("configuration")) {
826
+ formattedMessage = `\u2502 Applied best configuration
827
+ `;
828
+ } else {
829
+ formattedMessage = `\u2502 ${message}
830
+ `;
831
+ }
832
+ } else if (tags.includes("progress")) {
833
+ formattedMessage = `\u2502 ${message}
834
+ `;
835
+ } else if (tags.includes("complete")) {
836
+ const scoreMatch = message.match(/(score|performance):\s*([\d.]+)/);
837
+ if (scoreMatch && scoreMatch[2]) {
838
+ const score = parseFloat(scoreMatch[2]);
839
+ const percentage = score <= 1 ? (score * 100).toFixed(1) + "%" : score.toFixed(3);
840
+ formattedMessage = `\u251C\u2500 Complete! Best: ${percentage}
841
+ `;
842
+ } else if (message.includes("Bootstrap")) {
843
+ formattedMessage = `\u251C\u2500 ${message}
844
+ `;
845
+ } else {
846
+ formattedMessage = `\u251C\u2500 Optimization complete
847
+ `;
848
+ }
849
+ } else if (tags.includes("checkpoint")) {
850
+ if (message.includes("Resuming")) {
851
+ formattedMessage = `\u2502 ${message}
852
+ `;
853
+ } else {
854
+ const match = message.match(/checkpoint:\s*(.+)/) || message.match(/Saved\s+(.+)/);
855
+ if (match && match[1]) {
856
+ formattedMessage = `\u2514\u2500 Saved: ${match[1]}
857
+ `;
858
+ } else {
859
+ formattedMessage = `\u2514\u2500 Checkpoint saved
860
+ `;
861
+ }
862
+ }
863
+ }
864
+ } else if (tags.includes("discovery")) {
865
+ if (message.includes("Found") && message.includes("examples")) {
866
+ const match = message.match(/Found (\d+)/);
867
+ if (match && match[1]) {
868
+ formattedMessage = `\u2502 Found ${match[1]} examples
869
+ `;
870
+ }
871
+ }
872
+ }
873
+ if (tags.includes("error")) {
874
+ formattedMessage = `
875
+ \u2717 ${message}
876
+ `;
877
+ } else if (tags.includes("warning")) {
878
+ formattedMessage = `
879
+ \u26A0 ${message}
880
+ `;
881
+ } else if (tags.includes("success") && !tags.includes("optimizer")) {
882
+ formattedMessage = `\u2713 ${message}
883
+ `;
884
+ }
885
+ baseLogger(formattedMessage, options);
886
+ };
887
+ };
888
+ var axDefaultOptimizerLogger = axCreateOptimizerLogger();
889
+
890
+ // ai/debug.ts
891
+ var defaultLogger = axCreateDefaultLogger();
712
892
  var formatChatMessage = (msg, hideContent, hideSystemPrompt) => {
713
893
  switch (msg.role) {
714
894
  case "system":
@@ -785,9 +965,14 @@ var logResponseResult = (r, logger = defaultLogger) => {
785
965
  if (r.functionCalls && r.functionCalls.length > 0) {
786
966
  for (const [i, f2] of r.functionCalls.entries()) {
787
967
  if (f2.function.name) {
788
- logger(`[${i + 1}] ${f2.function.name}`, {
789
- tags: ["functionName"]
790
- });
968
+ const tags = ["functionName"];
969
+ if (i === 0) {
970
+ tags.push("firstFunction");
971
+ }
972
+ if (r.functionCalls.length > 1) {
973
+ tags.push("multipleFunctions");
974
+ }
975
+ logger(`[${i + 1}] ${f2.function.name}`, { tags });
791
976
  }
792
977
  if (f2.function.params) {
793
978
  const params = typeof f2.function.params === "string" ? f2.function.params : JSON.stringify(f2.function.params, null, 2);
@@ -1458,6 +1643,16 @@ function validateAxMessageArray(values) {
1458
1643
  function validateChatPrompt(chatPrompt) {
1459
1644
  for (let i = 0; i < chatPrompt.length; i++) {
1460
1645
  const message = chatPrompt[i];
1646
+ if (message && "functionCalls" in message && Array.isArray(message.functionCalls) && message.functionCalls.length === 0) {
1647
+ throw new Error(
1648
+ `Chat prompt validation failed: Message at index ${i} has empty functionCalls`
1649
+ );
1650
+ }
1651
+ if (message && "content" in message && Array.isArray(message.content) && message.content.length === 0) {
1652
+ throw new Error(
1653
+ `Chat prompt validation failed: Message at index ${i} has empty content`
1654
+ );
1655
+ }
1461
1656
  if (message && "content" in message && typeof message.content === "string" && message.content.trim() === "") {
1462
1657
  throw new Error(
1463
1658
  `Chat prompt validation failed: Message at index ${i} has empty content`
@@ -5785,9 +5980,11 @@ var updateProgressBar = (current, total, success, elapsedTime, msg, progressBarW
5785
5980
  const emptyBarLength = progressBarWidth - filledBarLength;
5786
5981
  const filledBar = colorLog3.blueBright("\u2588".repeat(filledBarLength));
5787
5982
  const emptyBar = " ".repeat(emptyBarLength);
5788
- const itemsPerSecond = elapsedTime > 0 ? (current / elapsedTime).toFixed(2) : "0.00";
5983
+ const successRate = total > 0 ? (success / total * 100).toFixed(1) : "0.0";
5984
+ const friendlyMsg = msg.includes("Running MIPROv2 optimization") ? "Testing prompt variations" : msg.includes("Tuning Prompt") ? "Generating training examples" : msg;
5789
5985
  process.stdout.write(
5790
- `\r${msg}: ${current} / ${total} (${colorLog3.yellow(percentage)}%): 100%|${filledBar}${emptyBar}| Success: ${success}/${total} [${colorLog3.red(elapsedTime.toFixed(2))}, ${itemsPerSecond}it/s]`
5986
+ `\u2502 ${friendlyMsg}: ${current}/${total} (${colorLog3.yellow(percentage)}%) |${filledBar}${emptyBar}| Success rate: ${colorLog3.greenBright(successRate)}%
5987
+ `
5791
5988
  );
5792
5989
  };
5793
5990
  var validateValue = (field, value) => {
@@ -5994,19 +6191,15 @@ function matchesContent(content, prefix, startIndex = 0, prefixCache = globalPre
5994
6191
  if (!prefixCache.get(prefix)) {
5995
6192
  prefixCache.set(prefix, prefixes);
5996
6193
  }
5997
- const contentEnd = content.slice(
5998
- Math.max(startIndex, content.length - prefix.length)
5999
- );
6000
- for (let i = 0; i < prefixes.length - 1; i++) {
6194
+ let longestPartialMatch = -1;
6195
+ for (let i = prefixes.length - 1; i >= 0; i--) {
6001
6196
  const partialPrefix = prefixes[i];
6002
- if (partialPrefix === "\n" || partialPrefix === ":") {
6003
- continue;
6004
- }
6005
- if (partialPrefix && contentEnd.endsWith(partialPrefix)) {
6006
- return -2;
6197
+ if (content.endsWith(partialPrefix)) {
6198
+ longestPartialMatch = i;
6199
+ break;
6007
6200
  }
6008
6201
  }
6009
- return -1;
6202
+ return longestPartialMatch >= 0 ? -2 : -1;
6010
6203
  }
6011
6204
  var formatTime = (ms) => {
6012
6205
  const seconds = Math.floor(ms / 1e3);
@@ -6029,11 +6222,10 @@ var updateDetailedProgress = (roundIndex, current, total, elapsedTime, example,
6029
6222
  process.stdout.write("\r\x1B[K");
6030
6223
  const percentage = (current / total * 100).toFixed(1);
6031
6224
  const formattedTime = formatTime(elapsedTime);
6032
- const itemsPerSecond = elapsedTime > 0 ? (current / elapsedTime * 1e3).toFixed(2) : "0.00";
6033
6225
  const eta = calculateETA(current, total, elapsedTime);
6034
- let output = `Round ${roundIndex + 1}/${configInfo.maxRounds}: ${current}/${total} (${percentage}%) [${formattedTime}, ${itemsPerSecond} it/s, ETA: ${eta}]`;
6226
+ let output = `Training round ${roundIndex + 1}/${configInfo.maxRounds}: ${current}/${total} (${percentage}%) [${formattedTime}, ETA: ${eta}]`;
6035
6227
  const successRate = stats.totalCalls > 0 ? stats.successfulDemos / stats.totalCalls * 100 : 0;
6036
- output += ` | Success: ${stats.successfulDemos}/${stats.totalCalls} (${successRate.toFixed(1)}%)`;
6228
+ output += ` | Success rate: ${successRate.toFixed(1)}% (${stats.successfulDemos}/${stats.totalCalls})`;
6037
6229
  if (configInfo.verboseMode || configInfo.debugMode) {
6038
6230
  if (configInfo.costMonitoring) {
6039
6231
  output += `
@@ -6159,7 +6351,7 @@ ${outputFields}`);
6159
6351
  content: systemContent
6160
6352
  };
6161
6353
  if (Array.isArray(values)) {
6162
- let userMessages = [];
6354
+ let messages = [];
6163
6355
  const history = values;
6164
6356
  for (const [index, message] of history.entries()) {
6165
6357
  let content;
@@ -6179,7 +6371,7 @@ ${outputFields}`);
6179
6371
  );
6180
6372
  }
6181
6373
  if (message.role === "user") {
6182
- userMessages.push({ role: "user", content });
6374
+ messages.push({ role: "user", content });
6183
6375
  continue;
6184
6376
  }
6185
6377
  if (message.role !== "assistant") {
@@ -6190,9 +6382,9 @@ ${outputFields}`);
6190
6382
  "Assistant message cannot contain non-text content like images, files,etc"
6191
6383
  );
6192
6384
  }
6193
- userMessages.push({ role: "assistant", content });
6385
+ messages.push({ role: "assistant", content });
6194
6386
  }
6195
- return [systemPrompt, ...userMessages];
6387
+ return [systemPrompt, ...messages];
6196
6388
  }
6197
6389
  const userContent = this.renderSingleValueUserContent(
6198
6390
  values,
@@ -6645,9 +6837,9 @@ var formatDateWithTimezone = (date) => {
6645
6837
  };
6646
6838
 
6647
6839
  // dsp/extract.ts
6648
- var extractValues = (sig, values, content) => {
6840
+ var extractValues = (sig, values, content, strictMode = false) => {
6649
6841
  const xstate = { extractedFields: [], streamedIndex: {}, s: -1 };
6650
- streamingExtractValues(sig, values, xstate, content);
6842
+ streamingExtractValues(sig, values, xstate, content, strictMode);
6651
6843
  streamingExtractFinalValue(sig, values, xstate, content);
6652
6844
  for (const field of sig.getOutputFields()) {
6653
6845
  if (field.isInternal) {
@@ -6655,10 +6847,9 @@ var extractValues = (sig, values, content) => {
6655
6847
  }
6656
6848
  }
6657
6849
  };
6658
- var checkMissingRequiredFields = (xstate, values, currentIndex) => {
6850
+ var checkMissingRequiredFields = (xstate, values, outputFields) => {
6659
6851
  const missingFields = [];
6660
- for (let i = 0; i < currentIndex; i++) {
6661
- const field = xstate.extractedFields[i];
6852
+ for (const field of outputFields) {
6662
6853
  if (field && !field.isOptional && values[field.name] === void 0) {
6663
6854
  missingFields.push(field);
6664
6855
  }
@@ -6670,23 +6861,34 @@ var checkMissingRequiredFields = (xstate, values, currentIndex) => {
6670
6861
  });
6671
6862
  }
6672
6863
  };
6673
- var streamingExtractValues = (sig, values, xstate, content, streamingValidation = false) => {
6864
+ var streamingExtractValues = (sig, values, xstate, content, strictMode = false) => {
6674
6865
  const fields = sig.getOutputFields();
6866
+ let expectedField;
6675
6867
  for (const [index, field] of fields.entries()) {
6868
+ if (index === xstate.currFieldIndex) {
6869
+ continue;
6870
+ }
6676
6871
  if (field.name in values) {
6677
6872
  continue;
6678
6873
  }
6679
6874
  const isFirst = xstate.extractedFields.length === 0;
6680
6875
  const prefix = (isFirst ? "" : "\n") + field.title + ":";
6681
6876
  let e = matchesContent(content, prefix, xstate.s);
6877
+ let prefixLen = prefix.length;
6682
6878
  switch (e) {
6683
6879
  case -1:
6684
- if (streamingValidation && values.length == 0 && !field.isOptional) {
6880
+ if (!strictMode && fields.length === 1 && xstate.currField === void 0) {
6881
+ prefixLen = 0;
6882
+ e = 0;
6883
+ break;
6884
+ }
6885
+ if (xstate.currField === void 0 && !field.isOptional) {
6685
6886
  throw new ValidationError({
6686
- message: "Required field not found",
6887
+ message: "Expected (Required) field not found",
6687
6888
  fields: [field]
6688
6889
  });
6689
6890
  }
6891
+ expectedField = field.isOptional ? void 0 : field;
6690
6892
  continue;
6691
6893
  // Field is not found, continue to the next field
6692
6894
  case -2:
@@ -6699,7 +6901,12 @@ var streamingExtractValues = (sig, values, xstate, content, streamingValidation
6699
6901
  xstate.inBlock = true;
6700
6902
  return true;
6701
6903
  }
6702
- let prefixLen = prefix.length;
6904
+ if (expectedField && expectedField.name !== field.name) {
6905
+ throw new ValidationError({
6906
+ message: "Expected (Required) field not found",
6907
+ fields: [expectedField]
6908
+ });
6909
+ }
6703
6910
  if (xstate.currField) {
6704
6911
  const val = content.substring(xstate.s, e).trim();
6705
6912
  const parsedValue = validateAndParseFieldValue(xstate.currField, val);
@@ -6712,7 +6919,6 @@ var streamingExtractValues = (sig, values, xstate, content, streamingValidation
6712
6919
  xstate.prevFields = [{ field: xstate.currField, s: xstate.s, e }];
6713
6920
  }
6714
6921
  }
6715
- checkMissingRequiredFields(xstate, values, index);
6716
6922
  xstate.s = e + prefixLen;
6717
6923
  xstate.currField = field;
6718
6924
  xstate.currFieldIndex = index;
@@ -6732,8 +6938,7 @@ var streamingExtractFinalValue = (sig, values, xstate, content) => {
6732
6938
  values[xstate.currField.name] = parsedValue;
6733
6939
  }
6734
6940
  }
6735
- const sigFields = sig.getOutputFields();
6736
- checkMissingRequiredFields(xstate, values, sigFields.length);
6941
+ checkMissingRequiredFields(xstate, values, sig.getOutputFields());
6737
6942
  };
6738
6943
  var convertValueToType = (field, val, required = false) => {
6739
6944
  switch (field.type?.name) {
@@ -8936,7 +9141,7 @@ var AxGen = class extends AxProgramWithSignature {
8936
9141
  traceContext
8937
9142
  }) {
8938
9143
  const { sessionId, traceId, functions: _functions } = options ?? {};
8939
- const fastFail = options?.fastFail ?? this.options?.fastFail;
9144
+ const strictMode = options?.strictMode ?? false;
8940
9145
  const model = options.model;
8941
9146
  const functions = _functions?.map((f2) => "toFunction" in f2 ? f2.toFunction() : f2)?.flat();
8942
9147
  const res = await this.forwardSendRequest({
@@ -8955,7 +9160,7 @@ var AxGen = class extends AxProgramWithSignature {
8955
9160
  traceId,
8956
9161
  sessionId,
8957
9162
  functions,
8958
- fastFail,
9163
+ strictMode,
8959
9164
  span
8960
9165
  });
8961
9166
  this.getLogger(ai, options)?.("", { tags: ["responseEnd"] });
@@ -8968,7 +9173,8 @@ var AxGen = class extends AxProgramWithSignature {
8968
9173
  traceId,
8969
9174
  sessionId,
8970
9175
  functions,
8971
- span
9176
+ span,
9177
+ strictMode
8972
9178
  });
8973
9179
  }
8974
9180
  }
@@ -8980,10 +9186,9 @@ var AxGen = class extends AxProgramWithSignature {
8980
9186
  sessionId,
8981
9187
  traceId,
8982
9188
  functions,
8983
- fastFail,
9189
+ strictMode,
8984
9190
  span
8985
9191
  }) {
8986
- const streamingValidation = fastFail ?? ai.getFeatures(model).functionCot !== true;
8987
9192
  const functionCalls = [];
8988
9193
  this.values = {};
8989
9194
  const xstate = {
@@ -9034,7 +9239,7 @@ var AxGen = class extends AxProgramWithSignature {
9034
9239
  this.values,
9035
9240
  xstate,
9036
9241
  content,
9037
- streamingValidation
9242
+ strictMode
9038
9243
  );
9039
9244
  if (skip) {
9040
9245
  continue;
@@ -9135,7 +9340,8 @@ Content: ${content}`
9135
9340
  sessionId,
9136
9341
  traceId,
9137
9342
  functions,
9138
- span
9343
+ span,
9344
+ strictMode
9139
9345
  }) {
9140
9346
  this.values = {};
9141
9347
  let results = res.results ?? [];
@@ -9169,7 +9375,7 @@ Content: ${content}`
9169
9375
  if (result.thought && result.thought.length > 0) {
9170
9376
  this.values[this.thoughtFieldName] = result.thought;
9171
9377
  }
9172
- extractValues(this.signature, this.values, result.content);
9378
+ extractValues(this.signature, this.values, result.content, strictMode);
9173
9379
  await assertAssertions(this.asserts, this.values);
9174
9380
  if (this.fieldProcessors.length) {
9175
9381
  await processFieldProcessors(
@@ -9341,8 +9547,7 @@ Content: ${result.content}`
9341
9547
  ...options?.thinkingTokenBudget ? { thinking_token_budget: options.thinkingTokenBudget } : {},
9342
9548
  ...options?.showThoughts ? { show_thoughts: options.showThoughts } : {},
9343
9549
  ...options?.maxSteps ? { max_steps: options.maxSteps } : {},
9344
- ...options?.maxRetries ? { max_retries: options.maxRetries } : {},
9345
- ...options?.fastFail ? { fast_fail: options.fastFail } : {}
9550
+ ...options?.maxRetries ? { max_retries: options.maxRetries } : {}
9346
9551
  };
9347
9552
  const traceLabel = options.traceLabel ?? this.options?.traceLabel;
9348
9553
  const spanName = traceLabel ? `${traceLabel} (AxGen)` : "AxGen";
@@ -10107,6 +10312,9 @@ var AxBaseOptimizer = class {
10107
10312
  checkpointLoad;
10108
10313
  checkpointInterval;
10109
10314
  resumeFromCheckpoint;
10315
+ // Logging fields
10316
+ logger;
10317
+ verbose;
10110
10318
  // Checkpoint state
10111
10319
  currentRound = 0;
10112
10320
  scoreHistory = [];
@@ -10130,6 +10338,8 @@ var AxBaseOptimizer = class {
10130
10338
  this.checkpointLoad = args.checkpointLoad;
10131
10339
  this.checkpointInterval = args.checkpointInterval ?? 10;
10132
10340
  this.resumeFromCheckpoint = args.resumeFromCheckpoint;
10341
+ this.logger = args.logger;
10342
+ this.verbose = args.verbose;
10133
10343
  const costTracker = new AxDefaultCostTracker({
10134
10344
  maxTokens: 1e6
10135
10345
  });
@@ -10308,8 +10518,14 @@ var AxBaseOptimizer = class {
10308
10518
  async compilePareto(program, metricFn, options) {
10309
10519
  const startTime = Date.now();
10310
10520
  if (options?.verbose) {
10311
- console.log("Starting Pareto optimization using base implementation");
10312
- console.log("This will run multiple single-objective optimizations");
10521
+ this.getLogger(options)?.(
10522
+ "Starting Pareto optimization using base implementation",
10523
+ { tags: ["discovery"] }
10524
+ );
10525
+ this.getLogger(options)?.(
10526
+ "This will run multiple single-objective optimizations",
10527
+ { tags: ["discovery"] }
10528
+ );
10313
10529
  }
10314
10530
  const solutions = await this.generateWeightedSolutions(
10315
10531
  program,
@@ -10323,13 +10539,22 @@ var AxBaseOptimizer = class {
10323
10539
  );
10324
10540
  const allSolutions = [...solutions, ...constraintSolutions];
10325
10541
  if (options?.verbose) {
10326
- console.log(`Generated ${allSolutions.length} candidate solutions`);
10542
+ this.getLogger(options)?.(
10543
+ `Generated ${allSolutions.length} candidate solutions`,
10544
+ { tags: ["discovery"] }
10545
+ );
10327
10546
  }
10328
10547
  const paretoFront = this.findParetoFrontier(allSolutions);
10329
10548
  const hypervolume = this.calculateHypervolume(paretoFront);
10330
10549
  if (options?.verbose) {
10331
- console.log(`Found ${paretoFront.length} non-dominated solutions`);
10332
- console.log(`Hypervolume: ${hypervolume?.toFixed(4) || "N/A"}`);
10550
+ this.getLogger(options)?.(
10551
+ `Found ${paretoFront.length} non-dominated solutions`,
10552
+ { tags: ["discovery"] }
10553
+ );
10554
+ this.getLogger(options)?.(
10555
+ `Hypervolume: ${hypervolume?.toFixed(4) || "N/A"}`,
10556
+ { tags: ["discovery"] }
10557
+ );
10333
10558
  }
10334
10559
  this.updateResourceUsage(startTime);
10335
10560
  this.stats.convergenceInfo.converged = true;
@@ -10367,13 +10592,19 @@ var AxBaseOptimizer = class {
10367
10592
  });
10368
10593
  const objectives = Object.keys(sampleScores);
10369
10594
  if (options?.verbose) {
10370
- console.log(`Detected objectives: ${objectives.join(", ")}`);
10595
+ this.getLogger(options)?.(
10596
+ `Detected objectives: ${objectives.join(", ")}`,
10597
+ { tags: ["discovery"] }
10598
+ );
10371
10599
  }
10372
10600
  const weightCombinations = this.generateWeightCombinations(objectives);
10373
10601
  for (let i = 0; i < weightCombinations.length; i++) {
10374
10602
  const weights = weightCombinations[i];
10375
10603
  if (options?.verbose) {
10376
- console.log(`Optimizing with weights: ${JSON.stringify(weights)}`);
10604
+ this.getLogger(options)?.(
10605
+ `Optimizing with weights: ${JSON.stringify(weights)}`,
10606
+ { tags: ["discovery"] }
10607
+ );
10377
10608
  }
10378
10609
  const weightedMetric = async ({ prediction, example }) => {
10379
10610
  const scores = await metricFn({ prediction, example });
@@ -10405,9 +10636,9 @@ var AxBaseOptimizer = class {
10405
10636
  });
10406
10637
  } catch (error) {
10407
10638
  if (options?.verbose) {
10408
- console.warn(
10409
- `Failed optimization with weights ${JSON.stringify(weights)}:`,
10410
- error
10639
+ this.getLogger(options)?.(
10640
+ `Failed optimization with weights ${JSON.stringify(weights)}: ${error}`,
10641
+ { tags: ["warning"] }
10411
10642
  );
10412
10643
  }
10413
10644
  continue;
@@ -10432,8 +10663,9 @@ var AxBaseOptimizer = class {
10432
10663
  const objectives = Object.keys(sampleScores);
10433
10664
  for (const primaryObjective of objectives) {
10434
10665
  if (options?.verbose) {
10435
- console.log(
10436
- `Optimizing ${primaryObjective} with constraints on other objectives`
10666
+ this.getLogger(options)?.(
10667
+ `Optimizing ${primaryObjective} with constraints on other objectives`,
10668
+ { tags: ["discovery"] }
10437
10669
  );
10438
10670
  }
10439
10671
  const constraintMetric = async ({ prediction, example }) => {
@@ -10470,9 +10702,9 @@ var AxBaseOptimizer = class {
10470
10702
  });
10471
10703
  } catch (error) {
10472
10704
  if (options?.verbose) {
10473
- console.warn(
10474
- `Failed constraint optimization for ${primaryObjective}:`,
10475
- error
10705
+ this.getLogger(options)?.(
10706
+ `Failed constraint optimization for ${primaryObjective}: ${error}`,
10707
+ { tags: ["warning"] }
10476
10708
  );
10477
10709
  }
10478
10710
  continue;
@@ -10707,6 +10939,39 @@ var AxBaseOptimizer = class {
10707
10939
  );
10708
10940
  }
10709
10941
  }
10942
+ /**
10943
+ * Get the logger function with fallback hierarchy:
10944
+ * 1. Explicit logger passed to optimizer
10945
+ * 2. Logger from student AI service
10946
+ * 3. Default optimizer logger
10947
+ * 4. undefined if verbose is false
10948
+ */
10949
+ getLogger(options) {
10950
+ const isVerbose = this.isLoggingEnabled(options);
10951
+ if (!isVerbose) {
10952
+ return void 0;
10953
+ }
10954
+ if (this.logger) {
10955
+ return this.logger;
10956
+ }
10957
+ try {
10958
+ const aiLogger = this.studentAI.getLogger();
10959
+ if (aiLogger) {
10960
+ return aiLogger;
10961
+ }
10962
+ } catch {
10963
+ }
10964
+ return axDefaultOptimizerLogger;
10965
+ }
10966
+ /**
10967
+ * Check if logging is enabled based on verbose settings
10968
+ */
10969
+ isLoggingEnabled(options) {
10970
+ if (options?.verbose !== void 0) {
10971
+ return options.verbose;
10972
+ }
10973
+ return this.verbose ?? true;
10974
+ }
10710
10975
  };
10711
10976
 
10712
10977
  // db/base.ts
@@ -12289,9 +12554,9 @@ var AxBootstrapFewShot = class extends AxBaseOptimizer {
12289
12554
  this.stats.earlyStopped = true;
12290
12555
  this.stats.earlyStopping.reason = `No improvement for ${this.earlyStoppingPatience} rounds`;
12291
12556
  if (this.verboseMode || this.debugMode) {
12292
- console.log(
12293
- `
12294
- Early stopping triggered after ${roundIndex + 1} rounds. No improvement for ${this.earlyStoppingPatience} rounds.`
12557
+ this.getLogger()?.(
12558
+ `Early stopping after ${roundIndex + 1} rounds (no improvement for ${this.earlyStoppingPatience} rounds)`,
12559
+ { tags: ["optimizer", "warning"] }
12295
12560
  );
12296
12561
  }
12297
12562
  return;
@@ -12302,6 +12567,16 @@ Early stopping triggered after ${roundIndex + 1} rounds. No improvement for ${th
12302
12567
  const maxRounds = options?.maxIterations ?? this.maxRounds;
12303
12568
  this.traces = [];
12304
12569
  this.reset();
12570
+ if (this.verboseMode || this.debugMode) {
12571
+ this.getLogger()?.(
12572
+ `Starting BootstrapFewshot optimization with ${maxRounds} rounds`,
12573
+ { tags: ["optimizer", "start"] }
12574
+ );
12575
+ this.getLogger()?.(
12576
+ `Using ${this.examples.length} examples, max ${this.maxDemos} demos`,
12577
+ { tags: ["optimizer", "config"] }
12578
+ );
12579
+ }
12305
12580
  for (let i = 0; i < maxRounds; i++) {
12306
12581
  await this.compileRound(program, i, metricFn, options);
12307
12582
  if (this.stats.earlyStopped) {
@@ -12318,6 +12593,12 @@ Early stopping triggered after ${roundIndex + 1} rounds. No improvement for ${th
12318
12593
  if (this.traces.length > 0) {
12319
12594
  bestScore = this.stats.successfulDemos / Math.max(1, this.stats.totalCalls);
12320
12595
  }
12596
+ if (this.verboseMode || this.debugMode) {
12597
+ this.getLogger()?.(
12598
+ `Bootstrap complete. Generated ${demos.length} demos with ${bestScore.toFixed(3)} success rate`,
12599
+ { tags: ["optimizer", "complete"] }
12600
+ );
12601
+ }
12321
12602
  return {
12322
12603
  demos,
12323
12604
  stats: this.stats,
@@ -12383,7 +12664,6 @@ var AxMiPRO = class extends AxBaseOptimizer {
12383
12664
  viewDataBatchSize;
12384
12665
  tipAwareProposer;
12385
12666
  fewshotAwareProposer;
12386
- verbose;
12387
12667
  earlyStoppingTrials;
12388
12668
  minImprovementThreshold;
12389
12669
  bayesianOptimization;
@@ -12405,7 +12685,6 @@ var AxMiPRO = class extends AxBaseOptimizer {
12405
12685
  this.viewDataBatchSize = options.viewDataBatchSize ?? 10;
12406
12686
  this.tipAwareProposer = options.tipAwareProposer ?? true;
12407
12687
  this.fewshotAwareProposer = options.fewshotAwareProposer ?? true;
12408
- this.verbose = options.verbose ?? false;
12409
12688
  this.earlyStoppingTrials = options.earlyStoppingTrials ?? 5;
12410
12689
  this.minImprovementThreshold = options.minImprovementThreshold ?? 0.01;
12411
12690
  this.bayesianOptimization = options.bayesianOptimization ?? false;
@@ -12496,8 +12775,10 @@ var AxMiPRO = class extends AxBaseOptimizer {
12496
12775
  * Bootstraps few-shot examples for the program
12497
12776
  */
12498
12777
  async bootstrapFewShotExamples(program, metricFn) {
12499
- if (this.verbose) {
12500
- console.log("Bootstrapping few-shot examples...");
12778
+ if (this.isLoggingEnabled()) {
12779
+ this.getLogger()?.("Bootstrapping few-shot examples...", {
12780
+ tags: ["optimizer", "phase"]
12781
+ });
12501
12782
  }
12502
12783
  const bootstrapper = new AxBootstrapFewShot({
12503
12784
  studentAI: this.studentAI,
@@ -12505,7 +12786,7 @@ var AxMiPRO = class extends AxBaseOptimizer {
12505
12786
  options: {
12506
12787
  maxDemos: this.maxBootstrappedDemos,
12507
12788
  maxRounds: 3,
12508
- verboseMode: this.verbose
12789
+ verboseMode: this.isLoggingEnabled()
12509
12790
  }
12510
12791
  });
12511
12792
  const result = await bootstrapper.compile(program, metricFn, {
@@ -12550,9 +12831,10 @@ var AxMiPRO = class extends AxBaseOptimizer {
12550
12831
  options
12551
12832
  );
12552
12833
  if (checkpoint && checkpoint.optimizerType === "MiPRO") {
12553
- if (this.verbose || options?.verbose) {
12554
- console.log(
12555
- `Resuming from checkpoint at round ${checkpoint.currentRound}`
12834
+ if (this.isLoggingEnabled(options)) {
12835
+ this.getLogger(options)?.(
12836
+ `Resuming from checkpoint at round ${checkpoint.currentRound}`,
12837
+ { tags: ["optimizer", "checkpoint"] }
12556
12838
  );
12557
12839
  }
12558
12840
  this.restoreFromCheckpoint(checkpoint);
@@ -12562,6 +12844,12 @@ var AxMiPRO = class extends AxBaseOptimizer {
12562
12844
  stagnationRounds = checkpoint.stats.convergenceInfo?.stagnationRounds || 0;
12563
12845
  }
12564
12846
  }
12847
+ if (this.isLoggingEnabled(options)) {
12848
+ this.getLogger(options)?.(
12849
+ `Running optimization trials (${this.numTrials} total)`,
12850
+ { tags: ["optimizer", "phase"] }
12851
+ );
12852
+ }
12565
12853
  for (let i = startRound; i < this.numTrials; i++) {
12566
12854
  const config = {
12567
12855
  instruction: instructions[i % instructions.length] || instructions[0] || "",
@@ -12588,6 +12876,12 @@ var AxMiPRO = class extends AxBaseOptimizer {
12588
12876
  bestScore = score;
12589
12877
  bestConfig = config;
12590
12878
  stagnationRounds = 0;
12879
+ if (this.isLoggingEnabled(options)) {
12880
+ this.getLogger(options)?.(
12881
+ `Trial ${i + 1}/${this.numTrials}: New best score ${bestScore.toFixed(3)}`,
12882
+ { tags: ["optimizer", "progress"] }
12883
+ );
12884
+ }
12591
12885
  } else {
12592
12886
  stagnationRounds++;
12593
12887
  }
@@ -12706,38 +13000,53 @@ var AxMiPRO = class extends AxBaseOptimizer {
12706
13000
  this.configureAuto(miproOptions.auto);
12707
13001
  }
12708
13002
  const valset = this.getValidationSet(options) || (miproOptions?.valset ?? this.examples.slice(0, Math.floor(this.examples.length * 0.2)));
12709
- if (this.verbose || options?.verbose) {
12710
- console.log(`Starting MIPROv2 optimization with ${this.numTrials} trials`);
12711
- console.log(
12712
- `Using ${this.examples.length} examples for training and ${valset.length} for validation`
13003
+ if (this.isLoggingEnabled(options)) {
13004
+ this.getLogger(options)?.(
13005
+ `Starting MIPROv2 optimization with ${this.numTrials} trials`,
13006
+ { tags: ["optimizer", "start"] }
13007
+ );
13008
+ this.getLogger(options)?.(
13009
+ `Using ${this.examples.length} examples for training and ${valset.length} for validation`,
13010
+ { tags: ["optimizer", "config"] }
12713
13011
  );
12714
13012
  if (this.teacherAI) {
12715
- console.log("Using separate teacher model for instruction generation");
13013
+ this.getLogger(options)?.(
13014
+ "Using separate teacher model for instruction generation",
13015
+ { tags: ["optimizer", "config"] }
13016
+ );
12716
13017
  }
12717
13018
  }
12718
13019
  let bootstrappedDemos = [];
12719
13020
  if (this.maxBootstrappedDemos > 0) {
12720
13021
  bootstrappedDemos = await this.bootstrapFewShotExamples(program, metricFn);
12721
- if (this.verbose) {
12722
- console.log(
12723
- `Generated ${bootstrappedDemos.length} bootstrapped demonstrations`
13022
+ if (this.isLoggingEnabled(options)) {
13023
+ this.getLogger(options)?.(
13024
+ `Generated ${bootstrappedDemos.length} bootstrapped demonstrations`,
13025
+ { tags: ["optimizer", "result"] }
12724
13026
  );
12725
13027
  }
12726
13028
  }
12727
13029
  let labeledExamples = [];
12728
13030
  if (this.maxLabeledDemos > 0) {
12729
13031
  labeledExamples = this.selectLabeledExamples();
12730
- if (this.verbose) {
12731
- console.log(
12732
- `Selected ${labeledExamples.length} labeled examples from training set`
13032
+ if (this.isLoggingEnabled(options)) {
13033
+ this.getLogger(options)?.(
13034
+ `Selected ${labeledExamples.length} labeled examples from training set`,
13035
+ { tags: ["optimizer", "result"] }
12733
13036
  );
12734
13037
  }
12735
13038
  }
12736
13039
  const instructions = await this.proposeInstructionCandidates(options);
12737
- if (this.verbose) {
12738
- console.log(`Generated ${instructions.length} instruction candidates`);
13040
+ if (this.isLoggingEnabled(options)) {
13041
+ this.getLogger(options)?.(
13042
+ `Generated ${instructions.length} instruction candidates`,
13043
+ { tags: ["optimizer", "result"] }
13044
+ );
12739
13045
  if (this.hasTeacherAI(options)) {
12740
- console.log("Using teacher AI for instruction generation");
13046
+ this.getLogger(options)?.(
13047
+ "Using teacher AI for instruction generation",
13048
+ { tags: ["optimizer", "config"] }
13049
+ );
12741
13050
  }
12742
13051
  }
12743
13052
  const { bestConfig, bestScore } = await this.runOptimization(
@@ -12749,9 +13058,15 @@ var AxMiPRO = class extends AxBaseOptimizer {
12749
13058
  metricFn,
12750
13059
  options
12751
13060
  );
12752
- if (this.verbose || options?.verbose) {
12753
- console.log(`Optimization complete. Best score: ${bestScore}`);
12754
- console.log(`Best configuration: ${JSON.stringify(bestConfig)}`);
13061
+ if (this.isLoggingEnabled(options)) {
13062
+ this.getLogger(options)?.(
13063
+ `Optimization complete. Best score: ${bestScore}`,
13064
+ { tags: ["optimizer", "complete"] }
13065
+ );
13066
+ this.getLogger(options)?.(
13067
+ `Best configuration: ${JSON.stringify(bestConfig)}`,
13068
+ { tags: ["optimizer", "result"] }
13069
+ );
12755
13070
  }
12756
13071
  if (this.checkTargetScore(bestScore)) {
12757
13072
  this.triggerEarlyStopping(
@@ -12878,9 +13193,6 @@ var AxMiPRO = class extends AxBaseOptimizer {
12878
13193
  if (config.minImprovementThreshold !== void 0) {
12879
13194
  this.minImprovementThreshold = config.minImprovementThreshold;
12880
13195
  }
12881
- if (config.verbose !== void 0) {
12882
- this.verbose = config.verbose;
12883
- }
12884
13196
  }
12885
13197
  /**
12886
13198
  * Reset optimizer state for reuse with different programs
@@ -15354,6 +15666,10 @@ export {
15354
15666
  axAITogetherDefaultConfig,
15355
15667
  axBaseAIDefaultConfig,
15356
15668
  axBaseAIDefaultCreativeConfig,
15669
+ axCreateDefaultLogger,
15670
+ axCreateDefaultTextLogger,
15671
+ axCreateOptimizerLogger,
15672
+ axDefaultOptimizerLogger,
15357
15673
  axGlobals,
15358
15674
  axModelInfoAnthropic,
15359
15675
  axModelInfoCohere,