@juspay/neurolink 9.41.0 → 9.42.1
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/CHANGELOG.md +8 -0
- package/README.md +7 -1
- package/dist/auth/anthropicOAuth.d.ts +18 -3
- package/dist/auth/anthropicOAuth.js +149 -4
- package/dist/auth/providers/firebase.js +5 -1
- package/dist/auth/providers/jwt.js +5 -1
- package/dist/auth/providers/workos.js +5 -1
- package/dist/auth/sessionManager.d.ts +1 -1
- package/dist/auth/sessionManager.js +58 -27
- package/dist/browser/neurolink.min.js +354 -334
- package/dist/cli/commands/mcp.d.ts +6 -0
- package/dist/cli/commands/mcp.js +188 -181
- package/dist/cli/commands/proxy.d.ts +2 -1
- package/dist/cli/commands/proxy.js +713 -431
- package/dist/cli/commands/task.js +3 -0
- package/dist/cli/factories/commandFactory.d.ts +2 -0
- package/dist/cli/factories/commandFactory.js +38 -0
- package/dist/cli/parser.js +4 -3
- package/dist/client/aiSdkAdapter.js +3 -0
- package/dist/client/streamingClient.js +30 -10
- package/dist/core/baseProvider.d.ts +6 -1
- package/dist/core/baseProvider.js +208 -230
- package/dist/core/factory.d.ts +3 -0
- package/dist/core/factory.js +138 -188
- package/dist/core/modules/GenerationHandler.js +3 -2
- package/dist/core/redisConversationMemoryManager.js +7 -3
- package/dist/evaluation/BatchEvaluator.js +4 -1
- package/dist/evaluation/hooks/observabilityHooks.js +5 -3
- package/dist/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
- package/dist/evaluation/pipeline/evaluationPipeline.js +24 -9
- package/dist/evaluation/pipeline/strategies/batchStrategy.js +6 -3
- package/dist/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
- package/dist/evaluation/scorers/scorerRegistry.d.ts +3 -0
- package/dist/evaluation/scorers/scorerRegistry.js +353 -282
- package/dist/lib/auth/anthropicOAuth.d.ts +18 -3
- package/dist/lib/auth/anthropicOAuth.js +149 -4
- package/dist/lib/auth/providers/firebase.js +5 -1
- package/dist/lib/auth/providers/jwt.js +5 -1
- package/dist/lib/auth/providers/workos.js +5 -1
- package/dist/lib/auth/sessionManager.d.ts +1 -1
- package/dist/lib/auth/sessionManager.js +58 -27
- package/dist/lib/client/aiSdkAdapter.js +3 -0
- package/dist/lib/client/streamingClient.js +30 -10
- package/dist/lib/core/baseProvider.d.ts +6 -1
- package/dist/lib/core/baseProvider.js +208 -230
- package/dist/lib/core/factory.d.ts +3 -0
- package/dist/lib/core/factory.js +138 -188
- package/dist/lib/core/modules/GenerationHandler.js +3 -2
- package/dist/lib/core/redisConversationMemoryManager.js +7 -3
- package/dist/lib/evaluation/BatchEvaluator.js +4 -1
- package/dist/lib/evaluation/hooks/observabilityHooks.js +5 -3
- package/dist/lib/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
- package/dist/lib/evaluation/pipeline/evaluationPipeline.js +24 -9
- package/dist/lib/evaluation/pipeline/strategies/batchStrategy.js +6 -3
- package/dist/lib/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
- package/dist/lib/evaluation/scorers/scorerRegistry.d.ts +3 -0
- package/dist/lib/evaluation/scorers/scorerRegistry.js +353 -282
- package/dist/lib/mcp/toolRegistry.d.ts +2 -0
- package/dist/lib/mcp/toolRegistry.js +32 -31
- package/dist/lib/neurolink.d.ts +41 -2
- package/dist/lib/neurolink.js +1616 -1681
- package/dist/lib/observability/otelBridge.d.ts +2 -2
- package/dist/lib/observability/otelBridge.js +12 -3
- package/dist/lib/providers/amazonBedrock.js +2 -4
- package/dist/lib/providers/anthropic.d.ts +9 -5
- package/dist/lib/providers/anthropic.js +19 -14
- package/dist/lib/providers/anthropicBaseProvider.d.ts +3 -3
- package/dist/lib/providers/anthropicBaseProvider.js +5 -4
- package/dist/lib/providers/azureOpenai.d.ts +1 -1
- package/dist/lib/providers/azureOpenai.js +5 -4
- package/dist/lib/providers/googleAiStudio.js +30 -6
- package/dist/lib/providers/googleVertex.d.ts +10 -0
- package/dist/lib/providers/googleVertex.js +437 -423
- package/dist/lib/providers/huggingFace.d.ts +3 -3
- package/dist/lib/providers/huggingFace.js +6 -8
- package/dist/lib/providers/litellm.d.ts +1 -0
- package/dist/lib/providers/litellm.js +76 -55
- package/dist/lib/providers/mistral.js +2 -1
- package/dist/lib/providers/ollama.js +93 -23
- package/dist/lib/providers/openAI.d.ts +2 -0
- package/dist/lib/providers/openAI.js +141 -141
- package/dist/lib/providers/openRouter.js +2 -1
- package/dist/lib/providers/openaiCompatible.d.ts +4 -4
- package/dist/lib/providers/openaiCompatible.js +4 -4
- package/dist/lib/proxy/claudeFormat.d.ts +3 -2
- package/dist/lib/proxy/claudeFormat.js +27 -14
- package/dist/lib/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
- package/dist/lib/proxy/cloaking/plugins/sessionIdentity.js +9 -33
- package/dist/lib/proxy/modelRouter.js +3 -0
- package/dist/lib/proxy/oauthFetch.d.ts +1 -1
- package/dist/lib/proxy/oauthFetch.js +289 -316
- package/dist/lib/proxy/proxyConfig.js +46 -24
- package/dist/lib/proxy/proxyEnv.d.ts +19 -0
- package/dist/lib/proxy/proxyEnv.js +73 -0
- package/dist/lib/proxy/proxyFetch.js +291 -217
- package/dist/lib/proxy/proxyTracer.d.ts +133 -0
- package/dist/lib/proxy/proxyTracer.js +645 -0
- package/dist/lib/proxy/rawStreamCapture.d.ts +10 -0
- package/dist/lib/proxy/rawStreamCapture.js +83 -0
- package/dist/lib/proxy/requestLogger.d.ts +32 -5
- package/dist/lib/proxy/requestLogger.js +503 -47
- package/dist/lib/proxy/sseInterceptor.d.ts +97 -0
- package/dist/lib/proxy/sseInterceptor.js +427 -0
- package/dist/lib/proxy/usageStats.d.ts +4 -3
- package/dist/lib/proxy/usageStats.js +25 -12
- package/dist/lib/rag/chunkers/MarkdownChunker.js +13 -5
- package/dist/lib/rag/chunking/markdownChunker.js +15 -6
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +17 -3
- package/dist/lib/server/routes/claudeProxyRoutes.js +3032 -1349
- package/dist/lib/services/server/ai/observability/instrumentation.d.ts +7 -1
- package/dist/lib/services/server/ai/observability/instrumentation.js +337 -161
- package/dist/lib/tasks/backends/bullmqBackend.d.ts +1 -0
- package/dist/lib/tasks/backends/bullmqBackend.js +35 -22
- package/dist/lib/tasks/store/redisTaskStore.d.ts +1 -0
- package/dist/lib/tasks/store/redisTaskStore.js +54 -39
- package/dist/lib/tasks/taskManager.d.ts +5 -0
- package/dist/lib/tasks/taskManager.js +158 -30
- package/dist/lib/telemetry/index.d.ts +2 -1
- package/dist/lib/telemetry/index.js +2 -1
- package/dist/lib/telemetry/telemetryService.d.ts +3 -0
- package/dist/lib/telemetry/telemetryService.js +69 -5
- package/dist/lib/types/cli.d.ts +10 -0
- package/dist/lib/types/proxyTypes.d.ts +160 -5
- package/dist/lib/types/streamTypes.d.ts +25 -3
- package/dist/lib/utils/messageBuilder.js +3 -2
- package/dist/lib/utils/providerHealth.d.ts +19 -0
- package/dist/lib/utils/providerHealth.js +279 -33
- package/dist/lib/utils/providerUtils.js +17 -22
- package/dist/lib/utils/toolChoice.d.ts +4 -0
- package/dist/lib/utils/toolChoice.js +7 -0
- package/dist/mcp/toolRegistry.d.ts +2 -0
- package/dist/mcp/toolRegistry.js +32 -31
- package/dist/neurolink.d.ts +41 -2
- package/dist/neurolink.js +1616 -1681
- package/dist/observability/otelBridge.d.ts +2 -2
- package/dist/observability/otelBridge.js +12 -3
- package/dist/providers/amazonBedrock.js +2 -4
- package/dist/providers/anthropic.d.ts +9 -5
- package/dist/providers/anthropic.js +19 -14
- package/dist/providers/anthropicBaseProvider.d.ts +3 -3
- package/dist/providers/anthropicBaseProvider.js +5 -4
- package/dist/providers/azureOpenai.d.ts +1 -1
- package/dist/providers/azureOpenai.js +5 -4
- package/dist/providers/googleAiStudio.js +30 -6
- package/dist/providers/googleVertex.d.ts +10 -0
- package/dist/providers/googleVertex.js +437 -423
- package/dist/providers/huggingFace.d.ts +3 -3
- package/dist/providers/huggingFace.js +6 -7
- package/dist/providers/litellm.d.ts +1 -0
- package/dist/providers/litellm.js +76 -55
- package/dist/providers/mistral.js +2 -1
- package/dist/providers/ollama.js +93 -23
- package/dist/providers/openAI.d.ts +2 -0
- package/dist/providers/openAI.js +141 -141
- package/dist/providers/openRouter.js +2 -1
- package/dist/providers/openaiCompatible.d.ts +4 -4
- package/dist/providers/openaiCompatible.js +4 -3
- package/dist/proxy/claudeFormat.d.ts +3 -2
- package/dist/proxy/claudeFormat.js +27 -14
- package/dist/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
- package/dist/proxy/cloaking/plugins/sessionIdentity.js +9 -33
- package/dist/proxy/modelRouter.js +3 -0
- package/dist/proxy/oauthFetch.d.ts +1 -1
- package/dist/proxy/oauthFetch.js +289 -316
- package/dist/proxy/proxyConfig.js +46 -24
- package/dist/proxy/proxyEnv.d.ts +19 -0
- package/dist/proxy/proxyEnv.js +72 -0
- package/dist/proxy/proxyFetch.js +291 -217
- package/dist/proxy/proxyTracer.d.ts +133 -0
- package/dist/proxy/proxyTracer.js +644 -0
- package/dist/proxy/rawStreamCapture.d.ts +10 -0
- package/dist/proxy/rawStreamCapture.js +82 -0
- package/dist/proxy/requestLogger.d.ts +32 -5
- package/dist/proxy/requestLogger.js +503 -47
- package/dist/proxy/sseInterceptor.d.ts +97 -0
- package/dist/proxy/sseInterceptor.js +426 -0
- package/dist/proxy/usageStats.d.ts +4 -3
- package/dist/proxy/usageStats.js +25 -12
- package/dist/rag/chunkers/MarkdownChunker.js +13 -5
- package/dist/rag/chunking/markdownChunker.js +15 -6
- package/dist/server/routes/claudeProxyRoutes.d.ts +17 -3
- package/dist/server/routes/claudeProxyRoutes.js +3032 -1349
- package/dist/services/server/ai/observability/instrumentation.d.ts +7 -1
- package/dist/services/server/ai/observability/instrumentation.js +337 -161
- package/dist/tasks/backends/bullmqBackend.d.ts +1 -0
- package/dist/tasks/backends/bullmqBackend.js +35 -22
- package/dist/tasks/store/redisTaskStore.d.ts +1 -0
- package/dist/tasks/store/redisTaskStore.js +54 -39
- package/dist/tasks/taskManager.d.ts +5 -0
- package/dist/tasks/taskManager.js +158 -30
- package/dist/telemetry/index.d.ts +2 -1
- package/dist/telemetry/index.js +2 -1
- package/dist/telemetry/telemetryService.d.ts +3 -0
- package/dist/telemetry/telemetryService.js +69 -5
- package/dist/types/cli.d.ts +10 -0
- package/dist/types/proxyTypes.d.ts +160 -5
- package/dist/types/streamTypes.d.ts +25 -3
- package/dist/utils/messageBuilder.js +3 -2
- package/dist/utils/providerHealth.d.ts +19 -0
- package/dist/utils/providerHealth.js +279 -33
- package/dist/utils/providerUtils.js +18 -22
- package/dist/utils/toolChoice.d.ts +4 -0
- package/dist/utils/toolChoice.js +6 -0
- package/docs/assets/dashboards/neurolink-proxy-observability-dashboard.json +6609 -0
- package/docs/changelog.md +252 -0
- package/package.json +19 -2
- package/scripts/observability/check-proxy-telemetry.mjs +235 -0
- package/scripts/observability/docker-compose.proxy-observability.yaml +55 -0
- package/scripts/observability/import-openobserve-dashboard.mjs +240 -0
- package/scripts/observability/manage-local-openobserve.sh +215 -0
- package/scripts/observability/otel-collector.proxy-observability.yaml +78 -0
- package/scripts/observability/proxy-observability.env.example +23 -0
package/dist/lib/core/factory.js
CHANGED
|
@@ -48,6 +48,141 @@ export class AIProviderFactory {
|
|
|
48
48
|
// This ensures the factory continues to work even if dynamic models fail
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
+
static resolveModelFromEnvironment(providerName, modelName, functionTag) {
|
|
52
|
+
if (modelName && modelName !== "default") {
|
|
53
|
+
logger.debug(`[${functionTag}] Skipping environment variable check - explicit model provided: ${modelName}`);
|
|
54
|
+
return modelName;
|
|
55
|
+
}
|
|
56
|
+
logger.debug(`[${functionTag}] Checking environment variables for provider: ${providerName}`);
|
|
57
|
+
const normalizedProvider = providerName.toLowerCase();
|
|
58
|
+
const envConfigs = [
|
|
59
|
+
{
|
|
60
|
+
match: ["bedrock"],
|
|
61
|
+
label: "Bedrock",
|
|
62
|
+
vars: ["BEDROCK_MODEL", "BEDROCK_MODEL_ID"],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
match: ["vertex"],
|
|
66
|
+
label: "Vertex",
|
|
67
|
+
vars: ["VERTEX_MODEL"],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
match: ["azure"],
|
|
71
|
+
label: "Azure",
|
|
72
|
+
vars: [
|
|
73
|
+
"AZURE_OPENAI_MODEL",
|
|
74
|
+
"AZURE_OPENAI_DEPLOYMENT",
|
|
75
|
+
"AZURE_OPENAI_DEPLOYMENT_ID",
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
match: ["openai", "gpt", "chatgpt", "openai-compat"],
|
|
80
|
+
label: "OpenAI",
|
|
81
|
+
vars: ["OPENAI_MODEL"],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
match: ["anthropic", "claude", "anthropic-claude"],
|
|
85
|
+
label: "Anthropic",
|
|
86
|
+
vars: ["ANTHROPIC_MODEL"],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
match: ["google", "gemini"],
|
|
90
|
+
label: "Google AI",
|
|
91
|
+
vars: ["GOOGLE_AI_MODEL"],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
match: ["mistral"],
|
|
95
|
+
label: "Mistral",
|
|
96
|
+
vars: ["MISTRAL_MODEL"],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
match: ["ollama"],
|
|
100
|
+
label: "Ollama",
|
|
101
|
+
vars: ["OLLAMA_MODEL"],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
match: ["litellm"],
|
|
105
|
+
label: "LiteLLM",
|
|
106
|
+
vars: ["LITELLM_MODEL"],
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
const envConfig = envConfigs.find((config) => config.match.some((match) => normalizedProvider.includes(match)));
|
|
110
|
+
if (!envConfig) {
|
|
111
|
+
logger.debug(`[${functionTag}] Provider ${providerName} - no environment variable check implemented`);
|
|
112
|
+
return modelName;
|
|
113
|
+
}
|
|
114
|
+
const matchedVar = envConfig.vars.find((name) => process.env[name]);
|
|
115
|
+
const envModel = matchedVar ? process.env[matchedVar] : undefined;
|
|
116
|
+
if (envModel) {
|
|
117
|
+
logger.debug(`[${functionTag}] Environment variable found for ${envConfig.label}`, {
|
|
118
|
+
envVariable: matchedVar,
|
|
119
|
+
resolvedModel: envModel,
|
|
120
|
+
});
|
|
121
|
+
return envModel;
|
|
122
|
+
}
|
|
123
|
+
logger.debug(`[${functionTag}] No ${envConfig.label} environment variables found (${envConfig.vars.join(", ")})`);
|
|
124
|
+
return modelName;
|
|
125
|
+
}
|
|
126
|
+
static async resolveDynamicModelName(providerName, modelName, resolvedModelName, functionTag) {
|
|
127
|
+
if ((resolvedModelName && resolvedModelName !== "default") ||
|
|
128
|
+
(modelName && modelName !== "default")) {
|
|
129
|
+
logger.debug(`[${functionTag}] Skipping dynamic model resolution`, {
|
|
130
|
+
resolvedModelName: resolvedModelName || "none",
|
|
131
|
+
reason: "Model already resolved from environment variables or explicit parameter",
|
|
132
|
+
});
|
|
133
|
+
return resolvedModelName;
|
|
134
|
+
}
|
|
135
|
+
logger.debug(`[${functionTag}] Attempting dynamic model resolution`, {
|
|
136
|
+
currentResolvedModel: resolvedModelName || "none",
|
|
137
|
+
reason: "No environment variable found and no explicit model provided",
|
|
138
|
+
});
|
|
139
|
+
try {
|
|
140
|
+
const normalizedProvider = this.normalizeProviderName(providerName);
|
|
141
|
+
if (dynamicModelProvider.needsRefresh()) {
|
|
142
|
+
logger.debug(`[${functionTag}] Dynamic model provider needs refresh - initializing`);
|
|
143
|
+
await this.initializeDynamicProviderWithTimeout();
|
|
144
|
+
}
|
|
145
|
+
const dynamicModel = dynamicModelProvider.resolveModel(normalizedProvider, modelName || undefined);
|
|
146
|
+
if (!dynamicModel) {
|
|
147
|
+
logger.debug(`[${functionTag}] Dynamic model resolution returned null`, {
|
|
148
|
+
provider: normalizedProvider,
|
|
149
|
+
requestedModel: modelName || "default",
|
|
150
|
+
});
|
|
151
|
+
return resolvedModelName;
|
|
152
|
+
}
|
|
153
|
+
logger.debug(`[${functionTag}] Resolved dynamic model`, {
|
|
154
|
+
provider: normalizedProvider,
|
|
155
|
+
requestedModel: modelName || "default",
|
|
156
|
+
resolvedModel: dynamicModel.id,
|
|
157
|
+
displayName: dynamicModel.displayName,
|
|
158
|
+
pricing: dynamicModel.pricing.input,
|
|
159
|
+
});
|
|
160
|
+
return dynamicModel.id;
|
|
161
|
+
}
|
|
162
|
+
catch (resolveError) {
|
|
163
|
+
logger.debug(`[${functionTag}] Dynamic model resolution failed, using static fallback`, {
|
|
164
|
+
error: resolveError instanceof Error
|
|
165
|
+
? resolveError.message
|
|
166
|
+
: String(resolveError),
|
|
167
|
+
});
|
|
168
|
+
return resolvedModelName;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
static async createResolvedProvider(providerName, resolvedModelName, sdk, region, functionTag) {
|
|
172
|
+
await withTimeout(ProviderRegistry.registerAllProviders(), 30_000, new Error("Provider registration timed out"));
|
|
173
|
+
const normalizedName = this.normalizeProviderName(providerName);
|
|
174
|
+
const finalModelName = resolvedModelName === "default" || resolvedModelName === null
|
|
175
|
+
? undefined
|
|
176
|
+
: resolvedModelName;
|
|
177
|
+
logger.debug(`[${functionTag}] Final provider configuration`, {
|
|
178
|
+
originalProviderName: providerName,
|
|
179
|
+
normalizedProviderName: normalizedName,
|
|
180
|
+
resolvedModelName: resolvedModelName || "not resolved",
|
|
181
|
+
finalModelName: finalModelName || "using provider default",
|
|
182
|
+
});
|
|
183
|
+
const provider = await withTimeout(ProviderFactory.createProvider(normalizedName, finalModelName, sdk, region), 30_000, new Error(`Provider creation timed out for ${normalizedName}`));
|
|
184
|
+
return { normalizedName, finalModelName, provider };
|
|
185
|
+
}
|
|
51
186
|
/**
|
|
52
187
|
* Create a provider instance for the specified provider type
|
|
53
188
|
* @param providerName - Name of the provider ('vertex', 'bedrock', 'openai')
|
|
@@ -89,194 +224,9 @@ export class AIProviderFactory {
|
|
|
89
224
|
// - Enhanced error handling and logging for debugging
|
|
90
225
|
//
|
|
91
226
|
// The dynamic model provider now provides reliable functionality without hanging
|
|
92
|
-
let resolvedModelName = modelName;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
logger.debug(`[${functionTag}] Checking environment variables for provider: ${providerName}`);
|
|
96
|
-
// Check for provider-specific environment variables first
|
|
97
|
-
if (providerName.toLowerCase().includes("bedrock")) {
|
|
98
|
-
const envModel = process.env.BEDROCK_MODEL || process.env.BEDROCK_MODEL_ID;
|
|
99
|
-
if (envModel) {
|
|
100
|
-
resolvedModelName = envModel;
|
|
101
|
-
logger.debug(`[${functionTag}] Environment variable found for Bedrock`, {
|
|
102
|
-
envVariable: process.env.BEDROCK_MODEL
|
|
103
|
-
? "BEDROCK_MODEL"
|
|
104
|
-
: "BEDROCK_MODEL_ID",
|
|
105
|
-
resolvedModel: envModel,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
logger.debug(`[${functionTag}] No Bedrock environment variables found (BEDROCK_MODEL, BEDROCK_MODEL_ID)`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
else if (providerName.toLowerCase().includes("vertex")) {
|
|
113
|
-
const envModel = process.env.VERTEX_MODEL;
|
|
114
|
-
if (envModel) {
|
|
115
|
-
resolvedModelName = envModel;
|
|
116
|
-
logger.debug(`[${functionTag}] Environment variable found for Vertex`, {
|
|
117
|
-
envVariable: "VERTEX_MODEL",
|
|
118
|
-
resolvedModel: envModel,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
logger.debug(`[${functionTag}] No Vertex environment variables found (VERTEX_MODEL)`);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else if (providerName.toLowerCase().includes("azure")) {
|
|
126
|
-
const envModel = process.env.AZURE_OPENAI_MODEL ||
|
|
127
|
-
process.env.AZURE_OPENAI_DEPLOYMENT ||
|
|
128
|
-
process.env.AZURE_OPENAI_DEPLOYMENT_ID;
|
|
129
|
-
if (envModel) {
|
|
130
|
-
resolvedModelName = envModel;
|
|
131
|
-
logger.debug(`[${functionTag}] Environment variable found for Azure`, {
|
|
132
|
-
envVariable: process.env.AZURE_OPENAI_MODEL
|
|
133
|
-
? "AZURE_OPENAI_MODEL"
|
|
134
|
-
: process.env.AZURE_OPENAI_DEPLOYMENT
|
|
135
|
-
? "AZURE_OPENAI_DEPLOYMENT"
|
|
136
|
-
: "AZURE_OPENAI_DEPLOYMENT_ID",
|
|
137
|
-
resolvedModel: envModel,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
logger.debug(`[${functionTag}] No Azure environment variables found (AZURE_OPENAI_MODEL, AZURE_OPENAI_DEPLOYMENT, AZURE_OPENAI_DEPLOYMENT_ID)`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
else if (providerName.toLowerCase().includes("openai")) {
|
|
145
|
-
const envModel = process.env.OPENAI_MODEL;
|
|
146
|
-
if (envModel) {
|
|
147
|
-
resolvedModelName = envModel;
|
|
148
|
-
logger.debug(`[${functionTag}] Environment variable found for OpenAI`, {
|
|
149
|
-
envVariable: "OPENAI_MODEL",
|
|
150
|
-
resolvedModel: envModel,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
logger.debug(`[${functionTag}] No OpenAI environment variables found (OPENAI_MODEL)`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
else if (providerName.toLowerCase().includes("anthropic")) {
|
|
158
|
-
const envModel = process.env.ANTHROPIC_MODEL;
|
|
159
|
-
if (envModel) {
|
|
160
|
-
resolvedModelName = envModel;
|
|
161
|
-
logger.debug(`[${functionTag}] Environment variable found for Anthropic`, {
|
|
162
|
-
envVariable: "ANTHROPIC_MODEL",
|
|
163
|
-
resolvedModel: envModel,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
logger.debug(`[${functionTag}] No Anthropic environment variables found (ANTHROPIC_MODEL)`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
else if (providerName.toLowerCase().includes("google") ||
|
|
171
|
-
providerName.toLowerCase().includes("gemini")) {
|
|
172
|
-
const envModel = process.env.GOOGLE_AI_MODEL;
|
|
173
|
-
if (envModel) {
|
|
174
|
-
resolvedModelName = envModel;
|
|
175
|
-
logger.debug(`[${functionTag}] Environment variable found for Google AI`, {
|
|
176
|
-
envVariable: "GOOGLE_AI_MODEL",
|
|
177
|
-
resolvedModel: envModel,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
logger.debug(`[${functionTag}] No Google AI environment variables found (GOOGLE_AI_MODEL)`);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
else if (providerName.toLowerCase().includes("mistral")) {
|
|
185
|
-
const envModel = process.env.MISTRAL_MODEL;
|
|
186
|
-
if (envModel) {
|
|
187
|
-
resolvedModelName = envModel;
|
|
188
|
-
logger.debug(`[${functionTag}] Environment variable found for Mistral`, {
|
|
189
|
-
envVariable: "MISTRAL_MODEL",
|
|
190
|
-
resolvedModel: envModel,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
logger.debug(`[${functionTag}] No Mistral environment variables found (MISTRAL_MODEL)`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
else if (providerName.toLowerCase().includes("ollama")) {
|
|
198
|
-
const envModel = process.env.OLLAMA_MODEL;
|
|
199
|
-
if (envModel) {
|
|
200
|
-
resolvedModelName = envModel;
|
|
201
|
-
logger.debug(`[${functionTag}] Environment variable found for Ollama`, {
|
|
202
|
-
envVariable: "OLLAMA_MODEL",
|
|
203
|
-
resolvedModel: envModel,
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
logger.debug(`[${functionTag}] No Ollama environment variables found (OLLAMA_MODEL)`);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
logger.debug(`[${functionTag}] Provider ${providerName} - no environment variable check implemented`);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
logger.debug(`[${functionTag}] Skipping environment variable check - explicit model provided: ${modelName}`);
|
|
216
|
-
}
|
|
217
|
-
// PRIORITY 2: Enable dynamic model resolution only if no env var found
|
|
218
|
-
if ((!resolvedModelName || resolvedModelName === "default") &&
|
|
219
|
-
(!modelName || modelName === "default")) {
|
|
220
|
-
logger.debug(`[${functionTag}] Attempting dynamic model resolution`, {
|
|
221
|
-
currentResolvedModel: resolvedModelName || "none",
|
|
222
|
-
reason: "No environment variable found and no explicit model provided",
|
|
223
|
-
});
|
|
224
|
-
try {
|
|
225
|
-
const normalizedProvider = this.normalizeProviderName(providerName);
|
|
226
|
-
// Initialize with timeout protection - won't hang anymore
|
|
227
|
-
if (dynamicModelProvider.needsRefresh()) {
|
|
228
|
-
logger.debug(`[${functionTag}] Dynamic model provider needs refresh - initializing`);
|
|
229
|
-
await this.initializeDynamicProviderWithTimeout();
|
|
230
|
-
}
|
|
231
|
-
const dynamicModel = dynamicModelProvider.resolveModel(normalizedProvider, modelName || undefined);
|
|
232
|
-
if (dynamicModel) {
|
|
233
|
-
resolvedModelName = dynamicModel.id;
|
|
234
|
-
logger.debug(`[${functionTag}] Resolved dynamic model`, {
|
|
235
|
-
provider: normalizedProvider,
|
|
236
|
-
requestedModel: modelName || "default",
|
|
237
|
-
resolvedModel: resolvedModelName,
|
|
238
|
-
displayName: dynamicModel.displayName,
|
|
239
|
-
pricing: dynamicModel.pricing.input,
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
logger.debug(`[${functionTag}] Dynamic model resolution returned null`, {
|
|
244
|
-
provider: normalizedProvider,
|
|
245
|
-
requestedModel: modelName || "default",
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
catch (resolveError) {
|
|
250
|
-
logger.debug(`[${functionTag}] Dynamic model resolution failed, using static fallback`, {
|
|
251
|
-
error: resolveError instanceof Error
|
|
252
|
-
? resolveError.message
|
|
253
|
-
: String(resolveError),
|
|
254
|
-
});
|
|
255
|
-
// Continue with static model name - no functionality loss
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
259
|
-
logger.debug(`[${functionTag}] Skipping dynamic model resolution`, {
|
|
260
|
-
resolvedModelName: resolvedModelName || "none",
|
|
261
|
-
reason: "Model already resolved from environment variables or explicit parameter",
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
// CRITICAL FIX: Initialize providers before using them
|
|
265
|
-
await withTimeout(ProviderRegistry.registerAllProviders(), 30_000, new Error("Provider registration timed out"));
|
|
266
|
-
// PURE FACTORY PATTERN: No switch statements - use ProviderFactory exclusively
|
|
267
|
-
const normalizedName = this.normalizeProviderName(providerName);
|
|
268
|
-
const finalModelName = resolvedModelName === "default" || resolvedModelName === null
|
|
269
|
-
? undefined
|
|
270
|
-
: resolvedModelName;
|
|
271
|
-
logger.debug(`[${functionTag}] Final provider configuration`, {
|
|
272
|
-
originalProviderName: providerName,
|
|
273
|
-
normalizedProviderName: normalizedName,
|
|
274
|
-
originalModelName: modelName || "not provided",
|
|
275
|
-
resolvedModelName: resolvedModelName || "not resolved",
|
|
276
|
-
finalModelName: finalModelName || "using provider default",
|
|
277
|
-
});
|
|
278
|
-
// Create provider with enhanced SDK and region support
|
|
279
|
-
const provider = await withTimeout(ProviderFactory.createProvider(normalizedName, finalModelName, sdk, region), 30_000, new Error(`Provider creation timed out for ${normalizedName}`));
|
|
227
|
+
let resolvedModelName = this.resolveModelFromEnvironment(providerName, modelName, functionTag);
|
|
228
|
+
resolvedModelName = await this.resolveDynamicModelName(providerName, modelName, resolvedModelName, functionTag);
|
|
229
|
+
const { normalizedName, finalModelName, provider } = await this.createResolvedProvider(providerName, resolvedModelName, sdk, region, functionTag);
|
|
280
230
|
// Summary logging in format expected by debugging tools
|
|
281
231
|
logger.debug(`[AIProviderFactory] Provider creation completed { providerName: '${normalizedName}', modelName: '${finalModelName}' }`);
|
|
282
232
|
logger.debug(`[AIProviderFactory] Resolved model: ${finalModelName}`);
|
|
@@ -95,6 +95,7 @@ export class GenerationHandler {
|
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
+
const prepareStep = options.prepareStep;
|
|
98
99
|
return await generateText({
|
|
99
100
|
model,
|
|
100
101
|
messages,
|
|
@@ -103,8 +104,8 @@ export class GenerationHandler {
|
|
|
103
104
|
stopWhen: stepCountIs(options.maxSteps ?? DEFAULT_MAX_STEPS),
|
|
104
105
|
...(shouldUseTools &&
|
|
105
106
|
options.toolChoice && { toolChoice: options.toolChoice }),
|
|
106
|
-
...(
|
|
107
|
-
experimental_prepareStep: ((stepOptions) =>
|
|
107
|
+
...(prepareStep && {
|
|
108
|
+
experimental_prepareStep: ((stepOptions) => prepareStep({
|
|
108
109
|
...stepOptions,
|
|
109
110
|
maxSteps: options.maxSteps ?? DEFAULT_MAX_STEPS,
|
|
110
111
|
})),
|
|
@@ -16,6 +16,7 @@ import { runWithCurrentLangfuseContext } from "../services/server/ai/observabili
|
|
|
16
16
|
import { logger } from "../utils/logger.js";
|
|
17
17
|
import { createRedisClient, deserializeConversation, getNormalizedConfig, getPooledRedisClient, getSessionKey, getUserSessionsKey, releasePooledRedisClient, scanKeys, serializeConversation, } from "../utils/redis.js";
|
|
18
18
|
const redisTracer = tracers.redis;
|
|
19
|
+
const REDIS_TIMEOUT_MS = 5000;
|
|
19
20
|
/**
|
|
20
21
|
* Redis-based implementation of the ConversationMemoryManager
|
|
21
22
|
* Uses the same interface but stores data in Redis
|
|
@@ -130,13 +131,14 @@ export class RedisConversationMemoryManager {
|
|
|
130
131
|
if (!this.redisClient) {
|
|
131
132
|
return undefined;
|
|
132
133
|
}
|
|
134
|
+
const redisClient = this.redisClient;
|
|
133
135
|
return redisTracer.startActiveSpan("neurolink.memory.getSession", { kind: SpanKind.CLIENT, attributes: { "session.id": sessionId } }, async (span) => {
|
|
134
136
|
if (userId) {
|
|
135
137
|
span.setAttribute("user.id", userId);
|
|
136
138
|
}
|
|
137
139
|
try {
|
|
138
140
|
const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
|
|
139
|
-
const conversationData = await
|
|
141
|
+
const conversationData = await withTimeout(redisClient.get(redisKey), REDIS_TIMEOUT_MS);
|
|
140
142
|
const conversation = deserializeConversation(conversationData || null);
|
|
141
143
|
if (!conversation) {
|
|
142
144
|
span.setAttribute("session.found", false);
|
|
@@ -630,6 +632,7 @@ export class RedisConversationMemoryManager {
|
|
|
630
632
|
logger.warn("[RedisConversationMemoryManager] Redis client not available in buildContextMessages");
|
|
631
633
|
return [];
|
|
632
634
|
}
|
|
635
|
+
const redisClient = this.redisClient;
|
|
633
636
|
// NLK-GAP-012: Add span for buildContext CRUD operation
|
|
634
637
|
return redisTracer.startActiveSpan("neurolink.memory.buildContext", {
|
|
635
638
|
kind: SpanKind.CLIENT,
|
|
@@ -645,7 +648,7 @@ export class RedisConversationMemoryManager {
|
|
|
645
648
|
method: "buildContextMessages",
|
|
646
649
|
});
|
|
647
650
|
const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
|
|
648
|
-
const conversationData = await
|
|
651
|
+
const conversationData = await withTimeout(redisClient.get(redisKey), REDIS_TIMEOUT_MS);
|
|
649
652
|
const conversation = deserializeConversation(conversationData || null);
|
|
650
653
|
if (!conversation) {
|
|
651
654
|
span.setAttribute("session.found", false);
|
|
@@ -1080,6 +1083,7 @@ User message: "${userMessage}"`;
|
|
|
1080
1083
|
if (!this.redisClient) {
|
|
1081
1084
|
return false;
|
|
1082
1085
|
}
|
|
1086
|
+
const redisClient = this.redisClient;
|
|
1083
1087
|
// NLK-GAP-012: Add span for clearSession CRUD operation
|
|
1084
1088
|
return redisTracer.startActiveSpan("neurolink.memory.clear", {
|
|
1085
1089
|
kind: SpanKind.CLIENT,
|
|
@@ -1090,7 +1094,7 @@ User message: "${userMessage}"`;
|
|
|
1090
1094
|
}, async (span) => {
|
|
1091
1095
|
try {
|
|
1092
1096
|
const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
|
|
1093
|
-
const result = await
|
|
1097
|
+
const result = await withTimeout(redisClient.del(redisKey), REDIS_TIMEOUT_MS);
|
|
1094
1098
|
if (Number(result) > 0) {
|
|
1095
1099
|
// Remove session from user's session set
|
|
1096
1100
|
if (userId) {
|
|
@@ -6,6 +6,9 @@ import { Evaluator } from "./index.js";
|
|
|
6
6
|
import { createBatchEvaluationError, isRetryableEvaluationError, } from "./errors/EvaluationError.js";
|
|
7
7
|
import { logger } from "../utils/logger.js";
|
|
8
8
|
import { NeuroLinkFeatureError } from "../core/infrastructure/index.js";
|
|
9
|
+
function hasEvaluationData(result) {
|
|
10
|
+
return result.success && result.data !== undefined;
|
|
11
|
+
}
|
|
9
12
|
/**
|
|
10
13
|
* BatchEvaluator - Performs evaluation on multiple items in parallel.
|
|
11
14
|
* Supports configurable concurrency, retry logic, and progress tracking.
|
|
@@ -201,7 +204,7 @@ export class BatchEvaluator {
|
|
|
201
204
|
}
|
|
202
205
|
}
|
|
203
206
|
// Calculate summary statistics
|
|
204
|
-
const successfulResults = results.filter(
|
|
207
|
+
const successfulResults = results.filter(hasEvaluationData);
|
|
205
208
|
const scores = successfulResults.map((r) => r.data.overall);
|
|
206
209
|
const passingScores = successfulResults.filter((r) => r.data.overall >=
|
|
207
210
|
(autoEvalConfig.threshold || this.config.threshold || 7));
|
|
@@ -41,10 +41,12 @@ export class ObservabilityHooks {
|
|
|
41
41
|
* Register an event handler
|
|
42
42
|
*/
|
|
43
43
|
on(event, handler) {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
let handlers = this._handlers.get(event);
|
|
45
|
+
if (!handlers) {
|
|
46
|
+
handlers = new Set();
|
|
47
|
+
this._handlers.set(event, handlers);
|
|
46
48
|
}
|
|
47
|
-
|
|
49
|
+
handlers.add(handler);
|
|
48
50
|
// Return unsubscribe function
|
|
49
51
|
return () => {
|
|
50
52
|
this._handlers.get(event)?.delete(handler);
|
|
@@ -12,9 +12,9 @@ export type PipelineExecutionOptions = {
|
|
|
12
12
|
correlationId?: string;
|
|
13
13
|
/** Custom timeout override */
|
|
14
14
|
timeout?: number;
|
|
15
|
-
/** Skip specific scorers */
|
|
15
|
+
/** Skip specific scorers. Mutually exclusive with onlyScorers. */
|
|
16
16
|
skipScorers?: string[];
|
|
17
|
-
/** Only run specific scorers */
|
|
17
|
+
/** Only run specific scorers. Mutually exclusive with skipScorers. */
|
|
18
18
|
onlyScorers?: string[];
|
|
19
19
|
/** Additional metadata to attach */
|
|
20
20
|
metadata?: JsonObject;
|
|
@@ -59,6 +59,7 @@ export declare class EvaluationPipeline {
|
|
|
59
59
|
* Execute the pipeline on input
|
|
60
60
|
*/
|
|
61
61
|
execute(input: ScorerInput, options?: PipelineExecutionOptions): Promise<PipelineResult>;
|
|
62
|
+
private _validateExecutionOptions;
|
|
62
63
|
/**
|
|
63
64
|
* Get scorers to run based on options
|
|
64
65
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Multi-scorer orchestration with configurable execution
|
|
4
4
|
*/
|
|
5
5
|
import { logger } from "../../utils/logger.js";
|
|
6
|
-
import { withTimeout } from "../../utils/errorHandling.js";
|
|
6
|
+
import { ErrorFactory, withTimeout } from "../../utils/errorHandling.js";
|
|
7
7
|
import { DEFAULT_SCORE_SCALE } from "../scorers/baseScorer.js";
|
|
8
8
|
import { ScorerRegistry } from "../scorers/scorerRegistry.js";
|
|
9
9
|
/**
|
|
@@ -91,6 +91,7 @@ export class EvaluationPipeline {
|
|
|
91
91
|
if (!this._initialized) {
|
|
92
92
|
await this.initialize();
|
|
93
93
|
}
|
|
94
|
+
this._validateExecutionOptions(options);
|
|
94
95
|
const startTime = Date.now();
|
|
95
96
|
const correlationId = options?.correlationId ?? `pipeline-${Date.now()}`;
|
|
96
97
|
logger.debug(`Executing pipeline: ${this._config.name ?? "unnamed"}`, {
|
|
@@ -173,16 +174,28 @@ export class EvaluationPipeline {
|
|
|
173
174
|
skippedScorers,
|
|
174
175
|
};
|
|
175
176
|
}
|
|
177
|
+
_validateExecutionOptions(options) {
|
|
178
|
+
const hasOnlyScorers = !!options?.onlyScorers && options.onlyScorers.length > 0;
|
|
179
|
+
const hasSkipScorers = !!options?.skipScorers && options.skipScorers.length > 0;
|
|
180
|
+
if (hasOnlyScorers && hasSkipScorers) {
|
|
181
|
+
throw ErrorFactory.invalidConfiguration("evaluation pipeline execution options", "Cannot specify both 'onlyScorers' and 'skipScorers' options", {
|
|
182
|
+
onlyScorers: options?.onlyScorers,
|
|
183
|
+
skipScorers: options?.skipScorers,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
176
187
|
/**
|
|
177
188
|
* Get scorers to run based on options
|
|
178
189
|
*/
|
|
179
190
|
_getScorersToRun(options) {
|
|
180
191
|
const allScorers = Array.from(this._scorers.entries());
|
|
181
|
-
|
|
182
|
-
|
|
192
|
+
const onlyScorers = options?.onlyScorers;
|
|
193
|
+
const skipScorers = options?.skipScorers;
|
|
194
|
+
if (onlyScorers && onlyScorers.length > 0) {
|
|
195
|
+
return allScorers.filter(([id]) => onlyScorers.includes(id));
|
|
183
196
|
}
|
|
184
|
-
if (
|
|
185
|
-
return allScorers.filter(([id]) => !
|
|
197
|
+
if (skipScorers && skipScorers.length > 0) {
|
|
198
|
+
return allScorers.filter(([id]) => !skipScorers.includes(id));
|
|
186
199
|
}
|
|
187
200
|
return allScorers;
|
|
188
201
|
}
|
|
@@ -191,11 +204,13 @@ export class EvaluationPipeline {
|
|
|
191
204
|
*/
|
|
192
205
|
_getSkippedScorers(options) {
|
|
193
206
|
const allIds = Array.from(this._scorers.keys());
|
|
194
|
-
|
|
195
|
-
|
|
207
|
+
const onlyScorers = options?.onlyScorers;
|
|
208
|
+
const skipScorers = options?.skipScorers;
|
|
209
|
+
if (onlyScorers && onlyScorers.length > 0) {
|
|
210
|
+
return allIds.filter((id) => !onlyScorers.includes(id));
|
|
196
211
|
}
|
|
197
|
-
if (
|
|
198
|
-
return
|
|
212
|
+
if (skipScorers && skipScorers.length > 0) {
|
|
213
|
+
return skipScorers.filter((id) => allIds.includes(id));
|
|
199
214
|
}
|
|
200
215
|
return [];
|
|
201
216
|
}
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* @file Batch Strategy
|
|
3
3
|
* Batch processing for evaluation pipelines
|
|
4
4
|
*/
|
|
5
|
+
function hasPipelineResult(result) {
|
|
6
|
+
return !result.error && result.result !== undefined;
|
|
7
|
+
}
|
|
5
8
|
/**
|
|
6
9
|
* Default batch configuration
|
|
7
10
|
*/
|
|
@@ -66,7 +69,7 @@ export class BatchStrategy {
|
|
|
66
69
|
}
|
|
67
70
|
// Calculate summary
|
|
68
71
|
const totalDuration = Date.now() - startTime;
|
|
69
|
-
const successfulResults = results.filter(
|
|
72
|
+
const successfulResults = results.filter(hasPipelineResult);
|
|
70
73
|
const scores = successfulResults.map((r) => r.result.overallScore);
|
|
71
74
|
const passed = successfulResults.filter((r) => r.result.passed);
|
|
72
75
|
return {
|
|
@@ -192,7 +195,7 @@ export async function* streamBatchEvaluation(pipeline, inputs, config) {
|
|
|
192
195
|
durations.push(result.duration);
|
|
193
196
|
// If continueOnError is false and this result has an error, abort and return summary
|
|
194
197
|
if (result.error && batchConfig.continueOnError === false) {
|
|
195
|
-
const successfulResults = results.filter(
|
|
198
|
+
const successfulResults = results.filter(hasPipelineResult);
|
|
196
199
|
const earlyScores = successfulResults.map((r) => r.result.overallScore);
|
|
197
200
|
const earlyPassed = successfulResults.filter((r) => r.result.passed);
|
|
198
201
|
return {
|
|
@@ -219,7 +222,7 @@ export async function* streamBatchEvaluation(pipeline, inputs, config) {
|
|
|
219
222
|
}
|
|
220
223
|
}
|
|
221
224
|
// Return summary
|
|
222
|
-
const successfulResults = results.filter(
|
|
225
|
+
const successfulResults = results.filter(hasPipelineResult);
|
|
223
226
|
const scores = successfulResults.map((r) => r.result.overallScore);
|
|
224
227
|
const passed = successfulResults.filter((r) => r.result.passed);
|
|
225
228
|
return {
|
|
@@ -17,6 +17,12 @@ export const DEFAULT_SAMPLING_CONFIG = {
|
|
|
17
17
|
maxRate: 1.0,
|
|
18
18
|
},
|
|
19
19
|
};
|
|
20
|
+
const DEFAULT_ADAPTIVE_CONFIG = {
|
|
21
|
+
enabled: false,
|
|
22
|
+
qualityThreshold: 0.7,
|
|
23
|
+
minRate: 0.1,
|
|
24
|
+
maxRate: 1.0,
|
|
25
|
+
};
|
|
20
26
|
/**
|
|
21
27
|
* Sampling strategy for evaluation
|
|
22
28
|
*/
|
|
@@ -27,9 +33,10 @@ export class SamplingStrategy {
|
|
|
27
33
|
_maxRecentScores = 100;
|
|
28
34
|
constructor(config = {}) {
|
|
29
35
|
const clamp01 = (v) => Math.max(0, Math.min(1, v));
|
|
36
|
+
const defaultAdaptive = DEFAULT_SAMPLING_CONFIG.adaptive ?? DEFAULT_ADAPTIVE_CONFIG;
|
|
30
37
|
const rawRate = config.rate ?? DEFAULT_SAMPLING_CONFIG.rate;
|
|
31
|
-
const rawMinRate = config.adaptive?.minRate ??
|
|
32
|
-
const rawMaxRate = config.adaptive?.maxRate ??
|
|
38
|
+
const rawMinRate = config.adaptive?.minRate ?? defaultAdaptive.minRate;
|
|
39
|
+
const rawMaxRate = config.adaptive?.maxRate ?? defaultAdaptive.maxRate;
|
|
33
40
|
const minRate = clamp01(Math.min(rawMinRate, rawMaxRate));
|
|
34
41
|
const maxRate = clamp01(Math.max(rawMinRate, rawMaxRate));
|
|
35
42
|
this._config = {
|
|
@@ -41,9 +48,8 @@ export class SamplingStrategy {
|
|
|
41
48
|
...(config.alwaysEvaluate ?? {}),
|
|
42
49
|
},
|
|
43
50
|
adaptive: {
|
|
44
|
-
enabled: config.adaptive?.enabled ??
|
|
45
|
-
qualityThreshold: clamp01(config.adaptive?.qualityThreshold ??
|
|
46
|
-
DEFAULT_SAMPLING_CONFIG.adaptive.qualityThreshold),
|
|
51
|
+
enabled: config.adaptive?.enabled ?? defaultAdaptive.enabled,
|
|
52
|
+
qualityThreshold: clamp01(config.adaptive?.qualityThreshold ?? defaultAdaptive.qualityThreshold),
|
|
47
53
|
minRate,
|
|
48
54
|
maxRate,
|
|
49
55
|
},
|
|
@@ -156,9 +162,12 @@ export class SamplingStrategy {
|
|
|
156
162
|
*/
|
|
157
163
|
configure(config) {
|
|
158
164
|
const clamp01 = (v) => Math.max(0, Math.min(1, v));
|
|
165
|
+
const currentAdaptive = this._config.adaptive ??
|
|
166
|
+
DEFAULT_SAMPLING_CONFIG.adaptive ??
|
|
167
|
+
DEFAULT_ADAPTIVE_CONFIG;
|
|
159
168
|
const rawRate = config.rate ?? this._config.rate;
|
|
160
|
-
const rawMinRate = config.adaptive?.minRate ??
|
|
161
|
-
const rawMaxRate = config.adaptive?.maxRate ??
|
|
169
|
+
const rawMinRate = config.adaptive?.minRate ?? currentAdaptive.minRate;
|
|
170
|
+
const rawMaxRate = config.adaptive?.maxRate ?? currentAdaptive.maxRate;
|
|
162
171
|
const minRate = clamp01(Math.min(rawMinRate, rawMaxRate));
|
|
163
172
|
const maxRate = clamp01(Math.max(rawMinRate, rawMaxRate));
|
|
164
173
|
this._config = {
|
|
@@ -170,9 +179,8 @@ export class SamplingStrategy {
|
|
|
170
179
|
...(config.alwaysEvaluate ?? {}),
|
|
171
180
|
},
|
|
172
181
|
adaptive: {
|
|
173
|
-
enabled: config.adaptive?.enabled ??
|
|
174
|
-
qualityThreshold: clamp01(config.adaptive?.qualityThreshold ??
|
|
175
|
-
this._config.adaptive.qualityThreshold),
|
|
182
|
+
enabled: config.adaptive?.enabled ?? currentAdaptive.enabled,
|
|
183
|
+
qualityThreshold: clamp01(config.adaptive?.qualityThreshold ?? currentAdaptive.qualityThreshold),
|
|
176
184
|
minRate,
|
|
177
185
|
maxRate,
|
|
178
186
|
},
|
|
@@ -19,6 +19,9 @@ export declare class ScorerRegistry {
|
|
|
19
19
|
* Register a scorer using a simple configuration
|
|
20
20
|
*/
|
|
21
21
|
static registerScorer(metadata: ScorerMetadata, factory: ScorerFactory, aliases?: string[]): void;
|
|
22
|
+
private static registerScorerDefinitions;
|
|
23
|
+
private static registerBuiltInLLMScorers;
|
|
24
|
+
private static registerBuiltInRuleScorers;
|
|
22
25
|
/**
|
|
23
26
|
* Register built-in scorers using dynamic imports
|
|
24
27
|
*/
|