@aj-archipelago/cortex 1.2.1 → 1.3.1

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.
Files changed (80) hide show
  1. package/config.js +38 -11
  2. package/helper-apps/cortex-autogen/OAI_CONFIG_LIST +2 -1
  3. package/helper-apps/cortex-autogen/agents.py +392 -0
  4. package/helper-apps/cortex-autogen/agents_extra.py +14 -0
  5. package/helper-apps/cortex-autogen/config.py +18 -0
  6. package/helper-apps/cortex-autogen/data_operations.py +29 -0
  7. package/helper-apps/cortex-autogen/function_app.py +6 -3
  8. package/helper-apps/cortex-autogen/main.py +4 -4
  9. package/helper-apps/cortex-autogen/prompts.py +196 -0
  10. package/helper-apps/cortex-autogen/prompts_extra.py +5 -0
  11. package/helper-apps/cortex-autogen/requirements.txt +2 -1
  12. package/helper-apps/cortex-autogen/search.py +83 -0
  13. package/helper-apps/cortex-autogen/test.sh +40 -0
  14. package/helper-apps/cortex-autogen/utils.py +78 -0
  15. package/lib/handleBars.js +25 -0
  16. package/lib/logger.js +2 -0
  17. package/lib/util.js +3 -1
  18. package/package.json +1 -1
  19. package/pathways/chat_code.js +1 -1
  20. package/pathways/chat_context.js +1 -1
  21. package/pathways/chat_jarvis.js +1 -1
  22. package/pathways/chat_persist.js +1 -1
  23. package/pathways/chat_title.js +25 -0
  24. package/pathways/image_recraft.js +1 -1
  25. package/pathways/rag.js +1 -1
  26. package/pathways/rag_jarvis.js +1 -1
  27. package/pathways/rag_search_helper.js +1 -1
  28. package/pathways/system/entity/memory/sys_memory_manager.js +71 -0
  29. package/pathways/system/entity/memory/sys_memory_required.js +21 -0
  30. package/pathways/system/entity/memory/sys_memory_update.js +196 -0
  31. package/pathways/system/entity/memory/sys_read_memory.js +37 -0
  32. package/pathways/system/entity/memory/sys_save_memory.js +60 -0
  33. package/pathways/system/entity/shared/sys_entity_constants.js +27 -0
  34. package/pathways/system/entity/sys_entity_continue.js +55 -0
  35. package/pathways/system/entity/sys_entity_start.js +239 -0
  36. package/pathways/system/entity/sys_generator_error.js +20 -0
  37. package/pathways/system/entity/sys_generator_expert.js +26 -0
  38. package/pathways/system/entity/sys_generator_image.js +127 -0
  39. package/pathways/system/entity/sys_generator_quick.js +19 -0
  40. package/pathways/system/entity/sys_generator_reasoning.js +27 -0
  41. package/pathways/system/entity/sys_generator_results.js +310 -0
  42. package/pathways/system/entity/sys_generator_video_vision.js +27 -0
  43. package/pathways/system/entity/sys_image_prompt_builder.js +35 -0
  44. package/pathways/system/entity/sys_query_builder.js +110 -0
  45. package/pathways/system/entity/sys_router_code.js +37 -0
  46. package/pathways/system/entity/sys_router_tool.js +67 -0
  47. package/pathways/{sys_claude_35_sonnet.js → system/rest_streaming/sys_claude_35_sonnet.js} +1 -1
  48. package/pathways/{sys_claude_3_haiku.js → system/rest_streaming/sys_claude_3_haiku.js} +1 -1
  49. package/pathways/{sys_google_chat.js → system/rest_streaming/sys_google_chat.js} +1 -1
  50. package/pathways/{sys_google_code_chat.js → system/rest_streaming/sys_google_code_chat.js} +1 -1
  51. package/pathways/{sys_google_gemini_chat.js → system/rest_streaming/sys_google_gemini_chat.js} +1 -1
  52. package/pathways/{sys_openai_chat.js → system/rest_streaming/sys_openai_chat.js} +1 -1
  53. package/pathways/{sys_openai_chat_16.js → system/rest_streaming/sys_openai_chat_16.js} +1 -1
  54. package/pathways/{sys_openai_chat_gpt4.js → system/rest_streaming/sys_openai_chat_gpt4.js} +1 -1
  55. package/pathways/{sys_openai_chat_gpt4_32.js → system/rest_streaming/sys_openai_chat_gpt4_32.js} +1 -1
  56. package/pathways/{sys_openai_chat_gpt4_turbo.js → system/rest_streaming/sys_openai_chat_gpt4_turbo.js} +1 -1
  57. package/pathways/{sys_parse_numbered_object_list.js → system/sys_parse_numbered_object_list.js} +2 -2
  58. package/pathways/{sys_repair_json.js → system/sys_repair_json.js} +1 -1
  59. package/pathways/{run_claude35_sonnet.js → system/workspaces/run_claude35_sonnet.js} +1 -1
  60. package/pathways/{run_claude3_haiku.js → system/workspaces/run_claude3_haiku.js} +1 -1
  61. package/pathways/{run_gpt35turbo.js → system/workspaces/run_gpt35turbo.js} +1 -1
  62. package/pathways/{run_gpt4.js → system/workspaces/run_gpt4.js} +1 -1
  63. package/pathways/{run_gpt4_32.js → system/workspaces/run_gpt4_32.js} +1 -1
  64. package/server/pathwayResolver.js +62 -10
  65. package/server/plugins/azureCognitivePlugin.js +14 -1
  66. package/server/plugins/azureVideoTranslatePlugin.js +1 -1
  67. package/server/plugins/claude3VertexPlugin.js +25 -15
  68. package/server/plugins/gemini15ChatPlugin.js +1 -1
  69. package/server/plugins/geminiChatPlugin.js +1 -1
  70. package/server/plugins/modelPlugin.js +10 -1
  71. package/server/plugins/openAiChatPlugin.js +4 -3
  72. package/server/plugins/openAiDallE3Plugin.js +12 -4
  73. package/server/plugins/openAiVisionPlugin.js +1 -2
  74. package/server/plugins/replicateApiPlugin.js +75 -17
  75. package/tests/multimodal_conversion.test.js +6 -8
  76. package/helper-apps/cortex-autogen/myautogen.py +0 -317
  77. package/helper-apps/cortex-autogen/prompt.txt +0 -0
  78. package/helper-apps/cortex-autogen/prompt_summary.txt +0 -37
  79. package/pathways/index.js +0 -154
  80. /package/pathways/{sys_openai_completion.js → system/rest_streaming/sys_openai_completion.js} +0 -0
@@ -0,0 +1,110 @@
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
+ Add a short message to the resultsMessage field that acknowledges the user's request and indicates you're processing it.
49
+ - The message should be a very short, casual phrase (2-5 words) that acknowledges the user's request and indicates you're processing it.
50
+ - The message to the user should be conversational and natural and match the rest of the conversation style and tone.
51
+ - The message should take 1-2 seconds to say out loud. Examples: 'Hmm, let's see...', 'Just a sec...', 'Checking...'"
52
+
53
+ You should only ever respond with the JSON object and never with any additional notes or commentary.
54
+
55
+ Example JSON objects and messages for different queries:
56
+
57
+ "What's the latest on the wires?"
58
+ {
59
+ "searchRequired": true,"
60
+ "searchWires": "*",
61
+ "dateFilter": "date ge 2024-02-22T00:00:00Z",
62
+ "titleOnly": false,
63
+ "language": "eng",
64
+ "languageStr": "English",
65
+ "resultsMessage": "Reading the wires..."
66
+ }
67
+
68
+ "What's going on in the world today?"
69
+ {
70
+ "searchRequired": true,
71
+ "searchWires": "world news",
72
+ "searchAJA": "عالم حدث اليوم",
73
+ "searchAJE": "world news",
74
+ "searchBing": "world news today",
75
+ "dateFilter": "date ge 2024-02-22T00:00:00Z",
76
+ "titleOnly": false,
77
+ "language": "eng",
78
+ "languageStr": "English",
79
+ "resultsMessage": "Just a few seconds..."
80
+ }
81
+
82
+ "What is this document about?"
83
+ {
84
+ "searchRequired": true,
85
+ "searchPersonal": "*",
86
+ "language": "eng",
87
+ "languageStr": "English",
88
+ "resultsMessage": "Almost done..."
89
+ }
90
+
91
+ "What topics were covered last week on AJE?"
92
+ {
93
+ "searchRequired": true,
94
+ "searchAJE": "*",
95
+ "dateFilter": "date ge 2024-02-22T00:00:00Z and date le 2024-02-28T23:59:59Z",
96
+ "titleOnly": true,
97
+ "language": "eng",
98
+ "languageStr": "English",
99
+ "resultsMessage": "Almost there..."
100
+ }`,
101
+ },
102
+ {"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."},
103
+ ]}),
104
+ ],
105
+ model: 'oai-gpt4o',
106
+ useInputChunking: false,
107
+ enableDuplicateRequests: false,
108
+ json: true,
109
+ ...entityConstants
110
+ }
@@ -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,67 @@
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
+ - The message to the user should flow naturally with the conversation history and match the rest of the conversation history in style and tone.
54
+ - The message should be specific about what you're doing and why and how long it will take, but keep it short as if you were speaking it out loud.
55
+
56
+ If no tool is required, return:
57
+ {"toolRequired": false, "toolReason": "explanation of why no tool was necessary"}
58
+
59
+ Return only the JSON object without additional commentary.`,
60
+ },
61
+ {"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."},
62
+ ]}),
63
+ ],
64
+ useInputChunking: false,
65
+ enableDuplicateRequests: false,
66
+ json: true,
67
+ }
@@ -1,7 +1,7 @@
1
1
  // sys_claude_35_sonnet.js
2
2
  // override handler for claude-35-sonnet
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_claude_3_haiku.js
2
2
  // override handler for claude-3-haiku
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_google_chat.js
2
2
  // override handler for palm-chat
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_google_code_chat.js
2
2
  // override handler for palm-code-chat
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_google_gemini_chat.js
2
2
  // override handler for gemini-chat
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_openai_chat.js
2
2
  // override handler for gpt-3.5-turbo
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_openai_chat_16.js
2
2
  // override handler for gpt-3.5-turbo-16k
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_openai_chat_gpt4.js
2
2
  // override handler for gpt-4
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_openai_chat_gpt4_32.js
2
2
  // override handler for gpt-4-32
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,7 +1,7 @@
1
1
  // sys_openai_chat_gpt4_turbo.js
2
2
  // override handler for gpt-4-turbo
3
3
 
4
- import { Prompt } from '../server/prompt.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
5
 
6
6
  export default {
7
7
  prompt:
@@ -1,10 +1,10 @@
1
- import { Prompt } from '../server/prompt.js';
1
+ import { Prompt } from '../../server/prompt.js';
2
2
 
3
3
  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 the list into a JSON object with the given fields. If there are extra fields, assistant will ignore them. If there are some missing fields, assistant will just skip the missing fields and return the rest. 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." },
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 the list 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 there are some missing fields, assistant will just skip the missing fields and return the rest. 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
  })
@@ -1,4 +1,4 @@
1
- import { Prompt } from '../server/prompt.js';
1
+ import { Prompt } from '../../server/prompt.js';
2
2
 
3
3
  export default {
4
4
  prompt: [
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Import required modules
3
- import { Prompt } from '../server/prompt.js';
3
+ import { Prompt } from '../../../server/prompt.js';
4
4
 
5
5
  export default {
6
6
  prompt: [
@@ -1,5 +1,5 @@
1
1
  // Import required modules
2
- import { Prompt } from '../server/prompt.js';
2
+ import { Prompt } from '../../../server/prompt.js';
3
3
 
4
4
  export default {
5
5
  prompt: [
@@ -1,5 +1,5 @@
1
1
  // Import required modules
2
- import { Prompt } from "../server/prompt.js"
2
+ import { Prompt } from "../../../server/prompt.js"
3
3
 
4
4
  export default {
5
5
  prompt: [
@@ -1,5 +1,5 @@
1
1
  // Import required modules
2
- import { Prompt } from '../server/prompt.js';
2
+ import { Prompt } from '../../../server/prompt.js';
3
3
 
4
4
  export default {
5
5
  prompt: [
@@ -1,5 +1,5 @@
1
1
  // Import required modules
2
- import { Prompt } from '../server/prompt.js';
2
+ import { Prompt } from '../../../server/prompt.js';
3
3
 
4
4
  export default {
5
5
  prompt: [
@@ -221,15 +221,59 @@ class PathwayResolver {
221
221
  // Get saved context from contextId or change contextId if needed
222
222
  const { contextId } = args;
223
223
  this.savedContextId = contextId ? contextId : uuidv4();
224
- this.savedContext = contextId ? (getv && (await getv(contextId)) || {}) : {};
225
-
226
- // Save the context before processing the request
227
- const savedContextStr = JSON.stringify(this.savedContext);
224
+
225
+ const loadMemory = async () => {
226
+ // Load initial values
227
+ this.savedContext = (getv && await getv(contextId)) || {};
228
+ this.memorySelf = (getv && await getv(`${contextId}-memorySelf`)) || "";
229
+ this.memoryDirectives = (getv && await getv(`${contextId}-memoryDirectives`)) || "";
230
+ this.memoryTopics = (getv && await getv(`${contextId}-memoryTopics`)) || "";
231
+ this.memoryUser = (getv && await getv(`${contextId}-memoryUser`)) || "";
232
+
233
+ // Store initial state for comparison
234
+ this.initialState = {
235
+ savedContext: this.savedContext,
236
+ memorySelf: this.memorySelf,
237
+ memoryDirectives: this.memoryDirectives,
238
+ memoryTopics: this.memoryTopics,
239
+ memoryUser: this.memoryUser
240
+ };
241
+ };
242
+
243
+ const saveChangedMemory = async () => {
244
+ this.savedContextId = this.savedContextId || uuidv4();
245
+
246
+ const currentState = {
247
+ savedContext: this.savedContext,
248
+ memorySelf: this.memorySelf,
249
+ memoryDirectives: this.memoryDirectives,
250
+ memoryTopics: this.memoryTopics,
251
+ memoryUser: this.memoryUser
252
+ };
253
+
254
+ if (currentState.savedContext !== this.initialState.savedContext) {
255
+ setv && await setv(this.savedContextId, this.savedContext);
256
+ }
257
+ if (currentState.memorySelf !== this.initialState.memorySelf) {
258
+ setv && await setv(`${this.savedContextId}-memorySelf`, this.memorySelf);
259
+ }
260
+ if (currentState.memoryDirectives !== this.initialState.memoryDirectives) {
261
+ setv && await setv(`${this.savedContextId}-memoryDirectives`, this.memoryDirectives);
262
+ }
263
+ if (currentState.memoryTopics !== this.initialState.memoryTopics) {
264
+ setv && await setv(`${this.savedContextId}-memoryTopics`, this.memoryTopics);
265
+ }
266
+ if (currentState.memoryUser !== this.initialState.memoryUser) {
267
+ setv && await setv(`${this.savedContextId}-memoryUser`, this.memoryUser);
268
+ }
269
+ };
228
270
 
229
271
  const MAX_RETRIES = 3;
230
272
  let data = null;
231
273
 
232
274
  for (let retries = 0; retries < MAX_RETRIES; retries++) {
275
+ await loadMemory(); // Reset memory state on each retry
276
+
233
277
  data = await this.processRequest(args);
234
278
  if (!data) {
235
279
  break;
@@ -241,13 +285,10 @@ class PathwayResolver {
241
285
  }
242
286
 
243
287
  logger.warn(`Bad pathway result - retrying pathway. Attempt ${retries + 1} of ${MAX_RETRIES}`);
244
- this.savedContext = JSON.parse(savedContextStr);
245
288
  }
246
289
 
247
- // Update saved context if it has changed, generating a new contextId if necessary
248
- if (savedContextStr !== JSON.stringify(this.savedContext)) {
249
- this.savedContextId = this.savedContextId || uuidv4();
250
- setv && setv(this.savedContextId, this.savedContext);
290
+ if (data !== null) {
291
+ await saveChangedMemory();
251
292
  }
252
293
 
253
294
  return data;
@@ -419,7 +460,14 @@ class PathwayResolver {
419
460
 
420
461
  // If this text is empty, skip applying the prompt as it will likely be a nonsensical result
421
462
  if (!/^\s*$/.test(text) || parameters?.file || parameters?.inputVector || this?.modelName.includes('cognitive')) {
422
- result = await this.modelExecutor.execute(text, { ...parameters, ...this.savedContext }, prompt, this);
463
+ result = await this.modelExecutor.execute(text, {
464
+ ...parameters,
465
+ ...this.savedContext,
466
+ memorySelf: this.memorySelf,
467
+ memoryDirectives: this.memoryDirectives,
468
+ memoryTopics: this.memoryTopics,
469
+ memoryUser: this.memoryUser
470
+ }, prompt, this);
423
471
  } else {
424
472
  result = text;
425
473
  }
@@ -439,6 +487,10 @@ class PathwayResolver {
439
487
 
440
488
  // save the result to the context if requested and no errors
441
489
  if (prompt.saveResultTo && this.errors.length === 0) {
490
+ // Update memory property if it matches a known type
491
+ if (["memorySelf", "memoryUser", "memoryDirectives", "memoryTopics"].includes(prompt.saveResultTo)) {
492
+ this[prompt.saveResultTo] = result;
493
+ }
442
494
  this.savedContext[prompt.saveResultTo] = result;
443
495
  }
444
496
  return result;
@@ -55,7 +55,7 @@ class AzureCognitivePlugin extends ModelPlugin {
55
55
  { search: searchQuery,
56
56
  "searchMode": "all",
57
57
  "queryType": "full",
58
- select: 'id', top: TOP
58
+ select: 'id', top: TOP, skip: 0
59
59
  };
60
60
 
61
61
  const docsToDelete = JSON.parse(await this.executeRequest(cortexRequest));
@@ -115,6 +115,19 @@ class AzureCognitivePlugin extends ModelPlugin {
115
115
  ];
116
116
  } else {
117
117
  data.search = modelPromptText;
118
+ data.top = parameters.top || 50;
119
+ data.skip = 0;
120
+ if (parameters.titleOnly) {
121
+ switch(indexName){
122
+ case 'indexcortex':
123
+ case 'indexwires':
124
+ data.select = 'title,id';
125
+ break;
126
+ default:
127
+ data.select = 'title,id,url';
128
+ break;
129
+ }
130
+ }
118
131
  }
119
132
 
120
133
  filter && (data.filter = filter);
@@ -27,7 +27,7 @@ class AzureVideoTranslatePlugin extends ModelPlugin {
27
27
 
28
28
  getRequestParameters(_, parameters, __) {
29
29
  const excludedParameters = [
30
- 'text', 'parameters', 'prompt', 'promptParameters', 'previousResult', 'stream'
30
+ 'text', 'parameters', 'prompt', 'promptParameters', 'previousResult', 'stream', 'memoryContext'
31
31
  ];
32
32
 
33
33
  return Object.fromEntries(
@@ -1,9 +1,10 @@
1
1
  import OpenAIVisionPlugin from "./openAiVisionPlugin.js";
2
2
  import logger from "../../lib/logger.js";
3
+ import axios from 'axios';
3
4
 
4
5
  const allowedMIMETypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
5
- async function convertContentItem(item) {
6
6
 
7
+ async function convertContentItem(item, maxImageSize) {
7
8
  let imageUrl = "";
8
9
 
9
10
  try {
@@ -27,6 +28,14 @@ async function convertContentItem(item) {
27
28
  try {
28
29
  const urlData = imageUrl.startsWith("data:") ? imageUrl : await fetchImageAsDataURL(imageUrl);
29
30
  if (!urlData) { return null; }
31
+
32
+ // Check base64 size
33
+ const base64Size = (urlData.length * 3) / 4;
34
+ if (base64Size > maxImageSize) {
35
+ logger.warn(`Image size ${base64Size} bytes exceeds maximum allowed size ${maxImageSize} - skipping image content.`);
36
+ return null;
37
+ }
38
+
30
39
  const [, mimeType = "image/jpeg"] = urlData.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/) || [];
31
40
  const base64Image = urlData.split(",")[1];
32
41
 
@@ -60,25 +69,26 @@ async function convertContentItem(item) {
60
69
  // Fetch image and convert to base 64 data URL
61
70
  async function fetchImageAsDataURL(imageUrl) {
62
71
  try {
63
- const response = await fetch(imageUrl, { method: 'HEAD' });
64
-
65
- if (!response.ok) {
66
- throw new Error(`HTTP error! status: ${response.status}`);
67
- }
72
+ // First check headers
73
+ const headResponse = await axios.head(imageUrl, {
74
+ timeout: 30000, // 30 second timeout
75
+ maxRedirects: 5
76
+ });
68
77
 
69
- const contentType = response.headers.get('content-type');
78
+ const contentType = headResponse.headers['content-type'];
70
79
  if (!contentType || !allowedMIMETypes.includes(contentType)) {
71
80
  logger.warn(`Unsupported image type: ${contentType} - skipping image content.`);
72
81
  return null;
73
82
  }
74
83
 
75
- const dataResponse = await fetch(imageUrl);
76
- if (!dataResponse.ok) {
77
- throw new Error(`HTTP error! status: ${dataResponse.status}`);
78
- }
84
+ // Then get the actual image data
85
+ const dataResponse = await axios.get(imageUrl, {
86
+ timeout: 30000,
87
+ responseType: 'arraybuffer',
88
+ maxRedirects: 5
89
+ });
79
90
 
80
- const buffer = await dataResponse.arrayBuffer();
81
- const base64Image = Buffer.from(buffer).toString("base64");
91
+ const base64Image = Buffer.from(dataResponse.data).toString('base64');
82
92
  return `data:${contentType};base64,${base64Image}`;
83
93
  }
84
94
  catch (e) {
@@ -151,7 +161,7 @@ class Claude3VertexPlugin extends OpenAIVisionPlugin {
151
161
  const claude3Messages = await Promise.all(
152
162
  finalMessages.map(async (message) => {
153
163
  const contentArray = Array.isArray(message.content) ? message.content : [message.content];
154
- const claude3Content = await Promise.all(contentArray.map(convertContentItem));
164
+ const claude3Content = await Promise.all(contentArray.map(item => convertContentItem(item, this.getModelMaxImageSize())));
155
165
  return {
156
166
  role: message.role,
157
167
  content: claude3Content.filter(Boolean),
@@ -301,7 +311,7 @@ class Claude3VertexPlugin extends OpenAIVisionPlugin {
301
311
 
302
312
  shortenContent(content, maxWords = 40) {
303
313
  const words = content.split(" ");
304
- if (words.length <= maxWords) {
314
+ if (words.length <= maxWords || logger.level === 'debug') {
305
315
  return content;
306
316
  }
307
317
  return words.slice(0, maxWords / 2).join(" ") +
@@ -200,7 +200,7 @@ class Gemini15ChatPlugin extends ModelPlugin {
200
200
  } else if (Array.isArray(responseData)) {
201
201
  const { mergedResult, safetyRatings } = mergeResults(responseData);
202
202
  if (safetyRatings?.length) {
203
- logger.warn(`!!! response was blocked because the input or response potentially violates policies`);
203
+ logger.warn(`response was blocked because the input or response potentially violates policies`);
204
204
  logger.verbose(`Safety Ratings: ${JSON.stringify(safetyRatings, null, 2)}`);
205
205
  }
206
206
  const { length, units } = this.getLength(mergedResult);
@@ -195,7 +195,7 @@ class GeminiChatPlugin extends ModelPlugin {
195
195
  } else if (Array.isArray(responseData)) {
196
196
  const { mergedResult, safetyRatings } = mergeResults(responseData);
197
197
  if (safetyRatings?.length) {
198
- logger.warn(`!!! response was blocked because the input or response potentially violates policies`);
198
+ logger.warn(`response was blocked because the input or response potentially violates policies`);
199
199
  logger.verbose(`Safety Ratings: ${JSON.stringify(safetyRatings, null, 2)}`);
200
200
  }
201
201
  const { length, units } = this.getLength(mergedResult);