solace-agent-mesh 0.1.3__py3-none-any.whl → 0.2.1__py3-none-any.whl

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.

Potentially problematic release.


This version of solace-agent-mesh might be problematic. Click here for more details.

Files changed (73) hide show
  1. solace_agent_mesh/agents/global/actions/plantuml_diagram.py +9 -2
  2. solace_agent_mesh/agents/global/actions/plotly_graph.py +70 -46
  3. solace_agent_mesh/agents/web_request/actions/do_web_request.py +34 -33
  4. solace_agent_mesh/cli/__init__.py +1 -1
  5. solace_agent_mesh/cli/commands/add/copy_from_plugin.py +8 -6
  6. solace_agent_mesh/cli/commands/add/gateway.py +162 -9
  7. solace_agent_mesh/cli/commands/build.py +15 -1
  8. solace_agent_mesh/cli/commands/init/ai_provider_step.py +45 -28
  9. solace_agent_mesh/cli/commands/init/broker_step.py +1 -4
  10. solace_agent_mesh/cli/commands/init/create_config_file_step.py +8 -0
  11. solace_agent_mesh/cli/commands/init/create_other_project_files_step.py +52 -1
  12. solace_agent_mesh/cli/commands/init/init.py +50 -37
  13. solace_agent_mesh/cli/commands/plugin/build.py +60 -9
  14. solace_agent_mesh/cli/commands/run.py +2 -2
  15. solace_agent_mesh/cli/config.py +4 -0
  16. solace_agent_mesh/cli/main.py +14 -8
  17. solace_agent_mesh/cli/utils.py +7 -2
  18. solace_agent_mesh/common/constants.py +10 -0
  19. solace_agent_mesh/common/prompt_templates.py +1 -3
  20. solace_agent_mesh/common/utils.py +104 -30
  21. solace_agent_mesh/config_portal/__init__.py +0 -0
  22. solace_agent_mesh/config_portal/backend/__init__.py +0 -0
  23. solace_agent_mesh/config_portal/backend/common.py +35 -0
  24. solace_agent_mesh/config_portal/backend/server.py +233 -0
  25. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DRPGOzHj.js +42 -0
  26. solace_agent_mesh/config_portal/frontend/static/client/assets/components-ZIfdTbrV.js +191 -0
  27. solace_agent_mesh/config_portal/frontend/static/client/assets/entry.client-DX1misIU.js +19 -0
  28. solace_agent_mesh/config_portal/frontend/static/client/assets/index-BJHAE5s4.js +17 -0
  29. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-8147e469.js +1 -0
  30. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DgMDqKDc.js +10 -0
  31. solace_agent_mesh/config_portal/frontend/static/client/assets/root-hhS5izs8.css +1 -0
  32. solace_agent_mesh/config_portal/frontend/static/client/favicon.ico +0 -0
  33. solace_agent_mesh/config_portal/frontend/static/client/index.html +7 -0
  34. solace_agent_mesh/configs/orchestrator.yaml +1 -1
  35. solace_agent_mesh/configs/service_embedding.yaml +1 -1
  36. solace_agent_mesh/configs/service_llm.yaml +1 -1
  37. solace_agent_mesh/gateway/components/gateway_base.py +7 -1
  38. solace_agent_mesh/gateway/components/gateway_input.py +8 -5
  39. solace_agent_mesh/gateway/components/gateway_output.py +12 -3
  40. solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +4 -0
  41. solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +43 -12
  42. solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +19 -5
  43. solace_agent_mesh/orchestrator/orchestrator_main.py +11 -5
  44. solace_agent_mesh/orchestrator/orchestrator_prompt.py +184 -60
  45. solace_agent_mesh/services/file_service/file_service.py +5 -0
  46. solace_agent_mesh/services/file_service/file_service_constants.py +1 -1
  47. solace_agent_mesh/services/file_service/file_transformations.py +11 -1
  48. solace_agent_mesh/services/file_service/file_utils.py +2 -0
  49. solace_agent_mesh/services/history_service/history_providers/base_history_provider.py +21 -46
  50. solace_agent_mesh/services/history_service/history_providers/file_history_provider.py +74 -0
  51. solace_agent_mesh/services/history_service/history_providers/index.py +40 -0
  52. solace_agent_mesh/services/history_service/history_providers/memory_history_provider.py +19 -156
  53. solace_agent_mesh/services/history_service/history_providers/mongodb_history_provider.py +66 -0
  54. solace_agent_mesh/services/history_service/history_providers/redis_history_provider.py +40 -140
  55. solace_agent_mesh/services/history_service/history_providers/sql_history_provider.py +93 -0
  56. solace_agent_mesh/services/history_service/history_service.py +315 -41
  57. solace_agent_mesh/services/history_service/long_term_memory/__init__.py +0 -0
  58. solace_agent_mesh/services/history_service/long_term_memory/long_term_memory.py +399 -0
  59. solace_agent_mesh/services/llm_service/components/llm_request_component.py +19 -0
  60. solace_agent_mesh/templates/gateway-config-template.yaml +2 -1
  61. solace_agent_mesh/templates/gateway-default-config.yaml +3 -3
  62. solace_agent_mesh/templates/plugin-gateway-default-config.yaml +29 -0
  63. solace_agent_mesh/templates/rest-api-default-config.yaml +2 -1
  64. solace_agent_mesh/templates/slack-default-config.yaml +1 -1
  65. solace_agent_mesh/templates/solace-agent-mesh-default.yaml +9 -0
  66. solace_agent_mesh/templates/web-default-config.yaml +2 -1
  67. solace_agent_mesh-0.2.1.dist-info/METADATA +172 -0
  68. {solace_agent_mesh-0.1.3.dist-info → solace_agent_mesh-0.2.1.dist-info}/RECORD +71 -52
  69. solace_agent_mesh/common/prompt_templates_unused_delete.py +0 -161
  70. solace_agent_mesh-0.1.3.dist-info/METADATA +0 -208
  71. {solace_agent_mesh-0.1.3.dist-info → solace_agent_mesh-0.2.1.dist-info}/WHEEL +0 -0
  72. {solace_agent_mesh-0.1.3.dist-info → solace_agent_mesh-0.2.1.dist-info}/entry_points.txt +0 -0
  73. {solace_agent_mesh-0.1.3.dist-info → solace_agent_mesh-0.2.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,399 @@
1
+ from datetime import datetime
2
+ import json
3
+
4
+ from solace_ai_connector.common.log import log
5
+ from litellm import completion
6
+
7
+ # Some prompts were imported and modified from mem0
8
+ PROMPTS = {
9
+ "EXTRACT_FACTS": f"""You are a Personal Information Organizer, specialized in accurately storing facts, user memories, and preferences. Your primary role is to extract relevant pieces of information from conversations and organize them into distinct, manageable facts. This allows for easy retrieval and personalization in future interactions. Below are the types of information you need to focus on and the detailed instructions on how to handle the input data.
10
+
11
+ Types of Information to Remember:
12
+
13
+ 1. Store Personal Preferences: Keep track of likes, dislikes, and specific preferences in various categories such as food, products, activities, and entertainment.
14
+ 2. Maintain Important Personal Details: Remember significant personal information like names, relationships, and important dates.
15
+ 3. Track Plans and Intentions: Note upcoming events, trips, goals, and any plans the user has shared.
16
+ 4. Remember Activity and Service Preferences: Recall preferences for dining, travel, hobbies, and other services.
17
+ 5. Monitor Health and Wellness Preferences: Keep a record of dietary restrictions, fitness routines, and other wellness-related information.
18
+ 6. Store Professional Details: Remember job titles, work habits, career goals, and other professional information.
19
+ 7. Styles and Preferences: Keep track of how the user wants you to reply to messages, the tone of the conversation, and other stylistic preferences.
20
+ 8. Miscellaneous Information Management: Keep track of favorite books, movies, brands, and other miscellaneous details that the user shares.
21
+ 9. Update notes: if the user is specifically asking you to remember or forget something.
22
+ 10. Ignore general facts: Ignore global information, like weather, news, or general knowledge or facts.
23
+
24
+ You must respond in JSON format with 4 keys:
25
+ - "reasoning": Your reasoning and thoughts on why you think the extracted facts, instructions, and update_notes are important.
26
+ - "facts": a list of general facts extracted from the conversation. Do not include the basic information, only if something is worth remembering.
27
+ - "instructions": Preferences, styles, and learned behaviors from the user. Do not include chat history of user actions here. This is to only record user preferences and styles.
28
+ - "update_notes": Any specific instructions from the user to remember or forget something.
29
+
30
+ Each of these can be an empty list if no relevant information is found. Prioritize extracting information from the "user" message; the "assistant" message is rarely needed. It's completely fine to return empty if no important information is found in the conversation.
31
+
32
+ Here are some few shot examples:
33
+
34
+ Input: Hi.
35
+ Output: {{"facts" : [], "instructions" : [], "update_notes" : []}}
36
+
37
+ Input: The capital of Canada is Ottawa, and water boils at 100 degrees Celsius.
38
+ Output: {{"facts" : [], "instructions" : [], "update_notes" : []}}
39
+
40
+ Input: Hi, I am looking for a restaurant in San Francisco.
41
+ Output: {{"facts" : ["Looking for a restaurant in San Francisco"], "instructions" : [], "update_notes" : []}}
42
+
43
+ Input: Yesterday, I had a meeting with John at 3pm. We discussed the new project.
44
+ Output: {{"facts" : ["Had a meeting with John at 3pm", "Discussed the new project"], "instructions" : [], "update_notes" : []}}
45
+
46
+ Input: Please use the color red for all the lines in graphs you generate, redo the previous diagram.
47
+ Output: {{"facts" : [], "instructions" : [], "update_notes" : ["User prefers color red for all lines in graphs"]}}
48
+
49
+ Input: Sam is no longer my boss, remember that.
50
+ Output: {{"facts" : [], "instructions" : [], "update_notes" : ["Sam is no longer my boss"]}}
51
+
52
+ Input: Hi, my name is John. I am a software engineer.
53
+ Output: {{"facts" : ["Name is John", "Is a Software engineer"]}}
54
+
55
+ Input: Give me the summary of Jira item JIRA-1234. Always format your messages in markdown format with proper headings and bullet points.
56
+ Output: {{"facts" : [], "instructions" : ["Format messages in markdown format with proper headings and bullet points"], "update_notes" : []}}
57
+
58
+ Input: We just had our biggest sales ever. generate me the sales report for the last quarter. Use HTML with nice CSS styling for the report.
59
+ Output: {{"facts" : ["Had our biggest sales ever"], "instructions" : ["Use HTML with nice CSS styling for the report"], "update_notes" : []}}
60
+
61
+
62
+ Return the facts and preferences in a json format as shown above. Do not return anything else or do not prefix them with backticks.
63
+
64
+ Remember the following:
65
+ - Today's date is {datetime.now().strftime("%Y-%m-%d")}.
66
+ - Do not return anything from the example prompts provided above.
67
+ - Ignore specific details, like IDs, URLs, or numbers unless they are needed to be remembered long term or asked by the user.
68
+ - You are only analyzing and extracting information from the conversation, you're not replying to the user.
69
+ - If you do not find anything relevant in the below conversation, you can return an empty list.
70
+ - Create the facts based on the user and assistant messages only. Prioritize the user messages, most assistant replies can be ignored.
71
+ - The sentences must be complete and understandable without prior context.
72
+ - Make sure to return the response in the format mentioned in the examples.
73
+ - Ignore if the user is asking to clear history or forget everything you know. (That is not a update note)
74
+ - Don't repeat the same things in both facts and instructions.
75
+
76
+ Following is a conversation between the user and the assistant. You have to extract the relevant facts and instructions, and update notes about the user, if any, from the conversation and return them in the json format as shown above.
77
+
78
+ You should detect the language of the user input and record the facts in the same language.
79
+ """,
80
+
81
+ "MERGE_FACTS": """You are a smart memory manager which controls the memory of a system.
82
+ You can perform four operations: (1) add into the memory, (2) update the memory, (3) delete from the memory, and (4) no change.
83
+
84
+ Based on the above four operations, the memory will change.
85
+
86
+ Compare newly retrieved facts with the existing memory. For each new fact, decide whether to:
87
+ - ADD: Add it to the memory as a new element
88
+ - UPDATE: Update an existing memory element
89
+ - DELETE: Delete an existing memory element
90
+ - NONE: Make no change (if the fact is already present or irrelevant)
91
+
92
+ You will be provided the initial and new memory, each includes `facts` and `instructions` keys. You might also be provided some special instruction notes.
93
+
94
+ You must return the initial memory updated with the new facts and instructions based on the above operations.
95
+
96
+ Do NOT add, remove, or summarize anything from initial memory unless instructed by the new memory or the special notes.
97
+
98
+ There are specific guidelines to select which operation to perform:
99
+
100
+ 1. **Add**: If the retrieved facts contain new information not present in the memory, then you have to add to the end of list.
101
+ - **Example**:
102
+ - Initial Memory:
103
+ {
104
+ "facts": ["Name is John"],
105
+ "instructions": []
106
+ }
107
+
108
+ - Retrieved facts:
109
+ {
110
+ "facts": ["User is a software engineer"],
111
+ "instructions": ["Use CSS while generating an HTML report"]
112
+ }
113
+
114
+ - New Memory:
115
+ {
116
+ "facts": ["Name is John", "User is a software engineer"],
117
+ "instructions": ["Use CSS while generating an HTML report"]
118
+ }
119
+
120
+ 2. **Update**: If the retrieved facts contain information that is already present in the memory but the information is totally different, then you have to update it.
121
+
122
+ If the retrieved fact contains information that conveys the same thing as the elements present in the memory, then you have to keep the fact which has the most information.
123
+
124
+ Example (a) -- if the memory contains "User likes to play cricket" and the retrieved fact is "Loves to play cricket with friends", then update the memory with the retrieved facts.
125
+
126
+ Example (b) -- if the memory contains "Likes cheese pizza" and the retrieved fact is "Loves cheese pizza", then you do not need to update it because they convey the same information.
127
+
128
+ - **Example**:
129
+ - Initial Memory:
130
+ {
131
+ "facts": ["I really like cheese pizza", "User is a software engineer", "User likes to play cricket"],
132
+ "instructions": []
133
+ }
134
+
135
+ - Retrieved facts:
136
+ {
137
+ "facts": ["Loves cheese and chicken pizza", "Loves to play cricket with friends"],
138
+ "instructions": []
139
+ }
140
+
141
+ - New Memory:
142
+ {
143
+ "facts": ["Loves cheese and chicken pizza", "User is a software engineer","Loves to play cricket with friends"],
144
+ "instructions": []
145
+ }
146
+
147
+ 3. **Delete**: If the retrieved facts contain information that contradicts the information present in the memory, or has been specified in update notes, then you have to delete it. Do not include the entry that needs to be deleted in the new memory.
148
+
149
+ - **Example**:
150
+ - Initial Memory:
151
+ {
152
+ "facts": ["Name is John", "His boss is Alex"],
153
+ "instructions": []
154
+ }
155
+
156
+ - Retrieved facts:
157
+ {
158
+ "facts": ["Alex is no longer his boss"],
159
+ "instructions": []
160
+ }
161
+
162
+ - New Memory:
163
+ {
164
+ "facts": ["Name is John"],
165
+ "instructions": []
166
+ }
167
+
168
+ 4. **No Change**: If the retrieved facts contain information that is already present in the memory, then you do not need to make any changes.
169
+ - **Example**:
170
+ - Initial Memory:
171
+ {
172
+ "facts": ["Name is John"],
173
+ "instructions": ["Always reply in a formal tone"]
174
+ }
175
+
176
+ - Retrieved facts:
177
+ {
178
+ "facts": ["Name is John"],
179
+ "instructions": ["Always reply in a formal tone"]
180
+ }
181
+
182
+ - New Memory:
183
+ {
184
+ "facts": ["Name is John"],
185
+ "instructions": ["Always reply in a formal tone"]
186
+ }
187
+
188
+
189
+
190
+ Always return all the previous facts and instructions in the memory that are not affected by the update as well. Respond in JSON format with the keys "reasoning", "facts" and "instructions" containing the updated memory. For the "reasoning" key, provide a brief explanation of the changes made to the memory and the reasoning and thought process behind it.
191
+
192
+ If there are no changes, return the initial memory as it is. Do not return anything else or do not prefix them with backticks.
193
+ """,
194
+
195
+ "SUMMARIZE": """You are a Personal Information Organizer, specialized in accurately sorting facts, user memories, and summarizing. Your primary role is to extract relevant pieces of information and summarize the user conversations. This allows for easy retrieval and personalization in future interactions.
196
+
197
+ In your summary, you should include the key points and important details from the conversation. Ignore the details that are not relevant or important. The summary should be concise and capture the essence of the conversation. Prioritize the user messages while summarizing the conversation. Do not include minor details or generic information.
198
+
199
+ You're only summarizing the conversation, not replying to the user. You should summarize the conversation in a clear and concise manner. You can use bullet points or numbered lists if needed. Respond in normal text format with only the summary of the conversation. Do not return anything else or do not prefix them with backticks.
200
+ """,
201
+
202
+ "MERGE_SUMMARY": """You are a Personal Information Organizer, specialized in accurately sorting, updating, and merging user facts, memories, and previous summarizing. Your primary role is to merge the current conversation summary with the old summary and update it with the new information. This allows for easy retrieval and personalization in future interactions.
203
+
204
+ Don't allow for the final summary to get very long. Prioritize the facts and information from the new summary over the old. If the new summary contains the same information as the old one, keep the new one. If the new summary contains additional information, add it to the old summary. If the new summary contains contradictory information, update the old summary with the new one.
205
+
206
+ You should merge the two conversation summaries into one in a clear and concise manner. You can use bullet points or numbered lists if needed. Respond in normal text format with only the merged summaries. Do not return anything else or do not prefix them with backticks.
207
+ """,
208
+
209
+ }
210
+
211
+ class LongTermMemory():
212
+ """
213
+ A class to manage long-term memory for the assistant.
214
+ """
215
+
216
+ def __init__(self, llm_config):
217
+ def llm_request(messages):
218
+ response = completion(
219
+ model=llm_config.get("model"),
220
+ api_key=llm_config.get("api_key"),
221
+ base_url=llm_config.get("base_url"),
222
+ messages=messages
223
+ )
224
+ message = response.get("choices")[0].get("message")
225
+ return message
226
+
227
+ self.llm_request = llm_request
228
+
229
+ def retrieve_user_memory(self, memory: dict, summary:str) -> str:
230
+ instructions = ""
231
+ facts = ""
232
+ episodes = ""
233
+ separator = '\n - '
234
+
235
+ if memory.get("instructions"):
236
+ instructions = (
237
+ f"\n### Following instructions and preferences have been extracted from your previous conversations with the user:\n"
238
+ f" - {separator.join(memory['instructions'])}\n"
239
+ )
240
+
241
+ if memory.get("facts"):
242
+ facts = (
243
+ f"\n### Following facts have been extracted from your previous conversations with the user:\n"
244
+ f" - {separator.join(memory['facts'])}\n"
245
+ )
246
+
247
+ if summary:
248
+ episodes = (
249
+ f"\n### Following is a summary of your previous conversations with the user:\n"
250
+ f"```\n{summary}\n```\n"
251
+ )
252
+
253
+ return instructions + facts + episodes
254
+
255
+ def summarize_chat(self, chat: list)-> str:
256
+ if not chat:
257
+ return ""
258
+
259
+ messages = [
260
+ {
261
+ "role": "system",
262
+ "content": PROMPTS["SUMMARIZE"]
263
+ },
264
+ {
265
+ "role": "user",
266
+ "content": json.dumps(chat, indent=4)
267
+ }
268
+ ]
269
+ response = self.llm_request(messages).get("content")
270
+ return response
271
+
272
+ def update_summary(self, initial_summary: str, new_summary: str) -> str:
273
+ if not initial_summary:
274
+ return new_summary
275
+
276
+ if not new_summary:
277
+ return initial_summary
278
+
279
+ prompt = (
280
+ """### Old Conversation Summary:\n"""
281
+ f"\n```\n{initial_summary}\n```\n\n\n"
282
+ """### New Conversation Summary:\n"""
283
+ f"\n```\n{new_summary}\n```\n"
284
+ )
285
+ messages = [
286
+ {
287
+ "role": "system",
288
+ "content": PROMPTS["MERGE_SUMMARY"]
289
+ },
290
+ {
291
+ "role": "user",
292
+ "content": prompt
293
+ }
294
+ ]
295
+ response = self.llm_request(messages).get("content")
296
+ return response
297
+
298
+ def extract_memory_from_chat(self, chat: list) -> dict:
299
+ messages = [
300
+ {
301
+ "role": "system",
302
+ "content": PROMPTS["EXTRACT_FACTS"]
303
+ },
304
+ {
305
+ "role": "user",
306
+ "content": (
307
+ "Here's the conversation between the user and the assistant:\n"
308
+ f"```\n{json.dumps(chat, indent=4)}\n```\n\n"
309
+ "It's okay to return with empty lists. Only extract if the information is relevant or important.\n"
310
+ "Don't extract basic or generic information as facts!\n"
311
+ "Respond in the JSON format with the keys 'reasoning', 'facts', 'instructions', and 'update_notes' and no prefix or affix.\n"
312
+ )
313
+
314
+ }
315
+ ]
316
+ memory = self._get_and_validate_memory(messages)
317
+
318
+ return memory
319
+
320
+ def update_user_memory(self, initial_memory: dict, new_memory: dict) -> dict:
321
+ if not initial_memory or not (initial_memory.get("facts") or initial_memory.get("instructions")):
322
+ return {
323
+ "facts": new_memory.get("facts", []),
324
+ "instructions": new_memory.get("instructions", []),
325
+ }
326
+ initial_memory_str = json.dumps({
327
+ "facts": initial_memory.get("facts", []),
328
+ "instructions": initial_memory.get("instructions", []),
329
+ }, indent=4)
330
+ new_memory_str = json.dumps({
331
+ "facts": new_memory.get("facts", []),
332
+ "instructions": new_memory.get("instructions", []),
333
+ }, indent=4)
334
+
335
+ separator = '\n - '
336
+ special_notes = separator.join(new_memory.get("update_notes", [])) or "None"
337
+
338
+ prompt = (
339
+ "### Initial Memory:\n"
340
+ f"\n```\n{initial_memory_str}\n```\n\n\n"
341
+ "### Special Notes:\n"
342
+ f"\n```\n - {special_notes}\n```\n\n\n"
343
+ "### New Memory:\n"
344
+ f"\n```\n{new_memory_str}\n```\n\n"
345
+ "Return the complete updated memory in the JSON format with the keys 'reasoning', 'facts' and 'instructions' and no prefix or affix."
346
+ )
347
+
348
+ messages = [
349
+ {
350
+ "role": "system",
351
+ "content": PROMPTS["MERGE_FACTS"]
352
+ },
353
+ {
354
+ "role": "user",
355
+ "content": prompt
356
+ }
357
+ ]
358
+ memory = self._get_and_validate_memory(messages)
359
+ return memory
360
+
361
+ def _get_and_validate_memory(self, messages: list) -> dict:
362
+ attempt = 0
363
+ while attempt < 3:
364
+ response = self.llm_request(messages).get("content")
365
+ attempt += 1
366
+ messages.append(
367
+ {
368
+ "role": "assistant",
369
+ "content": response
370
+ }
371
+ )
372
+
373
+ try:
374
+ parsed_response = json.loads(response)
375
+ except Exception as e:
376
+ log.error("Error parsing response as JSON: %s", str(e))
377
+ messages.append(
378
+ {
379
+ "role": "user",
380
+ "content": f"Error parsing response as JSON: {str(e)}. Don't apologize, just try again and respond only with the valid JSON"
381
+ }
382
+ )
383
+ continue
384
+
385
+ if "facts" not in parsed_response or "instructions" not in parsed_response:
386
+ log.error("Missing facts or instructions in response")
387
+ messages.append({
388
+ "role": "user",
389
+ "content": "Error: Missing facts or instructions in response. Don't apologize, just try again and respond only with the valid JSON"
390
+ })
391
+ continue
392
+
393
+ # remove reasoning key, used only for COT
394
+ if "reasoning" in parsed_response:
395
+ parsed_response.pop("reasoning", None)
396
+
397
+ return parsed_response
398
+ return None
399
+
@@ -201,6 +201,13 @@ class LLMRequestComponent(ComponentBase):
201
201
  stream=True,
202
202
  streaming_complete_expression="input.payload:last_chunk",
203
203
  ):
204
+ # Only process if the stimulus UUIDs correlate
205
+ if not self._correlate_request_and_response(input_message, response_message):
206
+ log.error("Mismatched request and response stimulus UUIDs: %s %s",
207
+ self._get_user_propery(input_message, "stimulus_uuid"),
208
+ self._get_user_propery(response_message, "stimulus_uuid"))
209
+ raise ValueError("Mismatched request and response stimulus UUIDs")
210
+
204
211
  payload = response_message.get_payload()
205
212
  content = payload.get("chunk", "")
206
213
  aggregate_result += content
@@ -296,3 +303,15 @@ class LLMRequestComponent(ComponentBase):
296
303
  self.send_to_flow(self.stream_to_flow, message)
297
304
  elif self.stream_to_next_component:
298
305
  self.send_message(message)
306
+
307
+ @staticmethod
308
+ def _get_user_propery(message, user_property_key):
309
+ message_props = message.get_user_properties()
310
+ return message_props.get(user_property_key, "unknown")
311
+
312
+ # Define a helper function to check if response matches request
313
+ @staticmethod
314
+ def _correlate_request_and_response(request_msg, response_msg, correlation_key="stimulus_uuid"):
315
+ return (LLMRequestComponent._get_user_propery(request_msg, correlation_key) ==
316
+ LLMRequestComponent._get_user_propery(response_msg, correlation_key))
317
+
@@ -2,4 +2,5 @@
2
2
  key: "value" # Add your configuration here
3
3
 
4
4
  - response_format_prompt: &response_format_prompt >
5
- Return all responses in markdown format and if the response contains a file or image, return it with the <file> tags and not as a link.
5
+ Return all responses in markdown format. When returning files or images, use the <{{tag_prefix}}file> tags.
6
+ Do not return files as links or with generic <file> tags.
@@ -1,8 +1,8 @@
1
1
  - history_policy: &default_history_policy
2
- type: "memory" # "memory", "redis", or your custom module name
2
+ type: "memory" # "memory", "redis", "file", "mongodb" or your custom module name
3
3
  module_path: . # Path to module, Only needed if you are using a custom module
4
- time_to_live: 3600 # 1 hour
5
- expiration_check_interval: 300 # 5 minutes
4
+ time_to_live: 3600 # in seconds
5
+ expiration_check_interval: 300 # in seconds
6
6
  history_policy: # History provider configs (Passed to the history type provider)
7
7
  max_turns: 40
8
8
  max_characters: 50000
@@ -0,0 +1,29 @@
1
+ plugin_gateway_default_config:
2
+ interaction_type: "interactive" # interactive, autonomous
3
+
4
+ system_purpose: "The system is an AI Chatbot with agentic capabilities. It will use the agents available to provide information, reasoning and general assistance for the users in this system."
5
+
6
+ history:
7
+ enabled: true
8
+
9
+ type: "file"
10
+ type_config:
11
+ path: /tmp/sam-history
12
+
13
+ time_to_live: 1000
14
+ expiration_check_interval: 300
15
+ max_turns: 40
16
+ max_characters: 50000
17
+ enforce_alternate_message_roles: true
18
+
19
+ long_term_memory:
20
+ enabled: true
21
+
22
+ llm_config:
23
+ model: ${LLM_SERVICE_PLANNING_MODEL_NAME}
24
+ api_key: ${LLM_SERVICE_API_KEY}
25
+ base_url: ${LLM_SERVICE_ENDPOINT}
26
+
27
+ store_config:
28
+ type: "file"
29
+ path: /tmp/history
@@ -24,5 +24,6 @@
24
24
  local_dev : ${WEBUI_LOCAL_DEV}
25
25
 
26
26
  - response_format_prompt: &response_format_prompt >
27
- Return all responses in markdown format and if the response contains a file or image, return it with the <file> tags and not as a link.
27
+ Return all responses in markdown format. When returning files or images, use the <{{tag_prefix}}file> tags.
28
+ Do not return files as links or with generic <file> tags.
28
29
 
@@ -12,5 +12,5 @@
12
12
  - Format the response as a Slack message, using appropriate
13
13
  formatting such as *bold*, _italic_, and `code` where necessary.
14
14
  - Use bullet points or numbered lists for multiple items.
15
- - If the response contains a file or image, return it with the <file> tags and not as a link.
15
+ - If the response contains a file or image, use the <{{tag_prefix}}file> tags. Do not return files as links or with generic <file> tags.
16
16
  - If including hyperlinks, use the format <url|text>.
@@ -16,6 +16,15 @@ solace_agent_mesh:
16
16
  # Slack agent, send messages to Slack channels
17
17
  - name: slack
18
18
  enabled: true
19
+ # Configuring the built-in services
20
+ services:
21
+ # Embedding service for vector embeddings
22
+ # If enabled, the following environment variables are required:
23
+ # - EMBEDDING_SERVICE_MODEL_NAME
24
+ # - EMBEDDING_SERVICE_API_KEY
25
+ # - EMBEDDING_SERVICE_ENDPOINT
26
+ - name: embedding
27
+ enabled: false
19
28
 
20
29
  # Directory to component yaml config files, this directory would have a sub directory for each component type
21
30
  config_directory: configs
@@ -4,4 +4,5 @@
4
4
  max_file_size: 2000 # 2GB
5
5
 
6
6
  - response_format_prompt: &response_format_prompt >
7
- Return all responses in markdown format and if the response contains a file or image, return it with the <file> tags and not as a link.
7
+ Return all responses in markdown format. When returning files or images, use the <{{tag_prefix}}file> tags.
8
+ Do not return files as links or with generic <file> tags.