@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 +297 -108
- package/index.cjs.map +1 -1
- package/index.d.cts +125 -38
- package/index.d.ts +125 -38
- package/index.js +294 -106
- package/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
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
|
-
|
|
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
|
-
|
|
950
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
2682
|
+
constructor(config, isVertex, endpointId, apiKey, options) {
|
|
2702
2683
|
this.config = config;
|
|
2703
2684
|
this.isVertex = isVertex;
|
|
2704
|
-
this.
|
|
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.
|
|
2711
|
+
if (this.endpointId) {
|
|
2731
2712
|
apiConfig = {
|
|
2732
|
-
name: stream ? `/${this.
|
|
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.
|
|
2872
|
+
if (this.endpointId) {
|
|
2892
2873
|
apiConfig = {
|
|
2893
|
-
name: `/${this.
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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: "
|
|
4007
|
-
description:
|
|
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
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
8333
|
-
for (const
|
|
8334
|
-
const ret = await this.ai.embed({ texts:
|
|
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:
|
|
8337
|
-
table: "
|
|
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: "
|
|
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
|
|
8361
|
-
if (!
|
|
8394
|
+
const matchedClass = m.at(0);
|
|
8395
|
+
if (!matchedClass) {
|
|
8362
8396
|
return "";
|
|
8363
8397
|
}
|
|
8364
|
-
return
|
|
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
|
});
|