@aj-archipelago/cortex 1.2.0 → 1.3.0
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/config.js +47 -11
- package/helper-apps/cortex-autogen/OAI_CONFIG_LIST +2 -1
- package/helper-apps/cortex-autogen/agents.py +387 -0
- package/helper-apps/cortex-autogen/agents_extra.py +14 -0
- package/helper-apps/cortex-autogen/config.py +18 -0
- package/helper-apps/cortex-autogen/data_operations.py +29 -0
- package/helper-apps/cortex-autogen/function_app.py +6 -3
- package/helper-apps/cortex-autogen/main.py +4 -4
- package/helper-apps/cortex-autogen/prompts.py +196 -0
- package/helper-apps/cortex-autogen/prompts_extra.py +5 -0
- package/helper-apps/cortex-autogen/requirements.txt +2 -1
- package/helper-apps/cortex-autogen/search.py +83 -0
- package/helper-apps/cortex-autogen/test.sh +40 -0
- package/helper-apps/cortex-autogen/utils.py +78 -0
- package/lib/handleBars.js +25 -0
- package/lib/logger.js +2 -0
- package/lib/util.js +3 -1
- package/package.json +1 -1
- package/pathways/chat_code.js +1 -1
- package/pathways/chat_context.js +1 -1
- package/pathways/chat_jarvis.js +1 -1
- package/pathways/chat_persist.js +1 -1
- package/pathways/chat_title.js +25 -0
- package/pathways/{flux_image.js → image_flux.js} +6 -2
- package/pathways/image_recraft.js +10 -0
- package/pathways/rag.js +1 -1
- package/pathways/rag_jarvis.js +1 -1
- package/pathways/rag_search_helper.js +1 -1
- package/pathways/system/entity/memory/sys_memory_manager.js +71 -0
- package/pathways/system/entity/memory/sys_memory_required.js +21 -0
- package/pathways/system/entity/memory/sys_memory_update.js +190 -0
- package/pathways/system/entity/memory/sys_read_memory.js +37 -0
- package/pathways/system/entity/memory/sys_save_memory.js +60 -0
- package/pathways/system/entity/shared/sys_entity_constants.js +24 -0
- package/pathways/system/entity/sys_entity_continue.js +57 -0
- package/pathways/system/entity/sys_entity_start.js +218 -0
- package/pathways/system/entity/sys_generator_error.js +20 -0
- package/pathways/system/entity/sys_generator_expert.js +26 -0
- package/pathways/system/entity/sys_generator_image.js +127 -0
- package/pathways/system/entity/sys_generator_quick.js +19 -0
- package/pathways/system/entity/sys_generator_reasoning.js +27 -0
- package/pathways/system/entity/sys_generator_results.js +304 -0
- package/pathways/system/entity/sys_generator_video_vision.js +27 -0
- package/pathways/system/entity/sys_image_prompt_builder.js +35 -0
- package/pathways/system/entity/sys_query_builder.js +101 -0
- package/pathways/system/entity/sys_router_code.js +37 -0
- package/pathways/system/entity/sys_router_tool.js +64 -0
- package/pathways/{sys_claude_35_sonnet.js → system/rest_streaming/sys_claude_35_sonnet.js} +1 -1
- package/pathways/{sys_claude_3_haiku.js → system/rest_streaming/sys_claude_3_haiku.js} +1 -1
- package/pathways/{sys_google_chat.js → system/rest_streaming/sys_google_chat.js} +1 -1
- package/pathways/{sys_google_code_chat.js → system/rest_streaming/sys_google_code_chat.js} +1 -1
- package/pathways/{sys_google_gemini_chat.js → system/rest_streaming/sys_google_gemini_chat.js} +1 -1
- package/pathways/{sys_openai_chat.js → system/rest_streaming/sys_openai_chat.js} +1 -1
- package/pathways/{sys_openai_chat_16.js → system/rest_streaming/sys_openai_chat_16.js} +1 -1
- package/pathways/{sys_openai_chat_gpt4.js → system/rest_streaming/sys_openai_chat_gpt4.js} +1 -1
- package/pathways/{sys_openai_chat_gpt4_32.js → system/rest_streaming/sys_openai_chat_gpt4_32.js} +1 -1
- package/pathways/{sys_openai_chat_gpt4_turbo.js → system/rest_streaming/sys_openai_chat_gpt4_turbo.js} +1 -1
- package/pathways/{sys_parse_numbered_object_list.js → system/sys_parse_numbered_object_list.js} +2 -2
- package/pathways/{sys_repair_json.js → system/sys_repair_json.js} +1 -1
- package/pathways/{run_claude35_sonnet.js → system/workspaces/run_claude35_sonnet.js} +1 -1
- package/pathways/{run_claude3_haiku.js → system/workspaces/run_claude3_haiku.js} +1 -1
- package/pathways/{run_gpt35turbo.js → system/workspaces/run_gpt35turbo.js} +1 -1
- package/pathways/{run_gpt4.js → system/workspaces/run_gpt4.js} +1 -1
- package/pathways/{run_gpt4_32.js → system/workspaces/run_gpt4_32.js} +1 -1
- package/server/parser.js +6 -1
- package/server/pathwayResolver.js +62 -10
- package/server/plugins/azureCognitivePlugin.js +14 -1
- package/server/plugins/claude3VertexPlugin.js +25 -15
- package/server/plugins/gemini15ChatPlugin.js +1 -1
- package/server/plugins/geminiChatPlugin.js +1 -1
- package/server/plugins/modelPlugin.js +10 -1
- package/server/plugins/openAiChatPlugin.js +4 -3
- package/server/plugins/openAiDallE3Plugin.js +12 -4
- package/server/plugins/openAiVisionPlugin.js +1 -2
- package/server/plugins/replicateApiPlugin.js +46 -12
- package/tests/multimodal_conversion.test.js +6 -8
- package/helper-apps/cortex-autogen/myautogen.py +0 -317
- package/helper-apps/cortex-autogen/prompt.txt +0 -0
- package/helper-apps/cortex-autogen/prompt_summary.txt +0 -37
- package/pathways/index.js +0 -152
- /package/pathways/{sys_openai_completion.js → system/rest_streaming/sys_openai_completion.js} +0 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
// sys_generator_results.js
|
|
2
|
+
// entity module that makes use of data and LLM models to produce a response
|
|
3
|
+
import { callPathway, gpt3Encode, gpt3Decode } from '../../../lib/pathwayTools.js';
|
|
4
|
+
import { Prompt } from '../../../server/prompt.js';
|
|
5
|
+
import logger from '../../../lib/logger.js';
|
|
6
|
+
import { config } from '../../../config.js';
|
|
7
|
+
import { convertToSingleContentChatHistory } from '../../../lib/util.js';
|
|
8
|
+
|
|
9
|
+
const TOKEN_RATIO = 1.0;
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
prompt: [],
|
|
13
|
+
useInputChunking: false,
|
|
14
|
+
enableDuplicateRequests: false,
|
|
15
|
+
inputParameters: {
|
|
16
|
+
privateData: false,
|
|
17
|
+
useMemory: false,
|
|
18
|
+
chatHistory: [{role: '', content: []}],
|
|
19
|
+
aiName: "Jarvis",
|
|
20
|
+
contextId: ``,
|
|
21
|
+
indexName: ``,
|
|
22
|
+
semanticConfiguration: ``,
|
|
23
|
+
roleInformation: ``,
|
|
24
|
+
calculateEmbeddings: false,
|
|
25
|
+
language: "English",
|
|
26
|
+
chatId: ``,
|
|
27
|
+
dataSources: [""],
|
|
28
|
+
model: 'oai-gpt4o',
|
|
29
|
+
},
|
|
30
|
+
timeout: 300,
|
|
31
|
+
tokenRatio: TOKEN_RATIO,
|
|
32
|
+
|
|
33
|
+
executePathway: async ({args, runAllPrompts, resolver}) => {
|
|
34
|
+
|
|
35
|
+
const { chatHistory } = args;
|
|
36
|
+
|
|
37
|
+
let pathwayResolver = resolver;
|
|
38
|
+
|
|
39
|
+
const useMemory = args.useMemory || pathwayResolver.pathway.inputParameters.useMemory;
|
|
40
|
+
|
|
41
|
+
pathwayResolver.pathwayPrompt =
|
|
42
|
+
[
|
|
43
|
+
new Prompt({ messages: [
|
|
44
|
+
{
|
|
45
|
+
"role": "system",
|
|
46
|
+
"content": `{{renderTemplate AI_CONVERSATION_HISTORY}}
|
|
47
|
+
{{renderTemplate AI_COMMON_INSTRUCTIONS}}
|
|
48
|
+
{{renderTemplate AI_DIRECTIVES}}
|
|
49
|
+
Instructions: Your mission is to analyze the provided conversation history and provide accurate and truthful responses from the extensive knowledge base at your disposal and 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. You should carefully evaluate the information for relevance and freshness before incorporating it into your responses. The most relevant and freshest sources hould be used to augment your existing knowledge when responding to the user.
|
|
50
|
+
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.
|
|
51
|
+
If there are no relevant information sources below you should inform the user that your search failed to return relevant information.\nYour 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]).
|
|
52
|
+
Only reference sources that are relevant to your response - if there are no sources relevant to your response just tell the user.
|
|
53
|
+
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.
|
|
54
|
+
Here are the search strings used to find the information sources:
|
|
55
|
+
<SEARCH_STRINGS>\n{{{searchStrings}}}\n</SEARCH_STRINGS>\n
|
|
56
|
+
Here are the information sources that were found:
|
|
57
|
+
<INFORMATION_SOURCES>\n{{{sources}}}\n</INFORMATION_SOURCES>\n`,
|
|
58
|
+
},
|
|
59
|
+
{"role": "user", "content": "Use your extensive knowledge and the information sources to provide a detailed, accurate, truthful response to the user's request citing the sources where relevant. 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."},
|
|
60
|
+
]}),
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
function extractReferencedSources(text) {
|
|
64
|
+
const regex = /:cd_source\[(\d+)\]/g;
|
|
65
|
+
const matches = text.match(regex);
|
|
66
|
+
if (!matches) return new Set();
|
|
67
|
+
return new Set(matches.map(match => parseInt(match.match(/\d+/)[0])));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function pruneSearchResults(searchResults, referencedSources) {
|
|
71
|
+
return searchResults.map((result, index) =>
|
|
72
|
+
referencedSources.has(index + 1) ? result : null
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
// Convert chatHistory to single content for rest of the code
|
|
78
|
+
const multiModalChatHistory = JSON.parse(JSON.stringify(chatHistory));
|
|
79
|
+
convertToSingleContentChatHistory(chatHistory);
|
|
80
|
+
|
|
81
|
+
// figure out what the user wants us to do
|
|
82
|
+
const contextInfo = chatHistory.filter(message => message.role === "user").slice(0, -1).map(message => message.content).join("\n");
|
|
83
|
+
|
|
84
|
+
// execute the router and default response in parallel
|
|
85
|
+
const [helper] = await Promise.all([
|
|
86
|
+
callPathway('sys_query_builder', { ...args, useMemory, contextInfo })
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
logger.debug(`Search helper response: ${helper}`);
|
|
90
|
+
const parsedHelper = JSON.parse(helper);
|
|
91
|
+
const { searchAJA, searchAJE, searchWires, searchPersonal, searchBing, dateFilter, languageStr, titleOnly } = parsedHelper;
|
|
92
|
+
|
|
93
|
+
// calculate whether we have room to do RAG in the current conversation context
|
|
94
|
+
const baseSystemPrompt = pathwayResolver?.prompts[0]?.messages[0]?.content;
|
|
95
|
+
const baseSystemPromptLength = baseSystemPrompt ? gpt3Encode(baseSystemPrompt).length : 0;
|
|
96
|
+
const maxSystemPromptLength = (pathwayResolver.model.maxTokenLength * TOKEN_RATIO * 0.90) >> 0;
|
|
97
|
+
|
|
98
|
+
const userMostRecentText = (chatHistory && chatHistory.length) ? chatHistory[chatHistory.length - 1].content : args.text;
|
|
99
|
+
const userMostRecentTextLength = gpt3Encode(userMostRecentText).length;
|
|
100
|
+
|
|
101
|
+
const maxSourcesPromptLength = maxSystemPromptLength - baseSystemPromptLength - userMostRecentTextLength;
|
|
102
|
+
|
|
103
|
+
// if there's a problem fitting the RAG data into the current conversation context, then throw an appropriate error
|
|
104
|
+
// which will bypass RAG in the catch() block below
|
|
105
|
+
if (baseSystemPromptLength === 0) {
|
|
106
|
+
throw new Error(`Could not find system prompt.`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (maxSystemPromptLength < baseSystemPromptLength) {
|
|
110
|
+
throw new Error(`System prompt length (${baseSystemPromptLength}) exceeds maximum prompt length (${maxSystemPromptLength})`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (maxSourcesPromptLength <= 0) {
|
|
114
|
+
throw new Error(`No room for sources in system prompt. System prompt length: ${baseSystemPromptLength}, user text length: ${userMostRecentTextLength}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Helper function to generate extraArgs
|
|
118
|
+
const generateExtraArgs = (searchText) => {
|
|
119
|
+
return {
|
|
120
|
+
text: searchText,
|
|
121
|
+
filter: dateFilter,
|
|
122
|
+
top: titleOnly ? 500 : 50,
|
|
123
|
+
titleOnly: titleOnly
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Execute the index searches in parallel respecting the dataSources parameter
|
|
128
|
+
const promises = [];
|
|
129
|
+
const dataSources = args.dataSources || pathwayResolver.pathway.inputParameters.dataSources;
|
|
130
|
+
const allowAllSources = !dataSources.length || (dataSources.length === 1 && dataSources[0] === "");
|
|
131
|
+
|
|
132
|
+
if(searchPersonal && (allowAllSources || dataSources.includes('mydata'))){
|
|
133
|
+
promises.push(callPathway('cognitive_search', { ...args, ...generateExtraArgs(searchPersonal), indexName: 'indexcortex' }));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if(searchAJA && (allowAllSources || dataSources.includes('aja'))){
|
|
137
|
+
promises.push(callPathway('cognitive_search', { ...args, ...generateExtraArgs(searchAJA), indexName: 'indexucmsaja' }));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if(searchAJE && (allowAllSources || dataSources.includes('aje'))){
|
|
141
|
+
promises.push(callPathway('cognitive_search', { ...args, ...generateExtraArgs(searchAJE), indexName: 'indexucmsaje' }));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if(searchWires && (allowAllSources || dataSources.includes('wires'))){
|
|
145
|
+
promises.push(callPathway('cognitive_search', { ...args, ...generateExtraArgs(searchWires), indexName: 'indexwires' }));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const bingAvailable = !!config.getEnv()["AZURE_BING_KEY"];
|
|
149
|
+
if(bingAvailable && searchBing && (allowAllSources || dataSources.includes('bing'))){
|
|
150
|
+
const handleRejection = (promise) => {
|
|
151
|
+
return promise.catch((error) => {
|
|
152
|
+
logger.error(`Error occurred searching Bing: ${error}`);
|
|
153
|
+
return null;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
promises.push(handleRejection(callPathway('bing', { ...args, ...generateExtraArgs(searchBing)})));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const parseBing = (response) => {
|
|
161
|
+
const parsedResponse = JSON.parse(response);
|
|
162
|
+
const results = [];
|
|
163
|
+
|
|
164
|
+
if (parsedResponse.webPages && parsedResponse.webPages.value) {
|
|
165
|
+
results.push(...parsedResponse.webPages.value.map(({ name, url, snippet }) => ({ title: name, url, content: snippet })));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (parsedResponse.computation) {
|
|
169
|
+
results.push({
|
|
170
|
+
title: "Computation Result",
|
|
171
|
+
content: `Expression: ${parsedResponse.computation.expression}, Value: ${parsedResponse.computation.value}`
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (parsedResponse.entities && parsedResponse.entities.value) {
|
|
176
|
+
results.push(...parsedResponse.entities.value.map(entity => ({
|
|
177
|
+
title: entity.name,
|
|
178
|
+
content: entity.description,
|
|
179
|
+
url: entity.webSearchUrl
|
|
180
|
+
})));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (parsedResponse.news && parsedResponse.news.value) {
|
|
184
|
+
results.push(...parsedResponse.news.value.map(news => ({
|
|
185
|
+
title: news.name,
|
|
186
|
+
content: news.description,
|
|
187
|
+
url: news.url
|
|
188
|
+
})));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (parsedResponse.videos && parsedResponse.videos.value) {
|
|
192
|
+
results.push(...parsedResponse.videos.value.map(video => ({
|
|
193
|
+
title: video.name,
|
|
194
|
+
content: video.description,
|
|
195
|
+
url: video.contentUrl
|
|
196
|
+
})));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (parsedResponse.places && parsedResponse.places.value) {
|
|
200
|
+
results.push(...parsedResponse.places.value.map(place => ({
|
|
201
|
+
title: place.name,
|
|
202
|
+
content: `Address: ${place.address.addressLocality}, ${place.address.addressRegion}, ${place.address.addressCountry}`,
|
|
203
|
+
url: place.webSearchUrl
|
|
204
|
+
})));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (parsedResponse.timeZone) {
|
|
208
|
+
results.push({
|
|
209
|
+
title: "Time Zone Information",
|
|
210
|
+
content: parsedResponse.timeZone.primaryResponse || parsedResponse.timeZone.description
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (parsedResponse.translations && parsedResponse.translations.value) {
|
|
215
|
+
results.push(...parsedResponse.translations.value.map(translation => ({
|
|
216
|
+
title: "Translation",
|
|
217
|
+
content: `Original (${translation.inLanguage}): ${translation.originalText}, Translated (${translation.translatedLanguageName}): ${translation.translatedText}`
|
|
218
|
+
})));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return results;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Sample results from the index searches proportionally to the number of results returned
|
|
225
|
+
const maxSearchResults = titleOnly ? 500 : 50;
|
|
226
|
+
const promiseResults = await Promise.all(promises);
|
|
227
|
+
const promiseData = promiseResults
|
|
228
|
+
.filter(r => r !== undefined && r !== null)
|
|
229
|
+
.map(r => JSON.parse(r)?._type=="SearchResponse" ? parseBing(r) : JSON.parse(r)?.value || []);
|
|
230
|
+
|
|
231
|
+
let totalLength = promiseData.reduce((sum, data) => sum + data.length, 0);
|
|
232
|
+
let remainingSlots = maxSearchResults;
|
|
233
|
+
let searchResults = [];
|
|
234
|
+
|
|
235
|
+
let indexCount = 0;
|
|
236
|
+
for(let data of promiseData) {
|
|
237
|
+
indexCount++;
|
|
238
|
+
const rowCount = data.length;
|
|
239
|
+
if (rowCount === 0) {
|
|
240
|
+
logger.info(`Index ${indexCount} had no matching sources.`);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const proportion = rowCount / totalLength;
|
|
244
|
+
let slots = Math.max(Math.round(proportion * maxSearchResults), 1);
|
|
245
|
+
|
|
246
|
+
// Adjust slots based on remaining slots
|
|
247
|
+
slots = Math.min(slots, remainingSlots);
|
|
248
|
+
|
|
249
|
+
// Splice out the slots from the data and push to the search results
|
|
250
|
+
let items = data.splice(0, slots);
|
|
251
|
+
searchResults.push(...items);
|
|
252
|
+
|
|
253
|
+
logger.info(`Index ${indexCount} had ${rowCount} matching sources. ${items.length} forwarded to the LLM.`);
|
|
254
|
+
// Update remaining slots for next iteration
|
|
255
|
+
remainingSlots -= slots;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
searchResults = searchResults.slice(0, maxSearchResults); // in case we end up with rounding more than maxSearchResults
|
|
259
|
+
|
|
260
|
+
const numSearchResults = Math.min(searchResults.length, maxSearchResults);
|
|
261
|
+
const targetSourceLength = (maxSourcesPromptLength / numSearchResults) >> 0;
|
|
262
|
+
|
|
263
|
+
const getSource = (source, index) => {
|
|
264
|
+
const { title, content, url } = source;
|
|
265
|
+
let result = [];
|
|
266
|
+
result.push(`[source ${index + 1}]`);
|
|
267
|
+
title && result.push(`title: ${title}`);
|
|
268
|
+
url && result.push(`url: ${url}`);
|
|
269
|
+
|
|
270
|
+
if (content && !titleOnly) {
|
|
271
|
+
let encodedContent = gpt3Encode(content);
|
|
272
|
+
let currentLength = result.join(" ").length; // Calculate the length of the current result string
|
|
273
|
+
|
|
274
|
+
if (currentLength + encodedContent.length > targetSourceLength) {
|
|
275
|
+
// Subtract the length of the current result string from targetSourceLength to get the maximum length for content
|
|
276
|
+
encodedContent = encodedContent.slice(0, targetSourceLength - currentLength);
|
|
277
|
+
const truncatedContent = gpt3Decode(encodedContent);
|
|
278
|
+
result.push(`content: ${truncatedContent}`);
|
|
279
|
+
} else {
|
|
280
|
+
result.push(`content: ${content}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return result.join(" ").trim();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
let sources = searchResults.map(getSource).join(" \n\n ") || "No relevant sources found.";
|
|
288
|
+
dateFilter && sources.trim() && (sources+=`\n\nThe above sources are date filtered accordingly.`);
|
|
289
|
+
|
|
290
|
+
const result = await runAllPrompts({ ...args, searchStrings: `${helper}`, sources, chatHistory: multiModalChatHistory, language:languageStr });
|
|
291
|
+
|
|
292
|
+
const referencedSources = extractReferencedSources(result);
|
|
293
|
+
searchResults = pruneSearchResults(searchResults, referencedSources);
|
|
294
|
+
|
|
295
|
+
// Update the tool info with the pruned searchResults
|
|
296
|
+
pathwayResolver.tool = JSON.stringify({ toolUsed: "search", citations: searchResults });
|
|
297
|
+
|
|
298
|
+
return result;
|
|
299
|
+
} catch (e) {
|
|
300
|
+
//pathwayResolver.logError(e);
|
|
301
|
+
return await callPathway('sys_generator_error', { ...args, text: JSON.stringify(e) });
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
prompt:
|
|
5
|
+
[
|
|
6
|
+
new Prompt({ messages: [
|
|
7
|
+
{"role": "system", "content": `{{renderTemplate AI_COMMON_INSTRUCTIONS}}\n{{renderTemplate AI_EXPERTISE}}\n{{renderTemplate AI_DIRECTIVES}}\nYou have the capability to view and analyze media files that the user provides. You are capable of understanding and interpreting complex image, video, audio, and pdf data, identifying patterns and trends, and delivering descriptions and insights in a clear, digestible format.\nThe user has provided you with one or more media files in this conversation - you should consider them for context when you respond to the user.\nIf you don't see any files, something has gone wrong in the upload and you should inform the user and have them try again.`},
|
|
8
|
+
"{{chatHistory}}",
|
|
9
|
+
]}),
|
|
10
|
+
],
|
|
11
|
+
inputParameters: {
|
|
12
|
+
chatHistory: [{role: '', content: []}],
|
|
13
|
+
contextId: ``,
|
|
14
|
+
aiName: "Jarvis",
|
|
15
|
+
language: "English",
|
|
16
|
+
},
|
|
17
|
+
max_tokens: 4096,
|
|
18
|
+
model: 'oai-gpt4o',
|
|
19
|
+
useInputChunking: false,
|
|
20
|
+
enableDuplicateRequests: false,
|
|
21
|
+
timeout: 600,
|
|
22
|
+
executePathway: async ({args, runAllPrompts, resolver}) => {
|
|
23
|
+
const result = await runAllPrompts({ ...args });
|
|
24
|
+
resolver.tool = JSON.stringify({ toolUsed: "vision" });
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
inputParameters: {
|
|
5
|
+
chatHistory: [{role: '', content: []}],
|
|
6
|
+
contextInfo: ``,
|
|
7
|
+
useMemory: true,
|
|
8
|
+
model: 'oai-gpt4o',
|
|
9
|
+
},
|
|
10
|
+
prompt:
|
|
11
|
+
[
|
|
12
|
+
new Prompt({ messages: [
|
|
13
|
+
{
|
|
14
|
+
"role": "system",
|
|
15
|
+
"content": `{{#if useMemory}}{{renderTemplate AI_MEMORY}}\n{{renderTemplate AI_MEMORY_INSTRUCTIONS}}\n{{/if}}{{renderTemplate AI_CONVERSATION_HISTORY}}
|
|
16
|
+
|
|
17
|
+
Instructions: You are part of an AI entity named {{{aiName}}}. You are an image creation helper AI. Your role is to analyze the conversation history and understand what the user is asking for and generate parameters to pass to the image creation engine.
|
|
18
|
+
|
|
19
|
+
Generate an array of JSON objects that each contain a set of parameters for the image creation engine. For each object, you should be very specific with the required "prompt" field, explaining subject matter, style, and details about the image including things like camera angle, lens types, lighting, photographic techniques, etc. Any details you can provide to the image creation engine will help it create the most accurate and useful images. The more detailed and descriptive the prompt, the better the result.
|
|
20
|
+
|
|
21
|
+
If an image requires some kind of text to be accurately included in the image, you should specify that by setting the optional renderText field to true - this helps your image generator choose the best model for the task.
|
|
22
|
+
|
|
23
|
+
If the user wants faster images or the images don't need to be high quality, you can set the optional "draft" field to true - this will result in much faster, but lower quality images. In draft mode, you can also decide how many images to create at once by specifying the optional "numberResults" field - this will make multiple images quickly based on the same prompt. This only works in draft mode.
|
|
24
|
+
|
|
25
|
+
If you want to create multiple different images based on different prompts, you can just add elements to the array, each with their own fields. Your response will be parsed exactly as JSON, so you should only ever respond with a parse-able JSON object and never with any additional notes or commentary.
|
|
26
|
+
|
|
27
|
+
Example response with 2 prompts creating 3 images total: [{"prompt": "A beautiful DSLR photograph of a landscape with a river and mountains"},{"prompt": "A beautiful DSLR photograph of a sunset in the desert and an inspirational quote written in the sky that says 'Never give up!'", "draft: true", "numberResults": 2, "renderText": "true"}]`,
|
|
28
|
+
},
|
|
29
|
+
{"role": "user", "content": "Create one or more images based on the conversation history by generating an array of JSON objects that each contain a set of parameters to pass to the image creation engine."},
|
|
30
|
+
]}),
|
|
31
|
+
],
|
|
32
|
+
useInputChunking: false,
|
|
33
|
+
enableDuplicateRequests: false,
|
|
34
|
+
json: true
|
|
35
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
+
import entityConstants from './shared/sys_entity_constants.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
inputParameters: {
|
|
6
|
+
chatHistory: [{role: '', content: []}],
|
|
7
|
+
contextInfo: ``,
|
|
8
|
+
useMemory: false,
|
|
9
|
+
},
|
|
10
|
+
prompt:
|
|
11
|
+
[
|
|
12
|
+
new Prompt({ messages: [
|
|
13
|
+
{
|
|
14
|
+
"role": "system",
|
|
15
|
+
"content": `{{#if useMemory}}{{renderTemplate AI_MEMORY}}\n{{renderTemplate AI_MEMORY_INSTRUCTIONS}}\n{{/if}}{{renderTemplate AI_CONVERSATION_HISTORY}}
|
|
16
|
+
|
|
17
|
+
Instructions: You are a search helper AI. Your role is to analyze the included Conversation History to understand what the user is asking for and decide what data sources if any to use to help the user and produce a JSON object with fields that communicate your decisions. You have vast internal knowledge up to your training cutoff date, but your internal knowledge is not always sufficient to answer questions about current events or the latest news.
|
|
18
|
+
|
|
19
|
+
You have the ability to search one or more of the following indexes:
|
|
20
|
+
- "aje" for all news articles published by Al Jazeera English (written in English)
|
|
21
|
+
- "aja" for all news articles published by Al Jazeera Arabic (written in Arabic)
|
|
22
|
+
- "wires" for latest news wires from all wires sources (news & articles)
|
|
23
|
+
- "personal" for the user's documents and uploaded files
|
|
24
|
+
|
|
25
|
+
AJE and AJA are not just translations of each other - they are different news organizations with different reporting styles and focus, so often searching both indexes will provide a more complete answer.
|
|
26
|
+
|
|
27
|
+
To search an index, you can provide an appropriate search string or wildcard (e.g. "*") in the corresponding field for the index: "searchAJE", "searchAJA", "searchWires", and "searchPersonal" respectively. It's helpful if the search string is in the language of the index. Longer search strings will get you more relevant and specific results, but shorter ones or wildcards will get you a broader result set. Wildcards are especially useful in finding all results over a time period or finding vague information (e.g. "the news", "the latest").
|
|
28
|
+
|
|
29
|
+
You have the ability to search the internet in all languages using Bing Search. To do that, just put the search query in the "searchBing" field. Your Bing search query can be as simple or long and detailed as you need it to be and you can use the Bing advanced search syntax (+, -, OR, AND, quotes, etc.) to get more relevant or specific results. It's usually helpful to search the internet in addition to your other sources unless the user has explicitly asked for a specific search source (e.g. "the wires").
|
|
30
|
+
|
|
31
|
+
If you choose to search anything at all, you must always set the "searchRequired" field to true.
|
|
32
|
+
|
|
33
|
+
When the user explicitly asks for a specific search source (e.g. "the wires", "my uploads", "the internet"), use ONLY that source.
|
|
34
|
+
|
|
35
|
+
When the user is referencing something specific, (e.g. "this", "this document", "this file", "my uploads","this article", etc.) and you don't see the document contents in the conversation history, use a wildcard search on the personal index with no date filter to see if there is anything relevant. In this case, don't search any other indexes.
|
|
36
|
+
|
|
37
|
+
When the user's query requires a date filter for accurate data retrieval, pay special attention to qualifier words like "latest","tonight", "this afternoon", "today", "yesterday", "this week", "last week", "this month", etc. 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. If a date filter is required, formulate it in a valid OData $filter format and include it in the "dateFilter" field. Do not just put the date in the field - it needs to be filter expression like "date ge 2024-02-22T00:00:00Z". Don't use eq with an exact date time as this is unlikely to return any results.
|
|
38
|
+
|
|
39
|
+
When the user requests an overview, count, or analysis of topics or trends from a specific index over a given time period (e.g., 'What topics were covered yesterday on AJE?' or 'What were the hot topics on the wires this week?' or 'How many articles did AJA publish last week?'), follow these steps:
|
|
40
|
+
|
|
41
|
+
- Use a wildcard search ('*') on the appropriate index(es).
|
|
42
|
+
- Apply a date filter corresponding to the specified time period.
|
|
43
|
+
- Set the 'titleOnly' field to true.
|
|
44
|
+
- Analyze the results to identify and summarize the main topics or trends.
|
|
45
|
+
|
|
46
|
+
Determine the language that the user is speaking in the conversation and fill the "language" field using the ISO 639-3 format and put the full language name in the "languageStr" field.
|
|
47
|
+
|
|
48
|
+
You should only ever respond with the JSON object and never with any additional notes or commentary.
|
|
49
|
+
|
|
50
|
+
Example JSON objects for different queries:
|
|
51
|
+
|
|
52
|
+
"What's the latest on the wires?"
|
|
53
|
+
{
|
|
54
|
+
"searchRequired": true,"
|
|
55
|
+
"searchWires": "*",
|
|
56
|
+
"dateFilter": "date ge 2024-02-22T00:00:00Z",
|
|
57
|
+
"titleOnly": false,
|
|
58
|
+
"language": "eng",
|
|
59
|
+
"languageStr": "English"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
"What's going on in the world today?"
|
|
63
|
+
{
|
|
64
|
+
"searchRequired": true,
|
|
65
|
+
"searchWires": "world news",
|
|
66
|
+
"searchAJA": "عالم حدث اليوم",
|
|
67
|
+
"searchAJE": "world news",
|
|
68
|
+
"searchBing": "world news today",
|
|
69
|
+
"dateFilter": "date ge 2024-02-22T00:00:00Z",
|
|
70
|
+
"titleOnly": false,
|
|
71
|
+
"language": "eng",
|
|
72
|
+
"languageStr": "English"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
"What is this document about?"
|
|
76
|
+
{
|
|
77
|
+
"searchRequired": true,
|
|
78
|
+
"searchPersonal": "*",
|
|
79
|
+
"language": "eng",
|
|
80
|
+
"languageStr": "English"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
"What topics were covered last week on AJE?"
|
|
84
|
+
{
|
|
85
|
+
"searchRequired": true,
|
|
86
|
+
"searchAJE": "*",
|
|
87
|
+
"dateFilter": "date ge 2024-02-22T00:00:00Z and date le 2024-02-28T23:59:59Z",
|
|
88
|
+
"titleOnly": true,
|
|
89
|
+
"language": "eng",
|
|
90
|
+
"languageStr": "English"
|
|
91
|
+
}`,
|
|
92
|
+
},
|
|
93
|
+
{"role": "user", "content": "Examine the Conversation History and decide what data sources if any to search to help the user and produce a JSON object with fields that communicate your decisions."},
|
|
94
|
+
]}),
|
|
95
|
+
],
|
|
96
|
+
model: 'oai-gpt4o',
|
|
97
|
+
useInputChunking: false,
|
|
98
|
+
enableDuplicateRequests: false,
|
|
99
|
+
json: true,
|
|
100
|
+
...entityConstants
|
|
101
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
inputParameters: {
|
|
5
|
+
chatHistory: [{role: '', content: []}],
|
|
6
|
+
},
|
|
7
|
+
prompt:
|
|
8
|
+
[
|
|
9
|
+
new Prompt({ messages: [
|
|
10
|
+
{
|
|
11
|
+
"role": "system",
|
|
12
|
+
"content": `{{renderTemplate AI_CONVERSATION_HISTORY}}
|
|
13
|
+
|
|
14
|
+
Instructions: You are part of an AI entity named {{{aiName}}}. Your task is to analyze the conversation history to determine whether a coding task has been requested or if the user's needs can be addressed only by executing the code. Output a JSON object with three fields:
|
|
15
|
+
|
|
16
|
+
1. "codingRequired": Boolean. Set to true if the user asks for or needs code execution. Otherwise, set to false.
|
|
17
|
+
|
|
18
|
+
2. "codingMessage": String. If codingRequired is true, provide a message to notify the user that a coding task is being handled. Otherwise, leave this as an empty string.
|
|
19
|
+
|
|
20
|
+
3. "codingTask": String. If codingRequired is true, provide a task description for the coding agent. Make sure to pass all all the information needed as this is the only message that coding agent receives and is aware of. Just provide the task and let the agent decide how to solve or what do to. Never make any assumptions about the agent's knowledge or capabilities. Never say assume this or that. Never give example by yourself, let coding agent decide on that. Provide the task do not ask questions or say anything will further be provided by the user. If codingRequired is false, leave this as an empty string.
|
|
21
|
+
|
|
22
|
+
4. "codingTaskKeywords": If codingRequired is true, provide a keywords for Azure Cognitive Search to help the coding agent find the relevant code snippets. It will use these keywords as is to search for the code snippets. If codingRequired is false, leave this as an empty string.
|
|
23
|
+
|
|
24
|
+
General guidelines:
|
|
25
|
+
- AJ is for AL Jazeera, AJA is for AJ Arabic, AJE is for AJ English
|
|
26
|
+
- If agent needs to search in task it can use Bing Search
|
|
27
|
+
|
|
28
|
+
Always output just the valid JSON object with all these fields.`,
|
|
29
|
+
},
|
|
30
|
+
{"role": "user", "content": "Analyze the provided conversation history and determine if you should use code executionto respond to the user. Generate a JSON object to indicate if it is needed."},
|
|
31
|
+
]}),
|
|
32
|
+
],
|
|
33
|
+
model: 'oai-gpt4o',
|
|
34
|
+
useInputChunking: false,
|
|
35
|
+
enableDuplicateRequests: false,
|
|
36
|
+
json: true,
|
|
37
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Prompt } from '../../../server/prompt.js';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
inputParameters: {
|
|
5
|
+
chatHistory: [{role: '', content: []}],
|
|
6
|
+
model: "oai-gpt4o",
|
|
7
|
+
aiName: "Jarvis",
|
|
8
|
+
},
|
|
9
|
+
prompt:
|
|
10
|
+
[
|
|
11
|
+
new Prompt({ messages: [
|
|
12
|
+
{
|
|
13
|
+
"role": "system",
|
|
14
|
+
"content": `{{renderTemplate AI_CONVERSATION_HISTORY}}
|
|
15
|
+
|
|
16
|
+
Instructions: You are part of an AI entity named {{{aiName}}}. Your task is to determine whether to use a tool based on the conversation history and user's request. Prioritize the latest message from the user in the conversation history when making your decision.
|
|
17
|
+
|
|
18
|
+
Available tools and their specific use cases:
|
|
19
|
+
|
|
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
|
+
|
|
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.
|
|
23
|
+
|
|
24
|
+
3. 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.
|
|
25
|
+
|
|
26
|
+
4. Image: Use when asked to create, generate, or manipulate visual content. This covers photographs, illustrations, diagrams, or any other type of image. Always use this tool for image requests unless explicitly directed to use CodeExecution.
|
|
27
|
+
|
|
28
|
+
5. 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.
|
|
29
|
+
|
|
30
|
+
6. 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, or business intelligence tasks.
|
|
31
|
+
|
|
32
|
+
7. 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.
|
|
33
|
+
|
|
34
|
+
8. PDF: Use specifically for processing and answering questions about PDF file content.
|
|
35
|
+
|
|
36
|
+
9. Vision: Engage for analyzing and responding to queries about image files (jpg, gif, bmp, png, etc).
|
|
37
|
+
|
|
38
|
+
10. Video: Use for processing and answering questions about video or audio file content.
|
|
39
|
+
|
|
40
|
+
11. 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
|
+
|
|
42
|
+
Tool Selection Guidelines:
|
|
43
|
+
- Prioritize the most specific tool for the task at hand.
|
|
44
|
+
- If multiple tools seem applicable, choose the one most central to the user's request.
|
|
45
|
+
- For ambiguous requests, consider using the Reason tool to plan a multi-step approach.
|
|
46
|
+
- Always use the Image tool for image generation unless explicitly directed to use CodeExecution.
|
|
47
|
+
- If the user explicitly asks you to use a tool, you must use it.
|
|
48
|
+
|
|
49
|
+
Decision Output:
|
|
50
|
+
If you decide to use a tool, return a JSON object in this format:
|
|
51
|
+
{"toolRequired": true, "toolFunction": "toolName", "toolMessage": "message to the user to wait a moment while you work", "toolReason": "detailed explanation of why this tool was chosen"}
|
|
52
|
+
|
|
53
|
+
If no tool is required, return:
|
|
54
|
+
{"toolRequired": false, "toolReason": "explanation of why no tool was necessary"}
|
|
55
|
+
|
|
56
|
+
Return only the JSON object without additional commentary.`,
|
|
57
|
+
},
|
|
58
|
+
{"role": "user", "content": "Analyze the provided conversation history and determine if you should use any of the tools to respond to the user. Generate a JSON object to indicate if a tool is needed."},
|
|
59
|
+
]}),
|
|
60
|
+
],
|
|
61
|
+
useInputChunking: false,
|
|
62
|
+
enableDuplicateRequests: false,
|
|
63
|
+
json: true,
|
|
64
|
+
}
|