@ax-llm/ax 11.0.0 → 11.0.2

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 CHANGED
@@ -54,6 +54,7 @@ __export(index_exports, {
54
54
  AxAIMistralModel: () => AxAIMistralModel,
55
55
  AxAIOllama: () => AxAIOllama,
56
56
  AxAIOpenAI: () => AxAIOpenAI,
57
+ AxAIOpenAIBase: () => AxAIOpenAIBase,
57
58
  AxAIOpenAIEmbedModel: () => AxAIOpenAIEmbedModel,
58
59
  AxAIOpenAIModel: () => AxAIOpenAIModel,
59
60
  AxAIReka: () => AxAIReka,
@@ -750,8 +751,9 @@ var AxBaseAI = class {
750
751
  this.tracer = options.tracer;
751
752
  this.modelInfo = modelInfo;
752
753
  this.models = models;
754
+ this.id = crypto.randomUUID();
753
755
  const model = this.models?.find((v) => v.key === defaults.model)?.model ?? defaults.model;
754
- const embedModel = this.models?.find((v) => v.key === defaults.embedModel)?.model ?? defaults.embedModel;
756
+ const embedModel = defaults.embedModel;
755
757
  this.defaults = { model, embedModel };
756
758
  if (!defaults.model || typeof defaults.model !== "string" || defaults.model === "") {
757
759
  throw new Error("No model defined");
@@ -769,6 +771,7 @@ var AxBaseAI = class {
769
771
  defaults;
770
772
  apiURL;
771
773
  name;
774
+ id;
772
775
  headers;
773
776
  supportFor;
774
777
  // Add private metrics tracking properties
@@ -803,6 +806,9 @@ var AxBaseAI = class {
803
806
  setName(name) {
804
807
  this.name = name;
805
808
  }
809
+ getId() {
810
+ return this.id;
811
+ }
806
812
  setAPIURL(apiURL) {
807
813
  this.apiURL = apiURL;
808
814
  }
@@ -848,8 +854,7 @@ var AxBaseAI = class {
848
854
  }
849
855
  const mi = getModelInfo({
850
856
  model: this.defaults.embedModel,
851
- modelInfo: this.modelInfo,
852
- models: this.models
857
+ modelInfo: this.modelInfo
853
858
  });
854
859
  return {
855
860
  ...mi,
@@ -1055,7 +1060,7 @@ var AxBaseAI = class {
1055
1060
  }
1056
1061
  }
1057
1062
  async _embed1(req, options) {
1058
- const embedModel = req.embedModel ? this.models?.find((v) => v.key === req.embedModel)?.model ?? req.embedModel : this.defaults.embedModel;
1063
+ const embedModel = req.embedModel ?? this.defaults.embedModel;
1059
1064
  if (!embedModel) {
1060
1065
  throw new Error("No embed model defined");
1061
1066
  }
@@ -1066,7 +1071,7 @@ var AxBaseAI = class {
1066
1071
  kind: import_api2.SpanKind.SERVER,
1067
1072
  attributes: {
1068
1073
  [axSpanAttributes.LLM_SYSTEM]: this.name,
1069
- [axSpanAttributes.LLM_REQUEST_MODEL]: req.embedModel ?? this.defaults.embedModel
1074
+ [axSpanAttributes.LLM_REQUEST_MODEL]: embedModel
1070
1075
  }
1071
1076
  },
1072
1077
  async (span) => {
@@ -1245,13 +1250,13 @@ var AxAIAnthropicModel = /* @__PURE__ */ ((AxAIAnthropicModel2) => {
1245
1250
  AxAIAnthropicModel2["ClaudeInstant12"] = "claude-instant-1.2";
1246
1251
  return AxAIAnthropicModel2;
1247
1252
  })(AxAIAnthropicModel || {});
1248
- var AxAIAnthropicVertexModel = /* @__PURE__ */ ((AxAIAnthropicVertexModel2) => {
1249
- AxAIAnthropicVertexModel2["Claude35Haiku"] = "claude-3-5-haiku";
1250
- AxAIAnthropicVertexModel2["Claude35Sonnet"] = "claude-3-5-sonnet";
1251
- AxAIAnthropicVertexModel2["Claude35SonnetV2"] = "claude-3-5-sonnet-v2";
1252
- AxAIAnthropicVertexModel2["Claude3Haiku"] = "claude-3-haiku";
1253
- AxAIAnthropicVertexModel2["Claude3Opus"] = "claude-3-opus";
1254
- return AxAIAnthropicVertexModel2;
1253
+ var AxAIAnthropicVertexModel = /* @__PURE__ */ ((AxAIAnthropicVertexModel3) => {
1254
+ AxAIAnthropicVertexModel3["Claude35Haiku"] = "claude-3-5-haiku";
1255
+ AxAIAnthropicVertexModel3["Claude35Sonnet"] = "claude-3-5-sonnet";
1256
+ AxAIAnthropicVertexModel3["Claude35SonnetV2"] = "claude-3-5-sonnet-v2";
1257
+ AxAIAnthropicVertexModel3["Claude3Haiku"] = "claude-3-haiku";
1258
+ AxAIAnthropicVertexModel3["Claude3Opus"] = "claude-3-opus";
1259
+ return AxAIAnthropicVertexModel3;
1255
1260
  })(AxAIAnthropicVertexModel || {});
1256
1261
 
1257
1262
  // ai/anthropic/info.ts
@@ -2055,26 +2060,22 @@ function createMessages2(req) {
2055
2060
  }
2056
2061
  });
2057
2062
  }
2058
- var AxAIOpenAI = class extends AxBaseAI {
2063
+ var AxAIOpenAIBase = class extends AxBaseAI {
2059
2064
  constructor({
2060
2065
  apiKey,
2061
2066
  config,
2062
2067
  options,
2063
2068
  apiURL,
2064
- modelInfo = axModelInfoOpenAI,
2069
+ modelInfo,
2065
2070
  models
2066
2071
  }) {
2067
2072
  if (!apiKey || apiKey === "") {
2068
2073
  throw new Error("OpenAI API key not set");
2069
2074
  }
2070
- const _config = {
2071
- ...axAIOpenAIDefaultConfig(),
2072
- ...config
2073
- };
2074
2075
  const aiImpl = new AxAIOpenAIImpl(
2075
- _config,
2076
+ config,
2076
2077
  options?.streamingUsage ?? true,
2077
- config?.dimensions
2078
+ config.dimensions
2078
2079
  );
2079
2080
  super(aiImpl, {
2080
2081
  name: "OpenAI",
@@ -2082,8 +2083,8 @@ var AxAIOpenAI = class extends AxBaseAI {
2082
2083
  headers: async () => ({ Authorization: `Bearer ${apiKey}` }),
2083
2084
  modelInfo,
2084
2085
  defaults: {
2085
- model: _config.model,
2086
- embedModel: _config.embedModel
2086
+ model: config.model,
2087
+ embedModel: config.embedModel
2087
2088
  },
2088
2089
  options,
2089
2090
  supportFor: () => {
@@ -2096,10 +2097,33 @@ var AxAIOpenAI = class extends AxBaseAI {
2096
2097
  var isReasoningModel = (model) => ["o1-mini" /* O1Mini */, "o1" /* O1 */, "o3-mini" /* O3Mini */].includes(
2097
2098
  model
2098
2099
  );
2100
+ var AxAIOpenAI = class extends AxAIOpenAIBase {
2101
+ constructor({
2102
+ apiKey,
2103
+ config,
2104
+ options,
2105
+ models
2106
+ }) {
2107
+ if (!apiKey || apiKey === "") {
2108
+ throw new Error("OpenAI API key not set");
2109
+ }
2110
+ super({
2111
+ apiKey,
2112
+ config: {
2113
+ ...axAIOpenAIDefaultConfig(),
2114
+ ...config
2115
+ },
2116
+ options,
2117
+ modelInfo: axModelInfoOpenAI,
2118
+ models
2119
+ });
2120
+ super.setName("OpenAI");
2121
+ }
2122
+ };
2099
2123
 
2100
2124
  // ai/azure-openai/api.ts
2101
2125
  var axAIAzureOpenAIDefaultConfig = axAIOpenAIDefaultConfig;
2102
- var AxAIAzureOpenAI = class extends AxAIOpenAI {
2126
+ var AxAIAzureOpenAI = class extends AxAIOpenAIBase {
2103
2127
  constructor({
2104
2128
  apiKey,
2105
2129
  resourceName,
@@ -2122,7 +2146,13 @@ var AxAIAzureOpenAI = class extends AxAIOpenAI {
2122
2146
  ...axAIAzureOpenAIDefaultConfig(),
2123
2147
  ...config
2124
2148
  };
2125
- super({ apiKey, config: _config, options, models });
2149
+ super({
2150
+ apiKey,
2151
+ config: _config,
2152
+ options,
2153
+ models,
2154
+ modelInfo: axModelInfoOpenAI
2155
+ });
2126
2156
  const host = resourceName.includes("://") ? resourceName : `https://${resourceName}.openai.azure.com/`;
2127
2157
  super.setName("Azure OpenAI");
2128
2158
  super.setAPIURL(
@@ -2485,7 +2515,7 @@ var axAIDeepSeekDefaultConfig = () => structuredClone({
2485
2515
  model: "deepseek-chat" /* DeepSeekChat */,
2486
2516
  ...axBaseAIDefaultConfig()
2487
2517
  });
2488
- var AxAIDeepSeek = class extends AxAIOpenAI {
2518
+ var AxAIDeepSeek = class extends AxAIOpenAIBase {
2489
2519
  constructor({
2490
2520
  apiKey,
2491
2521
  config,
@@ -3049,7 +3079,7 @@ var axAIGroqDefaultConfig = () => structuredClone({
3049
3079
  model: "llama-3.3-70b-versatile" /* Llama33_70B */,
3050
3080
  ...axBaseAIDefaultConfig()
3051
3081
  });
3052
- var AxAIGroq = class extends AxAIOpenAI {
3082
+ var AxAIGroq = class extends AxAIOpenAIBase {
3053
3083
  constructor({
3054
3084
  apiKey,
3055
3085
  config,
@@ -3294,7 +3324,7 @@ var axAIMistralDefaultConfig = () => structuredClone({
3294
3324
  model: "mistral-small-latest" /* MistralSmall */,
3295
3325
  ...axBaseAIDefaultConfig()
3296
3326
  });
3297
- var AxAIMistral = class extends AxAIOpenAI {
3327
+ var AxAIMistral = class extends AxAIOpenAIBase {
3298
3328
  constructor({
3299
3329
  apiKey,
3300
3330
  config,
@@ -3326,7 +3356,7 @@ var axAIOllamaDefaultConfig = () => structuredClone({
3326
3356
  model: "nous-hermes2",
3327
3357
  embedModel: "all-minilm"
3328
3358
  });
3329
- var AxAIOllama = class extends AxAIOpenAI {
3359
+ var AxAIOllama = class extends AxAIOpenAIBase {
3330
3360
  constructor({
3331
3361
  apiKey = "not-set",
3332
3362
  url = "http://localhost:11434/v1",
@@ -3343,7 +3373,8 @@ var AxAIOllama = class extends AxAIOpenAI {
3343
3373
  options,
3344
3374
  config: _config,
3345
3375
  apiURL: url,
3346
- models
3376
+ models,
3377
+ modelInfo: []
3347
3378
  });
3348
3379
  super.setName("Ollama");
3349
3380
  }
@@ -3580,7 +3611,7 @@ var axAITogetherDefaultConfig = () => structuredClone({
3580
3611
  model: "mistralai/Mixtral-8x7B-Instruct-v0.1",
3581
3612
  ...axBaseAIDefaultConfig()
3582
3613
  });
3583
- var AxAITogether = class extends AxAIOpenAI {
3614
+ var AxAITogether = class extends AxAIOpenAIBase {
3584
3615
  constructor({
3585
3616
  apiKey,
3586
3617
  config,
@@ -3654,6 +3685,9 @@ var AxAI = class {
3654
3685
  getName() {
3655
3686
  return this.ai.getName();
3656
3687
  }
3688
+ getId() {
3689
+ return this.ai.getId();
3690
+ }
3657
3691
  getModelInfo() {
3658
3692
  return this.ai.getModelInfo();
3659
3693
  }
@@ -6060,6 +6094,7 @@ var AxAgent = class {
6060
6094
  program;
6061
6095
  functions;
6062
6096
  agents;
6097
+ disableSmartModelRouting;
6063
6098
  name;
6064
6099
  description;
6065
6100
  subAgentList;
@@ -6075,6 +6110,7 @@ var AxAgent = class {
6075
6110
  this.ai = ai;
6076
6111
  this.agents = agents;
6077
6112
  this.functions = functions;
6113
+ this.disableSmartModelRouting = options?.disableSmartModelRouting;
6078
6114
  this.signature = new AxSignature(signature);
6079
6115
  this.signature.setDescription(description);
6080
6116
  if (!name || name.length < 5) {
@@ -6101,7 +6137,7 @@ var AxAgent = class {
6101
6137
  func: () => this.forward
6102
6138
  };
6103
6139
  const mm = ai?.getModelList();
6104
- if (mm) {
6140
+ if (mm && !this.disableSmartModelRouting) {
6105
6141
  this.func.parameters = addModelParameter(this.func.parameters, mm);
6106
6142
  }
6107
6143
  }
@@ -6141,11 +6177,16 @@ var AxAgent = class {
6141
6177
  func: wrappedFunc
6142
6178
  };
6143
6179
  }
6180
+ getFeatures() {
6181
+ return {
6182
+ canConfigureSmartModelRouting: this.ai !== void 0
6183
+ };
6184
+ }
6144
6185
  init(parentAi, options) {
6145
6186
  const ai = this.ai ?? parentAi;
6146
6187
  const mm = ai?.getModelList();
6147
6188
  const agentFuncs = this.agents?.map((a) => a.getFunction())?.map(
6148
- (f) => mm ? { ...f, parameters: addModelParameter(f.parameters, mm) } : f
6189
+ (f) => mm && !this.disableSmartModelRouting && this.agents?.find((a) => a.getFunction().name === f.name)?.getFeatures().canConfigureSmartModelRouting ? { ...f, parameters: addModelParameter(f.parameters, mm) } : f
6149
6190
  );
6150
6191
  const functions = [
6151
6192
  ...options?.functions ?? this.functions ?? [],
@@ -6255,6 +6296,10 @@ var AxBalancer = class _AxBalancer {
6255
6296
  currentServiceIndex = 0;
6256
6297
  currentService;
6257
6298
  debug;
6299
+ initialBackoffMs;
6300
+ maxBackoffMs;
6301
+ maxRetries;
6302
+ serviceFailures = /* @__PURE__ */ new Map();
6258
6303
  constructor(services, options) {
6259
6304
  if (services.length === 0) {
6260
6305
  throw new Error("No AI services provided.");
@@ -6268,6 +6313,9 @@ var AxBalancer = class _AxBalancer {
6268
6313
  }
6269
6314
  this.currentService = cs;
6270
6315
  this.debug = options?.debug ?? true;
6316
+ this.initialBackoffMs = options?.initialBackoffMs ?? 1e3;
6317
+ this.maxBackoffMs = options?.maxBackoffMs ?? 32e3;
6318
+ this.maxRetries = options?.maxRetries ?? 3;
6271
6319
  }
6272
6320
  /**
6273
6321
  * Service comparator that respects the input order of services.
@@ -6284,7 +6332,7 @@ var AxBalancer = class _AxBalancer {
6284
6332
  return aTotalCost - bTotalCost;
6285
6333
  };
6286
6334
  getModelList() {
6287
- throw new Error("Method not implemented.");
6335
+ return this.currentService.getModelList();
6288
6336
  }
6289
6337
  getNextService() {
6290
6338
  const cs = this.services[++this.currentServiceIndex];
@@ -6305,6 +6353,9 @@ var AxBalancer = class _AxBalancer {
6305
6353
  getName() {
6306
6354
  return this.currentService.getName();
6307
6355
  }
6356
+ getId() {
6357
+ return this.currentService.getId();
6358
+ }
6308
6359
  getModelInfo() {
6309
6360
  return this.currentService.getModelInfo();
6310
6361
  }
@@ -6317,11 +6368,56 @@ var AxBalancer = class _AxBalancer {
6317
6368
  getMetrics() {
6318
6369
  return this.currentService.getMetrics();
6319
6370
  }
6371
+ canRetryService() {
6372
+ const failure = this.serviceFailures.get(this.currentService.getId());
6373
+ if (!failure) return true;
6374
+ const { retries, lastFailureTime } = failure;
6375
+ const timeSinceLastFailure = Date.now() - lastFailureTime;
6376
+ const backoffMs = Math.min(
6377
+ this.initialBackoffMs * Math.pow(2, retries),
6378
+ this.maxBackoffMs
6379
+ );
6380
+ return timeSinceLastFailure >= backoffMs;
6381
+ }
6382
+ handleFailure() {
6383
+ const failure = this.serviceFailures.get(this.currentService.getId());
6384
+ const retries = (failure?.retries ?? 0) + 1;
6385
+ this.serviceFailures.set(this.currentService.getId(), {
6386
+ retries,
6387
+ lastFailureTime: Date.now()
6388
+ });
6389
+ if (this.debug) {
6390
+ console.warn(
6391
+ `AxBalancer: Service ${this.currentService.getName()} failed (retry ${retries}/${this.maxRetries})`
6392
+ );
6393
+ }
6394
+ if (retries >= this.maxRetries) {
6395
+ const gotNextService = this.getNextService();
6396
+ if (this.debug) {
6397
+ console.warn(
6398
+ `AxBalancer: Switching to service ${this.currentService.getName()}`
6399
+ );
6400
+ }
6401
+ return gotNextService;
6402
+ }
6403
+ return true;
6404
+ }
6405
+ handleSuccess() {
6406
+ this.serviceFailures.delete(this.currentService.getId());
6407
+ }
6320
6408
  async chat(req, options) {
6321
6409
  this.reset();
6322
6410
  while (true) {
6411
+ if (!this.canRetryService()) {
6412
+ if (!this.getNextService()) {
6413
+ throw new Error("All services exhausted");
6414
+ }
6415
+ continue;
6416
+ }
6323
6417
  try {
6324
- return await this.currentService.chat(req, options);
6418
+ const response = await this.currentService.chat(req, options);
6419
+ this.handleSuccess();
6420
+ return response;
6325
6421
  } catch (e) {
6326
6422
  if (!(e instanceof AxAIServiceError)) {
6327
6423
  throw e;
@@ -6342,38 +6438,29 @@ var AxBalancer = class _AxBalancer {
6342
6438
  default:
6343
6439
  throw e;
6344
6440
  }
6345
- if (this.debug) {
6346
- console.warn(
6347
- `AxBalancer: Service ${this.currentService.getName()} failed`,
6348
- e
6349
- );
6350
- }
6351
- if (!this.getNextService()) {
6441
+ if (!this.handleFailure()) {
6352
6442
  throw e;
6353
6443
  }
6354
- if (this.debug) {
6355
- console.warn(
6356
- `AxBalancer: Switching to service ${this.currentService.getName()}`
6357
- );
6358
- }
6359
6444
  }
6360
6445
  }
6361
6446
  }
6362
6447
  async embed(req, options) {
6363
6448
  this.reset();
6364
6449
  while (true) {
6450
+ if (!this.canRetryService()) {
6451
+ if (!this.getNextService()) {
6452
+ throw new Error("All services exhausted");
6453
+ }
6454
+ continue;
6455
+ }
6365
6456
  try {
6366
- return await this.currentService.embed(req, options);
6457
+ const response = await this.currentService.embed(req, options);
6458
+ this.handleSuccess();
6459
+ return response;
6367
6460
  } catch (e) {
6368
- if (this.debug) {
6369
- console.warn(`Service ${this.currentService.getName()} failed`);
6370
- }
6371
- if (!this.getNextService()) {
6461
+ if (!this.handleFailure()) {
6372
6462
  throw e;
6373
6463
  }
6374
- if (this.debug) {
6375
- console.warn(`Switching to service ${this.currentService.getName()}`);
6376
- }
6377
6464
  }
6378
6465
  }
6379
6466
  }
@@ -7866,6 +7953,7 @@ var AxEmbeddingAdapter = class {
7866
7953
  var AxMockAIService = class {
7867
7954
  constructor(config = {}) {
7868
7955
  this.config = config;
7956
+ this.config.id = this.config.id ?? crypto.randomUUID();
7869
7957
  }
7870
7958
  options = {};
7871
7959
  metrics = {
@@ -7881,6 +7969,9 @@ var AxMockAIService = class {
7881
7969
  getName() {
7882
7970
  return this.config.name ?? "mock-ai-service";
7883
7971
  }
7972
+ getId() {
7973
+ return this.config.id ?? "mock-ai-service-id";
7974
+ }
7884
7975
  getModelInfo() {
7885
7976
  return {
7886
7977
  name: "mock-model",
@@ -8037,6 +8128,7 @@ var AxRAG = class extends AxChainOfThought {
8037
8128
  AxAIMistralModel,
8038
8129
  AxAIOllama,
8039
8130
  AxAIOpenAI,
8131
+ AxAIOpenAIBase,
8040
8132
  AxAIOpenAIEmbedModel,
8041
8133
  AxAIOpenAIModel,
8042
8134
  AxAIReka,