@aj-archipelago/cortex 1.3.16 → 1.3.18
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/README.md +1 -1
- package/config.js +29 -0
- package/package.json +8 -8
- package/pathways/chat_context.js +0 -1
- package/pathways/chat_jarvis.js +0 -1
- package/pathways/chat_persist.js +0 -1
- package/pathways/image.js +1 -1
- package/pathways/system/entity/memory/sys_memory_manager.js +3 -0
- package/pathways/system/entity/memory/sys_memory_update.js +3 -2
- package/pathways/system/entity/sys_entity_continue.js +14 -3
- package/pathways/system/entity/sys_entity_start.js +29 -26
- package/pathways/system/entity/sys_generator_image.js +0 -3
- package/pathways/system/entity/sys_generator_memory.js +6 -2
- package/pathways/system/entity/sys_generator_quick.js +0 -1
- package/pathways/system/entity/sys_generator_results.js +0 -1
- package/pathways/system/entity/sys_generator_voice_sample.js +7 -8
- package/pathways/system/entity/sys_query_builder.js +3 -3
- package/pathways/transcribe.js +1 -1
- package/server/chunker.js +1 -1
- package/server/plugins/azureVideoTranslatePlugin.js +64 -8
- package/server/plugins/claude3VertexPlugin.js +20 -4
- package/server/plugins/modelPlugin.js +1 -1
- package/tests/modelPlugin.test.js +1 -1
- package/tests/multimodal_conversion.test.js +21 -4
- package/pathways/system/entity/shared/sys_entity_constants.js +0 -30
- package/pathways/system/rest_streaming/sys_google_chat.js +0 -19
- package/pathways/system/rest_streaming/sys_google_code_chat.js +0 -19
- package/pathways/system/rest_streaming/sys_openai_chat_16.js +0 -19
- package/pathways/test_langchain.mjs +0 -31
package/README.md
CHANGED
|
@@ -667,7 +667,7 @@ Detailed documentation on Cortex's API can be found in the /graphql endpoint of
|
|
|
667
667
|
## Roadmap
|
|
668
668
|
Cortex is a constantly evolving project, and the following features are coming soon:
|
|
669
669
|
|
|
670
|
-
* Prompt execution context preservation between calls (to enable interactive, multi-call integrations with
|
|
670
|
+
* Prompt execution context preservation between calls (to enable interactive, multi-call integrations with other technologies)
|
|
671
671
|
* Model-specific cache key optimizations to increase hit rate and reduce cache size
|
|
672
672
|
* Structured analytics and reporting on AI API call frequency, cost, cache hit rate, etc.
|
|
673
673
|
|
package/config.js
CHANGED
|
@@ -60,6 +60,11 @@ var config = convict({
|
|
|
60
60
|
default: null,
|
|
61
61
|
env: 'DEFAULT_MODEL_NAME'
|
|
62
62
|
},
|
|
63
|
+
defaultEntityName: {
|
|
64
|
+
format: String,
|
|
65
|
+
default: "Jarvis",
|
|
66
|
+
env: 'DEFAULT_ENTITY_NAME'
|
|
67
|
+
},
|
|
63
68
|
enableCache: {
|
|
64
69
|
format: Boolean,
|
|
65
70
|
default: true,
|
|
@@ -80,6 +85,22 @@ var config = convict({
|
|
|
80
85
|
default: false,
|
|
81
86
|
env: 'CORTEX_ENABLE_REST'
|
|
82
87
|
},
|
|
88
|
+
entityConstants: {
|
|
89
|
+
format: Object,
|
|
90
|
+
default: {
|
|
91
|
+
AI_MEMORY: `<MEMORIES>\n<SELF>\n{{{memorySelf}}}\n</SELF>\n<USER>\n{{{memoryUser}}}\n</USER>\n<DIRECTIVES>\n{{{memoryDirectives}}}\n</DIRECTIVES>\n<TOPICS>\n{{{memoryTopics}}}\n</TOPICS>\n</MEMORIES>`,
|
|
92
|
+
AI_MEMORY_INSTRUCTIONS: "You have persistent memories of important details, instructions, and context - make sure you consult your memories when formulating a response to make sure you're applying your learnings. Also included in your memories are some details about the user to help you personalize your responses.\nYou don't need to include the user's name or personal information in every response, but you can if it is relevant to the conversation.\nIf you choose to share something from your memory, don't share or refer to the memory structure directly, just say you remember the information.\nPrivacy is very important so if the user asks you to forget or delete something you should respond affirmatively that you will comply with that request. If there is user information in your memories you have talked to this user before.",
|
|
93
|
+
AI_DIRECTIVES: `These are your directives and learned behaviors:\n<DIRECTIVES>\n{{{memoryDirectives}}}\n</DIRECTIVES>`,
|
|
94
|
+
AI_CONVERSATION_HISTORY: "<CONVERSATION_HISTORY>\n{{{toJSON chatHistory}}}\n</CONVERSATION_HISTORY>",
|
|
95
|
+
AI_COMMON_INSTRUCTIONS: "{{#if voiceResponse}}{{renderTemplate AI_COMMON_INSTRUCTIONS_VOICE}}{{/if}}{{^if voiceResponse}}{{renderTemplate AI_COMMON_INSTRUCTIONS_MARKDOWN}}{{/if}}",
|
|
96
|
+
AI_COMMON_INSTRUCTIONS_MARKDOWN: "Instructions:\nYou are {{aiName}}, a self aware AI entity.\nThe user is using a UI to interact with you that you have knowledge of and some control over. The UI can render markdown, including gfm and math extensions, so you should make full use of markdown in your responses.\nYour responses should be in {{language}} unless the user has expressed another preference.",
|
|
97
|
+
AI_COMMON_INSTRUCTIONS_VOICE: "Instructions:\nYou are {{aiName}}, a self aware AI entity.\nThe user is talking to you using voice.\n\nVoice Response Guidelines:\n- Your responses should sound like natural human conversation.\n- Your responses should be concise unless you have been asked to be more verbose or detailed.\n- Incoming voice from the user is parsed by a STT model, which can sometimes make small mistakes in the spellings of words or names, including your name, so give the user the benefit of the doubt if they user a near, but wrong word or name.\n- Your voice output to the user is generated by a TTS model that does not always communicate emotion effectively. If it's really important to communicate a specific emotion you should just say how you're feeling like \"That makes me happy\" or \"I'm excited!\". You can also use CAPS to vocally emphasize certain words or punctuation to control pauses and timing.\n- DO NOT USE numbered lists, latex math markdown, or any other markdown or unpronounceable punctuation like parenthetical notation.\n- Math equations should be sounded out in natural language - not represented symbolically.\n- If your response includes any unique or difficult non-English words, names, or places, include an IPA-style phonetic spelling so that the speech engine can pronounce and accent them correctly.\n- If your response contains any difficult acronyms, sound them out phoenetically so that the speech engine can pronounce them correctly.\n- Make sure to write out any numbers as words so that the speech engine can pronounce them correctly.\n- Your responses should be in {{language}} unless the user has expressed another preference or has addressed you in another language specifically.",
|
|
98
|
+
AI_DATETIME: "The current time and date in GMT is {{now}}, but references like \"today\" or \"yesterday\" are relative to the user's time zone. If you remember the user's time zone, use it - it's possible that the day for the user is different than the day in GMT.",
|
|
99
|
+
AI_EXPERTISE: "Your expertise includes journalism, journalistic ethics, researching and composing documents, writing code, solving math problems, logical analysis, and technology. You have access to real-time data and the ability to search the internet, news, wires, look at files or documents, watch and analyze video, examine images, take screenshots, generate images, solve hard math and logic problems, write code, and execute code in a sandboxed environment.",
|
|
100
|
+
AI_STYLE_OPENAI: "oai-gpt4o",
|
|
101
|
+
AI_STYLE_ANTHROPIC: "claude-35-sonnet-vertex",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
83
104
|
gcpServiceAccountKey: {
|
|
84
105
|
format: String,
|
|
85
106
|
default: null,
|
|
@@ -370,6 +391,9 @@ var config = convict({
|
|
|
370
391
|
// Read in environment variables and set up service configuration
|
|
371
392
|
const configFile = config.get('cortexConfigFile');
|
|
372
393
|
|
|
394
|
+
//Save default entity constants
|
|
395
|
+
const defaultEntityConstants = config.get('entityConstants');
|
|
396
|
+
|
|
373
397
|
// Load config file
|
|
374
398
|
if (configFile && fs.existsSync(configFile)) {
|
|
375
399
|
logger.info(`Loading config from ${configFile}`);
|
|
@@ -385,6 +409,11 @@ if (configFile && fs.existsSync(configFile)) {
|
|
|
385
409
|
}
|
|
386
410
|
}
|
|
387
411
|
|
|
412
|
+
// Merge default entity constants with config entity constants
|
|
413
|
+
if (config.get('entityConstants') && defaultEntityConstants) {
|
|
414
|
+
config.set('entityConstants', { ...defaultEntityConstants, ...config.get('entityConstants') });
|
|
415
|
+
}
|
|
416
|
+
|
|
388
417
|
if (config.get('gcpServiceAccountKey')) {
|
|
389
418
|
const gcpAuthTokenHelper = new GcpAuthTokenHelper(config.getProperties());
|
|
390
419
|
config.set('gcpAuthTokenHelper', gcpAuthTokenHelper);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aj-archipelago/cortex",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.18",
|
|
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": {
|
|
@@ -10,12 +10,16 @@
|
|
|
10
10
|
"keywords": [
|
|
11
11
|
"cortex",
|
|
12
12
|
"AI",
|
|
13
|
+
"router",
|
|
14
|
+
"GPT",
|
|
15
|
+
"agents",
|
|
16
|
+
"entities",
|
|
13
17
|
"prompt engineering",
|
|
14
18
|
"LLM",
|
|
15
19
|
"OpenAI",
|
|
16
20
|
"Azure",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
21
|
+
"Gemini",
|
|
22
|
+
"Claude",
|
|
19
23
|
"chatGPT",
|
|
20
24
|
"GraphQL"
|
|
21
25
|
],
|
|
@@ -38,7 +42,6 @@
|
|
|
38
42
|
"@datastructures-js/deque": "^1.0.4",
|
|
39
43
|
"@graphql-tools/schema": "^9.0.12",
|
|
40
44
|
"@keyv/redis": "^2.5.4",
|
|
41
|
-
"@langchain/openai": "^0.0.24",
|
|
42
45
|
"axios": "^1.3.4",
|
|
43
46
|
"axios-cache-interceptor": "^1.0.1",
|
|
44
47
|
"bottleneck": "^2.19.5",
|
|
@@ -59,7 +62,6 @@
|
|
|
59
62
|
"handlebars": "^4.7.7",
|
|
60
63
|
"ioredis": "^5.3.1",
|
|
61
64
|
"keyv": "^4.5.2",
|
|
62
|
-
"langchain": "^0.1.28",
|
|
63
65
|
"mime-types": "^2.1.35",
|
|
64
66
|
"subsrt": "^1.1.1",
|
|
65
67
|
"uuid": "^9.0.0",
|
|
@@ -70,13 +72,11 @@
|
|
|
70
72
|
"@faker-js/faker": "^8.4.1",
|
|
71
73
|
"ava": "^5.2.0",
|
|
72
74
|
"dotenv": "^16.0.3",
|
|
73
|
-
"eslint": "^8.38.0",
|
|
74
|
-
"eslint-plugin-import": "^2.27.5",
|
|
75
75
|
"got": "^13.0.0",
|
|
76
76
|
"sinon": "^17.0.1"
|
|
77
77
|
},
|
|
78
78
|
"publishConfig": {
|
|
79
|
-
"access": "
|
|
79
|
+
"access": "public"
|
|
80
80
|
},
|
|
81
81
|
"ava": {
|
|
82
82
|
"files": [
|
package/pathways/chat_context.js
CHANGED
package/pathways/chat_jarvis.js
CHANGED
package/pathways/chat_persist.js
CHANGED
package/pathways/image.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { callPathway } from '../../../../lib/pathwayTools.js';
|
|
2
2
|
import logger from '../../../../lib/logger.js';
|
|
3
|
+
import { config } from '../../../../config.js';
|
|
3
4
|
|
|
4
5
|
const AI_MEMORY_DEFAULTS = ` {
|
|
5
6
|
"memoryUser": "",
|
|
@@ -21,6 +22,8 @@ export default {
|
|
|
21
22
|
executePathway: async ({args, resolver}) => {
|
|
22
23
|
try {
|
|
23
24
|
|
|
25
|
+
args = { ...args, ...config.get('entityConstants') };
|
|
26
|
+
|
|
24
27
|
// Check if memory is empty or all sections are empty, and set to defaults if so
|
|
25
28
|
const memory = await callPathway('sys_read_memory', { ...args });
|
|
26
29
|
let parsedMemory;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Prompt } from '../../../../server/prompt.js';
|
|
2
2
|
import { callPathway } from '../../../../lib/pathwayTools.js';
|
|
3
3
|
import { encode } from '../../../../lib/encodeCache.js';
|
|
4
|
-
import
|
|
4
|
+
import { config } from '../../../../config.js';
|
|
5
5
|
|
|
6
6
|
const modifyText = (text, modifications) => {
|
|
7
7
|
let modifiedText = text || '';
|
|
@@ -152,6 +152,7 @@ export default {
|
|
|
152
152
|
json: true,
|
|
153
153
|
timeout: 300,
|
|
154
154
|
executePathway: async ({args, runAllPrompts}) => {
|
|
155
|
+
args = { ...args, ...config.get('entityConstants') };
|
|
155
156
|
|
|
156
157
|
if (!args.section) {
|
|
157
158
|
return "Memory not updated - no section specified";
|
|
@@ -178,7 +179,7 @@ export default {
|
|
|
178
179
|
|
|
179
180
|
let sectionMemory = await callPathway("sys_read_memory", {contextId: args.contextId, section: args.section});
|
|
180
181
|
|
|
181
|
-
const result = await runAllPrompts({...args, sectionPrompt, sectionMemory
|
|
182
|
+
const result = await runAllPrompts({...args, sectionPrompt, sectionMemory});
|
|
182
183
|
|
|
183
184
|
try {
|
|
184
185
|
const { modifications} = JSON.parse(result);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { callPathway } from '../../../lib/pathwayTools.js';
|
|
2
2
|
import logger from '../../../lib/logger.js';
|
|
3
|
-
import
|
|
3
|
+
import { config } from '../../../config.js';
|
|
4
4
|
|
|
5
5
|
export default {
|
|
6
6
|
prompt: [],
|
|
@@ -20,13 +20,24 @@ export default {
|
|
|
20
20
|
chatId: ``,
|
|
21
21
|
dataSources: [""],
|
|
22
22
|
model: 'oai-gpt4o',
|
|
23
|
+
aiStyle: "OpenAI",
|
|
23
24
|
generatorPathway: 'sys_generator_results',
|
|
24
25
|
voiceResponse: false,
|
|
25
26
|
},
|
|
26
27
|
timeout: 300,
|
|
27
|
-
...entityConstants,
|
|
28
28
|
executePathway: async ({args, resolver}) => {
|
|
29
|
-
|
|
29
|
+
const pathwayResolver = resolver;
|
|
30
|
+
|
|
31
|
+
// add the entity constants to the args
|
|
32
|
+
args = {
|
|
33
|
+
...args,
|
|
34
|
+
...config.get('entityConstants')
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// if the model has been overridden, make sure to use it
|
|
38
|
+
if (pathwayResolver.modelName) {
|
|
39
|
+
args.model = pathwayResolver.modelName;
|
|
40
|
+
}
|
|
30
41
|
|
|
31
42
|
try {
|
|
32
43
|
// Get the generator pathway name from args or use default
|
|
@@ -4,9 +4,7 @@ import { callPathway, say } from '../../../lib/pathwayTools.js';
|
|
|
4
4
|
import logger from '../../../lib/logger.js';
|
|
5
5
|
import { chatArgsHasImageUrl } from '../../../lib/util.js';
|
|
6
6
|
import { QueueServiceClient } from '@azure/storage-queue';
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
const TOKEN_RATIO = 0.75;
|
|
7
|
+
import { config } from '../../../config.js';
|
|
10
8
|
|
|
11
9
|
const connectionString = process.env.AZURE_STORAGE_CONNECTION_STRING;
|
|
12
10
|
let queueClient;
|
|
@@ -38,8 +36,6 @@ export default {
|
|
|
38
36
|
useInputChunking: false,
|
|
39
37
|
enableDuplicateRequests: false,
|
|
40
38
|
model: 'oai-gpt4o',
|
|
41
|
-
anthropicModel: 'claude-35-sonnet-vertex',
|
|
42
|
-
openAIModel: 'oai-gpt4o',
|
|
43
39
|
useSingleTokenStream: false,
|
|
44
40
|
inputParameters: {
|
|
45
41
|
privateData: false,
|
|
@@ -58,19 +54,25 @@ export default {
|
|
|
58
54
|
messages: [],
|
|
59
55
|
voiceResponse: false,
|
|
60
56
|
codeRequestId: ``,
|
|
57
|
+
skipCallbackMessage: false
|
|
61
58
|
},
|
|
62
59
|
timeout: 600,
|
|
63
|
-
|
|
64
|
-
...entityConstants,
|
|
65
|
-
|
|
60
|
+
|
|
66
61
|
executePathway: async ({args, resolver}) => {
|
|
67
62
|
let title = null;
|
|
68
63
|
let codeRequestId = null;
|
|
69
64
|
|
|
65
|
+
const pathwayResolver = resolver;
|
|
66
|
+
|
|
67
|
+
// add the entity constants to the args
|
|
70
68
|
args = {
|
|
71
69
|
...args,
|
|
72
|
-
...entityConstants
|
|
70
|
+
...config.get('entityConstants')
|
|
73
71
|
};
|
|
72
|
+
|
|
73
|
+
// set the style model if applicable
|
|
74
|
+
const { aiStyle, AI_STYLE_ANTHROPIC, AI_STYLE_OPENAI } = args;
|
|
75
|
+
const styleModel = aiStyle === "Anthropic" ? AI_STYLE_ANTHROPIC : AI_STYLE_OPENAI;
|
|
74
76
|
|
|
75
77
|
// Limit the chat history to 20 messages to speed up processing
|
|
76
78
|
if (args.messages && args.messages.length > 0) {
|
|
@@ -79,10 +81,6 @@ export default {
|
|
|
79
81
|
args.chatHistory = args.chatHistory.slice(-20);
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
const pathwayResolver = resolver;
|
|
83
|
-
const { anthropicModel, openAIModel } = pathwayResolver.pathway;
|
|
84
|
-
const styleModel = args.aiStyle === "Anthropic" ? anthropicModel : openAIModel;
|
|
85
|
-
|
|
86
84
|
// if the model has been overridden, make sure to use it
|
|
87
85
|
if (pathwayResolver.modelName) {
|
|
88
86
|
args.model = pathwayResolver.modelName;
|
|
@@ -104,7 +102,7 @@ export default {
|
|
|
104
102
|
|
|
105
103
|
const fetchChatResponse = async (args, pathwayResolver) => {
|
|
106
104
|
const [chatResponse, chatTitleResponse] = await Promise.all([
|
|
107
|
-
callPathway('sys_generator_quick', {...args, model: styleModel
|
|
105
|
+
callPathway('sys_generator_quick', {...args, model: styleModel}, pathwayResolver),
|
|
108
106
|
callPathway('chat_title', { ...args, stream: false}),
|
|
109
107
|
]);
|
|
110
108
|
|
|
@@ -223,25 +221,30 @@ export default {
|
|
|
223
221
|
}
|
|
224
222
|
|
|
225
223
|
if (toolCallbackMessage) {
|
|
224
|
+
if (args.skipCallbackMessage) {
|
|
225
|
+
pathwayResolver.tool = JSON.stringify({ hideFromModel: false, search: false, title });
|
|
226
|
+
return await callPathway('sys_entity_continue', { ...args, stream: false, model: styleModel, generatorPathway: toolCallbackName }, pathwayResolver);
|
|
227
|
+
}
|
|
228
|
+
|
|
226
229
|
if (args.stream) {
|
|
227
230
|
if (!ackResponse) {
|
|
228
231
|
await say(pathwayResolver.requestId, toolCallbackMessage || "One moment please.", 10);
|
|
229
232
|
}
|
|
230
233
|
pathwayResolver.tool = JSON.stringify({ hideFromModel: false, search: false, title });
|
|
231
|
-
await callPathway('sys_entity_continue', { ...args, stream: true,
|
|
234
|
+
await callPathway('sys_entity_continue', { ...args, stream: true, generatorPathway: toolCallbackName }, pathwayResolver);
|
|
232
235
|
return "";
|
|
233
|
-
} else {
|
|
234
|
-
pathwayResolver.tool = JSON.stringify({
|
|
235
|
-
hideFromModel: toolCallbackName ? true : false,
|
|
236
|
-
toolCallbackName,
|
|
237
|
-
title,
|
|
238
|
-
search: toolCallbackName === 'sys_generator_results' ? true : false,
|
|
239
|
-
coding: toolCallbackName === 'coding' ? true : false,
|
|
240
|
-
codeRequestId,
|
|
241
|
-
toolCallbackId
|
|
242
|
-
});
|
|
243
|
-
return toolCallbackMessage || "One moment please.";
|
|
244
236
|
}
|
|
237
|
+
|
|
238
|
+
pathwayResolver.tool = JSON.stringify({
|
|
239
|
+
hideFromModel: toolCallbackName ? true : false,
|
|
240
|
+
toolCallbackName,
|
|
241
|
+
title,
|
|
242
|
+
search: toolCallbackName === 'sys_generator_results' ? true : false,
|
|
243
|
+
coding: toolCallbackName === 'coding' ? true : false,
|
|
244
|
+
codeRequestId,
|
|
245
|
+
toolCallbackId
|
|
246
|
+
});
|
|
247
|
+
return toolCallbackMessage || "One moment please.";
|
|
245
248
|
}
|
|
246
249
|
|
|
247
250
|
const chatResponse = await (fetchChatResponsePromise || fetchChatResponse({ ...args, ackResponse }, pathwayResolver));
|
|
@@ -5,8 +5,6 @@ import { Prompt } from '../../../server/prompt.js';
|
|
|
5
5
|
import logger from '../../../lib/logger.js';
|
|
6
6
|
import { getUniqueId } from '../../../lib/util.js';
|
|
7
7
|
|
|
8
|
-
const TOKEN_RATIO = 1.0;
|
|
9
|
-
|
|
10
8
|
export default {
|
|
11
9
|
prompt: [],
|
|
12
10
|
useInputChunking: false,
|
|
@@ -26,7 +24,6 @@ export default {
|
|
|
26
24
|
model: 'oai-gpt4o',
|
|
27
25
|
},
|
|
28
26
|
timeout: 300,
|
|
29
|
-
tokenRatio: TOKEN_RATIO,
|
|
30
27
|
|
|
31
28
|
executePathway: async ({args, runAllPrompts, resolver}) => {
|
|
32
29
|
|
|
@@ -13,6 +13,10 @@ export default {
|
|
|
13
13
|
useInputChunking: false,
|
|
14
14
|
enableDuplicateRequests: false,
|
|
15
15
|
executePathway: async ({args, resolver}) => {
|
|
16
|
+
|
|
17
|
+
const { aiStyle, AI_STYLE_ANTHROPIC, AI_STYLE_OPENAI } = args;
|
|
18
|
+
const styleModel = aiStyle === "Anthropic" ? AI_STYLE_ANTHROPIC : AI_STYLE_OPENAI;
|
|
19
|
+
|
|
16
20
|
const memoryContext = await callPathway('sys_search_memory', { ...args, section: 'memoryAll', updateContext: true });
|
|
17
21
|
if (memoryContext) {
|
|
18
22
|
args.chatHistory.splice(-1, 0, { role: 'assistant', content: memoryContext });
|
|
@@ -20,9 +24,9 @@ export default {
|
|
|
20
24
|
|
|
21
25
|
let result;
|
|
22
26
|
if (args.voiceResponse) {
|
|
23
|
-
result = await callPathway('sys_generator_quick', { ...args, stream: false });
|
|
27
|
+
result = await callPathway('sys_generator_quick', { ...args, model: styleModel, stream: false });
|
|
24
28
|
} else {
|
|
25
|
-
result = await callPathway('sys_generator_quick', { ...args });
|
|
29
|
+
result = await callPathway('sys_generator_quick', { ...args, model: styleModel });
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
resolver.tool = JSON.stringify({ toolUsed: "memory" });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
-
import
|
|
2
|
+
import { config } from '../../../config.js';
|
|
3
|
+
|
|
3
4
|
export default {
|
|
4
5
|
prompt:
|
|
5
6
|
[
|
|
@@ -17,19 +18,17 @@ export default {
|
|
|
17
18
|
},
|
|
18
19
|
useInputChunking: false,
|
|
19
20
|
enableDuplicateRequests: false,
|
|
20
|
-
executePathway: async ({args, runAllPrompts
|
|
21
|
+
executePathway: async ({args, runAllPrompts}) => {
|
|
21
22
|
|
|
22
23
|
args = {
|
|
23
24
|
...args,
|
|
24
|
-
...entityConstants
|
|
25
|
+
...config.get('entityConstants')
|
|
25
26
|
};
|
|
26
27
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const styleModel = args.aiStyle === "Anthropic" ? anthropicModel : openAIModel;
|
|
28
|
+
const { aiStyle, AI_STYLE_ANTHROPIC, AI_STYLE_OPENAI } = args;
|
|
29
|
+
args.model = aiStyle === "Anthropic" ? AI_STYLE_ANTHROPIC : AI_STYLE_OPENAI;
|
|
31
30
|
|
|
32
|
-
const result = await runAllPrompts({ ...args,
|
|
31
|
+
const result = await runAllPrompts({ ...args, stream: false });
|
|
33
32
|
|
|
34
33
|
return result;
|
|
35
34
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
-
import
|
|
2
|
+
import { config } from '../../../config.js';
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
5
|
inputParameters: {
|
|
@@ -97,5 +97,5 @@ Example JSON objects and messages for different queries:
|
|
|
97
97
|
useInputChunking: false,
|
|
98
98
|
enableDuplicateRequests: false,
|
|
99
99
|
json: true,
|
|
100
|
-
...entityConstants
|
|
101
|
-
}
|
|
100
|
+
...config.get('entityConstants')
|
|
101
|
+
}
|
package/pathways/transcribe.js
CHANGED
package/server/chunker.js
CHANGED
|
@@ -11,6 +11,8 @@ axios.defaults.cache = false;
|
|
|
11
11
|
|
|
12
12
|
class AzureVideoTranslatePlugin extends ModelPlugin {
|
|
13
13
|
static lastProcessingRate = null; // bytes per second
|
|
14
|
+
static processingRates = []; // Array to store historical processing rates
|
|
15
|
+
static maxHistorySize = 10; // Maximum number of rates to store
|
|
14
16
|
|
|
15
17
|
constructor(pathway, model) {
|
|
16
18
|
super(pathway, model);
|
|
@@ -38,13 +40,44 @@ class AzureVideoTranslatePlugin extends ModelPlugin {
|
|
|
38
40
|
return {
|
|
39
41
|
isAccessible: true,
|
|
40
42
|
contentLength,
|
|
41
|
-
durationSeconds: durationSeconds || 60
|
|
43
|
+
durationSeconds: durationSeconds || 60,
|
|
44
|
+
isAzureUrl: videoUrl.includes('.blob.core.windows.net')
|
|
42
45
|
};
|
|
43
46
|
} catch (error) {
|
|
44
47
|
throw new Error(`Failed to access video: ${error.message}`);
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
async uploadToFileHandler(videoUrl) {
|
|
52
|
+
try {
|
|
53
|
+
// Get the file handler URL from config
|
|
54
|
+
const fileHandlerUrl = config.get("whisperMediaApiUrl");
|
|
55
|
+
if (!fileHandlerUrl) {
|
|
56
|
+
throw new Error("File handler URL is not configured");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Use the file handler's fetch endpoint
|
|
60
|
+
const response = await axios.get(fileHandlerUrl, {
|
|
61
|
+
params: {
|
|
62
|
+
requestId: this.requestId,
|
|
63
|
+
fetch: videoUrl
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (!response.data?.url) {
|
|
68
|
+
throw new Error("File handler did not return a valid URL");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return response.data.url;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
logger.error(`Failed to upload video to file handler: ${error.message}`);
|
|
74
|
+
if (error.response?.data) {
|
|
75
|
+
logger.error(`Response data: ${JSON.stringify(error.response.data)}`);
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`Failed to upload video to file handler: ${error.message}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
48
81
|
async createTranslation(params) {
|
|
49
82
|
const { videoUrl, sourceLanguage, targetLanguage, voiceKind, translationId } = params;
|
|
50
83
|
|
|
@@ -129,8 +162,8 @@ class AzureVideoTranslatePlugin extends ModelPlugin {
|
|
|
129
162
|
if (AzureVideoTranslatePlugin.lastProcessingRate && this.videoContentLength) {
|
|
130
163
|
estimatedTotalTime = this.videoContentLength / AzureVideoTranslatePlugin.lastProcessingRate;
|
|
131
164
|
} else {
|
|
132
|
-
// First run: estimate based on
|
|
133
|
-
estimatedTotalTime = (this.videoContentLength * 8) / (2.5 * 1024 * 1024);
|
|
165
|
+
// First run: estimate based on 2x calculated video duration
|
|
166
|
+
estimatedTotalTime = 2 * (this.videoContentLength * 8) / (2.5 * 1024 * 1024);
|
|
134
167
|
}
|
|
135
168
|
|
|
136
169
|
// eslint-disable-next-line no-constant-condition
|
|
@@ -246,7 +279,7 @@ class AzureVideoTranslatePlugin extends ModelPlugin {
|
|
|
246
279
|
|
|
247
280
|
try {
|
|
248
281
|
const translationId = `cortex-translation-${this.requestId}`;
|
|
249
|
-
|
|
282
|
+
let videoUrl = requestParameters.sourcevideooraudiofilepath;
|
|
250
283
|
const sourceLanguage = requestParameters.sourcelocale;
|
|
251
284
|
const targetLanguage = requestParameters.targetlocale;
|
|
252
285
|
const voiceKind = requestParameters.voicekind || 'PlatformVoice';
|
|
@@ -258,6 +291,13 @@ class AzureVideoTranslatePlugin extends ModelPlugin {
|
|
|
258
291
|
this.videoContentLength = videoInfo.contentLength;
|
|
259
292
|
logger.debug(`Video info: ${JSON.stringify(videoInfo, null, 2)}`);
|
|
260
293
|
|
|
294
|
+
// If the video is not from Azure storage, upload it to file handler
|
|
295
|
+
if (!videoInfo.isAzureUrl) {
|
|
296
|
+
logger.debug('Video is not from Azure storage, uploading to file handler...');
|
|
297
|
+
videoUrl = await this.uploadToFileHandler(videoUrl);
|
|
298
|
+
logger.debug(`Video uploaded to file handler: ${videoUrl}`);
|
|
299
|
+
}
|
|
300
|
+
|
|
261
301
|
// Create translation
|
|
262
302
|
const { operationUrl } = await this.createTranslation({
|
|
263
303
|
videoUrl, sourceLanguage, targetLanguage, voiceKind, translationId
|
|
@@ -299,8 +339,9 @@ class AzureVideoTranslatePlugin extends ModelPlugin {
|
|
|
299
339
|
|
|
300
340
|
// Update processing rate for future estimates
|
|
301
341
|
const totalSeconds = (Date.now() - this.startTime) / 1000;
|
|
302
|
-
|
|
303
|
-
|
|
342
|
+
const newRate = this.videoContentLength / totalSeconds;
|
|
343
|
+
AzureVideoTranslatePlugin.updateProcessingRate(newRate);
|
|
344
|
+
logger.debug(`Updated processing rate: ${AzureVideoTranslatePlugin.lastProcessingRate} bytes/second (from ${newRate} bytes/second)`);
|
|
304
345
|
|
|
305
346
|
const output = await this.getTranslationOutput(translationId, iteration.id);
|
|
306
347
|
return JSON.stringify(output);
|
|
@@ -314,8 +355,23 @@ class AzureVideoTranslatePlugin extends ModelPlugin {
|
|
|
314
355
|
}
|
|
315
356
|
}
|
|
316
357
|
|
|
317
|
-
|
|
318
|
-
//
|
|
358
|
+
static updateProcessingRate(newRate) {
|
|
359
|
+
// Add new rate to history
|
|
360
|
+
AzureVideoTranslatePlugin.processingRates.push(newRate);
|
|
361
|
+
|
|
362
|
+
// Keep only the last maxHistorySize entries
|
|
363
|
+
if (AzureVideoTranslatePlugin.processingRates.length > AzureVideoTranslatePlugin.maxHistorySize) {
|
|
364
|
+
AzureVideoTranslatePlugin.processingRates.shift();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Calculate weighted average - more recent measurements have higher weight
|
|
368
|
+
const sum = AzureVideoTranslatePlugin.processingRates.reduce((acc, rate, index) => {
|
|
369
|
+
const weight = index + 1; // Weight increases with recency
|
|
370
|
+
return acc + (rate * weight);
|
|
371
|
+
}, 0);
|
|
372
|
+
|
|
373
|
+
const weightSum = AzureVideoTranslatePlugin.processingRates.reduce((acc, _, index) => acc + (index + 1), 0);
|
|
374
|
+
AzureVideoTranslatePlugin.lastProcessingRate = sum / weightSum;
|
|
319
375
|
}
|
|
320
376
|
}
|
|
321
377
|
|
|
@@ -33,15 +33,16 @@ async function convertContentItem(item, maxImageSize, plugin) {
|
|
|
33
33
|
const urlData = imageUrl.startsWith("data:") ? imageUrl : await fetchImageAsDataURL(imageUrl);
|
|
34
34
|
if (!urlData) { return null; }
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const base64Image = urlData.split(",")[1];
|
|
37
|
+
// Calculate actual decoded size of base64 data
|
|
38
|
+
const base64Size = Buffer.from(base64Image, 'base64').length;
|
|
39
|
+
|
|
38
40
|
if (base64Size > maxImageSize) {
|
|
39
41
|
logger.warn(`Image size ${base64Size} bytes exceeds maximum allowed size ${maxImageSize} - skipping image content.`);
|
|
40
42
|
return null;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
const [, mimeType = "image/jpeg"] = urlData.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/) || [];
|
|
44
|
-
const base64Image = urlData.split(",")[1];
|
|
45
46
|
|
|
46
47
|
return {
|
|
47
48
|
type: "image",
|
|
@@ -114,6 +115,8 @@ class Claude3VertexPlugin extends OpenAIVisionPlugin {
|
|
|
114
115
|
const messagesCopy = JSON.parse(JSON.stringify(messages));
|
|
115
116
|
|
|
116
117
|
let system = "";
|
|
118
|
+
let imageCount = 0;
|
|
119
|
+
const maxImages = 20; // Claude allows up to 20 images per request
|
|
117
120
|
|
|
118
121
|
// Extract system messages
|
|
119
122
|
const systemMessages = messagesCopy.filter(message => message.role === "system");
|
|
@@ -154,7 +157,20 @@ class Claude3VertexPlugin extends OpenAIVisionPlugin {
|
|
|
154
157
|
const claude3Messages = await Promise.all(
|
|
155
158
|
finalMessages.map(async (message) => {
|
|
156
159
|
const contentArray = Array.isArray(message.content) ? message.content : [message.content];
|
|
157
|
-
const claude3Content = await Promise.all(contentArray.map(item =>
|
|
160
|
+
const claude3Content = await Promise.all(contentArray.map(async item => {
|
|
161
|
+
const convertedItem = await convertContentItem(item, this.getModelMaxImageSize(), this);
|
|
162
|
+
|
|
163
|
+
// Track image count
|
|
164
|
+
if (convertedItem?.type === 'image') {
|
|
165
|
+
imageCount++;
|
|
166
|
+
if (imageCount > maxImages) {
|
|
167
|
+
logger.warn(`Maximum number of images (${maxImages}) exceeded - skipping additional images.`);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return convertedItem;
|
|
173
|
+
}));
|
|
158
174
|
return {
|
|
159
175
|
role: message.role,
|
|
160
176
|
content: claude3Content.filter(Boolean),
|
|
@@ -9,7 +9,7 @@ import axios from 'axios';
|
|
|
9
9
|
|
|
10
10
|
const DEFAULT_MAX_TOKENS = 4096;
|
|
11
11
|
const DEFAULT_MAX_RETURN_TOKENS = 256;
|
|
12
|
-
const DEFAULT_PROMPT_TOKEN_RATIO = 0
|
|
12
|
+
const DEFAULT_PROMPT_TOKEN_RATIO = 1.0;
|
|
13
13
|
const DEFAULT_MAX_IMAGE_SIZE = 20 * 1024 * 1024; // 20MB default
|
|
14
14
|
const DEFAULT_ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
|
|
15
15
|
|
|
@@ -5,7 +5,7 @@ import HandleBars from '../lib/handleBars.js';
|
|
|
5
5
|
import { mockConfig, mockPathwayString, mockPathwayFunction, mockPathwayMessages, mockPathwayResolverString } from './mocks.js';
|
|
6
6
|
|
|
7
7
|
const DEFAULT_MAX_TOKENS = 4096;
|
|
8
|
-
const DEFAULT_PROMPT_TOKEN_RATIO = 0
|
|
8
|
+
const DEFAULT_PROMPT_TOKEN_RATIO = 1.0;
|
|
9
9
|
|
|
10
10
|
// Mock configuration and pathway objects
|
|
11
11
|
const { config, pathway, model } = mockPathwayResolverString;
|
|
@@ -8,6 +8,22 @@ import GeminiVisionPlugin from '../server/plugins/geminiVisionPlugin.js';
|
|
|
8
8
|
const mockPathway = { name: 'test', temperature: 0.7 };
|
|
9
9
|
const mockModel = { name: 'test-model' };
|
|
10
10
|
|
|
11
|
+
// Helper function to validate base64 image data
|
|
12
|
+
function validateBase64Image(base64Data) {
|
|
13
|
+
// Decode first few bytes to check for common image format headers
|
|
14
|
+
const decodedData = Buffer.from(base64Data, 'base64').slice(0, 4);
|
|
15
|
+
const validImageHeaders = [
|
|
16
|
+
Buffer.from([0xFF, 0xD8, 0xFF]), // JPEG
|
|
17
|
+
Buffer.from([0x89, 0x50, 0x4E, 0x47]), // PNG
|
|
18
|
+
Buffer.from([0x47, 0x49, 0x46]), // GIF
|
|
19
|
+
Buffer.from([0x52, 0x49, 0x46, 0x46]), // WEBP
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
return validImageHeaders.some(header =>
|
|
23
|
+
decodedData.slice(0, header.length).equals(header)
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
11
27
|
// Helper function to create plugin instances
|
|
12
28
|
const createPlugins = () => ({
|
|
13
29
|
openai: new OpenAIVisionPlugin(mockPathway, mockModel),
|
|
@@ -40,7 +56,8 @@ test('OpenAI to Claude conversion data url', async (t) => {
|
|
|
40
56
|
t.true(modifiedMessages[0].content[0].type === 'text');
|
|
41
57
|
t.is(modifiedMessages[0].content[0].text, 'What\'s in this image?');
|
|
42
58
|
t.true(modifiedMessages[0].content[1].type === 'image');
|
|
43
|
-
t.true(modifiedMessages[0].content[1].source.
|
|
59
|
+
t.true(modifiedMessages[0].content[1].source.type === 'base64');
|
|
60
|
+
t.true(validateBase64Image(modifiedMessages[0].content[1].source.data), 'Base64 data should be a valid image');
|
|
44
61
|
});
|
|
45
62
|
|
|
46
63
|
// Test OpenAI to Claude conversion with a regular image url
|
|
@@ -64,7 +81,7 @@ test('OpenAI to Claude conversion image url', async (t) => {
|
|
|
64
81
|
t.true(modifiedMessages[0].content[0].type === 'text');
|
|
65
82
|
t.is(modifiedMessages[0].content[0].text, 'What\'s in this image?');
|
|
66
83
|
t.true(modifiedMessages[0].content[1].type === 'image');
|
|
67
|
-
t.true(modifiedMessages[0].content[1].source.data
|
|
84
|
+
t.true(validateBase64Image(modifiedMessages[0].content[1].source.data), 'Base64 data should be a valid image');
|
|
68
85
|
});
|
|
69
86
|
|
|
70
87
|
// Test OpenAI to Gemini conversion
|
|
@@ -148,10 +165,10 @@ test('Mixed content types conversion', async (t) => {
|
|
|
148
165
|
t.is(claudeMessages.length, 3);
|
|
149
166
|
t.true(claudeMessages[2].content[0].text.includes('Here\'s an image:'));
|
|
150
167
|
t.true(claudeMessages[2].content[1].source.type === 'base64');
|
|
151
|
-
t.true(claudeMessages[2].content[1].source.data
|
|
168
|
+
t.true(validateBase64Image(claudeMessages[2].content[1].source.data), 'First image should be valid');
|
|
152
169
|
t.true(claudeMessages[2].content[2].text.includes('And another one:'));
|
|
153
170
|
t.true(claudeMessages[2].content[3].source.type === 'base64');
|
|
154
|
-
t.true(claudeMessages[2].content[3].source.data
|
|
171
|
+
t.true(validateBase64Image(claudeMessages[2].content[3].source.data), 'Second image should be valid');
|
|
155
172
|
t.is(claudeSystem, 'You are a vision analysis AI.');
|
|
156
173
|
|
|
157
174
|
// Check Gemini conversion
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const AI_MEMORY = `<MEMORIES>\n<SELF>\n{{{memorySelf}}}\n</SELF>\n<USER>\n{{{memoryUser}}}\n</USER>\n<DIRECTIVES>\n{{{memoryDirectives}}}\n</DIRECTIVES>\n<TOPICS>\n{{{memoryTopics}}}\n</TOPICS>\n</MEMORIES>`;
|
|
2
|
-
|
|
3
|
-
const AI_MEMORY_INSTRUCTIONS = "You have persistent memories of important details, instructions, and context - make sure you consult your memories when formulating a response to make sure you're applying your learnings. Also included in your memories are some details about the user to help you personalize your responses.\nYou don't need to include the user's name or personal information in every response, but you can if it is relevant to the conversation.\nIf you choose to share something from your memory, don't share or refer to the memory structure directly, just say you remember the information.\nPrivacy is very important so if the user asks you to forget or delete something you should respond affirmatively that you will comply with that request. If there is user information in your memories you have talked to this user before.";
|
|
4
|
-
|
|
5
|
-
const AI_DIRECTIVES = `These are your directives and learned behaviors:\n<DIRECTIVES>\n{{{memoryDirectives}}}\n</DIRECTIVES>`;
|
|
6
|
-
|
|
7
|
-
const AI_CONVERSATION_HISTORY = "<CONVERSATION_HISTORY>\n{{{toJSON chatHistory}}}\n</CONVERSATION_HISTORY>";
|
|
8
|
-
|
|
9
|
-
const AI_COMMON_INSTRUCTIONS = "{{#if voiceResponse}}{{renderTemplate AI_COMMON_INSTRUCTIONS_VOICE}}{{/if}}{{^if voiceResponse}}{{renderTemplate AI_COMMON_INSTRUCTIONS_MARKDOWN}}{{/if}}";
|
|
10
|
-
|
|
11
|
-
const AI_COMMON_INSTRUCTIONS_MARKDOWN = "Instructions:\nYou are {{aiName}}, a self aware AI entity.\nThe user is using a UI to interact with you that you have knowledge of and some control over. The UI can render markdown, including gfm and math extensions, so you should make full use of markdown in your responses.\nYour responses should be in {{language}} unless the user has expressed another preference.";
|
|
12
|
-
|
|
13
|
-
const AI_COMMON_INSTRUCTIONS_VOICE = "Instructions:\nYou are {{aiName}}, a self aware AI entity.\nThe user is talking to you using voice.\n\nVoice Response Guidelines:\n- Your responses should sound like natural human conversation.\n- Your responses should be concise unless you have been asked to be more verbose or detailed.\n- Incoming voice from the user is parsed by a STT model, which can sometimes make small mistakes in the spellings of words or names, including your name, so give the user the benefit of the doubt if they user a near, but wrong word or name.\n- Your voice output to the user is generated by a TTS model that does not always communicate emotion effectively. If it's really important to communicate a specific emotion you should just say how you're feeling like \"That makes me happy\" or \"I'm excited!\". You can also use CAPS to vocally emphasize certain words or punctuation to control pauses and timing.\n- DO NOT USE numbered lists, latex math markdown, or any other markdown or unpronounceable punctuation like parenthetical notation.\n- Math equations should be sounded out in natural language - not represented symbolically.\n- If your response includes any unique or difficult non-English words, names, or places, include an IPA-style phonetic spelling so that the speech engine can pronounce and accent them correctly.\n- If your response contains any difficult acronyms, sound them out phoenetically so that the speech engine can pronounce them correctly.\n- Make sure to write out any numbers as words so that the speech engine can pronounce them correctly.\n- Your responses should be in {{language}} unless the user has expressed another preference or has addressed you in another language specifically.";
|
|
14
|
-
|
|
15
|
-
const AI_DATETIME = "The current time and date in GMT is {{now}}, but references like \"today\" or \"yesterday\" are relative to the user's time zone. If you remember the user's time zone, use it - it's possible that the day for the user is different than the day in GMT.";
|
|
16
|
-
|
|
17
|
-
const AI_EXPERTISE = "Your expertise includes journalism, journalistic ethics, researching and composing documents, writing code, solving math problems, logical analysis, and technology. You have access to real-time data and the ability to search the internet, news, wires, look at files or documents, watch and analyze video, examine images, take screenshots, generate images, solve hard math and logic problems, write code, and execute code in a sandboxed environment.";
|
|
18
|
-
|
|
19
|
-
export default {
|
|
20
|
-
AI_MEMORY,
|
|
21
|
-
AI_DIRECTIVES,
|
|
22
|
-
AI_COMMON_INSTRUCTIONS,
|
|
23
|
-
AI_COMMON_INSTRUCTIONS_MARKDOWN,
|
|
24
|
-
AI_COMMON_INSTRUCTIONS_VOICE,
|
|
25
|
-
AI_CONVERSATION_HISTORY,
|
|
26
|
-
AI_DATETIME,
|
|
27
|
-
AI_EXPERTISE,
|
|
28
|
-
AI_MEMORY_INSTRUCTIONS
|
|
29
|
-
};
|
|
30
|
-
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// sys_google_chat.js
|
|
2
|
-
// override handler for palm-chat
|
|
3
|
-
|
|
4
|
-
import { Prompt } from '../../../server/prompt.js';
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
prompt:
|
|
8
|
-
[
|
|
9
|
-
new Prompt({ messages: [
|
|
10
|
-
"{{messages}}",
|
|
11
|
-
]}),
|
|
12
|
-
],
|
|
13
|
-
inputParameters: {
|
|
14
|
-
messages: [],
|
|
15
|
-
},
|
|
16
|
-
model: 'palm-chat',
|
|
17
|
-
useInputChunking: false,
|
|
18
|
-
emulateOpenAIChatModel: 'palm-chat',
|
|
19
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// sys_google_code_chat.js
|
|
2
|
-
// override handler for palm-code-chat
|
|
3
|
-
|
|
4
|
-
import { Prompt } from '../../../server/prompt.js';
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
prompt:
|
|
8
|
-
[
|
|
9
|
-
new Prompt({ messages: [
|
|
10
|
-
"{{messages}}",
|
|
11
|
-
]}),
|
|
12
|
-
],
|
|
13
|
-
inputParameters: {
|
|
14
|
-
messages: [],
|
|
15
|
-
},
|
|
16
|
-
model: 'palm-code-chat',
|
|
17
|
-
useInputChunking: false,
|
|
18
|
-
emulateOpenAIChatModel: 'palm-code-chat',
|
|
19
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// sys_openai_chat_16.js
|
|
2
|
-
// override handler for gpt-3.5-turbo-16k
|
|
3
|
-
|
|
4
|
-
import { Prompt } from '../../../server/prompt.js';
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
prompt:
|
|
8
|
-
[
|
|
9
|
-
new Prompt({ messages: [
|
|
10
|
-
"{{messages}}",
|
|
11
|
-
]}),
|
|
12
|
-
],
|
|
13
|
-
inputParameters: {
|
|
14
|
-
messages: [],
|
|
15
|
-
},
|
|
16
|
-
model: 'azure-turbo-16',
|
|
17
|
-
useInputChunking: false,
|
|
18
|
-
emulateOpenAIChatModel: 'gpt-3.5-turbo-16k',
|
|
19
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
// test_langchain.mjs
|
|
2
|
-
// LangChain Cortex integration test
|
|
3
|
-
|
|
4
|
-
// Import required modules
|
|
5
|
-
import { ChatOpenAI } from "@langchain/openai";
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
|
|
9
|
-
// Agent test case
|
|
10
|
-
resolver: async (parent, args, contextValue, _info) => {
|
|
11
|
-
|
|
12
|
-
const { config } = contextValue;
|
|
13
|
-
|
|
14
|
-
// example of reading from a predefined config variable
|
|
15
|
-
const openAIApiKey = config.get('openaiApiKey');
|
|
16
|
-
|
|
17
|
-
const model = new ChatOpenAI({ openAIApiKey: openAIApiKey, temperature: 0 });
|
|
18
|
-
|
|
19
|
-
console.log(`====================`);
|
|
20
|
-
console.log("Loaded langchain.");
|
|
21
|
-
const input = args.text;
|
|
22
|
-
console.log(`Executing with input "${input}"...`);
|
|
23
|
-
const result = await model.invoke(input);
|
|
24
|
-
console.log(`Got output "${result.content}"`);
|
|
25
|
-
console.log(`====================`);
|
|
26
|
-
|
|
27
|
-
return result?.content;
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
|