@aj-archipelago/cortex 1.1.6 → 1.1.7
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/config.js +10 -0
- package/lib/cortexRequest.js +10 -0
- package/lib/requestExecutor.js +13 -9
- package/package.json +2 -2
- package/pathways/bing.js +12 -0
- package/pathways/index.js +2 -0
- package/server/modelExecutor.js +4 -0
- package/server/plugins/azureBingPlugin.js +44 -0
package/config.js
CHANGED
|
@@ -146,6 +146,16 @@ var config = convict({
|
|
|
146
146
|
"maxTokenLength": 128000,
|
|
147
147
|
"supportsStreaming": true
|
|
148
148
|
},
|
|
149
|
+
"azure-bing": {
|
|
150
|
+
"type": "AZURE-BING",
|
|
151
|
+
"url": "https://api.bing.microsoft.com/v7.0/search",
|
|
152
|
+
"headers": {
|
|
153
|
+
"Ocp-Apim-Subscription-Key": "{{AZURE_BING_KEY}}",
|
|
154
|
+
"Content-Type": "application/json"
|
|
155
|
+
},
|
|
156
|
+
"requestsPerSecond": 10,
|
|
157
|
+
"maxTokenLength": 200000
|
|
158
|
+
},
|
|
149
159
|
},
|
|
150
160
|
env: 'CORTEX_MODELS'
|
|
151
161
|
},
|
package/lib/cortexRequest.js
CHANGED
|
@@ -11,6 +11,7 @@ class CortexRequest {
|
|
|
11
11
|
this._pathwayResolver = pathwayResolver || {};
|
|
12
12
|
this._selectedEndpoint = selectedEndpoint || {};
|
|
13
13
|
this._stream = stream || false;
|
|
14
|
+
this._method = 'POST';
|
|
14
15
|
|
|
15
16
|
if (this._pathwayResolver) {
|
|
16
17
|
this._model = this._pathwayResolver.model;
|
|
@@ -41,6 +42,15 @@ class CortexRequest {
|
|
|
41
42
|
this._url = value;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
// method getter and setter
|
|
46
|
+
get method() {
|
|
47
|
+
return this._method;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
set method(value) {
|
|
51
|
+
this._method = value;
|
|
52
|
+
}
|
|
53
|
+
|
|
44
54
|
// data getter and setter
|
|
45
55
|
get data() {
|
|
46
56
|
return this._data;
|
package/lib/requestExecutor.js
CHANGED
|
@@ -183,11 +183,15 @@ setInterval(() => {
|
|
|
183
183
|
}
|
|
184
184
|
}, 30000); // Log rates every 30 seconds
|
|
185
185
|
|
|
186
|
-
const
|
|
186
|
+
const requestWithMonitor = async (endpoint, url, data, axiosConfigObj) => {
|
|
187
187
|
const callId = endpoint?.monitor?.startCall();
|
|
188
188
|
let response;
|
|
189
189
|
try {
|
|
190
|
-
|
|
190
|
+
if (axiosConfigObj?.method == 'GET'){
|
|
191
|
+
response = await cortexAxios.get(url, axiosConfigObj);
|
|
192
|
+
} else {
|
|
193
|
+
response = await cortexAxios.post(url, data, axiosConfigObj);
|
|
194
|
+
}
|
|
191
195
|
} catch (error) {
|
|
192
196
|
// throw new error with duration as part of the error data
|
|
193
197
|
throw { ...error, duration: endpoint?.monitor?.incrementErrorCount(callId, error?.response?.status || null) };
|
|
@@ -213,22 +217,22 @@ const getDuplicateRequestDelay = (index, duplicateRequestAfter) => {
|
|
|
213
217
|
return duplicateRequestTimeout;
|
|
214
218
|
}
|
|
215
219
|
|
|
216
|
-
const
|
|
220
|
+
const makeRequest = async (cortexRequest) => {
|
|
217
221
|
let promises = [];
|
|
218
222
|
// retry certain errors up to MAX_RETRY times
|
|
219
223
|
for (let i = 0; i < MAX_RETRY; i++) {
|
|
220
|
-
const { url, data, params, headers, cache, selectedEndpoint, requestId, pathway, model, stream} = cortexRequest;
|
|
224
|
+
const { url, data, params, headers, cache, selectedEndpoint, requestId, pathway, model, stream, method} = cortexRequest;
|
|
221
225
|
const enableDuplicateRequests = pathway?.enableDuplicateRequests !== undefined ? pathway.enableDuplicateRequests : config.get('enableDuplicateRequests');
|
|
222
226
|
const maxDuplicateRequests = enableDuplicateRequests ? MAX_DUPLICATE_REQUESTS : 1;
|
|
223
227
|
const duplicateRequestAfter = (pathway?.duplicateRequestAfter || DUPLICATE_REQUEST_AFTER) * 1000;
|
|
224
228
|
|
|
225
|
-
const axiosConfigObj = { params, headers, cache };
|
|
229
|
+
const axiosConfigObj = { params, headers, cache, method };
|
|
226
230
|
const streamRequested = (stream || params?.stream || data?.stream);
|
|
227
231
|
// if we're using streaming, duplicate requests are
|
|
228
232
|
// not supported, so we just push one promise into the array
|
|
229
233
|
if (streamRequested && model.supportsStreaming) {
|
|
230
234
|
axiosConfigObj.responseType = 'stream';
|
|
231
|
-
promises.push(selectedEndpoint.limiter.schedule({expiration: pathway.timeout * 1000 + 1000, id: `${requestId}_${uuidv4()}`},() =>
|
|
235
|
+
promises.push(selectedEndpoint.limiter.schedule({expiration: pathway.timeout * 1000 + 1000, id: `${requestId}_${uuidv4()}`},() => requestWithMonitor(selectedEndpoint, url, data, axiosConfigObj)));
|
|
232
236
|
} else {
|
|
233
237
|
if (streamRequested) {
|
|
234
238
|
logger.info(`>>> [${requestId}] ${model} does not support streaming - sending non-streaming request`);
|
|
@@ -253,7 +257,7 @@ const postRequest = async (cortexRequest) => {
|
|
|
253
257
|
if (!selectedEndpoint.limiter) {
|
|
254
258
|
throw new Error(`No limiter for endpoint ${endpointName}!`);
|
|
255
259
|
}
|
|
256
|
-
const axiosConfigObj = { params, headers, cache };
|
|
260
|
+
const axiosConfigObj = { params, headers, cache, method };
|
|
257
261
|
|
|
258
262
|
let response = null;
|
|
259
263
|
let duration = null;
|
|
@@ -269,7 +273,7 @@ const postRequest = async (cortexRequest) => {
|
|
|
269
273
|
logger.info(`\n${header}\n${logMessage}`);
|
|
270
274
|
}
|
|
271
275
|
|
|
272
|
-
({ response, duration } = await selectedEndpoint.limiter.schedule({expiration: pathway.timeout * 1000 + 1000, id: `${requestId}_${uuidv4()}`}, () =>
|
|
276
|
+
({ response, duration } = await selectedEndpoint.limiter.schedule({expiration: pathway.timeout * 1000 + 1000, id: `${requestId}_${uuidv4()}`}, () => requestWithMonitor(selectedEndpoint, url, data, axiosConfigObj)));
|
|
273
277
|
|
|
274
278
|
if (!controller.signal?.aborted) {
|
|
275
279
|
logger.debug(`<<< [${requestId}] received response for request ${index}`);
|
|
@@ -341,7 +345,7 @@ const postRequest = async (cortexRequest) => {
|
|
|
341
345
|
|
|
342
346
|
const executeRequest = async (cortexRequest) => {
|
|
343
347
|
try {
|
|
344
|
-
const { response, duration } = await
|
|
348
|
+
const { response, duration } = await makeRequest(cortexRequest);
|
|
345
349
|
const requestId = cortexRequest.requestId;
|
|
346
350
|
const { error, data, cached } = response;
|
|
347
351
|
if (cached) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aj-archipelago/cortex",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"description": "Cortex is a GraphQL API for AI. It provides a simple, extensible interface for using AI services from OpenAI, Azure and others.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"repository": {
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"handlebars": "^4.7.7",
|
|
53
53
|
"ioredis": "^5.3.1",
|
|
54
54
|
"keyv": "^4.5.2",
|
|
55
|
-
"langchain": "^0.
|
|
55
|
+
"langchain": "^0.1.28",
|
|
56
56
|
"mime-types": "^2.1.35",
|
|
57
57
|
"subsrt": "^1.1.1",
|
|
58
58
|
"uuid": "^9.0.0",
|
package/pathways/bing.js
ADDED
package/pathways/index.js
CHANGED
package/server/modelExecutor.js
CHANGED
|
@@ -19,6 +19,7 @@ import OpenAIDallE3Plugin from './plugins/openAiDallE3Plugin.js';
|
|
|
19
19
|
import OpenAIVisionPlugin from './plugins/openAiVisionPlugin.js';
|
|
20
20
|
import GeminiChatPlugin from './plugins/geminiChatPlugin.js';
|
|
21
21
|
import GeminiVisionPlugin from './plugins/geminiVisionPlugin.js';
|
|
22
|
+
import AzureBingPlugin from './plugins/azureBingPlugin.js';
|
|
22
23
|
|
|
23
24
|
class ModelExecutor {
|
|
24
25
|
constructor(pathway, model) {
|
|
@@ -80,6 +81,9 @@ class ModelExecutor {
|
|
|
80
81
|
case 'GEMINI-VISION':
|
|
81
82
|
plugin = new GeminiVisionPlugin(pathway, model);
|
|
82
83
|
break;
|
|
84
|
+
case 'AZURE-BING':
|
|
85
|
+
plugin = new AzureBingPlugin(pathway, model);
|
|
86
|
+
break;
|
|
83
87
|
default:
|
|
84
88
|
throw new Error(`Unsupported model type: ${model.type}`);
|
|
85
89
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import ModelPlugin from './modelPlugin.js';
|
|
2
|
+
import logger from '../../lib/logger.js';
|
|
3
|
+
|
|
4
|
+
class AzureBingPlugin extends ModelPlugin {
|
|
5
|
+
constructor(pathway, model) {
|
|
6
|
+
super(pathway, model);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
getRequestParameters(text) {
|
|
10
|
+
const requestParameters = {
|
|
11
|
+
data: [
|
|
12
|
+
],
|
|
13
|
+
params: {
|
|
14
|
+
q: text,
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
return requestParameters;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async execute(text, parameters, prompt, cortexRequest) {
|
|
21
|
+
const requestParameters = this.getRequestParameters(text, parameters, prompt);
|
|
22
|
+
|
|
23
|
+
cortexRequest.data = requestParameters.data;
|
|
24
|
+
cortexRequest.params = requestParameters.params;
|
|
25
|
+
cortexRequest.method = 'GET';
|
|
26
|
+
|
|
27
|
+
return this.executeRequest(cortexRequest);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
parseResponse(data) {
|
|
31
|
+
return JSON.stringify(data);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Override the logging function to display the request and response
|
|
35
|
+
logRequestData(data, responseData, prompt) {
|
|
36
|
+
this.logAIRequestFinished();
|
|
37
|
+
|
|
38
|
+
logger.debug(`${this.parseResponse(responseData)}`);
|
|
39
|
+
|
|
40
|
+
prompt && prompt.debugInfo && (prompt.debugInfo += `\n${JSON.stringify(data)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default AzureBingPlugin;
|