@aj-archipelago/cortex 1.1.3 → 1.1.4

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.
Files changed (63) hide show
  1. package/.eslintignore +3 -3
  2. package/README.md +17 -4
  3. package/config.js +45 -9
  4. package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/Dockerfile +1 -1
  5. package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/fileChunker.js +4 -1
  6. package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/package-lock.json +25 -216
  7. package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/package.json +2 -2
  8. package/helper-apps/cortex-whisper-wrapper/.dockerignore +27 -0
  9. package/helper-apps/cortex-whisper-wrapper/Dockerfile +32 -0
  10. package/helper-apps/cortex-whisper-wrapper/app.py +104 -0
  11. package/helper-apps/cortex-whisper-wrapper/docker-compose.debug.yml +12 -0
  12. package/helper-apps/cortex-whisper-wrapper/docker-compose.yml +10 -0
  13. package/helper-apps/cortex-whisper-wrapper/models/.gitkeep +0 -0
  14. package/helper-apps/cortex-whisper-wrapper/requirements.txt +5 -0
  15. package/lib/cortexRequest.js +117 -0
  16. package/lib/pathwayTools.js +2 -1
  17. package/lib/redisSubscription.js +2 -2
  18. package/lib/requestExecutor.js +360 -0
  19. package/lib/requestMonitor.js +131 -28
  20. package/package.json +2 -1
  21. package/pathways/summary.js +3 -3
  22. package/server/graphql.js +6 -6
  23. package/server/{pathwayPrompter.js → modelExecutor.js} +24 -21
  24. package/server/pathwayResolver.js +22 -17
  25. package/server/plugins/azureCognitivePlugin.js +25 -20
  26. package/server/plugins/azureTranslatePlugin.js +6 -10
  27. package/server/plugins/cohereGeneratePlugin.js +5 -12
  28. package/server/plugins/cohereSummarizePlugin.js +5 -12
  29. package/server/plugins/localModelPlugin.js +3 -3
  30. package/server/plugins/modelPlugin.js +18 -12
  31. package/server/plugins/openAiChatExtensionPlugin.js +5 -5
  32. package/server/plugins/openAiChatPlugin.js +8 -10
  33. package/server/plugins/openAiCompletionPlugin.js +9 -12
  34. package/server/plugins/openAiDallE3Plugin.js +14 -31
  35. package/server/plugins/openAiEmbeddingsPlugin.js +6 -9
  36. package/server/plugins/openAiImagePlugin.js +19 -15
  37. package/server/plugins/openAiWhisperPlugin.js +168 -100
  38. package/server/plugins/palmChatPlugin.js +9 -10
  39. package/server/plugins/palmCodeCompletionPlugin.js +2 -2
  40. package/server/plugins/palmCompletionPlugin.js +11 -12
  41. package/server/resolver.js +2 -2
  42. package/server/rest.js +1 -1
  43. package/tests/config.test.js +1 -1
  44. package/tests/mocks.js +5 -0
  45. package/tests/modelPlugin.test.js +3 -10
  46. package/tests/openAiChatPlugin.test.js +9 -8
  47. package/tests/openai_api.test.js +3 -3
  48. package/tests/palmChatPlugin.test.js +1 -1
  49. package/tests/palmCompletionPlugin.test.js +1 -1
  50. package/tests/pathwayResolver.test.js +2 -1
  51. package/tests/requestMonitor.test.js +94 -0
  52. package/tests/{requestDurationEstimator.test.js → requestMonitorDurationEstimator.test.js} +21 -17
  53. package/tests/truncateMessages.test.js +1 -1
  54. package/lib/request.js +0 -259
  55. package/lib/requestDurationEstimator.js +0 -90
  56. /package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/blobHandler.js +0 -0
  57. /package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/docHelper.js +0 -0
  58. /package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/function.json +0 -0
  59. /package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/helper.js +0 -0
  60. /package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/index.js +0 -0
  61. /package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/localFileHandler.js +0 -0
  62. /package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/redis.js +0 -0
  63. /package/{helper_apps/CortexFileHandler → helper-apps/cortex-file-handler}/start.js +0 -0
@@ -2,8 +2,8 @@
2
2
  import ModelPlugin from './modelPlugin.js';
3
3
 
4
4
  class CohereSummarizePlugin extends ModelPlugin {
5
- constructor(config, pathway, modelName, model) {
6
- super(config, pathway, modelName, model);
5
+ constructor(pathway, model) {
6
+ super(pathway, model);
7
7
  }
8
8
 
9
9
  // Set up parameters specific to the Cohere Summarize API
@@ -23,17 +23,10 @@ class CohereSummarizePlugin extends ModelPlugin {
23
23
  }
24
24
 
25
25
  // Execute the request to the Cohere Summarize API
26
- async execute(text, parameters, prompt, pathwayResolver) {
27
- const url = this.requestUrl();
26
+ async execute(text, parameters, prompt, cortexRequest) {
28
27
  const requestParameters = this.getRequestParameters(text, parameters, prompt);
29
- const { requestId, pathway} = pathwayResolver;
30
-
31
- const data = { ...(this.model.params || {}), ...requestParameters };
32
- const params = {};
33
- const headers = {
34
- ...this.model.headers || {}
35
- };
36
- return this.executeRequest(url, data, params, headers, prompt, requestId, pathway);
28
+ cortexRequest.data = { ...cortexRequest.data, ...requestParameters };
29
+ return this.executeRequest(cortexRequest);
37
30
  }
38
31
 
39
32
  // Parse the response from the Cohere Summarize API
@@ -5,8 +5,8 @@ import { encode } from 'gpt-3-encoder';
5
5
  import logger from '../../lib/logger.js';
6
6
 
7
7
  class LocalModelPlugin extends ModelPlugin {
8
- constructor(config, pathway, modelName, model) {
9
- super(config, pathway, modelName, model);
8
+ constructor(pathway, model) {
9
+ super(pathway, model);
10
10
  }
11
11
 
12
12
  // if the input starts with a chatML response, just return that
@@ -47,7 +47,7 @@ class LocalModelPlugin extends ModelPlugin {
47
47
  };
48
48
  }
49
49
 
50
- async execute(text, parameters, prompt, _pathwayResolver) {
50
+ async execute(text, parameters, prompt, _cortexRequest) {
51
51
  const requestParameters = this.getRequestParameters(text, parameters, prompt);
52
52
  const { executablePath, args } = this.model;
53
53
  args.push("--prompt", requestParameters.prompt);
@@ -1,18 +1,18 @@
1
1
  // ModelPlugin.js
2
2
  import HandleBars from '../../lib/handleBars.js';
3
-
4
- import { request } from '../../lib/request.js';
3
+ import { executeRequest } from '../../lib/requestExecutor.js';
5
4
  import { encode } from 'gpt-3-encoder';
6
5
  import { getFirstNToken } from '../chunker.js';
7
6
  import logger, { obscureUrlParams } from '../../lib/logger.js';
7
+ import { config } from '../../config.js';
8
8
 
9
9
  const DEFAULT_MAX_TOKENS = 4096;
10
10
  const DEFAULT_MAX_RETURN_TOKENS = 256;
11
11
  const DEFAULT_PROMPT_TOKEN_RATIO = 0.5;
12
12
 
13
13
  class ModelPlugin {
14
- constructor(config, pathway, modelName, model) {
15
- this.modelName = modelName;
14
+ constructor(pathway, model) {
15
+ this.modelName = model.name;
16
16
  this.model = model;
17
17
  this.config = config;
18
18
  this.environmentVariables = config.getEnv();
@@ -33,7 +33,6 @@ class ModelPlugin {
33
33
 
34
34
  this.requestCount = 0;
35
35
  this.lastRequestStartTime = new Date();
36
- this.shouldCache = config.get('enableCache') && (pathway.enableCache || pathway.temperature == 0);
37
36
  }
38
37
 
39
38
  truncateMessagesToTargetLength(messages, targetTokenLength) {
@@ -220,14 +219,14 @@ class ModelPlugin {
220
219
  parseResponse(data) { return data; }
221
220
 
222
221
  // Default simple logging
223
- logRequestStart(url, _data) {
222
+ logRequestStart() {
224
223
  this.requestCount++;
225
224
  this.lastRequestStartTime = new Date();
226
225
  const logMessage = `>>> [${this.requestId}: ${this.pathwayName}.${this.requestCount}] request`;
227
226
  const header = '>'.repeat(logMessage.length);
228
227
  logger.info(`${header}`);
229
228
  logger.info(`${logMessage}`);
230
- logger.info(`>>> Making API request to ${obscureUrlParams(url)}`);
229
+ logger.info(`>>> Making API request to ${obscureUrlParams(this.url)}`);
231
230
  }
232
231
 
233
232
  logAIRequestFinished() {
@@ -257,15 +256,22 @@ class ModelPlugin {
257
256
  prompt && prompt.debugInfo && (prompt.debugInfo += `\n${JSON.stringify(data)}`);
258
257
  }
259
258
 
260
- async executeRequest(url, data, params, headers, prompt, requestId, pathway) {
259
+ async executeRequest(cortexRequest) {
261
260
  try {
262
- this.aiRequestStartTime = new Date();
261
+ const { url, data, pathway, requestId, prompt } = cortexRequest;
262
+ this.url = url;
263
263
  this.requestId = requestId;
264
- this.logRequestStart(url, data);
265
- const responseData = await request({ url, data, params, headers, cache: this.shouldCache }, this.modelName, this.requestId, pathway);
264
+ this.pathwayName = pathway.name;
265
+ this.pathwayPrompt = pathway.prompt;
266
+
267
+ cortexRequest.cache = config.get('enableCache') && (pathway.enableCache || pathway.temperature == 0);
268
+ this.logRequestStart();
269
+
270
+ const responseData = await executeRequest(cortexRequest);
266
271
 
267
272
  if (responseData.error) {
268
- throw new Error(`An error was returned from the server: ${JSON.stringify(responseData.error)}`);
273
+ logger.error(`An error was returned from the server: ${JSON.stringify(responseData.error)}`);
274
+ throw responseData;
269
275
  }
270
276
 
271
277
  this.logRequestData(data, responseData, prompt);
@@ -2,8 +2,8 @@
2
2
  import OpenAIChatPlugin from './openAiChatPlugin.js';
3
3
 
4
4
  class OpenAIChatExtensionPlugin extends OpenAIChatPlugin {
5
- constructor(config, pathway, modelName, model) {
6
- super(config, pathway, modelName, model);
5
+ constructor(pathway, model) {
6
+ super(pathway, model);
7
7
  this.tool = '';
8
8
  }
9
9
 
@@ -47,9 +47,9 @@ class OpenAIChatExtensionPlugin extends OpenAIChatPlugin {
47
47
  return reqParams;
48
48
  }
49
49
 
50
- async execute(text, parameters, prompt, pathwayResolver) {
51
- const result = await super.execute(text, parameters, prompt, pathwayResolver);
52
- pathwayResolver.tool = this.tool; // add tool info back
50
+ async execute(text, parameters, prompt, cortexRequest) {
51
+ const result = await super.execute(text, parameters, prompt, cortexRequest);
52
+ cortexRequest.pathwayResolver.tool = this.tool; // add tool info back
53
53
  return result;
54
54
  }
55
55
 
@@ -4,8 +4,8 @@ import { encode } from 'gpt-3-encoder';
4
4
  import logger from '../../lib/logger.js';
5
5
 
6
6
  class OpenAIChatPlugin extends ModelPlugin {
7
- constructor(config, pathway, modelName, model) {
8
- super(config, pathway, modelName, model);
7
+ constructor(pathway, model) {
8
+ super(pathway, model);
9
9
  }
10
10
 
11
11
  // convert to OpenAI messages array format if necessary
@@ -76,16 +76,14 @@ class OpenAIChatPlugin extends ModelPlugin {
76
76
  return requestParameters;
77
77
  }
78
78
 
79
- // Execute the request to the OpenAI Chat API
80
- async execute(text, parameters, prompt, pathwayResolver) {
81
- const url = this.requestUrl(text);
79
+ // Assemble and execute the request to the OpenAI Chat API
80
+ async execute(text, parameters, prompt, cortexRequest) {
82
81
  const requestParameters = this.getRequestParameters(text, parameters, prompt);
83
- const { requestId, pathway} = pathwayResolver;
84
82
 
85
- const data = { ...(this.model.params || {}), ...requestParameters };
86
- const params = {}; // query params
87
- const headers = this.model.headers || {};
88
- return this.executeRequest(url, data, params, headers, prompt, requestId, pathway);
83
+ cortexRequest.data = { ...(cortexRequest.data || {}), ...requestParameters };
84
+ cortexRequest.params = {}; // query params
85
+
86
+ return this.executeRequest(cortexRequest);
89
87
  }
90
88
 
91
89
  // Parse the response from the OpenAI Chat API
@@ -16,8 +16,8 @@ const truncatePromptIfNecessary = (text, textTokenCount, modelMaxTokenCount, tar
16
16
  }
17
17
 
18
18
  class OpenAICompletionPlugin extends ModelPlugin {
19
- constructor(config, pathway, modelName, model) {
20
- super(config, pathway, modelName, model);
19
+ constructor(pathway, model) {
20
+ super(pathway, model);
21
21
  }
22
22
 
23
23
  // Set up parameters specific to the OpenAI Completion API
@@ -76,16 +76,13 @@ class OpenAICompletionPlugin extends ModelPlugin {
76
76
  }
77
77
 
78
78
  // Execute the request to the OpenAI Completion API
79
- async execute(text, parameters, prompt, pathwayResolver) {
80
- const url = this.requestUrl(text);
81
- const requestParameters = this.getRequestParameters(text, parameters, prompt, pathwayResolver);
82
- const { requestId, pathway} = pathwayResolver;
83
-
84
- const data = { ...(this.model.params || {}), ...requestParameters };
85
- const params = {};
86
- const headers = this.model.headers || {};
87
-
88
- return this.executeRequest(url, data, params, headers, prompt, requestId, pathway);
79
+ async execute(text, parameters, prompt, cortexRequest) {
80
+ const requestParameters = this.getRequestParameters(text, parameters, prompt, cortexRequest.pathwayResolver);
81
+
82
+ cortexRequest.data = { ...(cortexRequest.data || {}), ...requestParameters };
83
+ cortexRequest.params = {};
84
+
85
+ return this.executeRequest(cortexRequest);
89
86
  }
90
87
 
91
88
  // Parse the response from the OpenAI Completion API
@@ -1,17 +1,15 @@
1
- import RequestDurationEstimator from '../../lib/requestDurationEstimator.js';
1
+ import RequestMonitor from '../../lib/requestMonitor.js';
2
2
  import ModelPlugin from './modelPlugin.js';
3
- import { request } from '../../lib/request.js';
4
3
  import { publishRequestProgress } from '../../lib/redisSubscription.js';
5
- import logger from '../../lib/logger.js';
6
4
 
7
- const requestDurationEstimator = new RequestDurationEstimator(10);
5
+ const requestDurationEstimator = new RequestMonitor(10);
8
6
 
9
7
  /**
10
8
  * @description This plugin is for the OpenAI DALL-E 3 model.
11
9
  */
12
10
  class OpenAIDallE3Plugin extends ModelPlugin {
13
- constructor(config, pathway, modelName, model) {
14
- super(config, pathway, modelName, model);
11
+ constructor(pathway, model) {
12
+ super(pathway, model);
15
13
  }
16
14
 
17
15
  /**
@@ -20,28 +18,13 @@ class OpenAIDallE3Plugin extends ModelPlugin {
20
18
  * over a websocket.
21
19
  */
22
20
 
23
- async executeRequest(url, data, params, headers, prompt, requestId, pathway) {
24
- try {
25
- this.aiRequestStartTime = new Date();
26
- this.requestId = requestId;
27
- this.logRequestStart(url, data);
28
- const responseData = await request({ url, data, params, headers, cache: this.shouldCache }, this.modelName, this.requestId, pathway);
29
-
30
- this.logRequestData(data, responseData, prompt);
31
- return this.parseResponse(responseData);
32
- } catch (error) {
33
- // Log the error and continue
34
- logger.error(error.message || error);
35
- }
36
- }
37
-
38
- async execute(text, parameters, _, pathwayResolver) {
39
- const url = this.requestUrl(text);
40
- const data = JSON.stringify({ prompt: text });
21
+ async execute(text, parameters, _, cortexRequest) {
22
+ const { pathwayResolver } = cortexRequest;
23
+ cortexRequest.data = JSON.stringify({ prompt: text });
41
24
 
42
- const { requestId, pathway } = pathwayResolver;
25
+ const { requestId } = pathwayResolver;
43
26
 
44
- const makeRequest = () => this.executeRequest(url, data, {}, this.model.headers, {}, requestId, pathway);
27
+ const makeRequest = () => this.executeRequest(cortexRequest);
45
28
 
46
29
  if (!parameters.async) {
47
30
  // synchronous request
@@ -49,9 +32,9 @@ class OpenAIDallE3Plugin extends ModelPlugin {
49
32
  }
50
33
  else {
51
34
  // async request
52
- requestDurationEstimator.startRequest(requestId);
35
+ const callid = requestDurationEstimator.startCall();
53
36
  const requestPromise = makeRequest();
54
- this.#sendRequestUpdates(requestId, requestPromise);
37
+ this.#sendRequestUpdates(requestId, requestPromise, callid);
55
38
  }
56
39
  }
57
40
 
@@ -62,7 +45,7 @@ class OpenAIDallE3Plugin extends ModelPlugin {
62
45
  * @param {*} requestPromise
63
46
  * @returns
64
47
  */
65
- async #sendRequestUpdates(requestId, requestPromise) {
48
+ async #sendRequestUpdates(requestId, requestPromise, callid) {
66
49
  let state = { status: "pending" };
67
50
  let attemptCount = 0;
68
51
  let data = null;
@@ -83,7 +66,7 @@ class OpenAIDallE3Plugin extends ModelPlugin {
83
66
  };
84
67
 
85
68
  state.status = status;
86
- requestDurationEstimator.endRequest();
69
+ requestDurationEstimator.endCall(callid);
87
70
  publishRequestProgress(requestProgress);
88
71
  }
89
72
 
@@ -91,7 +74,7 @@ class OpenAIDallE3Plugin extends ModelPlugin {
91
74
  // the percent complete
92
75
  do {
93
76
  let progress =
94
- requestDurationEstimator.calculatePercentComplete();
77
+ requestDurationEstimator.calculatePercentComplete(callid);
95
78
 
96
79
  await publishRequestProgress({
97
80
  requestId,
@@ -2,8 +2,8 @@
2
2
  import ModelPlugin from './modelPlugin.js';
3
3
 
4
4
  class OpenAiEmbeddingsPlugin extends ModelPlugin {
5
- constructor(config, pathway, modelName, model) {
6
- super(config, pathway, modelName, model);
5
+ constructor(pathway, model) {
6
+ super(pathway, model);
7
7
  }
8
8
 
9
9
  getRequestParameters(text, parameters, prompt) {
@@ -17,16 +17,13 @@ class OpenAiEmbeddingsPlugin extends ModelPlugin {
17
17
  return requestParameters;
18
18
  }
19
19
 
20
- async execute(text, parameters, prompt, pathwayResolver) {
21
- const { requestId, pathway} = pathwayResolver;
20
+ async execute(text, parameters, prompt, cortexRequest) {
22
21
  const requestParameters = this.getRequestParameters(text, parameters, prompt);
23
- const url = this.requestUrl();
24
22
 
25
- const data = requestParameters.data || {};
26
- const params = requestParameters.params || {};
27
- const headers = this.model.headers || {};
23
+ cortexRequest.data = requestParameters.data || {};
24
+ cortexRequest.params = requestParameters.params || {};
28
25
 
29
- return this.executeRequest(url, data, params, headers, prompt, requestId, pathway);
26
+ return this.executeRequest(cortexRequest);
30
27
  }
31
28
 
32
29
  parseResponse(data) {
@@ -1,28 +1,32 @@
1
1
  // OpenAIImagePlugin.js
2
2
  import ModelPlugin from './modelPlugin.js';
3
3
  import axios from 'axios';
4
- import RequestDurationEstimator from '../../lib/requestDurationEstimator.js';
4
+ import RequestMonitor from '../../lib/requestMonitor.js';
5
5
  import { publishRequestProgress } from '../../lib/redisSubscription.js';
6
6
  import logger from '../../lib/logger.js';
7
7
 
8
- const requestDurationEstimator = new RequestDurationEstimator(10);
8
+ const requestDurationEstimator = new RequestMonitor(10);
9
9
 
10
10
  class OpenAIImagePlugin extends ModelPlugin {
11
- constructor(config, pathway, modelName, model) {
12
- super(config, pathway, modelName, model);
11
+ constructor(pathway, model) {
12
+ super(pathway, model);
13
13
  }
14
14
 
15
15
  // Implement the method to call the DALL-E API
16
- async execute(text, parameters, _, pathwayResolver) {
17
- const url = this.requestUrl(text);
18
- const data = JSON.stringify({ prompt: text });
16
+ async execute(text, parameters, _, cortexRequest) {
17
+ const { pathwayResolver } = cortexRequest;
18
+ cortexRequest.data = JSON.stringify({ prompt: text });
19
19
 
20
20
  let id;
21
- const { requestId, pathway } = pathwayResolver;
21
+ const { requestId } = pathwayResolver;
22
+
23
+ let callid;
22
24
 
23
25
  try {
24
- requestDurationEstimator.startRequest(requestId);
25
- id = (await this.executeRequest(url, data, {}, { ...this.model.headers }, {}, requestId, pathway))?.id;
26
+ callid = requestDurationEstimator.startCall();
27
+ await this.executeRequest(cortexRequest);
28
+ id = cortexRequest.requestId;
29
+
26
30
  } catch (error) {
27
31
  const errMsg = `Error generating image: ${error?.message || error}`;
28
32
  logger.error(errMsg);
@@ -30,14 +34,14 @@ class OpenAIImagePlugin extends ModelPlugin {
30
34
  }
31
35
 
32
36
  if (!parameters.async) {
33
- return await this.getStatus(text, id, requestId);
37
+ return await this.getStatus(text, id, requestId, callid);
34
38
  }
35
39
  else {
36
- this.getStatus(text, id, requestId);
40
+ this.getStatus(text, id, requestId, callid);
37
41
  }
38
42
  }
39
43
 
40
- async getStatus(text, id, requestId) {
44
+ async getStatus(text, id, requestId, callid) {
41
45
  // get the post URL which is used to send the request
42
46
  const url = this.requestUrl(text);
43
47
 
@@ -51,7 +55,7 @@ class OpenAIImagePlugin extends ModelPlugin {
51
55
  const response = (await axios.get(statusUrl, { cache: false, headers: { ...this.model.headers } })).data;
52
56
  status = response.status;
53
57
  let progress =
54
- requestDurationEstimator.calculatePercentComplete();
58
+ requestDurationEstimator.calculatePercentComplete(callid);
55
59
 
56
60
  if (status === "succeeded") {
57
61
  progress = 1;
@@ -66,7 +70,7 @@ class OpenAIImagePlugin extends ModelPlugin {
66
70
  });
67
71
 
68
72
  if (status === "succeeded") {
69
- requestDurationEstimator.endRequest();
73
+ requestDurationEstimator.endCall(callid);
70
74
  break;
71
75
  }
72
76
  // sleep for 5 seconds