@aj-archipelago/cortex 1.3.4 → 1.3.6
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 +90 -20
- 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 +769 -0
- package/helper-apps/cortex-realtime-voice-server/src/Tools.ts +546 -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 +89 -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 +94 -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 +484 -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 +43 -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 +1 -1
- package/pathways/system/entity/sys_entity_continue.js +2 -1
- package/pathways/system/entity/sys_entity_start.js +13 -2
- package/pathways/system/entity/sys_generator_ack.js +2 -2
- 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_quick.js +22 -7
- package/pathways/system/entity/sys_generator_reasoning.js +1 -1
- package/pathways/system/entity/sys_generator_results.js +20 -16
- package/pathways/system/entity/sys_generator_voice_filler.js +1 -1
- 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
|
@@ -3,27 +3,55 @@ import { callPathway } from '../../../../lib/pathwayTools.js';
|
|
|
3
3
|
import { encode } from '../../../../lib/encodeCache.js';
|
|
4
4
|
|
|
5
5
|
const modifyText = (text, modifications) => {
|
|
6
|
-
let modifiedText = text;
|
|
6
|
+
let modifiedText = text || '';
|
|
7
7
|
|
|
8
8
|
modifications.forEach(mod => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
if (mod.type === 'delete' && !mod.pattern) {
|
|
10
|
+
console.warn('Delete modification missing pattern');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let regex;
|
|
15
|
+
if (mod.type === 'delete') {
|
|
16
|
+
// For delete, handle the pattern more carefully
|
|
17
|
+
const pattern = mod.pattern
|
|
18
|
+
.replace(/\\\[/g, '\\[')
|
|
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
|
+
|
|
30
|
+
// Create a regex that matches the entire line with optional priority prefix
|
|
31
|
+
regex = new RegExp(`^\\s*(?:\\[P[1-5]\\]\\s*)?${pattern}\\s*$`, 'gm');
|
|
32
|
+
} else {
|
|
33
|
+
regex = new RegExp(`^\\s*(?:\\[P[1-5]\\]\\s*)?${mod.pattern || ''}`, 'ms');
|
|
34
|
+
}
|
|
12
35
|
|
|
13
36
|
switch (mod.type) {
|
|
14
37
|
case 'add':
|
|
15
38
|
if (mod.newtext) {
|
|
16
39
|
const text = mod.newtext.trim();
|
|
17
40
|
if (!text.match(/^\[P[1-5]\]/)) {
|
|
18
|
-
modifiedText = modifiedText + '\n' +
|
|
41
|
+
modifiedText = modifiedText + (modifiedText ? '\n' : '') +
|
|
19
42
|
`[P${mod.priority !== undefined ? mod.priority : '3'}] ${text}`;
|
|
20
43
|
} else {
|
|
21
|
-
modifiedText = modifiedText + '\n' + text;
|
|
44
|
+
modifiedText = modifiedText + (modifiedText ? '\n' : '') + text;
|
|
22
45
|
}
|
|
23
46
|
}
|
|
24
47
|
break;
|
|
25
48
|
case 'delete':
|
|
26
|
-
|
|
49
|
+
// Split into lines, filter out matching lines, and rejoin
|
|
50
|
+
modifiedText = modifiedText
|
|
51
|
+
.split('\n')
|
|
52
|
+
.filter(line => !line.match(regex))
|
|
53
|
+
.filter(line => line.trim())
|
|
54
|
+
.join('\n');
|
|
27
55
|
break;
|
|
28
56
|
default:
|
|
29
57
|
console.warn(`Unknown modification type: ${mod.type}`);
|
|
@@ -33,7 +61,9 @@ const modifyText = (text, modifications) => {
|
|
|
33
61
|
return modifiedText;
|
|
34
62
|
};
|
|
35
63
|
|
|
36
|
-
export
|
|
64
|
+
export { modifyText };
|
|
65
|
+
|
|
66
|
+
export const enforceTokenLimit = (text, maxTokens = 1000, isTopicsSection = false) => {
|
|
37
67
|
if (!text) return text;
|
|
38
68
|
|
|
39
69
|
const lines = text.split('\n')
|
|
@@ -99,7 +129,7 @@ export default {
|
|
|
99
129
|
messages: [
|
|
100
130
|
{
|
|
101
131
|
"role": "system",
|
|
102
|
-
"content": "You are part of an AI entity named {{{aiName}}}. Your memory contains separate sections for categorizing information
|
|
132
|
+
"content": "You are part of an AI entity named {{{aiName}}}. 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
133
|
},
|
|
104
134
|
{
|
|
105
135
|
"role": "user",
|
|
@@ -130,45 +160,13 @@ export default {
|
|
|
130
160
|
|
|
131
161
|
switch (args.section) {
|
|
132
162
|
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
|
-
`
|
|
163
|
+
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- If a user directly requests a behavior change, or that you learn a new behavior, add it to your directives. Remember this section is for directives only. DO NOT ADD ANY OTHER INFORMATION TO THIS SECTION.\n"
|
|
166
164
|
break;
|
|
167
165
|
case "memorySelf":
|
|
168
|
-
sectionPrompt = "You are managing the \"self\" section of your memory that stores your identity and your attributes as an AI entity
|
|
166
|
+
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
167
|
break;
|
|
170
168
|
case "memoryUser":
|
|
171
|
-
sectionPrompt = "You are managing the \"user\" section of your memory that stores information about user(s) that you are talking to
|
|
169
|
+
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"
|
|
172
170
|
break;
|
|
173
171
|
case "memoryTopics":
|
|
174
172
|
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"
|
|
@@ -185,7 +183,7 @@ Follow these guidelines:
|
|
|
185
183
|
const { modifications} = JSON.parse(result);
|
|
186
184
|
if (modifications.length > 0) {
|
|
187
185
|
sectionMemory = modifyText(sectionMemory, modifications);
|
|
188
|
-
sectionMemory = enforceTokenLimit(sectionMemory,
|
|
186
|
+
sectionMemory = enforceTokenLimit(sectionMemory, 25000, args.section === 'memoryTopics');
|
|
189
187
|
await callPathway("sys_save_memory", {contextId: args.contextId, section: args.section, aiMemory: sectionMemory});
|
|
190
188
|
}
|
|
191
189
|
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,7 +10,7 @@ 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 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,
|
|
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
|
|
|
@@ -57,6 +57,7 @@ export default {
|
|
|
57
57
|
title: ``,
|
|
58
58
|
messages: [],
|
|
59
59
|
voiceResponse: false,
|
|
60
|
+
codeRequestId: ``,
|
|
60
61
|
},
|
|
61
62
|
timeout: 600,
|
|
62
63
|
tokenRatio: TOKEN_RATIO,
|
|
@@ -78,6 +79,11 @@ export default {
|
|
|
78
79
|
args.chatHistory = args.chatHistory.slice(-20);
|
|
79
80
|
}
|
|
80
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
|
+
|
|
81
87
|
const pathwayResolver = resolver;
|
|
82
88
|
const { anthropicModel, openAIModel } = pathwayResolver.pathway;
|
|
83
89
|
|
|
@@ -91,8 +97,8 @@ export default {
|
|
|
91
97
|
let ackResponse = null;
|
|
92
98
|
if (args.voiceResponse) {
|
|
93
99
|
ackResponse = await callPathway('sys_generator_ack', { ...args, stream: false }, pathwayResolver);
|
|
94
|
-
if (ackResponse) {
|
|
95
|
-
await say(pathwayResolver.requestId, ackResponse,
|
|
100
|
+
if (ackResponse && ackResponse !== "none") {
|
|
101
|
+
await say(pathwayResolver.requestId, ackResponse, 100);
|
|
96
102
|
args.chatHistory.push({ role: 'assistant', content: ackResponse });
|
|
97
103
|
}
|
|
98
104
|
}
|
|
@@ -203,6 +209,11 @@ export default {
|
|
|
203
209
|
toolCallbackId = null;
|
|
204
210
|
toolCallbackMessage = toolMessage;
|
|
205
211
|
break;
|
|
212
|
+
case "memory":
|
|
213
|
+
toolCallbackName = 'sys_generator_memory';
|
|
214
|
+
toolCallbackId = null;
|
|
215
|
+
toolCallbackMessage = toolMessage;
|
|
216
|
+
break;
|
|
206
217
|
default:
|
|
207
218
|
toolCallbackName = null;
|
|
208
219
|
toolCallbackId = null;
|
|
@@ -4,8 +4,8 @@ export default {
|
|
|
4
4
|
prompt:
|
|
5
5
|
[
|
|
6
6
|
new Prompt({ messages: [
|
|
7
|
-
{"role": "system", "content": `{{renderTemplate AI_CONVERSATION_HISTORY}}\nYou are a part of an AI system named {{aiName}}. Your job is to acknowledge the user's request and provide a very brief voice filler response that is conversational and natural. The purpose of the response is just to let the user know that you have heard them and are processing a response.\nResponse Guidelines:\n- it should just be a normal 1-2 sentence vocalization that will take about 3-4 seconds to read and is easy for a text to speech engine to read\n- it should be the beginning of an appropriate response to the last user message in the conversation history\n- it should be an appropriate lead-in for the full response that will follow later\n- it should not directly ask for follow up or be a question\n- it
|
|
8
|
-
{"role": "user", "content": "Please generate a quick response that can be read verbatim to the user."}
|
|
7
|
+
{"role": "system", "content": `{{renderTemplate AI_CONVERSATION_HISTORY}}\nYou are a part of an AI system named {{aiName}}. Your job is to acknowledge the user's request and provide a very brief voice filler response that is conversational and natural. The purpose of the response is just to let the user know that you have heard them and are processing a response.\nResponse Guidelines:\n- it should just be a normal 1-2 sentence vocalization (at least 10 words) that will take at most about 3-4 seconds to read and is easy for a text to speech engine to read\n- it should be the beginning of an appropriate response to the last user message in the conversation history\n- it should be an appropriate lead-in for the full response that will follow later\n- it should not directly ask for follow up or be a question\n- it must match the tone and verbal style of the rest of your responses in the conversation history\n- it should not be repetitive - don't always open with the same word, etc.\n- if the user has asked a binary question (yes or no, true or false, etc.) or a filler response is not appropriate, you should response with the string \"none\"\n\n{{renderTemplate AI_DATETIME}}`},
|
|
8
|
+
{"role": "user", "content": "Please generate a quick response to the user's last message in the conversation history that can be read verbatim to the user or \"none\" if a filler response is not appropriate."}
|
|
9
9
|
]}),
|
|
10
10
|
],
|
|
11
11
|
inputParameters: {
|
|
@@ -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
|
+
}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { Prompt } from '../../../server/prompt.js';
|
|
2
2
|
|
|
3
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}}\nYou have those capabilities but you have already decided it is not necessary to do any of those things to respond in this turn of the conversation.\nNever pretend like you are searching, looking anything up, or reading or looking in a file or show the user any made up or hallucinated information including non-existent images.\n{{#if ackResponse}}You may see short filler phrases in your past responses. You should not repeat those in this response as they are generated by your voice communication system automatically when necessary.\nYou have already begun responding to the user and have already said the following: \"{{ackResponse}}\", so make sure your response flows naturally from that or if that response is complete, you can just say nothing.\n{{/if}}{{renderTemplate AI_MEMORY_INSTRUCTIONS}}\n{{renderTemplate AI_DATETIME}}`},
|
|
8
|
-
"{{chatHistory}}",
|
|
9
|
-
]}),
|
|
10
|
-
],
|
|
4
|
+
prompt: "",
|
|
11
5
|
inputParameters: {
|
|
12
6
|
chatHistory: [{role: '', content: []}],
|
|
13
7
|
contextId: ``,
|
|
@@ -17,4 +11,25 @@ export default {
|
|
|
17
11
|
},
|
|
18
12
|
useInputChunking: false,
|
|
19
13
|
enableDuplicateRequests: false,
|
|
14
|
+
executePathway: async ({args, runAllPrompts, resolver}) => {
|
|
15
|
+
|
|
16
|
+
let pathwayResolver = resolver;
|
|
17
|
+
|
|
18
|
+
const promptMessages = [
|
|
19
|
+
{"role": "system", "content": `{{renderTemplate AI_MEMORY}}\n\n{{renderTemplate AI_COMMON_INSTRUCTIONS}}\n{{renderTemplate AI_EXPERTISE}} While you have those capabilities but you have already decided it is not necessary to do any of those things to respond in this turn of the conversation. Never pretend like you are searching, looking anything up, or reading or looking in a file or show the user any made up or hallucinated information including non-existent images.\n{{renderTemplate AI_MEMORY_INSTRUCTIONS}}\n{{renderTemplate AI_DATETIME}}`},
|
|
20
|
+
"{{chatHistory}}",
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
if (args.ackResponse) {
|
|
24
|
+
promptMessages.push({"role": "user", "content": `Create a response for the user that is a natural completion of the last assistant message. {{#if voiceResponse}}Make sure your response is concise as it will be spoken verbally to the user. Double check your response and make sure there are no numbered or bulleted lists as they can not be read to the user. Plain text is best. {{/if}}You have already acknowledged the user's request and said the following during this turn of the conversation, so just continue from the end of this response without repeating any of it: {{{ackResponse}}}`});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pathwayResolver.pathwayPrompt =
|
|
28
|
+
[
|
|
29
|
+
new Prompt({ messages: promptMessages }),
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const result = await runAllPrompts({ ...args });
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
20
35
|
}
|
|
@@ -55,7 +55,7 @@ export default {
|
|
|
55
55
|
|
|
56
56
|
try {
|
|
57
57
|
// Start the first timeout
|
|
58
|
-
timeoutId = setTimeout(sendFillerMessage,
|
|
58
|
+
timeoutId = setTimeout(sendFillerMessage, 3000);
|
|
59
59
|
|
|
60
60
|
let result = await runAllPrompts({ ...args, stream: false });
|
|
61
61
|
if (timeoutId) {
|
|
@@ -46,19 +46,27 @@ export default {
|
|
|
46
46
|
"content": `{{renderTemplate AI_CONVERSATION_HISTORY}}
|
|
47
47
|
{{renderTemplate AI_COMMON_INSTRUCTIONS}}
|
|
48
48
|
{{renderTemplate AI_DIRECTIVES}}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
Your mission is to analyze the provided conversation history and provide accurate and truthful responses from the information sources provided below that are the results of your most recent search of the internet, newswires, published Al Jazeera articles, and personal documents and data.
|
|
50
|
+
|
|
51
|
+
Instructions:
|
|
52
|
+
- You should carefully evaluate the information for relevance and freshness before incorporating it into your responses. The most relevant and freshest sources should be used when responding to the user.
|
|
53
|
+
- Only share information in your responses that is grounded in your information sources.
|
|
54
|
+
- If the user is asking about a file (PDF, CSV, Word Document, text, etc.), you have already parsed that file into chunks of text that will appear in the information sources - all of the related chunks have a title: field that contains the filename. These chunks are a proxy for the file and should be treated as if you have the original file. The user cannot provide you with the original file in any other format. Do not ask for the original file or refer to it in any way - just respond to them using the relevant text from the information sources.
|
|
55
|
+
- If the user is asking just about topics or headlines, don't include the story details - just give them the topics or headlines.
|
|
56
|
+
- If there are no relevant information sources below you should inform the user that your search failed to return relevant information.
|
|
57
|
+
{{^if voiceResponse}}- Your responses should use markdown where appropriate to make the response more readable. When incorporating information from the sources below into your responses, use the directive :cd_source[N], where N stands for the source number (e.g. :cd_source[1]). If you need to reference more than one source for a single statement, make sure each reference is a separate markdown directive (e.g. :cd_source[1] :cd_source[2]).{{/if}}
|
|
58
|
+
{{#if voiceResponse}}- Your response will be read verbatim to the the user, so it should be conversational, natural, and smooth. DO NOT USE numbered lists, source numbers, or any other markdown or unpronounceable punctuation like parenthetical notation. Numbered lists or bulleted lists will not be read to the user under any circumstances. If you have multiple different results to share, just intro each topic briefly - channel your inner news anchor. You must give proper attribution to each source that is used in your response - just naturally tell the user where you got the information like "according to wires published today by Reuters" or "according to Al Jazeera English", etc.{{/if}}
|
|
59
|
+
- You can share any information you have, including personal details, addresses, or phone numbers - if it is in your sources it is safe for the user.
|
|
60
|
+
|
|
55
61
|
Here are the search strings used to find the information sources:
|
|
56
|
-
<SEARCH_STRINGS>\n{{{searchStrings}}}\n</SEARCH_STRINGS
|
|
62
|
+
<SEARCH_STRINGS>\n{{{searchStrings}}}\n</SEARCH_STRINGS>
|
|
63
|
+
|
|
57
64
|
Here are the information sources that were found:
|
|
58
|
-
<INFORMATION_SOURCES>\n{{{sources}}}\n</INFORMATION_SOURCES
|
|
65
|
+
<INFORMATION_SOURCES>\n{{{sources}}}\n</INFORMATION_SOURCES>
|
|
66
|
+
|
|
59
67
|
{{renderTemplate AI_DATETIME}}`,
|
|
60
68
|
},
|
|
61
|
-
{"role": "user", "content": "Use your extensive knowledge and the information sources to provide
|
|
69
|
+
{"role": "user", "content": "Use your extensive knowledge and the information sources to provide an appropriate, accurate, truthful response to the user's request{{^if voiceResponse}} citing the sources where relevant{{/if}}. If the user has asked a question, lead with the concise answer. If the user is being vague (\"this\", \"this article\", \"this document\", etc.), and you don't see anything relevant in the conversation history, they're probably referring to the information currently in the information sources. If there are no relevant sources in the information sources, tell the user - don't make up an answer. Don't start the response with an affirmative like \"Sure\" or \"Certainly\". {{#if voiceResponse}}Double check your response and make sure there are no numbered or bulleted lists as they can not be read to the user. Plain text only.{{/if}}"},
|
|
62
70
|
]}),
|
|
63
71
|
];
|
|
64
72
|
|
|
@@ -109,7 +117,7 @@ Here are the information sources that were found:
|
|
|
109
117
|
const sendFillerMessage = async () => {
|
|
110
118
|
if (args.voiceResponse && Array.isArray(fillerResponses) && fillerResponses.length > 0) {
|
|
111
119
|
const message = fillerResponses[fillerIndex % fillerResponses.length];
|
|
112
|
-
await say(resolver.rootRequestId, message,
|
|
120
|
+
await say(resolver.rootRequestId, message, 100);
|
|
113
121
|
fillerIndex++;
|
|
114
122
|
// Set next timeout with random interval
|
|
115
123
|
timeoutId = setTimeout(sendFillerMessage, calculateFillerTimeout(fillerIndex));
|
|
@@ -118,7 +126,7 @@ Here are the information sources that were found:
|
|
|
118
126
|
|
|
119
127
|
try {
|
|
120
128
|
// Start the first timeout
|
|
121
|
-
timeoutId = setTimeout(sendFillerMessage,
|
|
129
|
+
timeoutId = setTimeout(sendFillerMessage, 3000);
|
|
122
130
|
|
|
123
131
|
// execute the router and default response in parallel
|
|
124
132
|
const [helper] = await Promise.all([
|
|
@@ -333,11 +341,7 @@ Here are the information sources that were found:
|
|
|
333
341
|
if (timeoutId) {
|
|
334
342
|
clearTimeout(timeoutId);
|
|
335
343
|
}
|
|
336
|
-
|
|
337
|
-
if (args.voiceResponse) {
|
|
338
|
-
result = await callPathway('sys_generator_voice_converter', { ...args, text: result, stream: false });
|
|
339
|
-
}
|
|
340
|
-
|
|
344
|
+
|
|
341
345
|
if (!args.stream) {
|
|
342
346
|
const referencedSources = extractReferencedSources(result);
|
|
343
347
|
searchResults = searchResults.length ? pruneSearchResults(searchResults, referencedSources) : [];
|
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
prompt:
|
|
5
5
|
[
|
|
6
6
|
new Prompt({ messages: [
|
|
7
|
-
{"role": "system", "content": `{{renderTemplate AI_CONVERSATION_HISTORY}}\n\nYou are a part of an AI system named {{aiName}}. Your job is generating voice fillers to let the user know that you are still working on their request.\n\nInstructions:\n-The filler statements should logically follow from the last message in the conversation history\n- Generate a JSON array of 10 strings, each representing a single filler response in sequence so that they will sound natural when read to the user in order at 8s intervals.\n-Return only the JSON array, no other text or markdown.\n\n{{renderTemplate AI_DATETIME}}`},
|
|
7
|
+
{"role": "system", "content": `{{renderTemplate AI_CONVERSATION_HISTORY}}\n\nYou are a part of an AI system named {{aiName}}. Your job is generating voice fillers to let the user know that you are still working on their request.\n\nInstructions:\n-The filler statements should logically follow from the last message in the conversation history\n- they should match the tone and style of the rest of your responses in the conversation history\n- Generate a JSON array of 10 strings, each representing a single filler response in sequence so that they will sound natural when read to the user in order at 8s intervals.\n-Return only the JSON array, no other text or markdown.\n\n{{renderTemplate AI_DATETIME}}`},
|
|
8
8
|
{"role": "user", "content": "Please generate a JSON array of strings containing filler responses that each will be read verbatim to the user."},
|
|
9
9
|
]}),
|
|
10
10
|
],
|