@@ -54,7 +54,7 @@ def __init__(
5454 ## set to groq if key available
5555 if self .llm_service :
5656 if self .llm_service .provider_name == "google" :
57- self .llm_service .model = "gemini-2.5-flash-lite-preview-06-17 "
57+ self .llm_service .model = "gemini-2.5-flash-lite"
5858 elif self .llm_service .provider_name == "claude" :
5959 self .llm_service .model = "claude-3-5-haiku-latest"
6060 elif self .llm_service .provider_name == "openai" :
@@ -241,88 +241,66 @@ async def _store_conversation_internal(self, operation_data: Dict[str, Any]):
241241 session_id = operation_data ["session_id" ]
242242
243243 # Use the existing storage logic but make it synchronous
244- ids = []
245- memory_data = {}
246- # avaialble_ids = collection.get(
247- # where={
248- # "agent": agent_name,
249- # },
250- # include=[],
251- # )["ids"]
244+ memory_data = None
245+ retried = 0
252246 if self .llm_service :
253- try :
254- # Process with LLM using asyncio.run to handle async call in worker thread
255- if self .current_conversation_context .get (session_id , "" ):
256- analyzed_prompt = PRE_ANALYZE_WITH_CONTEXT_PROMPT .replace (
257- "{conversation_context}" ,
258- f"""<PREVIOUS_CONVERSATION_CONTEXT>
259- { self .current_conversation_context [session_id ]}
260- </PREVIOUS_CONVERSATION_CONTEXT>""" ,
247+ while retried < 3 :
248+ try :
249+ # Process with LLM using asyncio.run to handle async call in worker thread
250+ if self .current_conversation_context .get (session_id , "" ):
251+ analyzed_prompt = PRE_ANALYZE_WITH_CONTEXT_PROMPT .replace (
252+ "{conversation_context}" ,
253+ f"""<PREVIOUS_CONVERSATION_CONTEXT>
254+ { self .current_conversation_context [session_id ]}
255+ </PREVIOUS_CONVERSATION_CONTEXT>""" ,
256+ )
257+ else :
258+ analyzed_prompt = PRE_ANALYZE_PROMPT
259+ analyzed_prompt = (
260+ analyzed_prompt .replace (
261+ "{current_date}" ,
262+ datetime .today ().strftime ("%Y-%m-%d %H:%M:%S" ),
263+ )
264+ .replace ("{user_message}" , user_message )
265+ .replace ("{assistant_response}" , assistant_response )
261266 )
262- else :
263- analyzed_prompt = PRE_ANALYZE_PROMPT
264- analyzed_prompt = (
265- analyzed_prompt .replace (
266- "{current_date}" ,
267- datetime .today ().strftime ("%Y-%m-%d %H:%M:%S" ),
267+ analyzed_text = await self .llm_service .process_message (
268+ analyzed_prompt
268269 )
269- .replace ("{user_message}" , user_message )
270- .replace ("{assistant_response}" , assistant_response )
271- )
272- analyzed_text = await self .llm_service .process_message (
273- analyzed_prompt
274- )
275- start_xml = analyzed_text .index ("<MEMORY>" )
276- end_xml = analyzed_text .index ("</MEMORY>" )
277- xml_content = analyzed_text [start_xml : end_xml + len ("</MEMORY>" )]
278- xml_content .replace ("&" , "&" ).replace ("'" , "'" ).replace (
279- '"' , """
280- )
281- memory_data = xmltodict .parse (xml_content )
282- if (
283- "MEMORY" in memory_data
284- and "ID" in memory_data ["MEMORY" ]
285- and memory_data ["MEMORY" ]["ID" ]
286- ):
287- ids .append (memory_data ["MEMORY" ]["ID" ])
288- # if (
289- # "MEMORY" in memory_data
290- # and "USER_REQUEST" not in memory_data["MEMORY"]
291- # ):
292- # memory_data["MEMORY"]["USER_REQUEST"] = user_message
293- # if (
294- # "MEMORY" in memory_data
295- # and "ASSISTANT_RESPONSE" not in memory_data["MEMORY"]
296- # ):
297- # memory_data["MEMORY"]["ASSISTANT_RESPONSE"] = assistant_response
298-
299- except Exception as e :
300- logger .warning (f"Error processing conversation with LLM: { e } " )
301- # Fallback to simple concatenation if LLM fails
302- memory_data = {
303- "MEMORY" : {
304- "DATE" : datetime .today ().strftime ("%Y-%m-%d" ),
305- "USER_REQUEST" : user_message ,
306- "ASSISTANT_RESPONSE" : assistant_response
307- if len (assistant_response ) < 200
308- else assistant_response [:197 ] + "..." ,
309- }
310- }
311- else :
270+ start_xml = analyzed_text .index ("<MEMORY>" )
271+ end_xml = analyzed_text .index ("</MEMORY>" )
272+ xml_content = analyzed_text [
273+ start_xml : end_xml + len ("</MEMORY>" )
274+ ]
275+ xml_content = (
276+ xml_content .replace ("&" , "&" )
277+ .replace ("'" , "'" )
278+ .replace ('"' , """ )
279+ )
280+ memory_data = xmltodict .parse (xml_content )
281+ break
282+ except Exception as e :
283+ logger .warning (
284+ f"Error processing conversation with LLM: { e } { xml_content } " # type: ignore
285+ )
286+ retried += 1
287+ continue
288+
289+ if memory_data is None :
312290 # Create the memory document by combining user message and response
313291 memory_data = {
314292 "MEMORY" : {
315293 "DATE" : datetime .today ().strftime ("%Y-%m-%d" ),
316- "USER_REQUEST" : user_message ,
317- "ASSISTANT_RESPONSE" : assistant_response
318- if len (assistant_response ) < 200
319- else assistant_response [:197 ] + "..." ,
294+ "CONVERSATION_NOTES" : {
295+ "NOTE" : [user_message , assistant_response ]
296+ },
320297 }
321298 }
322299
323300 # Store in ChromaDB (existing logic)
324- memory_id = str (uuid .uuid4 ())
325301 timestamp = datetime .now ().timestamp ()
302+
303+ memory_header = memory_data ["MEMORY" ].get ("HEAD" , None )
326304 conversation_document = xmltodict .unparse (
327305 memory_data , pretty = True , full_document = False
328306 )
@@ -335,27 +313,19 @@ async def _store_conversation_internal(self, operation_data: Dict[str, Any]):
335313
336314 metadata = {
337315 "date" : timestamp ,
338- "conversation_id" : memory_id ,
339316 "session_id" : session_id ,
340317 "agent" : agent_name ,
341318 "type" : "conversation" ,
342319 }
343-
344- # Add to ChromaDB collection (existing logic)
345- if ids :
346- collection .upsert (
347- ids = [ids [0 ]],
348- documents = [conversation_document ],
349- embeddings = conversation_embedding ,
350- metadatas = [metadata ],
351- )
352- else :
353- collection .add (
354- documents = [conversation_document ],
355- embeddings = conversation_embedding ,
356- metadatas = [metadata ],
357- ids = [memory_id ],
358- )
320+ if memory_header :
321+ metadata ["header" ] = memory_header
322+
323+ collection .upsert (
324+ ids = [f"{ session_id } _{ agent_name } " ],
325+ documents = [conversation_document ],
326+ embeddings = conversation_embedding ,
327+ metadatas = [metadata ],
328+ )
359329
360330 logger .debug (f"Stored conversation: { operation_data ['operation_id' ]} " )
361331
@@ -388,7 +358,7 @@ def clear_conversation_context(self):
388358 self .current_conversation_context = {}
389359 self .context_embedding = []
390360
391- def load_conversation_context (self , session_id : str ):
361+ def load_conversation_context (self , session_id : str , agent_name : str = "None" ):
392362 collection = self ._initialize_collection ()
393363 latest_memory = collection .get (
394364 where = {
@@ -399,6 +369,7 @@ def load_conversation_context(self, session_id: str):
399369 self .current_conversation_context [session_id ] = latest_memory ["documents" ][
400370 - 1
401371 ]
372+ print (self .current_conversation_context [session_id ])
402373
403374 def generate_user_context (self , user_input : str , agent_name : str = "None" ) -> str :
404375 """
@@ -425,7 +396,7 @@ async def _semantic_extracting(self, input: str) -> str:
425396 else :
426397 return input
427398
428- def list_memory_ids (
399+ def list_memory_headers (
429400 self ,
430401 from_date : Optional [int ] = None ,
431402 to_date : Optional [int ] = None ,
@@ -450,9 +421,14 @@ def list_memory_ids(
450421 else and_conditions [0 ]
451422 if and_conditions
452423 else None ,
453- include = [],
424+ include = ["metadatas" ],
454425 )
455- return list_memory ["ids" ]
426+ headers = []
427+ if list_memory and list_memory ["metadatas" ]:
428+ for metadata in list_memory ["metadatas" ]:
429+ if metadata .get ("header" , None ):
430+ headers .append (metadata .get ("header" ))
431+ return headers
456432
457433 def retrieve_memory (
458434 self ,
@@ -498,36 +474,30 @@ def retrieve_memory(
498474 if not results ["documents" ] or not results ["documents" ][0 ]:
499475 return "No relevant memories found."
500476
501- # Group chunks by conversation_id
502- conversation_chunks = {}
503- for i , (doc , metadata ) in enumerate (
504- zip (results ["documents" ][0 ], results ["metadatas" ][0 ]) # type:ignore
477+ conversation_chunks = []
478+ for i , (id , doc , metadata ) in enumerate (
479+ zip (results ["ids" ][0 ], results ["documents" ][0 ], results ["metadatas" ][0 ]) # type:ignore
505480 ):
506- conv_id = metadata . get ( "conversation_id" , "unknown" )
507- if conv_id not in conversation_chunks :
508- conversation_chunks [ conv_id ] = {
509- "chunks " : [] ,
481+ conversation_chunks . append (
482+ {
483+ "id" : id ,
484+ "document " : doc ,
510485 "timestamp" : metadata .get ("date" , None )
511486 or metadata .get ("timestamp" , "unknown" ),
512487 "relevance" : results ["distances" ][0 ][i ]
513488 if results ["distances" ]
514489 else 99 ,
515490 }
516- conversation_chunks [conv_id ]["chunks" ].append (
517- (metadata .get ("chunk_index" , 0 ), doc )
518491 )
519492
520493 # Sort conversations by relevance
521- sorted_conversations = sorted (
522- conversation_chunks .items (), key = lambda x : x [1 ]["relevance" ]
523- )
494+ sorted_conversations = sorted (conversation_chunks , key = lambda x : x ["relevance" ])
524495
525496 # Format the output
526497 output = []
527- for conv_id , conv_data in sorted_conversations :
498+ for conv_data in sorted_conversations :
528499 # Sort chunks by index
529- sorted_chunks = sorted (conv_data ["chunks" ], key = lambda x : x [0 ])
530- conversation_text = "\n " .join ([chunk for _ , chunk in sorted_chunks ])
500+ conversation_text = conv_data ["document" ]
531501 if conv_data ["relevance" ] > RELEVANT_THRESHOLD :
532502 continue
533503 # Format timestamp
@@ -544,22 +514,10 @@ def retrieve_memory(
544514 timestamp = conv_data ["timestamp" ]
545515
546516 output .append (
547- f"--- Memory from { timestamp } (relevance point(lower is better): { conv_data ['relevance ' ]} ) ---\n { conversation_text } \n ---"
517+ f"--- Memory from { timestamp } [id: { conv_data ['id ' ]} ] ---\n { conversation_text } \n ---"
548518 )
549519
550520 memories = "\n \n " .join (output )
551- # if self.llm_service:
552- # try:
553- # return await self.llm_service.process_message(
554- # POST_RETRIEVE_MEMORY.replace("{keywords}", keywords).replace(
555- # "{memory_list}", memories
556- # )
557- # )
558- # except Exception as e:
559- # logger.warning(f"Error processing retrieved memories with LLM: {e}")
560- # # Fallback to returning raw memories if LLM processing fails
561- # return memories
562- # else:
563521 return memories
564522
565523 def _cosine_similarity (self , vec_a , vec_b ):
@@ -663,23 +621,8 @@ def forget_topic(
663621 "count" : 0 ,
664622 }
665623
666- # Collect all conversation IDs related to the topic
667- conversation_ids = set ()
668- if results ["metadatas" ] and results ["metadatas" ][0 ]:
669- for metadata in results ["metadatas" ][0 ]:
670- conv_id = metadata .get ("conversation_id" )
671- if conv_id :
672- conversation_ids .add (conv_id )
673-
674- # Get all memories to find those with matching conversation IDs
675- all_memories = collection .get ()
676-
677624 # Find IDs to remove
678- ids_to_remove = []
679- if all_memories ["metadatas" ]:
680- for i , metadata in enumerate (all_memories ["metadatas" ]):
681- if metadata .get ("conversation_id" ) in conversation_ids :
682- ids_to_remove .append (all_memories ["ids" ][i ])
625+ ids_to_remove = results ["ids" ][0 ]
683626
684627 # Remove the memories
685628 if ids_to_remove :
@@ -689,7 +632,6 @@ def forget_topic(
689632 "success" : True ,
690633 "message" : f"Successfully removed { len (ids_to_remove )} memory chunks related to '{ topic } '" ,
691634 "count" : len (ids_to_remove ),
692- "conversations_affected" : len (conversation_ids ),
693635 }
694636
695637 except Exception as e :
0 commit comments