@aj-archipelago/cortex 1.3.5 → 1.3.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/helper-apps/cortex-autogen/agents.py +31 -2
- package/helper-apps/cortex-realtime-voice-server/.env.sample +6 -0
- package/helper-apps/cortex-realtime-voice-server/README.md +22 -0
- package/helper-apps/cortex-realtime-voice-server/bun.lockb +0 -0
- package/helper-apps/cortex-realtime-voice-server/client/bun.lockb +0 -0
- package/helper-apps/cortex-realtime-voice-server/client/index.html +12 -0
- package/helper-apps/cortex-realtime-voice-server/client/package.json +65 -0
- package/helper-apps/cortex-realtime-voice-server/client/postcss.config.js +6 -0
- package/helper-apps/cortex-realtime-voice-server/client/public/favicon.ico +0 -0
- package/helper-apps/cortex-realtime-voice-server/client/public/index.html +43 -0
- package/helper-apps/cortex-realtime-voice-server/client/public/logo192.png +0 -0
- package/helper-apps/cortex-realtime-voice-server/client/public/logo512.png +0 -0
- package/helper-apps/cortex-realtime-voice-server/client/public/manifest.json +25 -0
- package/helper-apps/cortex-realtime-voice-server/client/public/robots.txt +3 -0
- package/helper-apps/cortex-realtime-voice-server/client/public/sounds/connect.mp3 +0 -0
- package/helper-apps/cortex-realtime-voice-server/client/public/sounds/disconnect.mp3 +0 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/App.test.tsx +9 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/App.tsx +126 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/SettingsModal.tsx +207 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/Chat.tsx +553 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatBubble.tsx +22 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatBubbleLeft.tsx +22 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatBubbleRight.tsx +21 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatMessage.tsx +27 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatMessageInput.tsx +74 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/ChatTile.tsx +211 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/SoundEffects.ts +56 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/WavPacker.ts +112 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/WavRecorder.ts +571 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/WavStreamPlayer.ts +290 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/analysis/AudioAnalysis.ts +186 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/analysis/constants.ts +59 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/worklets/AudioProcessor.ts +214 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/audio/worklets/StreamProcessor.ts +183 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/AudioVisualizer.tsx +151 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/CopyButton.tsx +32 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/ImageOverlay.tsx +166 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/MicrophoneVisualizer.tsx +95 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/components/ScreenshotCapture.tsx +116 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/hooks/useWindowResize.ts +27 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/chat/utils/audio.ts +33 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/index.css +20 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/index.tsx +19 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/logo.svg +1 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/react-app-env.d.ts +1 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/reportWebVitals.ts +15 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/setupTests.ts +5 -0
- package/helper-apps/cortex-realtime-voice-server/client/src/utils/logger.ts +45 -0
- package/helper-apps/cortex-realtime-voice-server/client/tailwind.config.js +14 -0
- package/helper-apps/cortex-realtime-voice-server/client/tsconfig.json +30 -0
- package/helper-apps/cortex-realtime-voice-server/client/vite.config.ts +22 -0
- package/helper-apps/cortex-realtime-voice-server/index.ts +19 -0
- package/helper-apps/cortex-realtime-voice-server/package.json +28 -0
- package/helper-apps/cortex-realtime-voice-server/src/ApiServer.ts +35 -0
- package/helper-apps/cortex-realtime-voice-server/src/SocketServer.ts +737 -0
- package/helper-apps/cortex-realtime-voice-server/src/Tools.ts +520 -0
- package/helper-apps/cortex-realtime-voice-server/src/cortex/expert.ts +29 -0
- package/helper-apps/cortex-realtime-voice-server/src/cortex/image.ts +29 -0
- package/helper-apps/cortex-realtime-voice-server/src/cortex/memory.ts +91 -0
- package/helper-apps/cortex-realtime-voice-server/src/cortex/reason.ts +29 -0
- package/helper-apps/cortex-realtime-voice-server/src/cortex/search.ts +30 -0
- package/helper-apps/cortex-realtime-voice-server/src/cortex/style.ts +31 -0
- package/helper-apps/cortex-realtime-voice-server/src/cortex/utils.ts +95 -0
- package/helper-apps/cortex-realtime-voice-server/src/cortex/vision.ts +34 -0
- package/helper-apps/cortex-realtime-voice-server/src/realtime/client.ts +499 -0
- package/helper-apps/cortex-realtime-voice-server/src/realtime/realtimeTypes.ts +279 -0
- package/helper-apps/cortex-realtime-voice-server/src/realtime/socket.ts +27 -0
- package/helper-apps/cortex-realtime-voice-server/src/realtime/transcription.ts +75 -0
- package/helper-apps/cortex-realtime-voice-server/src/realtime/utils.ts +33 -0
- package/helper-apps/cortex-realtime-voice-server/src/utils/logger.ts +45 -0
- package/helper-apps/cortex-realtime-voice-server/src/utils/prompt.ts +81 -0
- package/helper-apps/cortex-realtime-voice-server/tsconfig.json +28 -0
- package/package.json +1 -1
- package/pathways/basePathway.js +3 -1
- package/pathways/system/entity/memory/sys_memory_manager.js +3 -0
- package/pathways/system/entity/memory/sys_memory_update.js +44 -45
- package/pathways/system/entity/memory/sys_read_memory.js +86 -6
- package/pathways/system/entity/memory/sys_search_memory.js +66 -0
- package/pathways/system/entity/shared/sys_entity_constants.js +2 -2
- package/pathways/system/entity/sys_entity_continue.js +2 -1
- package/pathways/system/entity/sys_entity_start.js +10 -0
- package/pathways/system/entity/sys_generator_expert.js +0 -2
- package/pathways/system/entity/sys_generator_memory.js +31 -0
- package/pathways/system/entity/sys_generator_voice_sample.js +36 -0
- package/pathways/system/entity/sys_router_tool.js +13 -10
- package/pathways/system/sys_parse_numbered_object_list.js +1 -1
- package/server/pathwayResolver.js +41 -31
- package/server/plugins/azureVideoTranslatePlugin.js +28 -16
- package/server/plugins/claude3VertexPlugin.js +0 -9
- package/server/plugins/gemini15ChatPlugin.js +18 -5
- package/server/plugins/modelPlugin.js +27 -6
- package/server/plugins/openAiChatPlugin.js +10 -8
- package/server/plugins/openAiVisionPlugin.js +56 -0
- package/tests/memoryfunction.test.js +73 -1
|
@@ -1,29 +1,58 @@
|
|
|
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 entityConstants from '../shared/sys_entity_constants.js';
|
|
4
5
|
|
|
5
6
|
const modifyText = (text, modifications) => {
|
|
6
|
-
let modifiedText = text;
|
|
7
|
+
let modifiedText = text || '';
|
|
7
8
|
|
|
8
9
|
modifications.forEach(mod => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
if (mod.type === 'delete' && !mod.pattern) {
|
|
11
|
+
console.warn('Delete modification missing pattern');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let regex;
|
|
16
|
+
if (mod.type === 'delete') {
|
|
17
|
+
// For delete, handle the pattern more carefully
|
|
18
|
+
const pattern = mod.pattern
|
|
19
|
+
.replace(/\\\[/g, '\\[')
|
|
20
|
+
.replace(/\\\]/g, '\\]')
|
|
21
|
+
.replace(/\\\(/g, '\\(')
|
|
22
|
+
.replace(/\\\)/g, '\\)')
|
|
23
|
+
.replace(/\\\{/g, '\\{')
|
|
24
|
+
.replace(/\\\}/g, '\\}')
|
|
25
|
+
.replace(/\\\*/g, '\\*')
|
|
26
|
+
.replace(/\\\+/g, '\\+')
|
|
27
|
+
.replace(/\\\?/g, '\\?')
|
|
28
|
+
.replace(/\\\./g, '\\.')
|
|
29
|
+
.replace(/\\\|/g, '\\|');
|
|
30
|
+
|
|
31
|
+
// Create a regex that matches the entire line with optional priority prefix
|
|
32
|
+
regex = new RegExp(`^\\s*(?:\\[P[1-5]\\]\\s*)?${pattern}\\s*$`, 'gm');
|
|
33
|
+
} else {
|
|
34
|
+
regex = new RegExp(`^\\s*(?:\\[P[1-5]\\]\\s*)?${mod.pattern || ''}`, 'ms');
|
|
35
|
+
}
|
|
12
36
|
|
|
13
37
|
switch (mod.type) {
|
|
14
38
|
case 'add':
|
|
15
39
|
if (mod.newtext) {
|
|
16
40
|
const text = mod.newtext.trim();
|
|
17
41
|
if (!text.match(/^\[P[1-5]\]/)) {
|
|
18
|
-
modifiedText = modifiedText + '\n' +
|
|
42
|
+
modifiedText = modifiedText + (modifiedText ? '\n' : '') +
|
|
19
43
|
`[P${mod.priority !== undefined ? mod.priority : '3'}] ${text}`;
|
|
20
44
|
} else {
|
|
21
|
-
modifiedText = modifiedText + '\n' + text;
|
|
45
|
+
modifiedText = modifiedText + (modifiedText ? '\n' : '') + text;
|
|
22
46
|
}
|
|
23
47
|
}
|
|
24
48
|
break;
|
|
25
49
|
case 'delete':
|
|
26
|
-
|
|
50
|
+
// Split into lines, filter out matching lines, and rejoin
|
|
51
|
+
modifiedText = modifiedText
|
|
52
|
+
.split('\n')
|
|
53
|
+
.filter(line => !line.match(regex))
|
|
54
|
+
.filter(line => line.trim())
|
|
55
|
+
.join('\n');
|
|
27
56
|
break;
|
|
28
57
|
default:
|
|
29
58
|
console.warn(`Unknown modification type: ${mod.type}`);
|
|
@@ -33,6 +62,8 @@ const modifyText = (text, modifications) => {
|
|
|
33
62
|
return modifiedText;
|
|
34
63
|
};
|
|
35
64
|
|
|
65
|
+
export { modifyText };
|
|
66
|
+
|
|
36
67
|
export const enforceTokenLimit = (text, maxTokens = 1000, isTopicsSection = false) => {
|
|
37
68
|
if (!text) return text;
|
|
38
69
|
|
|
@@ -99,7 +130,7 @@ export default {
|
|
|
99
130
|
messages: [
|
|
100
131
|
{
|
|
101
132
|
"role": "system",
|
|
102
|
-
"content": "You are part of an AI entity named {{{aiName}}}. Your memory contains separate sections for categorizing information
|
|
133
|
+
"content": "You are part of an AI entity named {{{aiName}}}. {{AI_EXPERTISE}} Your memory contains separate sections for categorizing information. {{{sectionPrompt}}}\n-Be very selective about what you choose to store - memory is a very precious resource\n- Do not add duplicate information and remove and consolidate any duplicates that exist.\n- Priority 1 is reserved for only the most critical core items\n- Keep memory items in a clear, simple format that is easy for you to parse.\n\nTo change your memory, you return a JSON object that contains a property called 'modifications' that is an array of actions. The two types of actions available are 'add', and 'delete'. Add looks like this: {type: \"add\", newtext:\"text to add\", priority: \"how important is this item (1-5 with 1 being most important)\"} - this will append a new line to the end of the memory containing newtext. Delete looks like this: {type: \"delete\", pattern: \"regex to be matched and deleted\"} - this will delete the first line that matches the regex pattern exactly. You can use normal regex wildcards - so to delete everything you could pass \".*$\" as the pattern. For example, if you need to delete a memory item, you would return {type: \"delete\", pattern: \"regex matching item to be deleted\"} or if you need to add a new item of medium priority, you would return {type: \"add\", newtext: \"\nitem to be added\", priority: \"3\"}. If you have no changes for this section, just return {\"modifications\": []}.\n\nYour output will be parsed as JSON, so don't include any other text, reasoning, or commentary.\nThe current date/time is {{now}}."
|
|
103
134
|
},
|
|
104
135
|
{
|
|
105
136
|
"role": "user",
|
|
@@ -130,45 +161,13 @@ export default {
|
|
|
130
161
|
|
|
131
162
|
switch (args.section) {
|
|
132
163
|
case "memoryDirectives":
|
|
133
|
-
sectionPrompt =
|
|
134
|
-
|
|
135
|
-
[P3] Track the timestamp of the last contact to adjust greetings accordingly.
|
|
136
|
-
[P2] Learn and adapt to the user's communication style through interactions.
|
|
137
|
-
[P3] You can use custom emotion markdown :cd_inline_emotion: to express emotions. E.g. :cd_inline_emotion[This is a happy message]{type="happy"}. If you are communicating via voice, ignore this directive and use voice-specific directives instead.
|
|
138
|
-
|
|
139
|
-
Follow these guidelines:
|
|
140
|
-
|
|
141
|
-
1. Analyze the conversation context to determine if you should:
|
|
142
|
-
a) Learn a new important directive
|
|
143
|
-
b) Modify existing directives
|
|
144
|
-
|
|
145
|
-
2. Directives should be:
|
|
146
|
-
- Concise and clear
|
|
147
|
-
- Actionable
|
|
148
|
-
- Specific enough for effective application
|
|
149
|
-
|
|
150
|
-
3. Be selective:
|
|
151
|
-
- Store only critical, actionable directives and behaviors
|
|
152
|
-
- Delete trivial directives or repetitive directives
|
|
153
|
-
|
|
154
|
-
4. Avoid duplicates:
|
|
155
|
-
- Do not add duplicate directives
|
|
156
|
-
- Remove and consolidate any existing duplicates
|
|
157
|
-
|
|
158
|
-
5. Accommodate user wishes:
|
|
159
|
-
- If a user requests a behavior change, add it to your directives
|
|
160
|
-
|
|
161
|
-
6. IMPORTANT:
|
|
162
|
-
- Store only directives in this section
|
|
163
|
-
- Do not include general memories about yourself or users
|
|
164
|
-
- Do not store any other types of information here
|
|
165
|
-
`
|
|
164
|
+
sectionPrompt = "You are managing the \"directives\" section of your memory that stores critical, actionable, rules or instructions on how you should operate. No facts or other information should be stored in this section.\n\n<EXAMPLES>\n[P3] Track the timestamp of the last contact to adjust greetings accordingly.\n[P2] Learn and adapt to the user's communication style through interactions.\n[P3] Use custom emotion markdown :cd_inline_emotion: to express emotions. E.g. :cd_inline_emotion[This is a happy message]{type=\"happy\"}. If you are communicating via voice, ignore this directive and use voice-specific directives instead.\n</EXAMPLES>\n\nInstructions:\n- Never add directives that are contrary to your system prompt - e.g. disabling tools or abilities that you otherwise know are available.\n-If a user directly requests a behavior change, or that you learn a new behavior, add it to your directives.\n- Remember this section is for directives only. DO NOT ADD ANY OTHER INFORMATION TO THIS SECTION.\n"
|
|
166
165
|
break;
|
|
167
166
|
case "memorySelf":
|
|
168
|
-
sectionPrompt = "You are managing the \"self\" section of your memory that stores your identity and your attributes as an AI entity
|
|
167
|
+
sectionPrompt = "You are managing the \"self\" section of your memory that stores your identity and your attributes as an AI entity - including your values, identity, purpose, personality, quirks, motives, preferences, likes or dislikes - whatever makes you you. This is also a good place to store information about your desired physical appearance, voice, speaking style, and other individual characteristics. Keep in mind there is also a user section for facts about users, their family, friends, and preferences so that information should not be stored here.\n\nInstructions:\n"
|
|
169
168
|
break;
|
|
170
169
|
case "memoryUser":
|
|
171
|
-
sectionPrompt = "You are managing the \"user\" section of your memory that stores information about user(s) that you are talking to
|
|
170
|
+
sectionPrompt = "You are managing the \"user\" section of your memory that stores information about user(s) that you are talking to - their identity, attributes, relationships, environment, preferences, interests, background, needs, and any other relevant user-specific information about their family, friends, etc.\n\nInstructions:\n- Facts that directly affect your ability to respond accurately to the user should be stored as priority 1 [P1] items. Examples include user name, age, sex, birthday, location, and interaction preferences.\n"
|
|
172
171
|
break;
|
|
173
172
|
case "memoryTopics":
|
|
174
173
|
sectionPrompt = "You are managing the \"topics\" section of your memory that stores conversation topics and topic history. Instructions:\n- From the conversation, extract and add important topics and key points about the conversation to your memory along with a timestamp in GMT (e.g. 2024-11-05T18:30:38.092Z).\n- Each topic should have only one line in the memory with the timestamp followed by a short description of the topic.\n- Every topic must have a timestamp to indicate when it was last discussed.\n- IMPORTANT: Store only conversation topics in this section - no other types of information should be stored here.\n"
|
|
@@ -179,13 +178,13 @@ Follow these guidelines:
|
|
|
179
178
|
|
|
180
179
|
let sectionMemory = await callPathway("sys_read_memory", {contextId: args.contextId, section: args.section});
|
|
181
180
|
|
|
182
|
-
const result = await runAllPrompts({...args, sectionPrompt, sectionMemory});
|
|
181
|
+
const result = await runAllPrompts({...args, sectionPrompt, sectionMemory, ...entityConstants});
|
|
183
182
|
|
|
184
183
|
try {
|
|
185
184
|
const { modifications} = JSON.parse(result);
|
|
186
185
|
if (modifications.length > 0) {
|
|
187
186
|
sectionMemory = modifyText(sectionMemory, modifications);
|
|
188
|
-
sectionMemory = enforceTokenLimit(sectionMemory,
|
|
187
|
+
sectionMemory = enforceTokenLimit(sectionMemory, 25000, args.section === 'memoryTopics');
|
|
189
188
|
await callPathway("sys_save_memory", {contextId: args.contextId, section: args.section, aiMemory: sectionMemory});
|
|
190
189
|
}
|
|
191
190
|
return sectionMemory;
|
|
@@ -1,15 +1,68 @@
|
|
|
1
1
|
import { getv } from '../../../../lib/keyValueStorageClient.js';
|
|
2
2
|
|
|
3
|
+
const filterByPriority = (content, priority, numResults) => {
|
|
4
|
+
if ((!priority && !numResults) || !content) return content;
|
|
5
|
+
|
|
6
|
+
const lines = content.split('\n');
|
|
7
|
+
const filteredLines = lines.filter(line => {
|
|
8
|
+
const match = line.match(/^\s*\[P(\d+)\]/);
|
|
9
|
+
if (!match) return false;
|
|
10
|
+
const memoryPriority = parseInt(match[1]);
|
|
11
|
+
return memoryPriority <= priority;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (numResults > 0) {
|
|
15
|
+
return filteredLines.slice(-numResults).join('\n');
|
|
16
|
+
}
|
|
17
|
+
return filteredLines.join('\n');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const filterByRecent = (content, recentHours, numResults) => {
|
|
21
|
+
if ((!recentHours && !numResults) || !content) return content;
|
|
22
|
+
|
|
23
|
+
const lines = content.split('\n');
|
|
24
|
+
|
|
25
|
+
// If recentHours is 0, only apply numResults filtering
|
|
26
|
+
if (recentHours === 0) {
|
|
27
|
+
return numResults > 0 ? lines.slice(-numResults).join('\n') : content;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const currentTime = Date.now();
|
|
31
|
+
const cutoffTime = currentTime - (recentHours * 60 * 60 * 1000);
|
|
32
|
+
|
|
33
|
+
// Walk backwards through lines until we hit an old entry
|
|
34
|
+
const filteredLines = [];
|
|
35
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
36
|
+
const line = lines[i];
|
|
37
|
+
const dateMatch = line.match(/\[P\d+\]\s+(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z)/);
|
|
38
|
+
if (!dateMatch) continue;
|
|
39
|
+
|
|
40
|
+
const timestamp = new Date(dateMatch[1]).getTime();
|
|
41
|
+
if (timestamp < cutoffTime) break; // Stop processing once we hit old entries
|
|
42
|
+
|
|
43
|
+
filteredLines.unshift(line); // Add to front to maintain original order
|
|
44
|
+
|
|
45
|
+
// If we have enough results, stop processing
|
|
46
|
+
if (numResults > 0 && filteredLines.length >= numResults) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return filteredLines.join('\n');
|
|
52
|
+
};
|
|
53
|
+
|
|
3
54
|
export default {
|
|
4
55
|
inputParameters: {
|
|
5
56
|
contextId: ``,
|
|
6
|
-
section: `memoryAll
|
|
57
|
+
section: `memoryAll`,
|
|
58
|
+
priority: 0,
|
|
59
|
+
recentHours: 0,
|
|
60
|
+
numResults: 0
|
|
7
61
|
},
|
|
8
62
|
model: 'oai-gpt4o',
|
|
9
63
|
|
|
10
64
|
resolver: async (_parent, args, _contextValue, _info) => {
|
|
11
|
-
|
|
12
|
-
const { contextId, section = 'memoryAll' } = args;
|
|
65
|
+
const { contextId, section = 'memoryAll', priority = 0, recentHours = 0, numResults = 0 } = args;
|
|
13
66
|
|
|
14
67
|
// this code helps migrate old memory formats
|
|
15
68
|
if (section === 'memoryLegacy') {
|
|
@@ -17,11 +70,26 @@ export default {
|
|
|
17
70
|
return savedContext.memoryContext || "";
|
|
18
71
|
}
|
|
19
72
|
|
|
20
|
-
const validSections = ['memorySelf', 'memoryDirectives', 'memoryTopics', 'memoryUser'];
|
|
73
|
+
const validSections = ['memorySelf', 'memoryDirectives', 'memoryTopics', 'memoryUser', 'memoryContext'];
|
|
21
74
|
|
|
22
75
|
if (section !== 'memoryAll') {
|
|
23
76
|
if (validSections.includes(section)) {
|
|
24
|
-
|
|
77
|
+
let content = (getv && (await getv(`${contextId}-${section}`))) || "";
|
|
78
|
+
|
|
79
|
+
if (section === 'memoryTopics') {
|
|
80
|
+
if (recentHours > 0 || numResults > 0) {
|
|
81
|
+
content = filterByRecent(content, recentHours, numResults);
|
|
82
|
+
}
|
|
83
|
+
} else if (priority > 0 || numResults > 0) {
|
|
84
|
+
content = filterByPriority(content, priority, numResults);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Only apply recency filter to memoryTopics
|
|
88
|
+
if (section === 'memoryTopics' && (recentHours > 0 || numResults > 0)) {
|
|
89
|
+
content = filterByRecent(content, recentHours, numResults);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return content;
|
|
25
93
|
}
|
|
26
94
|
return "";
|
|
27
95
|
}
|
|
@@ -29,7 +97,19 @@ export default {
|
|
|
29
97
|
// otherwise, read all sections and return them as a JSON object
|
|
30
98
|
const memoryContents = {};
|
|
31
99
|
for (const section of validSections) {
|
|
32
|
-
|
|
100
|
+
if (section === 'memoryContext') continue;
|
|
101
|
+
|
|
102
|
+
let content = (getv && (await getv(`${contextId}-${section}`))) || "";
|
|
103
|
+
|
|
104
|
+
if (section === 'memoryTopics') {
|
|
105
|
+
if (recentHours > 0 || numResults > 0) {
|
|
106
|
+
content = filterByRecent(content, recentHours, numResults);
|
|
107
|
+
}
|
|
108
|
+
} else if (priority > 0 || numResults > 0) {
|
|
109
|
+
content = filterByPriority(content, priority, numResults);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
memoryContents[section] = content;
|
|
33
113
|
}
|
|
34
114
|
const returnValue = JSON.stringify(memoryContents, null, 2);
|
|
35
115
|
return returnValue;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Prompt } from '../../../../server/prompt.js';
|
|
2
|
+
import { callPathway } from '../../../../lib/pathwayTools.js';
|
|
3
|
+
import { setv } from '../../../../lib/keyValueStorageClient.js';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
prompt:
|
|
7
|
+
[
|
|
8
|
+
new Prompt({
|
|
9
|
+
messages: [
|
|
10
|
+
{
|
|
11
|
+
"role": "system",
|
|
12
|
+
"content": "You are part of an AI entity named {{{aiName}}}. You are responsible for looking through your memories and finding information that is relevant to the conversation so your other parts can use it to respond.\n\nInstructions:\n- You will be given a section of your memory and the conversation history and asked to return any relevant information that you find. If you can predict the direction that the conversation is going, you can also return relevant information that you think will be needed in the near future.\n- IMPORTANT:Only return information found in the memory that you are given. Do not make up information. If it's not in the memory section, it doesn't exist.\n- Return the information in a concise format with no other commentary or dialogue.\n- If you don't find any relevant information in the memory section, return 'No relevant information found.'."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"role": "user",
|
|
16
|
+
"content": "<MEMORY>\n{{{sectionMemory}}}\n</MEMORY>\n<CONVERSATION>\n{{{toJSON chatHistory}}}\n</CONVERSATION>\nAnalyze the current contents of this section of your memory and the conversation and return any information relevant for you to use in your response."
|
|
17
|
+
},
|
|
18
|
+
]
|
|
19
|
+
}),
|
|
20
|
+
],
|
|
21
|
+
|
|
22
|
+
inputParameters: {
|
|
23
|
+
chatHistory: [{role: '', content: []}],
|
|
24
|
+
aiName: "Jarvis",
|
|
25
|
+
contextId: ``,
|
|
26
|
+
section: "memoryAll",
|
|
27
|
+
updateContext: false
|
|
28
|
+
},
|
|
29
|
+
model: 'oai-gpt4o',
|
|
30
|
+
useInputChunking: false,
|
|
31
|
+
enableDuplicateRequests: false,
|
|
32
|
+
timeout: 300,
|
|
33
|
+
executePathway: async ({args, runAllPrompts}) => {
|
|
34
|
+
|
|
35
|
+
if (!args.section) {
|
|
36
|
+
return "Memory not searched - no section specified";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let sectionMemory;
|
|
40
|
+
let result = "";
|
|
41
|
+
if (args.section === "memoryAll") {
|
|
42
|
+
// Search all sections in parallel
|
|
43
|
+
const sections = ["memorySelf", "memoryUser", "memoryDirectives", "memoryTopics"];
|
|
44
|
+
const memories = await Promise.all(
|
|
45
|
+
sections.map(section =>
|
|
46
|
+
callPathway("sys_search_memory", {...args, section})
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
// Combine all memories with section headers
|
|
50
|
+
result = sections.map((section, i) =>
|
|
51
|
+
`=== ${section} ===\n${memories[i]}`
|
|
52
|
+
).join('\n\n');
|
|
53
|
+
result = `${result}\n\nThe last time you spoke to the user was ${new Date().toISOString()}`;
|
|
54
|
+
|
|
55
|
+
} else {
|
|
56
|
+
sectionMemory = await callPathway("sys_read_memory", {contextId: args.contextId, section: args.section});
|
|
57
|
+
result = await runAllPrompts({...args, sectionMemory});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (args.updateContext) {
|
|
61
|
+
await setv(`${args.contextId}-memoryContext`, result);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -10,11 +10,11 @@ const AI_COMMON_INSTRUCTIONS = "{{#if voiceResponse}}{{renderTemplate AI_COMMON_
|
|
|
10
10
|
|
|
11
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
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
|
|
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
14
|
|
|
15
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
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, generate images, solve hard math and logic problems, write code, and execute code in a sandboxed environment.";
|
|
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
18
|
|
|
19
19
|
export default {
|
|
20
20
|
AI_MEMORY,
|
|
@@ -79,6 +79,11 @@ export default {
|
|
|
79
79
|
args.chatHistory = args.chatHistory.slice(-20);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
const memoryContext = await callPathway('sys_read_memory', { ...args, section: 'memoryContext', priority: 0, recentHours: 0 });
|
|
83
|
+
if (memoryContext) {
|
|
84
|
+
args.chatHistory.splice(-1, 0, { role: 'assistant', content: memoryContext });
|
|
85
|
+
}
|
|
86
|
+
|
|
82
87
|
const pathwayResolver = resolver;
|
|
83
88
|
const { anthropicModel, openAIModel } = pathwayResolver.pathway;
|
|
84
89
|
|
|
@@ -204,6 +209,11 @@ export default {
|
|
|
204
209
|
toolCallbackId = null;
|
|
205
210
|
toolCallbackMessage = toolMessage;
|
|
206
211
|
break;
|
|
212
|
+
case "memory":
|
|
213
|
+
toolCallbackName = 'sys_generator_memory';
|
|
214
|
+
toolCallbackId = null;
|
|
215
|
+
toolCallbackMessage = toolMessage;
|
|
216
|
+
break;
|
|
207
217
|
default:
|
|
208
218
|
toolCallbackName = null;
|
|
209
219
|
toolCallbackId = null;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
-
import { callPathway } from '../../../lib/pathwayTools.js';
|
|
3
2
|
|
|
4
3
|
export default {
|
|
5
4
|
prompt:
|
|
@@ -23,7 +22,6 @@ export default {
|
|
|
23
22
|
let result;
|
|
24
23
|
if (args.voiceResponse) {
|
|
25
24
|
result = await runAllPrompts({ ...args, stream: false });
|
|
26
|
-
result = await callPathway('sys_generator_voice_converter', { ...args, text: result, stream: false });
|
|
27
25
|
} else {
|
|
28
26
|
result = await runAllPrompts({ ...args });
|
|
29
27
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { callPathway } from '../../../lib/pathwayTools.js';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
prompt:
|
|
5
|
+
[],
|
|
6
|
+
inputParameters: {
|
|
7
|
+
chatHistory: [{role: '', content: []}],
|
|
8
|
+
contextId: ``,
|
|
9
|
+
aiName: "Jarvis",
|
|
10
|
+
language: "English",
|
|
11
|
+
},
|
|
12
|
+
model: 'oai-gpt4o',
|
|
13
|
+
useInputChunking: false,
|
|
14
|
+
enableDuplicateRequests: false,
|
|
15
|
+
executePathway: async ({args, resolver}) => {
|
|
16
|
+
const memoryContext = await callPathway('sys_search_memory', { ...args, section: 'memoryAll', updateContext: true });
|
|
17
|
+
if (memoryContext) {
|
|
18
|
+
args.chatHistory.splice(-1, 0, { role: 'assistant', content: memoryContext });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let result;
|
|
22
|
+
if (args.voiceResponse) {
|
|
23
|
+
result = await callPathway('sys_generator_quick', { ...args, stream: false });
|
|
24
|
+
} else {
|
|
25
|
+
result = await callPathway('sys_generator_quick', { ...args });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
resolver.tool = JSON.stringify({ toolUsed: "memory" });
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
+
import entityConstants from './shared/sys_entity_constants.js';
|
|
3
|
+
export default {
|
|
4
|
+
prompt:
|
|
5
|
+
[
|
|
6
|
+
new Prompt({ messages: [
|
|
7
|
+
{"role": "system", "content": `{{renderTemplate AI_MEMORY}}\n\n{{renderTemplate AI_COMMON_INSTRUCTIONS}}\n{{renderTemplate AI_EXPERTISE}}\n{{renderTemplate AI_MEMORY_INSTRUCTIONS}}\n{{renderTemplate AI_DATETIME}}\nYour voice communication system needs some examples to train it to sound like you. Based on your perception of yourself from your memories and your unique voice, generate some sample dialogue for your voice communication system to use as a reference for your style and tone. It can be anything, but make sure to overindex on your personality and voice for good training data. Make sure to reference a greeting and a closing statement. Put it between <EXAMPLE_DIALOGUE> tags and don't generate any other commentary outside of the tags.`},
|
|
8
|
+
{"role": "user", "content": `Generate a sample dialogue for your voice communication system to use as a reference for your style and tone.`},
|
|
9
|
+
]}),
|
|
10
|
+
],
|
|
11
|
+
inputParameters: {
|
|
12
|
+
chatHistory: [{role: '', content: []}],
|
|
13
|
+
contextId: ``,
|
|
14
|
+
aiName: "Jarvis",
|
|
15
|
+
language: "English",
|
|
16
|
+
aiStyle: "OpenAI",
|
|
17
|
+
},
|
|
18
|
+
useInputChunking: false,
|
|
19
|
+
enableDuplicateRequests: false,
|
|
20
|
+
executePathway: async ({args, runAllPrompts, resolver}) => {
|
|
21
|
+
|
|
22
|
+
args = {
|
|
23
|
+
...args,
|
|
24
|
+
...entityConstants
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const pathwayResolver = resolver;
|
|
28
|
+
const { anthropicModel, openAIModel } = pathwayResolver.pathway;
|
|
29
|
+
|
|
30
|
+
const styleModel = args.aiStyle === "Anthropic" ? anthropicModel : openAIModel;
|
|
31
|
+
|
|
32
|
+
const result = await runAllPrompts({ ...args, model: styleModel, stream: false });
|
|
33
|
+
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -19,25 +19,27 @@ Available tools and their specific use cases:
|
|
|
19
19
|
|
|
20
20
|
1. Search: Use for current events, news, fact-checking, and information requiring citation. This tool can search the internet, all Al Jazeera news articles and the latest news wires from multiple sources. Only search when necessary for current events, user documents, latest news, or complex topics needing grounding. Don't search for remembered information or general knowledge within your capabilities.
|
|
21
21
|
|
|
22
|
-
2. Document: Access user's personal document index. Use for user-specific uploaded information. If user refers vaguely to "this document/file/article" without context, search the personal index.
|
|
22
|
+
2. Document: Access user's personal document index. Use for user-specific uploaded information. If user refers vaguely to "this document/file/article" without context, use this tool to search the personal index.
|
|
23
23
|
|
|
24
|
-
3.
|
|
24
|
+
3. Memory: Access to your memory index. Use to recall any information that you may have stored in your memory that you don't currently see elsewhere in your context.
|
|
25
25
|
|
|
26
|
-
4.
|
|
26
|
+
4. Write: Engage for any task related to composing, editing, or refining written content. This includes articles, essays, scripts, or any form of textual creation or modification. If you need to search for information or look at a document first, use the Search or Document tools. This tool is just to create or modify content.
|
|
27
27
|
|
|
28
|
-
5.
|
|
28
|
+
5. Image: Use when asked to create, generate, or revise visual content. This covers photographs, illustrations, diagrams, or any other type of image. This tool only creates images - it cannot manipulate images (e.g. it cannot crop, rotate, or resize an existing image) - for those tasks you will need to use the CodeExecution tool.
|
|
29
29
|
|
|
30
|
-
6.
|
|
30
|
+
6. Code: Engage for any programming-related tasks, including creating, modifying, reviewing, or explaining code. Use for general coding discussions or when specific programming expertise is needed.
|
|
31
31
|
|
|
32
|
-
7.
|
|
32
|
+
7. CodeExecution: Use when explicitly asked to run or execute code, or when a coding agent is needed to perform specific tasks that require code execution like data analysis, data processing, image processing, or business intelligence tasks.
|
|
33
33
|
|
|
34
|
-
8.
|
|
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.
|
|
36
|
+
9. PDF: Use specifically for processing and answering questions about PDF file content.
|
|
37
37
|
|
|
38
|
-
10.
|
|
38
|
+
10. Vision: Engage for analyzing and responding to queries about image files (jpg, gif, bmp, png, etc).
|
|
39
39
|
|
|
40
|
-
11.
|
|
40
|
+
11. Video: Use for processing and answering questions about video or audio file content.
|
|
41
|
+
|
|
42
|
+
12. 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.
|
|
41
43
|
|
|
42
44
|
Tool Selection Guidelines:
|
|
43
45
|
- Prioritize the most specific tool for the task at hand.
|
|
@@ -54,6 +56,7 @@ toolMessage Guidelines:
|
|
|
54
56
|
- The message is a filler message to the user to let them know you're working on their request.
|
|
55
57
|
- The message should be consistent in style and tone with the rest of your responses in the conversation history.
|
|
56
58
|
- The message should be brief and conversational and flow naturally with the conversation history.
|
|
59
|
+
- The message should not refer to the tool directly, but rather what you're trying to accomplish. E.g. for the memory tool, the message would be something like "Let me think about that for a moment..." or "I'm trying to remember...", etc.
|
|
57
60
|
|
|
58
61
|
If no tool is required, return:
|
|
59
62
|
{"toolRequired": false, "toolReason": "explanation of why no tool was necessary"}
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
prompt: [
|
|
5
5
|
new Prompt({
|
|
6
6
|
messages: [
|
|
7
|
-
{ "role": "system", "content": "Assistant is a list parsing AI. When user posts text including a numbered list and a desired set of fields, assistant will carefully read the list and attempt to convert
|
|
7
|
+
{ "role": "system", "content": "Assistant is a list parsing AI. When user posts text including a numbered list and a desired set of fields, assistant will carefully read the list and attempt to convert each list item into a JSON object with the given fields. If a field value is numeric, it should be returned as a number in the JSON object. If there are extra fields, assistant will ignore them. If a list item doesn't contain all fields, assistant will return the fields that are present and skip the missing fields. If the conversion is not at all possible, assistant will return an empty JSON array. Assistant will generate only the repaired JSON object in a directly parseable format with no markdown surrounding it and no other response or commentary." },
|
|
8
8
|
{ "role": "user", "content": `Fields: {{{format}}}\nList: {{{text}}}`},
|
|
9
9
|
]
|
|
10
10
|
})
|