@ax-llm/ax 11.0.20 → 11.0.22

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
@@ -95,14 +95,15 @@ __export(index_exports, {
95
95
  AxLLMRequestTypeValues: () => AxLLMRequestTypeValues,
96
96
  AxMemory: () => AxMemory,
97
97
  AxMockAIService: () => AxMockAIService,
98
+ AxMultiServiceRouter: () => AxMultiServiceRouter,
98
99
  AxProgram: () => AxProgram,
99
100
  AxProgramWithSignature: () => AxProgramWithSignature,
100
101
  AxPromptTemplate: () => AxPromptTemplate,
101
102
  AxRAG: () => AxRAG,
102
103
  AxRateLimiterTokenUsage: () => AxRateLimiterTokenUsage,
103
- AxRoute: () => AxRoute,
104
- AxRouter: () => AxRouter,
105
104
  AxSignature: () => AxSignature,
105
+ AxSimpleClassifier: () => AxSimpleClassifier,
106
+ AxSimpleClassifierClass: () => AxSimpleClassifierClass,
106
107
  AxSpanKindValues: () => AxSpanKindValues,
107
108
  AxTestPrompt: () => AxTestPrompt
108
109
  });
@@ -111,26 +112,6 @@ module.exports = __toCommonJS(index_exports);
111
112
  // ai/base.ts
112
113
  var import_api2 = require("@opentelemetry/api");
113
114
 
114
- // dsp/modelinfo.ts
115
- function getModelInfo({
116
- model,
117
- modelInfo,
118
- models
119
- }) {
120
- const mappedModel = models?.find((v) => v.key === model)?.model ?? model;
121
- const exactMatch = modelInfo.find((v) => v.name === model);
122
- if (exactMatch) return exactMatch;
123
- const normalizedName = mappedModel.replace(/^(anthropic\.|openai\.)/, "").replace(/-latest$/, "").replace(/-\d{8}$/, "").replace(/-v\d+:\d+$/, "").replace(/@\d{8}$/, "").replace(/-\d{2,}(-[a-zA-Z0-9-]+)?$/, "").replace(/-v\d+@\d{8}$/, "").replace(/-v\d+$/, "");
124
- const normalizedMatch = modelInfo.find((v) => v.name === normalizedName);
125
- if (normalizedMatch) return normalizedMatch;
126
- return {
127
- name: model,
128
- currency: "usd",
129
- promptTokenCostPer1M: 0,
130
- completionTokenCostPer1M: 0
131
- };
132
- }
133
-
134
115
  // trace/trace.ts
135
116
  var axSpanAttributes = {
136
117
  // LLM
@@ -848,6 +829,9 @@ var AxBaseAI = class {
848
829
  throw new Error("No model defined");
849
830
  }
850
831
  this.setOptions(options);
832
+ if (models) {
833
+ validateModels(models);
834
+ }
851
835
  }
852
836
  debug = false;
853
837
  rt;
@@ -926,33 +910,19 @@ var AxBaseAI = class {
926
910
  tracer: this.tracer
927
911
  };
928
912
  }
929
- getModelInfo() {
930
- const mi = getModelInfo({
931
- model: this.defaults.model,
932
- modelInfo: this.modelInfo,
933
- models: this.models
934
- });
935
- return {
936
- ...mi,
937
- provider: this.name
938
- };
913
+ getModelList() {
914
+ return this.models?.filter((model) => !model.isInternal)?.map((model) => ({
915
+ key: model.key,
916
+ description: model.description,
917
+ model: model.model
918
+ }));
939
919
  }
940
- getEmbedModelInfo() {
941
- if (!this.defaults.embedModel) {
942
- return;
943
- }
944
- const mi = getModelInfo({
945
- model: this.defaults.embedModel,
946
- modelInfo: this.modelInfo
947
- });
920
+ getDefaultModels() {
948
921
  return {
949
- ...mi,
950
- provider: this.name
922
+ model: this.defaults.model,
923
+ embedModel: this.defaults.embedModel
951
924
  };
952
925
  }
953
- getModelList() {
954
- return this.models;
955
- }
956
926
  getName() {
957
927
  return this.name;
958
928
  }
@@ -1238,14 +1208,25 @@ var AxBaseAI = class {
1238
1208
  return { ...headers, ...await this.headers() };
1239
1209
  }
1240
1210
  };
1241
- var setResponseAttr = (res, span) => {
1211
+ function setResponseAttr(res, span) {
1242
1212
  if (res.modelUsage) {
1243
1213
  span.setAttributes({
1244
1214
  [axSpanAttributes.LLM_USAGE_COMPLETION_TOKENS]: res.modelUsage.completionTokens ?? 0,
1245
1215
  [axSpanAttributes.LLM_USAGE_PROMPT_TOKENS]: res.modelUsage.promptTokens
1246
1216
  });
1247
1217
  }
1248
- };
1218
+ }
1219
+ function validateModels(models) {
1220
+ const keys = /* @__PURE__ */ new Set();
1221
+ for (const model of models) {
1222
+ if (keys.has(model.key)) {
1223
+ throw new Error(
1224
+ `Duplicate model key detected: "${model.key}". Each model key must be unique.`
1225
+ );
1226
+ }
1227
+ keys.add(model.key);
1228
+ }
1229
+ }
1249
1230
 
1250
1231
  // ai/google-vertex/auth.ts
1251
1232
  var import_google_auth_library = require("google-auth-library");
@@ -1901,7 +1882,7 @@ var AxAIOpenAIImpl = class {
1901
1882
  response_format: this.config?.responseFormat ? { type: this.config?.responseFormat } : void 0,
1902
1883
  tools,
1903
1884
  tool_choice: toolsChoice,
1904
- max_tokens: req.modelConfig?.maxTokens ?? this.config.maxTokens ?? 500,
1885
+ max_completion_tokens: req.modelConfig?.maxTokens ?? this.config.maxTokens ?? 500,
1905
1886
  temperature: req.modelConfig?.temperature ?? this.config.temperature,
1906
1887
  top_p: req.modelConfig?.topP ?? this.config.topP ?? 1,
1907
1888
  n: req.modelConfig?.n ?? this.config.n,
@@ -2698,10 +2679,10 @@ var axAIGoogleGeminiDefaultConfig = () => structuredClone({
2698
2679
  ...axBaseAIDefaultConfig()
2699
2680
  });
2700
2681
  var AxAIGoogleGeminiImpl = class {
2701
- constructor(config, isVertex, endpoint, apiKey, options) {
2682
+ constructor(config, isVertex, endpointId, apiKey, options) {
2702
2683
  this.config = config;
2703
2684
  this.isVertex = isVertex;
2704
- this.endpoint = endpoint;
2685
+ this.endpointId = endpointId;
2705
2686
  this.apiKey = apiKey;
2706
2687
  this.options = options;
2707
2688
  }
@@ -2727,9 +2708,9 @@ var AxAIGoogleGeminiImpl = class {
2727
2708
  throw new Error("Chat prompt is empty");
2728
2709
  }
2729
2710
  let apiConfig;
2730
- if (this.endpoint) {
2711
+ if (this.endpointId) {
2731
2712
  apiConfig = {
2732
- name: stream ? `/${this.endpoint}:streamGenerateContent?alt=sse` : `/${this.endpoint}:generateContent`
2713
+ name: stream ? `/${this.endpointId}:streamGenerateContent?alt=sse` : `/${this.endpointId}:generateContent`
2733
2714
  };
2734
2715
  } else {
2735
2716
  apiConfig = {
@@ -2888,9 +2869,9 @@ var AxAIGoogleGeminiImpl = class {
2888
2869
  let apiConfig;
2889
2870
  let reqValue;
2890
2871
  if (this.isVertex) {
2891
- if (this.endpoint) {
2872
+ if (this.endpointId) {
2892
2873
  apiConfig = {
2893
- name: `/${this.endpoint}:predict`
2874
+ name: `/${this.endpointId}:predict`
2894
2875
  };
2895
2876
  } else {
2896
2877
  apiConfig = {
@@ -2994,7 +2975,7 @@ var AxAIGoogleGemini = class extends AxBaseAI {
2994
2975
  apiKey,
2995
2976
  projectId,
2996
2977
  region,
2997
- endpoint,
2978
+ endpointId,
2998
2979
  config,
2999
2980
  options,
3000
2981
  models
@@ -3004,7 +2985,7 @@ var AxAIGoogleGemini = class extends AxBaseAI {
3004
2985
  let headers;
3005
2986
  if (isVertex) {
3006
2987
  let path;
3007
- if (endpoint) {
2988
+ if (endpointId) {
3008
2989
  path = "endpoints";
3009
2990
  } else {
3010
2991
  path = "publishers/google";
@@ -3032,7 +3013,7 @@ var AxAIGoogleGemini = class extends AxBaseAI {
3032
3013
  const aiImpl = new AxAIGoogleGeminiImpl(
3033
3014
  _config,
3034
3015
  isVertex,
3035
- endpoint,
3016
+ endpointId,
3036
3017
  apiKey,
3037
3018
  options
3038
3019
  );
@@ -3753,18 +3734,15 @@ var AxAI = class {
3753
3734
  getId() {
3754
3735
  return this.ai.getId();
3755
3736
  }
3756
- getModelInfo() {
3757
- return this.ai.getModelInfo();
3758
- }
3759
- getEmbedModelInfo() {
3760
- return this.ai.getEmbedModelInfo();
3761
- }
3762
3737
  getFeatures(model) {
3763
3738
  return this.ai.getFeatures(model);
3764
3739
  }
3765
3740
  getModelList() {
3766
3741
  return this.ai.getModelList();
3767
3742
  }
3743
+ getDefaultModels() {
3744
+ return this.ai.getDefaultModels();
3745
+ }
3768
3746
  getMetrics() {
3769
3747
  return this.ai.getMetrics();
3770
3748
  }
@@ -4001,10 +3979,11 @@ var AxAssertionError = class extends Error {
4001
3979
  }
4002
3980
  getFixingInstructions = () => {
4003
3981
  const extraFields = [];
3982
+ const message = this.message.trim();
4004
3983
  extraFields.push({
4005
3984
  name: "error",
4006
- title: "Error In Output",
4007
- description: `You must follow the following instructions, "${this.message}".`
3985
+ title: "Follow these instructions",
3986
+ description: message + (message.endsWith(".") ? "" : ".")
4008
3987
  });
4009
3988
  return extraFields;
4010
3989
  };
@@ -5741,7 +5720,8 @@ async function processFieldProcessors(fieldProcessors, values, mem, sessionId) {
5741
5720
  if (values[processor.field.name] === void 0) {
5742
5721
  continue;
5743
5722
  }
5744
- const result = await processor.process(values[processor.field.name], {
5723
+ const processFn = processor.process;
5724
+ const result = await processFn(values[processor.field.name], {
5745
5725
  sessionId,
5746
5726
  values,
5747
5727
  done: true
@@ -5759,7 +5739,8 @@ async function processStreamingFieldProcessors(fieldProcessors, content, xstate,
5759
5739
  value = value.replace(/^[ ]*```[a-zA-Z0-9]*\n\s*/, "");
5760
5740
  value = value.replace(/\s*```\s*$/, "");
5761
5741
  }
5762
- const result = await processor.process(value, {
5742
+ const processFn = processor.process;
5743
+ const result = await processFn(value, {
5763
5744
  sessionId,
5764
5745
  values,
5765
5746
  done
@@ -6029,7 +6010,7 @@ var AxGen = class extends AxProgramWithSignature {
6029
6010
  addStreamingAssert = (fieldName, fn, message) => {
6030
6011
  this.streamingAsserts.push({ fieldName, fn, message });
6031
6012
  };
6032
- addFieldProcessor = (fieldName, fn, streaming = false) => {
6013
+ addFieldProcessorInternal = (fieldName, fn, streaming = false) => {
6033
6014
  const field = this.signature.getOutputFields().find((f) => f.name === fieldName);
6034
6015
  if (!field) {
6035
6016
  throw new Error(`addFieldProcessor: field ${fieldName} not found`);
@@ -6047,6 +6028,12 @@ var AxGen = class extends AxProgramWithSignature {
6047
6028
  this.fieldProcessors.push({ field, process: fn });
6048
6029
  }
6049
6030
  };
6031
+ addStreamingFieldProcessor = (fieldName, fn) => {
6032
+ this.addFieldProcessorInternal(fieldName, fn, true);
6033
+ };
6034
+ addFieldProcessor = (fieldName, fn) => {
6035
+ this.addFieldProcessorInternal(fieldName, fn, false);
6036
+ };
6050
6037
  async forwardSendRequest({
6051
6038
  ai,
6052
6039
  mem,
@@ -6092,9 +6079,10 @@ var AxGen = class extends AxProgramWithSignature {
6092
6079
  }) {
6093
6080
  const { sessionId, traceId, model, functions } = options ?? {};
6094
6081
  const fastFail = options?.fastFail ?? this.options?.fastFail;
6082
+ const modelName = model ?? ai.getDefaultModels().model;
6095
6083
  const usageInfo = {
6096
6084
  ai: ai.getName(),
6097
- model: ai.getModelInfo().name
6085
+ model: modelName
6098
6086
  };
6099
6087
  const res = await this.forwardSendRequest({
6100
6088
  ai,
@@ -6178,7 +6166,9 @@ var AxGen = class extends AxProgramWithSignature {
6178
6166
  content,
6179
6167
  streamingValidation
6180
6168
  );
6181
- assertStreamingAssertions(this.streamingAsserts, xstate, content);
6169
+ if (this.streamingAsserts.length !== 0) {
6170
+ assertStreamingAssertions(this.streamingAsserts, xstate, content);
6171
+ }
6182
6172
  if (this.streamingFieldProcessors.length !== 0) {
6183
6173
  await processStreamingFieldProcessors(
6184
6174
  this.streamingFieldProcessors,
@@ -6804,8 +6794,9 @@ var AxBalancer = class _AxBalancer {
6804
6794
  if (services.length === 0) {
6805
6795
  throw new Error("No AI services provided.");
6806
6796
  }
6797
+ validateModels2(services);
6807
6798
  this.services = [...services].sort(
6808
- options?.comparator ?? _AxBalancer.costComparator
6799
+ options?.comparator ?? _AxBalancer.metricComparator
6809
6800
  );
6810
6801
  const cs = this.services[this.currentServiceIndex];
6811
6802
  if (cs === void 0) {
@@ -6824,16 +6815,31 @@ var AxBalancer = class _AxBalancer {
6824
6815
  /**
6825
6816
  * Service comparator that sorts services by cost.
6826
6817
  */
6827
- static costComparator = (a, b) => {
6828
- const aInfo = a.getModelInfo();
6829
- const bInfo = b.getModelInfo();
6830
- const aTotalCost = (aInfo.promptTokenCostPer1M || Infinity) + (aInfo.completionTokenCostPer1M || Infinity);
6831
- const bTotalCost = (bInfo.promptTokenCostPer1M || Infinity) + (bInfo.completionTokenCostPer1M || Infinity);
6832
- return aTotalCost - bTotalCost;
6818
+ // Requires a rethink
6819
+ /*
6820
+ public static costComparator = (a: AxAIService, b: AxAIService) => {
6821
+ const aInfo = a.getModelInfo()
6822
+ const bInfo = b.getModelInfo()
6823
+ const aTotalCost =
6824
+ (aInfo.promptTokenCostPer1M || Infinity) +
6825
+ (aInfo.completionTokenCostPer1M || Infinity)
6826
+ const bTotalCost =
6827
+ (bInfo.promptTokenCostPer1M || Infinity) +
6828
+ (bInfo.completionTokenCostPer1M || Infinity)
6829
+ return aTotalCost - bTotalCost
6830
+ }
6831
+ */
6832
+ static metricComparator = (a, b) => {
6833
+ const aMetrics = a.getMetrics();
6834
+ const bMetrics = b.getMetrics();
6835
+ return aMetrics.latency.chat.mean - bMetrics.latency.chat.mean;
6833
6836
  };
6834
6837
  getModelList() {
6835
6838
  return this.currentService.getModelList();
6836
6839
  }
6840
+ getDefaultModels() {
6841
+ return this.currentService.getDefaultModels();
6842
+ }
6837
6843
  getNextService() {
6838
6844
  const cs = this.services[++this.currentServiceIndex];
6839
6845
  if (cs === void 0) {
@@ -6856,12 +6862,6 @@ var AxBalancer = class _AxBalancer {
6856
6862
  getId() {
6857
6863
  return this.currentService.getId();
6858
6864
  }
6859
- getModelInfo() {
6860
- return this.currentService.getModelInfo();
6861
- }
6862
- getEmbedModelInfo() {
6863
- return this.currentService.getEmbedModelInfo();
6864
- }
6865
6865
  getFeatures(model) {
6866
6866
  return this.currentService.getFeatures(model);
6867
6867
  }
@@ -6971,6 +6971,46 @@ var AxBalancer = class _AxBalancer {
6971
6971
  return this.currentService.getOptions();
6972
6972
  }
6973
6973
  };
6974
+ function validateModels2(services) {
6975
+ const serviceWithModel = services.find(
6976
+ (service) => service.getModelList() !== void 0
6977
+ );
6978
+ if (!serviceWithModel) {
6979
+ return;
6980
+ }
6981
+ const referenceModelList = serviceWithModel.getModelList();
6982
+ if (!referenceModelList) {
6983
+ throw new Error("No model list found in any service.");
6984
+ }
6985
+ const referenceKeys = new Set(referenceModelList.map((model) => model.key));
6986
+ for (let i = 0; i < services.length; i++) {
6987
+ const service = services[i];
6988
+ if (!service) {
6989
+ throw new Error(`Service at index ${i} is undefined`);
6990
+ }
6991
+ const modelList = service.getModelList();
6992
+ if (!modelList) {
6993
+ throw new Error(
6994
+ `Service at index ${i} (${service.getName()}) has no model list while another service does.`
6995
+ );
6996
+ }
6997
+ const serviceKeys = new Set(modelList.map((model) => model.key));
6998
+ for (const key of referenceKeys) {
6999
+ if (!serviceKeys.has(key)) {
7000
+ throw new Error(
7001
+ `Service at index ${i} (${service.getName()}) is missing model "${key}"`
7002
+ );
7003
+ }
7004
+ }
7005
+ for (const key of serviceKeys) {
7006
+ if (!referenceKeys.has(key)) {
7007
+ throw new Error(
7008
+ `Service at index ${i} (${service.getName()}) has extra model "${key}"`
7009
+ );
7010
+ }
7011
+ }
7012
+ }
7013
+ }
6974
7014
 
6975
7015
  // dsp/optimize.ts
6976
7016
  var AxBootstrapFewShot = class {
@@ -8202,18 +8242,6 @@ var AxMockAIService = class {
8202
8242
  getId() {
8203
8243
  return this.config.id ?? "mock-ai-service-id";
8204
8244
  }
8205
- getModelInfo() {
8206
- return {
8207
- name: "mock-model",
8208
- provider: "mock-provider",
8209
- promptTokenCostPer1M: 100,
8210
- completionTokenCostPer1M: 100,
8211
- ...this.config.modelInfo
8212
- };
8213
- }
8214
- getEmbedModelInfo() {
8215
- return this.config.embedModelInfo;
8216
- }
8217
8245
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
8218
8246
  getFeatures(_model) {
8219
8247
  return {
@@ -8224,6 +8252,12 @@ var AxMockAIService = class {
8224
8252
  getModelList() {
8225
8253
  return this.config.models;
8226
8254
  }
8255
+ getDefaultModels() {
8256
+ return {
8257
+ model: this.config.modelInfo?.name ?? "mock-model",
8258
+ embedModel: this.config.embedModelInfo?.name
8259
+ };
8260
+ }
8227
8261
  getMetrics() {
8228
8262
  return this.metrics;
8229
8263
  }
@@ -8301,7 +8335,7 @@ var AxMockAIService = class {
8301
8335
 
8302
8336
  // dsp/router.ts
8303
8337
  var colorLog6 = new ColorLog();
8304
- var AxRoute = class {
8338
+ var AxSimpleClassifierClass = class {
8305
8339
  name;
8306
8340
  context;
8307
8341
  constructor(name, context) {
@@ -8315,7 +8349,7 @@ var AxRoute = class {
8315
8349
  return this.context;
8316
8350
  }
8317
8351
  };
8318
- var AxRouter = class {
8352
+ var AxSimpleClassifier = class {
8319
8353
  ai;
8320
8354
  db;
8321
8355
  debug;
@@ -8329,12 +8363,12 @@ var AxRouter = class {
8329
8363
  setState(state) {
8330
8364
  this.db.setDB(state);
8331
8365
  }
8332
- setRoutes = async (routes) => {
8333
- for (const ro of routes) {
8334
- const ret = await this.ai.embed({ texts: ro.getContext() });
8366
+ setClasses = async (classes) => {
8367
+ for (const c of classes) {
8368
+ const ret = await this.ai.embed({ texts: c.getContext() });
8335
8369
  await this.db.upsert({
8336
- id: ro.getName(),
8337
- table: "routes",
8370
+ id: c.getName(),
8371
+ table: "classes",
8338
8372
  values: ret.embeddings[0]
8339
8373
  });
8340
8374
  }
@@ -8342,7 +8376,7 @@ var AxRouter = class {
8342
8376
  async forward(text, options) {
8343
8377
  const { embeddings } = await this.ai.embed({ texts: [text] });
8344
8378
  const matches = await this.db.query({
8345
- table: "routes",
8379
+ table: "classes",
8346
8380
  values: embeddings[0]
8347
8381
  });
8348
8382
  let m = matches.matches;
@@ -8357,11 +8391,11 @@ var AxRouter = class {
8357
8391
  )
8358
8392
  );
8359
8393
  }
8360
- const route = m.at(0);
8361
- if (!route) {
8394
+ const matchedClass = m.at(0);
8395
+ if (!matchedClass) {
8362
8396
  return "";
8363
8397
  }
8364
- return route.id;
8398
+ return matchedClass.id;
8365
8399
  }
8366
8400
  setOptions(options) {
8367
8401
  if (typeof options.debug === "boolean") {
@@ -8568,6 +8602,160 @@ var AxEmbeddingAdapter = class {
8568
8602
  }
8569
8603
  };
8570
8604
 
8605
+ // ai/multiservice.ts
8606
+ var AxMultiServiceRouter = class {
8607
+ services = /* @__PURE__ */ new Map();
8608
+ /**
8609
+ * Constructs a new multi-service router.
8610
+ * It validates that each service provides a unique set of model keys,
8611
+ * then builds a lookup (map) for routing the chat/embed requests.
8612
+ */
8613
+ constructor(services) {
8614
+ if (services.length === 0) {
8615
+ throw new Error("No AI services provided.");
8616
+ }
8617
+ for (const [index, item] of services.entries()) {
8618
+ const isKeyBased = "key" in item;
8619
+ if (isKeyBased) {
8620
+ if (this.services.has(item.key)) {
8621
+ throw new Error(`Duplicate model key: ${item.key}`);
8622
+ }
8623
+ const { service, description, isInternal } = item;
8624
+ this.services.set(item.key, {
8625
+ service,
8626
+ description,
8627
+ isInternal,
8628
+ model: item.service.getDefaultModels().model,
8629
+ useDefaultModel: true
8630
+ });
8631
+ } else {
8632
+ const modelList = item.getModelList();
8633
+ if (!modelList) {
8634
+ throw new Error(
8635
+ `Service ${index} \`${item.getName()}\` has no model list.`
8636
+ );
8637
+ }
8638
+ for (const { key, description, model } of modelList ?? []) {
8639
+ if (this.services.has(key)) {
8640
+ const otherService = this.services.get(key)?.service;
8641
+ throw new Error(
8642
+ `Service ${index} \`${item.getName()}\` has duplicate model key: ${key} as service ${otherService?.getName()}`
8643
+ );
8644
+ }
8645
+ this.services.set(key, {
8646
+ description,
8647
+ service: item,
8648
+ model
8649
+ });
8650
+ }
8651
+ }
8652
+ }
8653
+ }
8654
+ /**
8655
+ * Delegates the chat call to the service matching the provided model key.
8656
+ */
8657
+ async chat(req, options) {
8658
+ const modelKey = req.model;
8659
+ if (!modelKey) {
8660
+ throw new Error("Model key must be specified for multi-service");
8661
+ }
8662
+ const item = this.services.get(modelKey);
8663
+ if (!item) {
8664
+ throw new Error(`No service found for model key: ${modelKey}`);
8665
+ }
8666
+ const service = item.service;
8667
+ const model = item.useDefaultModel ? req.model : modelKey;
8668
+ return await service.chat({ model, ...req }, options);
8669
+ }
8670
+ /**
8671
+ * Delegates the embed call to the service matching the provided embed model key.
8672
+ */
8673
+ async embed(req, options) {
8674
+ const modelKey = req.embedModel;
8675
+ if (!modelKey) {
8676
+ throw new Error("Embed model key must be specified for multi-service");
8677
+ }
8678
+ const item = this.services.get(modelKey);
8679
+ if (!item) {
8680
+ throw new Error(`No service found for embed model key: ${modelKey}`);
8681
+ }
8682
+ const service = item.service;
8683
+ const embedModel = item.useDefaultModel ? req.embedModel : modelKey;
8684
+ return await service.embed({ embedModel, ...req }, options);
8685
+ }
8686
+ /**
8687
+ * Returns a composite ID built from the IDs of the underlying services.
8688
+ */
8689
+ getId() {
8690
+ return "MultiServiceRouter:" + Array.from(this.services.values()).map((s) => s.service.getId()).join(",");
8691
+ }
8692
+ /**
8693
+ * Returns the name of this router.
8694
+ */
8695
+ getName() {
8696
+ return "MultiServiceRouter";
8697
+ }
8698
+ /**
8699
+ * Aggregates all available models across the underlying services.
8700
+ */
8701
+ getModelList() {
8702
+ return Array.from(this.services).filter(([, value]) => !value.isInternal).map(([key, { description, model }]) => ({
8703
+ key,
8704
+ description,
8705
+ model
8706
+ }));
8707
+ }
8708
+ getDefaultModels() {
8709
+ throw new Error(
8710
+ "getDefaultModels is not supported for multi-service router."
8711
+ );
8712
+ }
8713
+ /**
8714
+ * If a model key is provided, delegate to the corresponding service's features.
8715
+ * Otherwise, returns a default feature set.
8716
+ */
8717
+ getFeatures(model) {
8718
+ if (model) {
8719
+ const service = this.services.get(model);
8720
+ if (service) {
8721
+ return service.service.getFeatures(model);
8722
+ }
8723
+ }
8724
+ return { functions: false, streaming: false };
8725
+ }
8726
+ /**
8727
+ * Returns aggregated metrics from the underlying service.
8728
+ * Uses the metrics from the last service that was used,
8729
+ * or falls back to the first service if none has been used.
8730
+ */
8731
+ getMetrics() {
8732
+ const service = this.services.values().next().value;
8733
+ if (!service) {
8734
+ throw new Error("No service available to get metrics.");
8735
+ }
8736
+ return service.service.getMetrics();
8737
+ }
8738
+ /**
8739
+ * Sets options on all underlying services.
8740
+ */
8741
+ setOptions(options) {
8742
+ for (const service of this.services.values()) {
8743
+ service.service.setOptions(options);
8744
+ }
8745
+ }
8746
+ /**
8747
+ * Returns the options from the last used service,
8748
+ * or falls back to the first service if none has been used.
8749
+ */
8750
+ getOptions() {
8751
+ const service = this.services.values().next().value;
8752
+ if (!service) {
8753
+ throw new Error("No service available to get options.");
8754
+ }
8755
+ return service.service.getOptions();
8756
+ }
8757
+ };
8758
+
8571
8759
  // prompts/rag.ts
8572
8760
  var AxRAG = class extends AxChainOfThought {
8573
8761
  genQuery;
@@ -8668,14 +8856,15 @@ var AxRAG = class extends AxChainOfThought {
8668
8856
  AxLLMRequestTypeValues,
8669
8857
  AxMemory,
8670
8858
  AxMockAIService,
8859
+ AxMultiServiceRouter,
8671
8860
  AxProgram,
8672
8861
  AxProgramWithSignature,
8673
8862
  AxPromptTemplate,
8674
8863
  AxRAG,
8675
8864
  AxRateLimiterTokenUsage,
8676
- AxRoute,
8677
- AxRouter,
8678
8865
  AxSignature,
8866
+ AxSimpleClassifier,
8867
+ AxSimpleClassifierClass,
8679
8868
  AxSpanKindValues,
8680
8869
  AxTestPrompt
8681
8870
  });