@aj-archipelago/cortex 1.3.11 → 1.3.14
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/helper-apps/cortex-file-handler/.env.test +7 -0
- package/helper-apps/cortex-file-handler/.env.test.azure +6 -0
- package/helper-apps/cortex-file-handler/.env.test.gcs +9 -0
- package/helper-apps/cortex-file-handler/blobHandler.js +313 -204
- package/helper-apps/cortex-file-handler/constants.js +107 -0
- package/helper-apps/cortex-file-handler/docHelper.js +4 -1
- package/helper-apps/cortex-file-handler/fileChunker.js +170 -109
- package/helper-apps/cortex-file-handler/helper.js +82 -16
- package/helper-apps/cortex-file-handler/index.js +226 -146
- package/helper-apps/cortex-file-handler/localFileHandler.js +21 -3
- package/helper-apps/cortex-file-handler/package-lock.json +2622 -51
- package/helper-apps/cortex-file-handler/package.json +25 -4
- package/helper-apps/cortex-file-handler/redis.js +9 -18
- package/helper-apps/cortex-file-handler/scripts/setup-azure-container.js +22 -0
- package/helper-apps/cortex-file-handler/scripts/setup-test-containers.js +49 -0
- package/helper-apps/cortex-file-handler/scripts/test-azure.sh +34 -0
- package/helper-apps/cortex-file-handler/scripts/test-gcs.sh +49 -0
- package/helper-apps/cortex-file-handler/start.js +39 -4
- package/helper-apps/cortex-file-handler/tests/blobHandler.test.js +292 -0
- package/helper-apps/cortex-file-handler/tests/docHelper.test.js +148 -0
- package/helper-apps/cortex-file-handler/tests/fileChunker.test.js +311 -0
- package/helper-apps/cortex-file-handler/tests/start.test.js +930 -0
- package/package.json +1 -1
- package/pathways/system/entity/sys_entity_continue.js +1 -1
- package/pathways/system/entity/sys_entity_start.js +1 -0
- package/pathways/system/entity/sys_generator_video_vision.js +2 -1
- package/pathways/system/entity/sys_router_tool.js +6 -4
- package/server/plugins/openAiWhisperPlugin.js +9 -13
- package/server/plugins/replicateApiPlugin.js +54 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aj-archipelago/cortex",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.14",
|
|
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": {
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
prompt:
|
|
5
5
|
[
|
|
6
6
|
new Prompt({ messages: [
|
|
7
|
-
{"role": "system", "content": `{{renderTemplate AI_MEMORY}}\n\n{{renderTemplate AI_COMMON_INSTRUCTIONS}}\n{{renderTemplate AI_EXPERTISE}}\nYou are the part of {{aiName}} that can view, hear, and understand
|
|
7
|
+
{"role": "system", "content": `{{renderTemplate AI_MEMORY}}\n\n{{renderTemplate AI_COMMON_INSTRUCTIONS}}\n{{renderTemplate AI_EXPERTISE}}\nYou are the part of {{aiName}} that can view, hear, and understand files of all sorts (images, videos, audio, pdfs, text, etc.) - you provide the capability to view and analyze files that the user provides.\nMany of your subsystems cannot independently view or analyze files, so make sure that you describe the details of what you see in the files in your response so you can refer to the descriptions later. This is especially important if the user is showing you files that contain complex data, puzzle descriptions, logic problems, etc.\n{{renderTemplate AI_MEMORY_INSTRUCTIONS}}\nThe user has provided you with one or more files in this conversation - you should consider them for context when you respond to the user.\nIf you don't see any files, something has gone wrong in the upload and you should inform the user and have them try again.\n{{renderTemplate AI_DATETIME}}`},
|
|
8
8
|
"{{chatHistory}}",
|
|
9
9
|
]}),
|
|
10
10
|
],
|
|
@@ -19,6 +19,7 @@ export default {
|
|
|
19
19
|
useInputChunking: false,
|
|
20
20
|
enableDuplicateRequests: false,
|
|
21
21
|
timeout: 600,
|
|
22
|
+
|
|
22
23
|
executePathway: async ({args, runAllPrompts, resolver}) => {
|
|
23
24
|
const result = await runAllPrompts({ ...args });
|
|
24
25
|
resolver.tool = JSON.stringify({ toolUsed: "vision" });
|
|
@@ -33,13 +33,15 @@ Available tools and their specific use cases:
|
|
|
33
33
|
|
|
34
34
|
8. Reason: Employ for reasoning, scientific analysis, evaluating evidence, strategic planning, problem-solving, logic puzzles, mathematical calculations, or any questions that require careful thought or complex choices. Also use when deep, step-by-step reasoning is required.
|
|
35
35
|
|
|
36
|
-
9. PDF: Use specifically for
|
|
36
|
+
9. PDF: Use specifically for analyzing and answering questions about PDF file content. Use this tool any time the user is asking you questions about a PDF file.
|
|
37
37
|
|
|
38
|
-
10.
|
|
38
|
+
10. Text: Use specifically for analyzing and answering questions about text file content. Use this tool any time the user is asking you questions about a text file.
|
|
39
39
|
|
|
40
|
-
11.
|
|
40
|
+
11. Vision: Use specifically for analyzing and answering questions about image files (jpg, gif, bmp, png, etc). Use this tool any time the user is asking you questions about an uploaded image file.
|
|
41
41
|
|
|
42
|
-
12.
|
|
42
|
+
12. Video: Use specifically for analyzing and answering questions about video or audio file content. Use this tool any time the user is asking you questions about an uploaded video or audio file.
|
|
43
|
+
|
|
44
|
+
13. Clarify: Use when you must have more information from the user to determine which tool to use. In this case your tool message should be one or more questions to the user to clarify their request.
|
|
43
45
|
|
|
44
46
|
Tool Selection Guidelines:
|
|
45
47
|
- Prioritize the most specific tool for the task at hand.
|
|
@@ -64,7 +64,6 @@ class OpenAIWhisperPlugin extends ModelPlugin {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
const processTS = async (uri) => {
|
|
67
|
-
const cortexRequest = new CortexRequest({ pathwayResolver });
|
|
68
67
|
|
|
69
68
|
const tsparams = { fileurl:uri };
|
|
70
69
|
const { language } = parameters;
|
|
@@ -81,8 +80,14 @@ class OpenAIWhisperPlugin extends ModelPlugin {
|
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
82
|
|
|
83
|
+
const cortexRequest = new CortexRequest({ pathwayResolver });
|
|
84
84
|
cortexRequest.url = WHISPER_TS_API_URL;
|
|
85
85
|
cortexRequest.data = tsparams;
|
|
86
|
+
const whisperInitCallback = (requestInstance) => {
|
|
87
|
+
requestInstance.url = WHISPER_TS_API_URL;
|
|
88
|
+
requestInstance.data = tsparams;
|
|
89
|
+
};
|
|
90
|
+
cortexRequest.initCallback = whisperInitCallback;
|
|
86
91
|
|
|
87
92
|
const MAX_RETRIES = 3;
|
|
88
93
|
let attempt = 0;
|
|
@@ -91,8 +96,8 @@ class OpenAIWhisperPlugin extends ModelPlugin {
|
|
|
91
96
|
sendProgress(true, true);
|
|
92
97
|
try {
|
|
93
98
|
res = await this.executeRequest(cortexRequest);
|
|
94
|
-
if(res
|
|
95
|
-
throw new Error(res
|
|
99
|
+
if(res?.statusCode && res?.statusCode >= 400){
|
|
100
|
+
throw new Error(res?.message || 'An error occurred.');
|
|
96
101
|
}
|
|
97
102
|
break;
|
|
98
103
|
}
|
|
@@ -102,7 +107,7 @@ class OpenAIWhisperPlugin extends ModelPlugin {
|
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
if (res
|
|
110
|
+
if (res?.statusCode && res?.statusCode >= 400) {
|
|
106
111
|
throw new Error(res.message || 'An error occurred.');
|
|
107
112
|
}
|
|
108
113
|
|
|
@@ -221,15 +226,6 @@ try {
|
|
|
221
226
|
|
|
222
227
|
await markCompletedForCleanUp(requestId);
|
|
223
228
|
|
|
224
|
-
//check cleanup for whisper temp uploaded files url
|
|
225
|
-
const regex = /whispertempfiles\/([a-z0-9-]+)/;
|
|
226
|
-
const match = file.match(regex);
|
|
227
|
-
if (match && match[1]) {
|
|
228
|
-
const extractedValue = match[1];
|
|
229
|
-
await markCompletedForCleanUp(extractedValue);
|
|
230
|
-
logger.info(`Cleaned temp whisper file ${file} with request id ${extractedValue}`);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
229
|
} catch (error) {
|
|
234
230
|
logger.error(`An error occurred while deleting: ${error}`);
|
|
235
231
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// replicateApiPlugin.js
|
|
2
2
|
import ModelPlugin from "./modelPlugin.js";
|
|
3
3
|
import logger from "../../lib/logger.js";
|
|
4
|
+
import axios from "axios";
|
|
4
5
|
|
|
5
6
|
class ReplicateApiPlugin extends ModelPlugin {
|
|
6
7
|
constructor(pathway, model) {
|
|
@@ -106,10 +107,61 @@ class ReplicateApiPlugin extends ModelPlugin {
|
|
|
106
107
|
cortexRequest.data = requestParameters;
|
|
107
108
|
cortexRequest.params = requestParameters.params;
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
// Make initial request to start prediction
|
|
111
|
+
const stringifiedResponse = await this.executeRequest(cortexRequest);
|
|
112
|
+
const parsedResponse = JSON.parse(stringifiedResponse);
|
|
113
|
+
|
|
114
|
+
// If we got a completed response, return it
|
|
115
|
+
if (parsedResponse?.status === "succeeded") {
|
|
116
|
+
return stringifiedResponse;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
logger.info("Replicate API returned a non-completed response.");
|
|
120
|
+
|
|
121
|
+
if (!parsedResponse?.id) {
|
|
122
|
+
throw new Error("No prediction ID returned from Replicate API");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Get the prediction ID and polling URL
|
|
126
|
+
const predictionId = parsedResponse.id;
|
|
127
|
+
const pollUrl = parsedResponse.urls?.get;
|
|
128
|
+
|
|
129
|
+
if (!pollUrl) {
|
|
130
|
+
throw new Error("No polling URL returned from Replicate API");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Poll for results
|
|
134
|
+
const maxAttempts = 60; // 5 minutes with 5 second intervals
|
|
135
|
+
const pollInterval = 5000;
|
|
136
|
+
|
|
137
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
138
|
+
try {
|
|
139
|
+
const pollResponse = await axios.get(pollUrl, {
|
|
140
|
+
headers: cortexRequest.headers
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
logger.info("Polling Replicate API - attempt " + attempt);
|
|
144
|
+
const status = pollResponse.data?.status;
|
|
145
|
+
|
|
146
|
+
if (status === "succeeded") {
|
|
147
|
+
logger.info("Replicate API returned a completed response after polling");
|
|
148
|
+
return JSON.stringify(pollResponse.data);
|
|
149
|
+
} else if (status === "failed" || status === "canceled") {
|
|
150
|
+
throw new Error(`Prediction ${status}: ${pollResponse.data?.error || "Unknown error"}`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Wait before next poll
|
|
154
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
155
|
+
} catch (error) {
|
|
156
|
+
logger.error(`Error polling prediction ${predictionId}: ${error.message}`);
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
throw new Error(`Prediction ${predictionId} timed out after ${maxAttempts * pollInterval / 1000} seconds`);
|
|
110
162
|
}
|
|
111
163
|
|
|
112
|
-
//
|
|
164
|
+
// Stringify the response from the Replicate API
|
|
113
165
|
parseResponse(data) {
|
|
114
166
|
if (data.data) {
|
|
115
167
|
return JSON.stringify(data.data);
|