@ax-llm/ax 11.0.21 → 11.0.23
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 +290 -99
- package/index.cjs.map +1 -1
- package/index.d.cts +125 -36
- package/index.d.ts +125 -36
- package/index.js +287 -97
- package/index.js.map +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
// ai/base.ts
|
|
2
2
|
import { SpanKind } from "@opentelemetry/api";
|
|
3
3
|
|
|
4
|
-
// dsp/modelinfo.ts
|
|
5
|
-
function getModelInfo({
|
|
6
|
-
model,
|
|
7
|
-
modelInfo,
|
|
8
|
-
models
|
|
9
|
-
}) {
|
|
10
|
-
const mappedModel = models?.find((v) => v.key === model)?.model ?? model;
|
|
11
|
-
const exactMatch = modelInfo.find((v) => v.name === model);
|
|
12
|
-
if (exactMatch) return exactMatch;
|
|
13
|
-
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+$/, "");
|
|
14
|
-
const normalizedMatch = modelInfo.find((v) => v.name === normalizedName);
|
|
15
|
-
if (normalizedMatch) return normalizedMatch;
|
|
16
|
-
return {
|
|
17
|
-
name: model,
|
|
18
|
-
currency: "usd",
|
|
19
|
-
promptTokenCostPer1M: 0,
|
|
20
|
-
completionTokenCostPer1M: 0
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
4
|
// trace/trace.ts
|
|
25
5
|
var axSpanAttributes = {
|
|
26
6
|
// LLM
|
|
@@ -746,6 +726,9 @@ var AxBaseAI = class {
|
|
|
746
726
|
throw new Error("No model defined");
|
|
747
727
|
}
|
|
748
728
|
this.setOptions(options);
|
|
729
|
+
if (models) {
|
|
730
|
+
validateModels(models);
|
|
731
|
+
}
|
|
749
732
|
}
|
|
750
733
|
debug = false;
|
|
751
734
|
rt;
|
|
@@ -824,33 +807,19 @@ var AxBaseAI = class {
|
|
|
824
807
|
tracer: this.tracer
|
|
825
808
|
};
|
|
826
809
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
});
|
|
833
|
-
return {
|
|
834
|
-
...mi,
|
|
835
|
-
provider: this.name
|
|
836
|
-
};
|
|
810
|
+
getModelList() {
|
|
811
|
+
return this.models?.filter((model) => !model.isInternal)?.map((model) => ({
|
|
812
|
+
key: model.key,
|
|
813
|
+
description: model.description,
|
|
814
|
+
model: model.model
|
|
815
|
+
}));
|
|
837
816
|
}
|
|
838
|
-
|
|
839
|
-
if (!this.defaults.embedModel) {
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
const mi = getModelInfo({
|
|
843
|
-
model: this.defaults.embedModel,
|
|
844
|
-
modelInfo: this.modelInfo
|
|
845
|
-
});
|
|
817
|
+
getDefaultModels() {
|
|
846
818
|
return {
|
|
847
|
-
|
|
848
|
-
|
|
819
|
+
model: this.defaults.model,
|
|
820
|
+
embedModel: this.defaults.embedModel
|
|
849
821
|
};
|
|
850
822
|
}
|
|
851
|
-
getModelList() {
|
|
852
|
-
return this.models;
|
|
853
|
-
}
|
|
854
823
|
getName() {
|
|
855
824
|
return this.name;
|
|
856
825
|
}
|
|
@@ -1136,14 +1105,25 @@ var AxBaseAI = class {
|
|
|
1136
1105
|
return { ...headers, ...await this.headers() };
|
|
1137
1106
|
}
|
|
1138
1107
|
};
|
|
1139
|
-
|
|
1108
|
+
function setResponseAttr(res, span) {
|
|
1140
1109
|
if (res.modelUsage) {
|
|
1141
1110
|
span.setAttributes({
|
|
1142
1111
|
[axSpanAttributes.LLM_USAGE_COMPLETION_TOKENS]: res.modelUsage.completionTokens ?? 0,
|
|
1143
1112
|
[axSpanAttributes.LLM_USAGE_PROMPT_TOKENS]: res.modelUsage.promptTokens
|
|
1144
1113
|
});
|
|
1145
1114
|
}
|
|
1146
|
-
}
|
|
1115
|
+
}
|
|
1116
|
+
function validateModels(models) {
|
|
1117
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1118
|
+
for (const model of models) {
|
|
1119
|
+
if (keys.has(model.key)) {
|
|
1120
|
+
throw new Error(
|
|
1121
|
+
`Duplicate model key detected: "${model.key}". Each model key must be unique.`
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
keys.add(model.key);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1147
1127
|
|
|
1148
1128
|
// ai/google-vertex/auth.ts
|
|
1149
1129
|
import { GoogleAuth } from "google-auth-library";
|
|
@@ -1174,6 +1154,7 @@ var GoogleVertexAuth = class {
|
|
|
1174
1154
|
|
|
1175
1155
|
// ai/anthropic/types.ts
|
|
1176
1156
|
var AxAIAnthropicModel = /* @__PURE__ */ ((AxAIAnthropicModel2) => {
|
|
1157
|
+
AxAIAnthropicModel2["Claude37Sonnet"] = "claude-3-7-sonnet-latest";
|
|
1177
1158
|
AxAIAnthropicModel2["Claude35Sonnet"] = "claude-3-5-sonnet-latest";
|
|
1178
1159
|
AxAIAnthropicModel2["Claude35Haiku"] = "claude-3-5-haiku-latest";
|
|
1179
1160
|
AxAIAnthropicModel2["Claude3Opus"] = "claude-3-opus-latest";
|
|
@@ -1184,6 +1165,7 @@ var AxAIAnthropicModel = /* @__PURE__ */ ((AxAIAnthropicModel2) => {
|
|
|
1184
1165
|
return AxAIAnthropicModel2;
|
|
1185
1166
|
})(AxAIAnthropicModel || {});
|
|
1186
1167
|
var AxAIAnthropicVertexModel = /* @__PURE__ */ ((AxAIAnthropicVertexModel3) => {
|
|
1168
|
+
AxAIAnthropicVertexModel3["Claude37Sonnet"] = "claude-3-7-sonnet";
|
|
1187
1169
|
AxAIAnthropicVertexModel3["Claude35Haiku"] = "claude-3-5-haiku";
|
|
1188
1170
|
AxAIAnthropicVertexModel3["Claude35Sonnet"] = "claude-3-5-sonnet";
|
|
1189
1171
|
AxAIAnthropicVertexModel3["Claude35SonnetV2"] = "claude-3-5-sonnet-v2";
|
|
@@ -1799,7 +1781,7 @@ var AxAIOpenAIImpl = class {
|
|
|
1799
1781
|
response_format: this.config?.responseFormat ? { type: this.config?.responseFormat } : void 0,
|
|
1800
1782
|
tools,
|
|
1801
1783
|
tool_choice: toolsChoice,
|
|
1802
|
-
|
|
1784
|
+
max_completion_tokens: req.modelConfig?.maxTokens ?? this.config.maxTokens ?? 500,
|
|
1803
1785
|
temperature: req.modelConfig?.temperature ?? this.config.temperature,
|
|
1804
1786
|
top_p: req.modelConfig?.topP ?? this.config.topP ?? 1,
|
|
1805
1787
|
n: req.modelConfig?.n ?? this.config.n,
|
|
@@ -3651,18 +3633,15 @@ var AxAI = class {
|
|
|
3651
3633
|
getId() {
|
|
3652
3634
|
return this.ai.getId();
|
|
3653
3635
|
}
|
|
3654
|
-
getModelInfo() {
|
|
3655
|
-
return this.ai.getModelInfo();
|
|
3656
|
-
}
|
|
3657
|
-
getEmbedModelInfo() {
|
|
3658
|
-
return this.ai.getEmbedModelInfo();
|
|
3659
|
-
}
|
|
3660
3636
|
getFeatures(model) {
|
|
3661
3637
|
return this.ai.getFeatures(model);
|
|
3662
3638
|
}
|
|
3663
3639
|
getModelList() {
|
|
3664
3640
|
return this.ai.getModelList();
|
|
3665
3641
|
}
|
|
3642
|
+
getDefaultModels() {
|
|
3643
|
+
return this.ai.getDefaultModels();
|
|
3644
|
+
}
|
|
3666
3645
|
getMetrics() {
|
|
3667
3646
|
return this.ai.getMetrics();
|
|
3668
3647
|
}
|
|
@@ -3899,10 +3878,11 @@ var AxAssertionError = class extends Error {
|
|
|
3899
3878
|
}
|
|
3900
3879
|
getFixingInstructions = () => {
|
|
3901
3880
|
const extraFields = [];
|
|
3881
|
+
const message = this.message.trim();
|
|
3902
3882
|
extraFields.push({
|
|
3903
3883
|
name: "error",
|
|
3904
|
-
title: "
|
|
3905
|
-
description:
|
|
3884
|
+
title: "Follow these instructions",
|
|
3885
|
+
description: message + (message.endsWith(".") ? "" : ".")
|
|
3906
3886
|
});
|
|
3907
3887
|
return extraFields;
|
|
3908
3888
|
};
|
|
@@ -5639,7 +5619,8 @@ async function processFieldProcessors(fieldProcessors, values, mem, sessionId) {
|
|
|
5639
5619
|
if (values[processor.field.name] === void 0) {
|
|
5640
5620
|
continue;
|
|
5641
5621
|
}
|
|
5642
|
-
const
|
|
5622
|
+
const processFn = processor.process;
|
|
5623
|
+
const result = await processFn(values[processor.field.name], {
|
|
5643
5624
|
sessionId,
|
|
5644
5625
|
values,
|
|
5645
5626
|
done: true
|
|
@@ -5657,7 +5638,8 @@ async function processStreamingFieldProcessors(fieldProcessors, content, xstate,
|
|
|
5657
5638
|
value = value.replace(/^[ ]*```[a-zA-Z0-9]*\n\s*/, "");
|
|
5658
5639
|
value = value.replace(/\s*```\s*$/, "");
|
|
5659
5640
|
}
|
|
5660
|
-
const
|
|
5641
|
+
const processFn = processor.process;
|
|
5642
|
+
const result = await processFn(value, {
|
|
5661
5643
|
sessionId,
|
|
5662
5644
|
values,
|
|
5663
5645
|
done
|
|
@@ -5927,7 +5909,7 @@ var AxGen = class extends AxProgramWithSignature {
|
|
|
5927
5909
|
addStreamingAssert = (fieldName, fn, message) => {
|
|
5928
5910
|
this.streamingAsserts.push({ fieldName, fn, message });
|
|
5929
5911
|
};
|
|
5930
|
-
|
|
5912
|
+
addFieldProcessorInternal = (fieldName, fn, streaming = false) => {
|
|
5931
5913
|
const field = this.signature.getOutputFields().find((f) => f.name === fieldName);
|
|
5932
5914
|
if (!field) {
|
|
5933
5915
|
throw new Error(`addFieldProcessor: field ${fieldName} not found`);
|
|
@@ -5945,6 +5927,12 @@ var AxGen = class extends AxProgramWithSignature {
|
|
|
5945
5927
|
this.fieldProcessors.push({ field, process: fn });
|
|
5946
5928
|
}
|
|
5947
5929
|
};
|
|
5930
|
+
addStreamingFieldProcessor = (fieldName, fn) => {
|
|
5931
|
+
this.addFieldProcessorInternal(fieldName, fn, true);
|
|
5932
|
+
};
|
|
5933
|
+
addFieldProcessor = (fieldName, fn) => {
|
|
5934
|
+
this.addFieldProcessorInternal(fieldName, fn, false);
|
|
5935
|
+
};
|
|
5948
5936
|
async forwardSendRequest({
|
|
5949
5937
|
ai,
|
|
5950
5938
|
mem,
|
|
@@ -5990,9 +5978,10 @@ var AxGen = class extends AxProgramWithSignature {
|
|
|
5990
5978
|
}) {
|
|
5991
5979
|
const { sessionId, traceId, model, functions } = options ?? {};
|
|
5992
5980
|
const fastFail = options?.fastFail ?? this.options?.fastFail;
|
|
5981
|
+
const modelName = model ?? ai.getDefaultModels().model;
|
|
5993
5982
|
const usageInfo = {
|
|
5994
5983
|
ai: ai.getName(),
|
|
5995
|
-
model:
|
|
5984
|
+
model: modelName
|
|
5996
5985
|
};
|
|
5997
5986
|
const res = await this.forwardSendRequest({
|
|
5998
5987
|
ai,
|
|
@@ -6076,7 +6065,9 @@ var AxGen = class extends AxProgramWithSignature {
|
|
|
6076
6065
|
content,
|
|
6077
6066
|
streamingValidation
|
|
6078
6067
|
);
|
|
6079
|
-
|
|
6068
|
+
if (this.streamingAsserts.length !== 0) {
|
|
6069
|
+
assertStreamingAssertions(this.streamingAsserts, xstate, content);
|
|
6070
|
+
}
|
|
6080
6071
|
if (this.streamingFieldProcessors.length !== 0) {
|
|
6081
6072
|
await processStreamingFieldProcessors(
|
|
6082
6073
|
this.streamingFieldProcessors,
|
|
@@ -6702,8 +6693,9 @@ var AxBalancer = class _AxBalancer {
|
|
|
6702
6693
|
if (services.length === 0) {
|
|
6703
6694
|
throw new Error("No AI services provided.");
|
|
6704
6695
|
}
|
|
6696
|
+
validateModels2(services);
|
|
6705
6697
|
this.services = [...services].sort(
|
|
6706
|
-
options?.comparator ?? _AxBalancer.
|
|
6698
|
+
options?.comparator ?? _AxBalancer.metricComparator
|
|
6707
6699
|
);
|
|
6708
6700
|
const cs = this.services[this.currentServiceIndex];
|
|
6709
6701
|
if (cs === void 0) {
|
|
@@ -6722,16 +6714,31 @@ var AxBalancer = class _AxBalancer {
|
|
|
6722
6714
|
/**
|
|
6723
6715
|
* Service comparator that sorts services by cost.
|
|
6724
6716
|
*/
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6717
|
+
// Requires a rethink
|
|
6718
|
+
/*
|
|
6719
|
+
public static costComparator = (a: AxAIService, b: AxAIService) => {
|
|
6720
|
+
const aInfo = a.getModelInfo()
|
|
6721
|
+
const bInfo = b.getModelInfo()
|
|
6722
|
+
const aTotalCost =
|
|
6723
|
+
(aInfo.promptTokenCostPer1M || Infinity) +
|
|
6724
|
+
(aInfo.completionTokenCostPer1M || Infinity)
|
|
6725
|
+
const bTotalCost =
|
|
6726
|
+
(bInfo.promptTokenCostPer1M || Infinity) +
|
|
6727
|
+
(bInfo.completionTokenCostPer1M || Infinity)
|
|
6728
|
+
return aTotalCost - bTotalCost
|
|
6729
|
+
}
|
|
6730
|
+
*/
|
|
6731
|
+
static metricComparator = (a, b) => {
|
|
6732
|
+
const aMetrics = a.getMetrics();
|
|
6733
|
+
const bMetrics = b.getMetrics();
|
|
6734
|
+
return aMetrics.latency.chat.mean - bMetrics.latency.chat.mean;
|
|
6731
6735
|
};
|
|
6732
6736
|
getModelList() {
|
|
6733
6737
|
return this.currentService.getModelList();
|
|
6734
6738
|
}
|
|
6739
|
+
getDefaultModels() {
|
|
6740
|
+
return this.currentService.getDefaultModels();
|
|
6741
|
+
}
|
|
6735
6742
|
getNextService() {
|
|
6736
6743
|
const cs = this.services[++this.currentServiceIndex];
|
|
6737
6744
|
if (cs === void 0) {
|
|
@@ -6754,12 +6761,6 @@ var AxBalancer = class _AxBalancer {
|
|
|
6754
6761
|
getId() {
|
|
6755
6762
|
return this.currentService.getId();
|
|
6756
6763
|
}
|
|
6757
|
-
getModelInfo() {
|
|
6758
|
-
return this.currentService.getModelInfo();
|
|
6759
|
-
}
|
|
6760
|
-
getEmbedModelInfo() {
|
|
6761
|
-
return this.currentService.getEmbedModelInfo();
|
|
6762
|
-
}
|
|
6763
6764
|
getFeatures(model) {
|
|
6764
6765
|
return this.currentService.getFeatures(model);
|
|
6765
6766
|
}
|
|
@@ -6869,6 +6870,46 @@ var AxBalancer = class _AxBalancer {
|
|
|
6869
6870
|
return this.currentService.getOptions();
|
|
6870
6871
|
}
|
|
6871
6872
|
};
|
|
6873
|
+
function validateModels2(services) {
|
|
6874
|
+
const serviceWithModel = services.find(
|
|
6875
|
+
(service) => service.getModelList() !== void 0
|
|
6876
|
+
);
|
|
6877
|
+
if (!serviceWithModel) {
|
|
6878
|
+
return;
|
|
6879
|
+
}
|
|
6880
|
+
const referenceModelList = serviceWithModel.getModelList();
|
|
6881
|
+
if (!referenceModelList) {
|
|
6882
|
+
throw new Error("No model list found in any service.");
|
|
6883
|
+
}
|
|
6884
|
+
const referenceKeys = new Set(referenceModelList.map((model) => model.key));
|
|
6885
|
+
for (let i = 0; i < services.length; i++) {
|
|
6886
|
+
const service = services[i];
|
|
6887
|
+
if (!service) {
|
|
6888
|
+
throw new Error(`Service at index ${i} is undefined`);
|
|
6889
|
+
}
|
|
6890
|
+
const modelList = service.getModelList();
|
|
6891
|
+
if (!modelList) {
|
|
6892
|
+
throw new Error(
|
|
6893
|
+
`Service at index ${i} (${service.getName()}) has no model list while another service does.`
|
|
6894
|
+
);
|
|
6895
|
+
}
|
|
6896
|
+
const serviceKeys = new Set(modelList.map((model) => model.key));
|
|
6897
|
+
for (const key of referenceKeys) {
|
|
6898
|
+
if (!serviceKeys.has(key)) {
|
|
6899
|
+
throw new Error(
|
|
6900
|
+
`Service at index ${i} (${service.getName()}) is missing model "${key}"`
|
|
6901
|
+
);
|
|
6902
|
+
}
|
|
6903
|
+
}
|
|
6904
|
+
for (const key of serviceKeys) {
|
|
6905
|
+
if (!referenceKeys.has(key)) {
|
|
6906
|
+
throw new Error(
|
|
6907
|
+
`Service at index ${i} (${service.getName()}) has extra model "${key}"`
|
|
6908
|
+
);
|
|
6909
|
+
}
|
|
6910
|
+
}
|
|
6911
|
+
}
|
|
6912
|
+
}
|
|
6872
6913
|
|
|
6873
6914
|
// dsp/optimize.ts
|
|
6874
6915
|
var AxBootstrapFewShot = class {
|
|
@@ -8100,18 +8141,6 @@ var AxMockAIService = class {
|
|
|
8100
8141
|
getId() {
|
|
8101
8142
|
return this.config.id ?? "mock-ai-service-id";
|
|
8102
8143
|
}
|
|
8103
|
-
getModelInfo() {
|
|
8104
|
-
return {
|
|
8105
|
-
name: "mock-model",
|
|
8106
|
-
provider: "mock-provider",
|
|
8107
|
-
promptTokenCostPer1M: 100,
|
|
8108
|
-
completionTokenCostPer1M: 100,
|
|
8109
|
-
...this.config.modelInfo
|
|
8110
|
-
};
|
|
8111
|
-
}
|
|
8112
|
-
getEmbedModelInfo() {
|
|
8113
|
-
return this.config.embedModelInfo;
|
|
8114
|
-
}
|
|
8115
8144
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
8116
8145
|
getFeatures(_model) {
|
|
8117
8146
|
return {
|
|
@@ -8122,6 +8151,12 @@ var AxMockAIService = class {
|
|
|
8122
8151
|
getModelList() {
|
|
8123
8152
|
return this.config.models;
|
|
8124
8153
|
}
|
|
8154
|
+
getDefaultModels() {
|
|
8155
|
+
return {
|
|
8156
|
+
model: this.config.modelInfo?.name ?? "mock-model",
|
|
8157
|
+
embedModel: this.config.embedModelInfo?.name
|
|
8158
|
+
};
|
|
8159
|
+
}
|
|
8125
8160
|
getMetrics() {
|
|
8126
8161
|
return this.metrics;
|
|
8127
8162
|
}
|
|
@@ -8199,7 +8234,7 @@ var AxMockAIService = class {
|
|
|
8199
8234
|
|
|
8200
8235
|
// dsp/router.ts
|
|
8201
8236
|
var colorLog6 = new ColorLog();
|
|
8202
|
-
var
|
|
8237
|
+
var AxSimpleClassifierClass = class {
|
|
8203
8238
|
name;
|
|
8204
8239
|
context;
|
|
8205
8240
|
constructor(name, context) {
|
|
@@ -8213,7 +8248,7 @@ var AxRoute = class {
|
|
|
8213
8248
|
return this.context;
|
|
8214
8249
|
}
|
|
8215
8250
|
};
|
|
8216
|
-
var
|
|
8251
|
+
var AxSimpleClassifier = class {
|
|
8217
8252
|
ai;
|
|
8218
8253
|
db;
|
|
8219
8254
|
debug;
|
|
@@ -8227,12 +8262,12 @@ var AxRouter = class {
|
|
|
8227
8262
|
setState(state) {
|
|
8228
8263
|
this.db.setDB(state);
|
|
8229
8264
|
}
|
|
8230
|
-
|
|
8231
|
-
for (const
|
|
8232
|
-
const ret = await this.ai.embed({ texts:
|
|
8265
|
+
setClasses = async (classes) => {
|
|
8266
|
+
for (const c of classes) {
|
|
8267
|
+
const ret = await this.ai.embed({ texts: c.getContext() });
|
|
8233
8268
|
await this.db.upsert({
|
|
8234
|
-
id:
|
|
8235
|
-
table: "
|
|
8269
|
+
id: c.getName(),
|
|
8270
|
+
table: "classes",
|
|
8236
8271
|
values: ret.embeddings[0]
|
|
8237
8272
|
});
|
|
8238
8273
|
}
|
|
@@ -8240,7 +8275,7 @@ var AxRouter = class {
|
|
|
8240
8275
|
async forward(text, options) {
|
|
8241
8276
|
const { embeddings } = await this.ai.embed({ texts: [text] });
|
|
8242
8277
|
const matches = await this.db.query({
|
|
8243
|
-
table: "
|
|
8278
|
+
table: "classes",
|
|
8244
8279
|
values: embeddings[0]
|
|
8245
8280
|
});
|
|
8246
8281
|
let m = matches.matches;
|
|
@@ -8255,11 +8290,11 @@ var AxRouter = class {
|
|
|
8255
8290
|
)
|
|
8256
8291
|
);
|
|
8257
8292
|
}
|
|
8258
|
-
const
|
|
8259
|
-
if (!
|
|
8293
|
+
const matchedClass = m.at(0);
|
|
8294
|
+
if (!matchedClass) {
|
|
8260
8295
|
return "";
|
|
8261
8296
|
}
|
|
8262
|
-
return
|
|
8297
|
+
return matchedClass.id;
|
|
8263
8298
|
}
|
|
8264
8299
|
setOptions(options) {
|
|
8265
8300
|
if (typeof options.debug === "boolean") {
|
|
@@ -8466,6 +8501,160 @@ var AxEmbeddingAdapter = class {
|
|
|
8466
8501
|
}
|
|
8467
8502
|
};
|
|
8468
8503
|
|
|
8504
|
+
// ai/multiservice.ts
|
|
8505
|
+
var AxMultiServiceRouter = class {
|
|
8506
|
+
services = /* @__PURE__ */ new Map();
|
|
8507
|
+
/**
|
|
8508
|
+
* Constructs a new multi-service router.
|
|
8509
|
+
* It validates that each service provides a unique set of model keys,
|
|
8510
|
+
* then builds a lookup (map) for routing the chat/embed requests.
|
|
8511
|
+
*/
|
|
8512
|
+
constructor(services) {
|
|
8513
|
+
if (services.length === 0) {
|
|
8514
|
+
throw new Error("No AI services provided.");
|
|
8515
|
+
}
|
|
8516
|
+
for (const [index, item] of services.entries()) {
|
|
8517
|
+
const isKeyBased = "key" in item;
|
|
8518
|
+
if (isKeyBased) {
|
|
8519
|
+
if (this.services.has(item.key)) {
|
|
8520
|
+
throw new Error(`Duplicate model key: ${item.key}`);
|
|
8521
|
+
}
|
|
8522
|
+
const { service, description, isInternal } = item;
|
|
8523
|
+
this.services.set(item.key, {
|
|
8524
|
+
service,
|
|
8525
|
+
description,
|
|
8526
|
+
isInternal,
|
|
8527
|
+
model: item.service.getDefaultModels().model,
|
|
8528
|
+
useDefaultModel: true
|
|
8529
|
+
});
|
|
8530
|
+
} else {
|
|
8531
|
+
const modelList = item.getModelList();
|
|
8532
|
+
if (!modelList) {
|
|
8533
|
+
throw new Error(
|
|
8534
|
+
`Service ${index} \`${item.getName()}\` has no model list.`
|
|
8535
|
+
);
|
|
8536
|
+
}
|
|
8537
|
+
for (const { key, description, model } of modelList ?? []) {
|
|
8538
|
+
if (this.services.has(key)) {
|
|
8539
|
+
const otherService = this.services.get(key)?.service;
|
|
8540
|
+
throw new Error(
|
|
8541
|
+
`Service ${index} \`${item.getName()}\` has duplicate model key: ${key} as service ${otherService?.getName()}`
|
|
8542
|
+
);
|
|
8543
|
+
}
|
|
8544
|
+
this.services.set(key, {
|
|
8545
|
+
description,
|
|
8546
|
+
service: item,
|
|
8547
|
+
model
|
|
8548
|
+
});
|
|
8549
|
+
}
|
|
8550
|
+
}
|
|
8551
|
+
}
|
|
8552
|
+
}
|
|
8553
|
+
/**
|
|
8554
|
+
* Delegates the chat call to the service matching the provided model key.
|
|
8555
|
+
*/
|
|
8556
|
+
async chat(req, options) {
|
|
8557
|
+
const modelKey = req.model;
|
|
8558
|
+
if (!modelKey) {
|
|
8559
|
+
throw new Error("Model key must be specified for multi-service");
|
|
8560
|
+
}
|
|
8561
|
+
const item = this.services.get(modelKey);
|
|
8562
|
+
if (!item) {
|
|
8563
|
+
throw new Error(`No service found for model key: ${modelKey}`);
|
|
8564
|
+
}
|
|
8565
|
+
const service = item.service;
|
|
8566
|
+
const model = item.useDefaultModel ? req.model : modelKey;
|
|
8567
|
+
return await service.chat({ model, ...req }, options);
|
|
8568
|
+
}
|
|
8569
|
+
/**
|
|
8570
|
+
* Delegates the embed call to the service matching the provided embed model key.
|
|
8571
|
+
*/
|
|
8572
|
+
async embed(req, options) {
|
|
8573
|
+
const modelKey = req.embedModel;
|
|
8574
|
+
if (!modelKey) {
|
|
8575
|
+
throw new Error("Embed model key must be specified for multi-service");
|
|
8576
|
+
}
|
|
8577
|
+
const item = this.services.get(modelKey);
|
|
8578
|
+
if (!item) {
|
|
8579
|
+
throw new Error(`No service found for embed model key: ${modelKey}`);
|
|
8580
|
+
}
|
|
8581
|
+
const service = item.service;
|
|
8582
|
+
const embedModel = item.useDefaultModel ? req.embedModel : modelKey;
|
|
8583
|
+
return await service.embed({ embedModel, ...req }, options);
|
|
8584
|
+
}
|
|
8585
|
+
/**
|
|
8586
|
+
* Returns a composite ID built from the IDs of the underlying services.
|
|
8587
|
+
*/
|
|
8588
|
+
getId() {
|
|
8589
|
+
return "MultiServiceRouter:" + Array.from(this.services.values()).map((s) => s.service.getId()).join(",");
|
|
8590
|
+
}
|
|
8591
|
+
/**
|
|
8592
|
+
* Returns the name of this router.
|
|
8593
|
+
*/
|
|
8594
|
+
getName() {
|
|
8595
|
+
return "MultiServiceRouter";
|
|
8596
|
+
}
|
|
8597
|
+
/**
|
|
8598
|
+
* Aggregates all available models across the underlying services.
|
|
8599
|
+
*/
|
|
8600
|
+
getModelList() {
|
|
8601
|
+
return Array.from(this.services).filter(([, value]) => !value.isInternal).map(([key, { description, model }]) => ({
|
|
8602
|
+
key,
|
|
8603
|
+
description,
|
|
8604
|
+
model
|
|
8605
|
+
}));
|
|
8606
|
+
}
|
|
8607
|
+
getDefaultModels() {
|
|
8608
|
+
throw new Error(
|
|
8609
|
+
"getDefaultModels is not supported for multi-service router."
|
|
8610
|
+
);
|
|
8611
|
+
}
|
|
8612
|
+
/**
|
|
8613
|
+
* If a model key is provided, delegate to the corresponding service's features.
|
|
8614
|
+
* Otherwise, returns a default feature set.
|
|
8615
|
+
*/
|
|
8616
|
+
getFeatures(model) {
|
|
8617
|
+
if (model) {
|
|
8618
|
+
const service = this.services.get(model);
|
|
8619
|
+
if (service) {
|
|
8620
|
+
return service.service.getFeatures(model);
|
|
8621
|
+
}
|
|
8622
|
+
}
|
|
8623
|
+
return { functions: false, streaming: false };
|
|
8624
|
+
}
|
|
8625
|
+
/**
|
|
8626
|
+
* Returns aggregated metrics from the underlying service.
|
|
8627
|
+
* Uses the metrics from the last service that was used,
|
|
8628
|
+
* or falls back to the first service if none has been used.
|
|
8629
|
+
*/
|
|
8630
|
+
getMetrics() {
|
|
8631
|
+
const service = this.services.values().next().value;
|
|
8632
|
+
if (!service) {
|
|
8633
|
+
throw new Error("No service available to get metrics.");
|
|
8634
|
+
}
|
|
8635
|
+
return service.service.getMetrics();
|
|
8636
|
+
}
|
|
8637
|
+
/**
|
|
8638
|
+
* Sets options on all underlying services.
|
|
8639
|
+
*/
|
|
8640
|
+
setOptions(options) {
|
|
8641
|
+
for (const service of this.services.values()) {
|
|
8642
|
+
service.service.setOptions(options);
|
|
8643
|
+
}
|
|
8644
|
+
}
|
|
8645
|
+
/**
|
|
8646
|
+
* Returns the options from the last used service,
|
|
8647
|
+
* or falls back to the first service if none has been used.
|
|
8648
|
+
*/
|
|
8649
|
+
getOptions() {
|
|
8650
|
+
const service = this.services.values().next().value;
|
|
8651
|
+
if (!service) {
|
|
8652
|
+
throw new Error("No service available to get options.");
|
|
8653
|
+
}
|
|
8654
|
+
return service.service.getOptions();
|
|
8655
|
+
}
|
|
8656
|
+
};
|
|
8657
|
+
|
|
8469
8658
|
// prompts/rag.ts
|
|
8470
8659
|
var AxRAG = class extends AxChainOfThought {
|
|
8471
8660
|
genQuery;
|
|
@@ -8565,14 +8754,15 @@ export {
|
|
|
8565
8754
|
AxLLMRequestTypeValues,
|
|
8566
8755
|
AxMemory,
|
|
8567
8756
|
AxMockAIService,
|
|
8757
|
+
AxMultiServiceRouter,
|
|
8568
8758
|
AxProgram,
|
|
8569
8759
|
AxProgramWithSignature,
|
|
8570
8760
|
AxPromptTemplate,
|
|
8571
8761
|
AxRAG,
|
|
8572
8762
|
AxRateLimiterTokenUsage,
|
|
8573
|
-
AxRoute,
|
|
8574
|
-
AxRouter,
|
|
8575
8763
|
AxSignature,
|
|
8764
|
+
AxSimpleClassifier,
|
|
8765
|
+
AxSimpleClassifierClass,
|
|
8576
8766
|
AxSpanKindValues,
|
|
8577
8767
|
AxTestPrompt
|
|
8578
8768
|
};
|