@juspay/neurolink 7.25.0 → 7.26.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/dist/cli/factories/commandFactory.d.ts +8 -0
- package/dist/cli/factories/commandFactory.js +14 -0
- package/dist/cli/factories/ollamaCommandFactory.d.ts +38 -0
- package/dist/cli/factories/ollamaCommandFactory.js +375 -0
- package/dist/cli/factories/sagemakerCommandFactory.d.ts +62 -0
- package/dist/cli/factories/sagemakerCommandFactory.js +783 -0
- package/dist/cli/index.js +5 -7
- package/dist/core/baseProvider.js +42 -0
- package/dist/core/evaluationProviders.d.ts +26 -0
- package/dist/core/evaluationProviders.js +160 -0
- package/dist/lib/core/baseProvider.js +42 -0
- package/dist/lib/core/evaluationProviders.d.ts +26 -0
- package/dist/lib/core/evaluationProviders.js +160 -0
- package/package.json +1 -1
- package/dist/cli/commands/ollama.d.ts +0 -3
- package/dist/cli/commands/ollama.js +0 -339
- package/dist/cli/commands/sagemaker.d.ts +0 -11
- package/dist/cli/commands/sagemaker.js +0 -779
package/dist/cli/index.js
CHANGED
|
@@ -11,8 +11,6 @@ import chalk from "chalk";
|
|
|
11
11
|
import _fs from "fs";
|
|
12
12
|
import path from "path";
|
|
13
13
|
import { fileURLToPath } from "url";
|
|
14
|
-
import { addOllamaCommands } from "./commands/ollama.js";
|
|
15
|
-
import { addSageMakerCommands } from "./commands/sagemaker.js";
|
|
16
14
|
import { CLICommandFactory } from "./factories/commandFactory.js";
|
|
17
15
|
import { AuthenticationError, AuthorizationError, NetworkError, RateLimitError, } from "../lib/types/errors.js";
|
|
18
16
|
import { logger } from "../lib/utils/logger.js";
|
|
@@ -178,11 +176,11 @@ const cli = yargs(args)
|
|
|
178
176
|
// Validate Command (alias for config validate)
|
|
179
177
|
.command(CLICommandFactory.createValidateCommand())
|
|
180
178
|
// Completion Command - Using CLICommandFactory
|
|
181
|
-
.command(CLICommandFactory.createCompletionCommand())
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
//
|
|
185
|
-
|
|
179
|
+
.command(CLICommandFactory.createCompletionCommand())
|
|
180
|
+
// Ollama Command Group - Using CLICommandFactory
|
|
181
|
+
.command(CLICommandFactory.createOllamaCommands())
|
|
182
|
+
// SageMaker Command Group - Using CLICommandFactory
|
|
183
|
+
.command(CLICommandFactory.createSageMakerCommands());
|
|
186
184
|
// Execute CLI
|
|
187
185
|
(async () => {
|
|
188
186
|
try {
|
|
@@ -9,6 +9,8 @@ import { shouldDisableBuiltinTools } from "../utils/toolUtils.js";
|
|
|
9
9
|
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
10
10
|
import { getKeysAsString, getKeyCount } from "../utils/transformationUtils.js";
|
|
11
11
|
import { validateStreamOptions as validateStreamOpts, validateTextGenerationOptions, ValidationError, createValidationSummary, } from "../utils/parameterValidation.js";
|
|
12
|
+
import { recordProviderPerformanceFromMetrics, getPerformanceOptimizedProvider, } from "./evaluationProviders.js";
|
|
13
|
+
import { modelConfig } from "./modelConfiguration.js";
|
|
12
14
|
/**
|
|
13
15
|
* Abstract base class for all AI providers
|
|
14
16
|
* Tools are integrated as first-class citizens - always available by default
|
|
@@ -182,6 +184,46 @@ export class BaseProvider {
|
|
|
182
184
|
temperature: options.temperature,
|
|
183
185
|
maxTokens: options.maxTokens || 8192,
|
|
184
186
|
});
|
|
187
|
+
const responseTime = Date.now() - startTime;
|
|
188
|
+
try {
|
|
189
|
+
// Calculate actual cost based on token usage and provider configuration
|
|
190
|
+
const calculateActualCost = () => {
|
|
191
|
+
try {
|
|
192
|
+
const costInfo = modelConfig.getCostInfo(this.providerName, this.modelName);
|
|
193
|
+
if (!costInfo) {
|
|
194
|
+
return 0; // No cost info available
|
|
195
|
+
}
|
|
196
|
+
const promptTokens = result.usage?.promptTokens || 0;
|
|
197
|
+
const completionTokens = result.usage?.completionTokens || 0;
|
|
198
|
+
// Calculate cost per 1K tokens
|
|
199
|
+
const inputCost = (promptTokens / 1000) * costInfo.input;
|
|
200
|
+
const outputCost = (completionTokens / 1000) * costInfo.output;
|
|
201
|
+
return inputCost + outputCost;
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
logger.debug(`Cost calculation failed for ${this.providerName}:`, error);
|
|
205
|
+
return 0; // Fallback to 0 on any error
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
const actualCost = calculateActualCost();
|
|
209
|
+
recordProviderPerformanceFromMetrics(this.providerName, {
|
|
210
|
+
responseTime,
|
|
211
|
+
tokensGenerated: result.usage?.totalTokens || 0,
|
|
212
|
+
cost: actualCost,
|
|
213
|
+
success: true,
|
|
214
|
+
});
|
|
215
|
+
// Show what the system learned (updated to include cost)
|
|
216
|
+
const optimizedProvider = getPerformanceOptimizedProvider("speed");
|
|
217
|
+
logger.debug(`🚀 Performance recorded for ${this.providerName}:`, {
|
|
218
|
+
responseTime: `${responseTime}ms`,
|
|
219
|
+
tokens: result.usage?.totalTokens || 0,
|
|
220
|
+
estimatedCost: `$${actualCost.toFixed(6)}`,
|
|
221
|
+
recommendedSpeedProvider: optimizedProvider?.provider || "none",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch (perfError) {
|
|
225
|
+
logger.warn("⚠️ Performance recording failed:", perfError);
|
|
226
|
+
}
|
|
185
227
|
// Extract tool names from tool calls for tracking
|
|
186
228
|
// AI SDK puts tool calls in steps array for multi-step generation
|
|
187
229
|
const toolsUsed = [];
|
|
@@ -32,3 +32,29 @@ export declare function isProviderAvailable(providerName: string): boolean;
|
|
|
32
32
|
* Get the best available provider based on preference
|
|
33
33
|
*/
|
|
34
34
|
export declare function getBestAvailableProvider(preferCheap?: boolean): ProviderModelConfig | null;
|
|
35
|
+
/**
|
|
36
|
+
Record actual provider performance for optimization
|
|
37
|
+
*/
|
|
38
|
+
export declare function recordProviderPerformanceFromMetrics(providerName: string, metrics: {
|
|
39
|
+
responseTime: number;
|
|
40
|
+
tokensGenerated: number;
|
|
41
|
+
cost: number;
|
|
42
|
+
success: boolean;
|
|
43
|
+
}): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get performance-optimized provider based on real metrics
|
|
46
|
+
*/
|
|
47
|
+
export declare function getPerformanceOptimizedProvider(priority?: "speed" | "cost" | "reliability"): ProviderModelConfig | null;
|
|
48
|
+
export declare function getProviderPerformanceAnalytics(): Record<string, {
|
|
49
|
+
avgResponseTime: number;
|
|
50
|
+
successRate: number;
|
|
51
|
+
tokenThroughput: number;
|
|
52
|
+
costEfficiency: number;
|
|
53
|
+
recommendation: string;
|
|
54
|
+
sampleCount: number;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Reset performance metrics for a provider or all providers.
|
|
58
|
+
* @param providerName - (Optional) The name of the provider to reset. If omitted, resets all providers.
|
|
59
|
+
*/
|
|
60
|
+
export declare function resetProviderMetrics(providerName?: string): void;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { modelConfig } from "./modelConfiguration.js";
|
|
2
|
+
const PERFORMANCE_THRESHOLDS = {
|
|
3
|
+
EXCELLENT_SUCCESS_RATE: 0.95,
|
|
4
|
+
EXCELLENT_RESPONSE_TIME_MS: 2000,
|
|
5
|
+
GOOD_SUCCESS_RATE: 0.9,
|
|
6
|
+
FAIR_SUCCESS_RATE: 0.8,
|
|
7
|
+
};
|
|
8
|
+
const providerMetrics = new Map();
|
|
2
9
|
/**
|
|
3
10
|
* Convert new configuration format to legacy format for backwards compatibility
|
|
4
11
|
*/
|
|
@@ -101,3 +108,156 @@ export function getBestAvailableProvider(preferCheap = true) {
|
|
|
101
108
|
const sortedProviders = sortProvidersByPreference(availableProviders, preferCheap);
|
|
102
109
|
return sortedProviders[0];
|
|
103
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
Record actual provider performance for optimization
|
|
113
|
+
*/
|
|
114
|
+
export function recordProviderPerformanceFromMetrics(providerName, metrics) {
|
|
115
|
+
const existing = providerMetrics.get(providerName) || {
|
|
116
|
+
responseTime: [],
|
|
117
|
+
successRate: 0,
|
|
118
|
+
tokenThroughput: 0,
|
|
119
|
+
costEfficiency: 0,
|
|
120
|
+
lastUpdated: new Date(),
|
|
121
|
+
sampleCount: 0,
|
|
122
|
+
};
|
|
123
|
+
// Keep rolling window of last 50 response times
|
|
124
|
+
existing.responseTime.push(metrics.responseTime);
|
|
125
|
+
if (existing.responseTime.length > 50) {
|
|
126
|
+
existing.responseTime.shift();
|
|
127
|
+
}
|
|
128
|
+
// Update success rate
|
|
129
|
+
const totalSamples = existing.sampleCount + 1;
|
|
130
|
+
existing.successRate =
|
|
131
|
+
(existing.successRate * existing.sampleCount + (metrics.success ? 1 : 0)) /
|
|
132
|
+
totalSamples;
|
|
133
|
+
// Update throughput (tokens per second)
|
|
134
|
+
if (metrics.responseTime > 0) {
|
|
135
|
+
const tokensPerSecond = metrics.tokensGenerated / (metrics.responseTime / 1000);
|
|
136
|
+
existing.tokenThroughput =
|
|
137
|
+
(existing.tokenThroughput * existing.sampleCount + tokensPerSecond) /
|
|
138
|
+
totalSamples;
|
|
139
|
+
}
|
|
140
|
+
// If responseTime is 0, skip updating tokenThroughput for this sample
|
|
141
|
+
// but still update other metrics
|
|
142
|
+
// Update cost efficiency (tokens per dollar)
|
|
143
|
+
if (metrics.cost > 0) {
|
|
144
|
+
const tokensPerDollar = metrics.tokensGenerated / metrics.cost;
|
|
145
|
+
existing.costEfficiency =
|
|
146
|
+
(existing.costEfficiency * existing.sampleCount + tokensPerDollar) /
|
|
147
|
+
totalSamples;
|
|
148
|
+
}
|
|
149
|
+
existing.sampleCount = totalSamples;
|
|
150
|
+
existing.lastUpdated = new Date();
|
|
151
|
+
providerMetrics.set(providerName, existing);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get performance-optimized provider based on real metrics
|
|
155
|
+
*/
|
|
156
|
+
export function getPerformanceOptimizedProvider(priority = "speed") {
|
|
157
|
+
const availableProviders = getAvailableProviders();
|
|
158
|
+
if (availableProviders.length === 0) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
// Score providers based on real performance data
|
|
162
|
+
const scoredProviders = availableProviders.map((provider) => {
|
|
163
|
+
const metrics = providerMetrics.get(provider.provider);
|
|
164
|
+
if (!metrics || metrics.sampleCount < 3) {
|
|
165
|
+
// Fall back to static performance ratings for providers without data
|
|
166
|
+
return {
|
|
167
|
+
provider,
|
|
168
|
+
score: getStaticPerformanceScore(provider, priority),
|
|
169
|
+
metrics: null,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
let score = 0;
|
|
173
|
+
switch (priority) {
|
|
174
|
+
case "speed": {
|
|
175
|
+
const avgResponseTime = metrics.responseTime.reduce((a, b) => a + b, 0) /
|
|
176
|
+
metrics.responseTime.length;
|
|
177
|
+
score =
|
|
178
|
+
metrics.tokenThroughput * 0.6 +
|
|
179
|
+
(5000 / Math.max(avgResponseTime, 100)) * 0.4;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case "cost": {
|
|
183
|
+
score = metrics.costEfficiency * 0.7 + metrics.successRate * 0.3;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case "reliability": {
|
|
187
|
+
score = metrics.successRate * 0.8 + (metrics.sampleCount / 100) * 0.2;
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return { provider, score, metrics };
|
|
192
|
+
});
|
|
193
|
+
// Sort by score and return best
|
|
194
|
+
scoredProviders.sort((a, b) => b.score - a.score);
|
|
195
|
+
return scoredProviders[0].provider;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Helper function for providers without performance data
|
|
199
|
+
*/
|
|
200
|
+
function getStaticPerformanceScore(provider, priority) {
|
|
201
|
+
switch (priority) {
|
|
202
|
+
case "speed": {
|
|
203
|
+
const speedScore = provider.performance?.speed || 1;
|
|
204
|
+
return speedScore;
|
|
205
|
+
}
|
|
206
|
+
case "cost": {
|
|
207
|
+
const costScore = provider.performance?.cost || 1;
|
|
208
|
+
return costScore;
|
|
209
|
+
}
|
|
210
|
+
case "reliability": {
|
|
211
|
+
const qualityScore = provider.performance?.quality || 1;
|
|
212
|
+
return qualityScore;
|
|
213
|
+
}
|
|
214
|
+
default: {
|
|
215
|
+
throw new Error(`Invalid priority: "${priority}". Must be one of: speed, cost, reliability`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export function getProviderPerformanceAnalytics() {
|
|
220
|
+
const analytics = {};
|
|
221
|
+
for (const [providerName, metrics] of providerMetrics.entries()) {
|
|
222
|
+
if (metrics.sampleCount === 0) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const avgResponseTime = metrics.responseTime.reduce((a, b) => a + b, 0) /
|
|
226
|
+
metrics.responseTime.length;
|
|
227
|
+
let recommendation = "";
|
|
228
|
+
if (metrics.successRate > PERFORMANCE_THRESHOLDS.EXCELLENT_SUCCESS_RATE &&
|
|
229
|
+
avgResponseTime < PERFORMANCE_THRESHOLDS.EXCELLENT_RESPONSE_TIME_MS) {
|
|
230
|
+
recommendation = "Excellent - Recommended for production";
|
|
231
|
+
}
|
|
232
|
+
else if (metrics.successRate > PERFORMANCE_THRESHOLDS.GOOD_SUCCESS_RATE) {
|
|
233
|
+
recommendation = "Good - Suitable for most tasks";
|
|
234
|
+
}
|
|
235
|
+
else if (metrics.successRate > PERFORMANCE_THRESHOLDS.FAIR_SUCCESS_RATE) {
|
|
236
|
+
recommendation = "Fair - Monitor closely";
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
recommendation = "Poor - Consider alternative providers";
|
|
240
|
+
}
|
|
241
|
+
analytics[providerName] = {
|
|
242
|
+
avgResponseTime,
|
|
243
|
+
successRate: metrics.successRate,
|
|
244
|
+
tokenThroughput: metrics.tokenThroughput,
|
|
245
|
+
costEfficiency: metrics.costEfficiency,
|
|
246
|
+
recommendation,
|
|
247
|
+
sampleCount: metrics.sampleCount,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
return analytics;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Reset performance metrics for a provider or all providers.
|
|
254
|
+
* @param providerName - (Optional) The name of the provider to reset. If omitted, resets all providers.
|
|
255
|
+
*/
|
|
256
|
+
export function resetProviderMetrics(providerName) {
|
|
257
|
+
if (providerName) {
|
|
258
|
+
providerMetrics.delete(providerName);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
providerMetrics.clear();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
@@ -9,6 +9,8 @@ import { shouldDisableBuiltinTools } from "../utils/toolUtils.js";
|
|
|
9
9
|
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
|
10
10
|
import { getKeysAsString, getKeyCount } from "../utils/transformationUtils.js";
|
|
11
11
|
import { validateStreamOptions as validateStreamOpts, validateTextGenerationOptions, ValidationError, createValidationSummary, } from "../utils/parameterValidation.js";
|
|
12
|
+
import { recordProviderPerformanceFromMetrics, getPerformanceOptimizedProvider, } from "./evaluationProviders.js";
|
|
13
|
+
import { modelConfig } from "./modelConfiguration.js";
|
|
12
14
|
/**
|
|
13
15
|
* Abstract base class for all AI providers
|
|
14
16
|
* Tools are integrated as first-class citizens - always available by default
|
|
@@ -182,6 +184,46 @@ export class BaseProvider {
|
|
|
182
184
|
temperature: options.temperature,
|
|
183
185
|
maxTokens: options.maxTokens || 8192,
|
|
184
186
|
});
|
|
187
|
+
const responseTime = Date.now() - startTime;
|
|
188
|
+
try {
|
|
189
|
+
// Calculate actual cost based on token usage and provider configuration
|
|
190
|
+
const calculateActualCost = () => {
|
|
191
|
+
try {
|
|
192
|
+
const costInfo = modelConfig.getCostInfo(this.providerName, this.modelName);
|
|
193
|
+
if (!costInfo) {
|
|
194
|
+
return 0; // No cost info available
|
|
195
|
+
}
|
|
196
|
+
const promptTokens = result.usage?.promptTokens || 0;
|
|
197
|
+
const completionTokens = result.usage?.completionTokens || 0;
|
|
198
|
+
// Calculate cost per 1K tokens
|
|
199
|
+
const inputCost = (promptTokens / 1000) * costInfo.input;
|
|
200
|
+
const outputCost = (completionTokens / 1000) * costInfo.output;
|
|
201
|
+
return inputCost + outputCost;
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
logger.debug(`Cost calculation failed for ${this.providerName}:`, error);
|
|
205
|
+
return 0; // Fallback to 0 on any error
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
const actualCost = calculateActualCost();
|
|
209
|
+
recordProviderPerformanceFromMetrics(this.providerName, {
|
|
210
|
+
responseTime,
|
|
211
|
+
tokensGenerated: result.usage?.totalTokens || 0,
|
|
212
|
+
cost: actualCost,
|
|
213
|
+
success: true,
|
|
214
|
+
});
|
|
215
|
+
// Show what the system learned (updated to include cost)
|
|
216
|
+
const optimizedProvider = getPerformanceOptimizedProvider("speed");
|
|
217
|
+
logger.debug(`🚀 Performance recorded for ${this.providerName}:`, {
|
|
218
|
+
responseTime: `${responseTime}ms`,
|
|
219
|
+
tokens: result.usage?.totalTokens || 0,
|
|
220
|
+
estimatedCost: `$${actualCost.toFixed(6)}`,
|
|
221
|
+
recommendedSpeedProvider: optimizedProvider?.provider || "none",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch (perfError) {
|
|
225
|
+
logger.warn("⚠️ Performance recording failed:", perfError);
|
|
226
|
+
}
|
|
185
227
|
// Extract tool names from tool calls for tracking
|
|
186
228
|
// AI SDK puts tool calls in steps array for multi-step generation
|
|
187
229
|
const toolsUsed = [];
|
|
@@ -32,3 +32,29 @@ export declare function isProviderAvailable(providerName: string): boolean;
|
|
|
32
32
|
* Get the best available provider based on preference
|
|
33
33
|
*/
|
|
34
34
|
export declare function getBestAvailableProvider(preferCheap?: boolean): ProviderModelConfig | null;
|
|
35
|
+
/**
|
|
36
|
+
Record actual provider performance for optimization
|
|
37
|
+
*/
|
|
38
|
+
export declare function recordProviderPerformanceFromMetrics(providerName: string, metrics: {
|
|
39
|
+
responseTime: number;
|
|
40
|
+
tokensGenerated: number;
|
|
41
|
+
cost: number;
|
|
42
|
+
success: boolean;
|
|
43
|
+
}): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get performance-optimized provider based on real metrics
|
|
46
|
+
*/
|
|
47
|
+
export declare function getPerformanceOptimizedProvider(priority?: "speed" | "cost" | "reliability"): ProviderModelConfig | null;
|
|
48
|
+
export declare function getProviderPerformanceAnalytics(): Record<string, {
|
|
49
|
+
avgResponseTime: number;
|
|
50
|
+
successRate: number;
|
|
51
|
+
tokenThroughput: number;
|
|
52
|
+
costEfficiency: number;
|
|
53
|
+
recommendation: string;
|
|
54
|
+
sampleCount: number;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Reset performance metrics for a provider or all providers.
|
|
58
|
+
* @param providerName - (Optional) The name of the provider to reset. If omitted, resets all providers.
|
|
59
|
+
*/
|
|
60
|
+
export declare function resetProviderMetrics(providerName?: string): void;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { modelConfig } from "./modelConfiguration.js";
|
|
2
|
+
const PERFORMANCE_THRESHOLDS = {
|
|
3
|
+
EXCELLENT_SUCCESS_RATE: 0.95,
|
|
4
|
+
EXCELLENT_RESPONSE_TIME_MS: 2000,
|
|
5
|
+
GOOD_SUCCESS_RATE: 0.9,
|
|
6
|
+
FAIR_SUCCESS_RATE: 0.8,
|
|
7
|
+
};
|
|
8
|
+
const providerMetrics = new Map();
|
|
2
9
|
/**
|
|
3
10
|
* Convert new configuration format to legacy format for backwards compatibility
|
|
4
11
|
*/
|
|
@@ -101,3 +108,156 @@ export function getBestAvailableProvider(preferCheap = true) {
|
|
|
101
108
|
const sortedProviders = sortProvidersByPreference(availableProviders, preferCheap);
|
|
102
109
|
return sortedProviders[0];
|
|
103
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
Record actual provider performance for optimization
|
|
113
|
+
*/
|
|
114
|
+
export function recordProviderPerformanceFromMetrics(providerName, metrics) {
|
|
115
|
+
const existing = providerMetrics.get(providerName) || {
|
|
116
|
+
responseTime: [],
|
|
117
|
+
successRate: 0,
|
|
118
|
+
tokenThroughput: 0,
|
|
119
|
+
costEfficiency: 0,
|
|
120
|
+
lastUpdated: new Date(),
|
|
121
|
+
sampleCount: 0,
|
|
122
|
+
};
|
|
123
|
+
// Keep rolling window of last 50 response times
|
|
124
|
+
existing.responseTime.push(metrics.responseTime);
|
|
125
|
+
if (existing.responseTime.length > 50) {
|
|
126
|
+
existing.responseTime.shift();
|
|
127
|
+
}
|
|
128
|
+
// Update success rate
|
|
129
|
+
const totalSamples = existing.sampleCount + 1;
|
|
130
|
+
existing.successRate =
|
|
131
|
+
(existing.successRate * existing.sampleCount + (metrics.success ? 1 : 0)) /
|
|
132
|
+
totalSamples;
|
|
133
|
+
// Update throughput (tokens per second)
|
|
134
|
+
if (metrics.responseTime > 0) {
|
|
135
|
+
const tokensPerSecond = metrics.tokensGenerated / (metrics.responseTime / 1000);
|
|
136
|
+
existing.tokenThroughput =
|
|
137
|
+
(existing.tokenThroughput * existing.sampleCount + tokensPerSecond) /
|
|
138
|
+
totalSamples;
|
|
139
|
+
}
|
|
140
|
+
// If responseTime is 0, skip updating tokenThroughput for this sample
|
|
141
|
+
// but still update other metrics
|
|
142
|
+
// Update cost efficiency (tokens per dollar)
|
|
143
|
+
if (metrics.cost > 0) {
|
|
144
|
+
const tokensPerDollar = metrics.tokensGenerated / metrics.cost;
|
|
145
|
+
existing.costEfficiency =
|
|
146
|
+
(existing.costEfficiency * existing.sampleCount + tokensPerDollar) /
|
|
147
|
+
totalSamples;
|
|
148
|
+
}
|
|
149
|
+
existing.sampleCount = totalSamples;
|
|
150
|
+
existing.lastUpdated = new Date();
|
|
151
|
+
providerMetrics.set(providerName, existing);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get performance-optimized provider based on real metrics
|
|
155
|
+
*/
|
|
156
|
+
export function getPerformanceOptimizedProvider(priority = "speed") {
|
|
157
|
+
const availableProviders = getAvailableProviders();
|
|
158
|
+
if (availableProviders.length === 0) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
// Score providers based on real performance data
|
|
162
|
+
const scoredProviders = availableProviders.map((provider) => {
|
|
163
|
+
const metrics = providerMetrics.get(provider.provider);
|
|
164
|
+
if (!metrics || metrics.sampleCount < 3) {
|
|
165
|
+
// Fall back to static performance ratings for providers without data
|
|
166
|
+
return {
|
|
167
|
+
provider,
|
|
168
|
+
score: getStaticPerformanceScore(provider, priority),
|
|
169
|
+
metrics: null,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
let score = 0;
|
|
173
|
+
switch (priority) {
|
|
174
|
+
case "speed": {
|
|
175
|
+
const avgResponseTime = metrics.responseTime.reduce((a, b) => a + b, 0) /
|
|
176
|
+
metrics.responseTime.length;
|
|
177
|
+
score =
|
|
178
|
+
metrics.tokenThroughput * 0.6 +
|
|
179
|
+
(5000 / Math.max(avgResponseTime, 100)) * 0.4;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case "cost": {
|
|
183
|
+
score = metrics.costEfficiency * 0.7 + metrics.successRate * 0.3;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case "reliability": {
|
|
187
|
+
score = metrics.successRate * 0.8 + (metrics.sampleCount / 100) * 0.2;
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return { provider, score, metrics };
|
|
192
|
+
});
|
|
193
|
+
// Sort by score and return best
|
|
194
|
+
scoredProviders.sort((a, b) => b.score - a.score);
|
|
195
|
+
return scoredProviders[0].provider;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Helper function for providers without performance data
|
|
199
|
+
*/
|
|
200
|
+
function getStaticPerformanceScore(provider, priority) {
|
|
201
|
+
switch (priority) {
|
|
202
|
+
case "speed": {
|
|
203
|
+
const speedScore = provider.performance?.speed || 1;
|
|
204
|
+
return speedScore;
|
|
205
|
+
}
|
|
206
|
+
case "cost": {
|
|
207
|
+
const costScore = provider.performance?.cost || 1;
|
|
208
|
+
return costScore;
|
|
209
|
+
}
|
|
210
|
+
case "reliability": {
|
|
211
|
+
const qualityScore = provider.performance?.quality || 1;
|
|
212
|
+
return qualityScore;
|
|
213
|
+
}
|
|
214
|
+
default: {
|
|
215
|
+
throw new Error(`Invalid priority: "${priority}". Must be one of: speed, cost, reliability`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export function getProviderPerformanceAnalytics() {
|
|
220
|
+
const analytics = {};
|
|
221
|
+
for (const [providerName, metrics] of providerMetrics.entries()) {
|
|
222
|
+
if (metrics.sampleCount === 0) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const avgResponseTime = metrics.responseTime.reduce((a, b) => a + b, 0) /
|
|
226
|
+
metrics.responseTime.length;
|
|
227
|
+
let recommendation = "";
|
|
228
|
+
if (metrics.successRate > PERFORMANCE_THRESHOLDS.EXCELLENT_SUCCESS_RATE &&
|
|
229
|
+
avgResponseTime < PERFORMANCE_THRESHOLDS.EXCELLENT_RESPONSE_TIME_MS) {
|
|
230
|
+
recommendation = "Excellent - Recommended for production";
|
|
231
|
+
}
|
|
232
|
+
else if (metrics.successRate > PERFORMANCE_THRESHOLDS.GOOD_SUCCESS_RATE) {
|
|
233
|
+
recommendation = "Good - Suitable for most tasks";
|
|
234
|
+
}
|
|
235
|
+
else if (metrics.successRate > PERFORMANCE_THRESHOLDS.FAIR_SUCCESS_RATE) {
|
|
236
|
+
recommendation = "Fair - Monitor closely";
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
recommendation = "Poor - Consider alternative providers";
|
|
240
|
+
}
|
|
241
|
+
analytics[providerName] = {
|
|
242
|
+
avgResponseTime,
|
|
243
|
+
successRate: metrics.successRate,
|
|
244
|
+
tokenThroughput: metrics.tokenThroughput,
|
|
245
|
+
costEfficiency: metrics.costEfficiency,
|
|
246
|
+
recommendation,
|
|
247
|
+
sampleCount: metrics.sampleCount,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
return analytics;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Reset performance metrics for a provider or all providers.
|
|
254
|
+
* @param providerName - (Optional) The name of the provider to reset. If omitted, resets all providers.
|
|
255
|
+
*/
|
|
256
|
+
export function resetProviderMetrics(providerName) {
|
|
257
|
+
if (providerName) {
|
|
258
|
+
providerMetrics.delete(providerName);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
providerMetrics.clear();
|
|
262
|
+
}
|
|
263
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.26.1",
|
|
4
4
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Juspay Technologies",
|