LiamKhoaLe commited on
Commit
f80e242
·
1 Parent(s): 48a0d5a

Add memo planner

Browse files
memo/__pycache__/core.cpython-311.pyc ADDED
Binary file (23.2 kB). View file
 
memo/__pycache__/legacy.cpython-311.pyc ADDED
Binary file (3.51 kB). View file
 
memo/__pycache__/persistent.cpython-311.pyc ADDED
Binary file (14.3 kB). View file
 
memo/__pycache__/planning.cpython-311.pyc ADDED
Binary file (34.6 kB). View file
 
memo/conversation.py CHANGED
@@ -35,7 +35,7 @@ class ConversationManager:
35
  nvidia_rotator=None, project_id: Optional[str] = None,
36
  conversation_mode: str = "chat") -> Tuple[str, str, Dict[str, Any]]:
37
  """
38
- Get intelligent context for conversation with enhanced edge case handling.
39
 
40
  Args:
41
  user_id: User identifier
@@ -55,6 +55,17 @@ class ConversationManager:
55
  logger.error(f"[CONVERSATION_MANAGER] Smart context failed: {e}")
56
  return "", "", {"error": str(e)}
57
 
 
 
 
 
 
 
 
 
 
 
 
58
  async def consolidate_memories(self, user_id: str, nvidia_rotator=None) -> Dict[str, Any]:
59
  """Consolidate and prune memories to prevent information overload"""
60
  try:
 
35
  nvidia_rotator=None, project_id: Optional[str] = None,
36
  conversation_mode: str = "chat") -> Tuple[str, str, Dict[str, Any]]:
37
  """
38
+ Get intelligent context for conversation with enhanced memory planning.
39
 
40
  Args:
41
  user_id: User identifier
 
55
  logger.error(f"[CONVERSATION_MANAGER] Smart context failed: {e}")
56
  return "", "", {"error": str(e)}
57
 
58
+ async def get_enhancement_context(self, user_id: str, question: str,
59
+ nvidia_rotator=None, project_id: Optional[str] = None) -> Tuple[str, str, Dict[str, Any]]:
60
+ """Get context specifically optimized for enhancement requests"""
61
+ try:
62
+ return await self.retrieval_manager.get_enhancement_context(
63
+ user_id, question, nvidia_rotator, project_id
64
+ )
65
+ except Exception as e:
66
+ logger.error(f"[CONVERSATION_MANAGER] Enhancement context failed: {e}")
67
+ return "", "", {"error": str(e)}
68
+
69
  async def consolidate_memories(self, user_id: str, nvidia_rotator=None) -> Dict[str, Any]:
70
  """Consolidate and prune memories to prevent information overload"""
71
  try:
memo/core.py CHANGED
@@ -142,6 +142,15 @@ class MemorySystem:
142
  logger.error(f"[CORE_MEMORY] Failed to get conversation context: {e}")
143
  return "", ""
144
 
 
 
 
 
 
 
 
 
 
145
  async def search_memories(self, user_id: str, query: str,
146
  project_id: Optional[str] = None,
147
  limit: int = 10) -> List[Tuple[str, float]]:
@@ -211,16 +220,90 @@ class MemorySystem:
211
  async def get_smart_context(self, user_id: str, question: str,
212
  nvidia_rotator=None, project_id: Optional[str] = None,
213
  conversation_mode: str = "chat") -> Tuple[str, str, Dict[str, Any]]:
214
- """Get smart context using advanced conversation management"""
215
  try:
216
- from memo.conversation import get_conversation_manager
217
- conversation_manager = get_conversation_manager(self, self.embedder)
 
 
 
 
 
218
 
219
- return await conversation_manager.get_smart_context(
220
- user_id, question, nvidia_rotator, project_id, conversation_mode
 
221
  )
 
 
 
 
 
 
 
 
 
 
 
 
222
  except Exception as e:
223
  logger.error(f"[CORE_MEMORY] Failed to get smart context: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  return "", "", {"error": str(e)}
225
 
226
  # ────────────────────────────── Private Helper Methods ──────────────────────────────
 
142
  logger.error(f"[CORE_MEMORY] Failed to get conversation context: {e}")
143
  return "", ""
144
 
145
+ async def get_enhanced_context(self, user_id: str, question: str,
146
+ project_id: Optional[str] = None) -> Tuple[str, str, Dict[str, Any]]:
147
+ """Get enhanced context using the new memory planning system"""
148
+ try:
149
+ return await self.get_smart_context(user_id, question, None, project_id, "chat")
150
+ except Exception as e:
151
+ logger.error(f"[CORE_MEMORY] Failed to get enhanced context: {e}")
152
+ return "", "", {"error": str(e)}
153
+
154
  async def search_memories(self, user_id: str, query: str,
155
  project_id: Optional[str] = None,
156
  limit: int = 10) -> List[Tuple[str, float]]:
 
220
  async def get_smart_context(self, user_id: str, question: str,
221
  nvidia_rotator=None, project_id: Optional[str] = None,
222
  conversation_mode: str = "chat") -> Tuple[str, str, Dict[str, Any]]:
223
+ """Get smart context using advanced memory planning strategy"""
224
  try:
225
+ from memo.planning import get_memory_planner
226
+ memory_planner = get_memory_planner(self, self.embedder)
227
+
228
+ # Plan memory strategy based on user intent
229
+ execution_plan = await memory_planner.plan_memory_strategy(
230
+ user_id, question, nvidia_rotator, project_id
231
+ )
232
 
233
+ # Execute the planned strategy
234
+ recent_context, semantic_context, metadata = await memory_planner.execute_memory_plan(
235
+ user_id, question, execution_plan, nvidia_rotator, project_id
236
  )
237
+
238
+ # Add planning metadata to response
239
+ metadata.update({
240
+ "memory_planning": True,
241
+ "intent": execution_plan["intent"].value,
242
+ "strategy": execution_plan["strategy"].value,
243
+ "enhancement_focus": execution_plan["enhancement_focus"],
244
+ "qa_focus": execution_plan["qa_focus"]
245
+ })
246
+
247
+ return recent_context, semantic_context, metadata
248
+
249
  except Exception as e:
250
  logger.error(f"[CORE_MEMORY] Failed to get smart context: {e}")
251
+ # Fallback to original conversation manager
252
+ try:
253
+ from memo.conversation import get_conversation_manager
254
+ conversation_manager = get_conversation_manager(self, self.embedder)
255
+
256
+ return await conversation_manager.get_smart_context(
257
+ user_id, question, nvidia_rotator, project_id, conversation_mode
258
+ )
259
+ except Exception as fallback_error:
260
+ logger.error(f"[CORE_MEMORY] Fallback also failed: {fallback_error}")
261
+ return "", "", {"error": str(e)}
262
+
263
+ async def get_enhancement_context(self, user_id: str, question: str,
264
+ nvidia_rotator=None, project_id: Optional[str] = None) -> Tuple[str, str, Dict[str, Any]]:
265
+ """Get context specifically optimized for enhancement requests"""
266
+ try:
267
+ from memo.planning import get_memory_planner, QueryIntent, MemoryStrategy
268
+ memory_planner = get_memory_planner(self, self.embedder)
269
+
270
+ # Force enhancement intent and focused Q&A strategy
271
+ execution_plan = {
272
+ "intent": QueryIntent.ENHANCEMENT,
273
+ "strategy": MemoryStrategy.FOCUSED_QA,
274
+ "retrieval_params": {
275
+ "recent_limit": 5,
276
+ "semantic_limit": 10,
277
+ "qa_focus": True,
278
+ "enhancement_mode": True,
279
+ "priority_types": ["conversation", "qa"],
280
+ "similarity_threshold": 0.05, # Very low threshold for maximum recall
281
+ "use_ai_selection": True
282
+ },
283
+ "conversation_context": {},
284
+ "enhancement_focus": True,
285
+ "qa_focus": True
286
+ }
287
+
288
+ # Execute the enhancement-focused strategy
289
+ recent_context, semantic_context, metadata = await memory_planner.execute_memory_plan(
290
+ user_id, question, execution_plan, nvidia_rotator, project_id
291
+ )
292
+
293
+ # Add enhancement-specific metadata
294
+ metadata.update({
295
+ "enhancement_mode": True,
296
+ "qa_focused": True,
297
+ "memory_planning": True,
298
+ "intent": "enhancement",
299
+ "strategy": "focused_qa"
300
+ })
301
+
302
+ logger.info(f"[CORE_MEMORY] Enhancement context retrieved: {len(recent_context)} recent, {len(semantic_context)} semantic")
303
+ return recent_context, semantic_context, metadata
304
+
305
+ except Exception as e:
306
+ logger.error(f"[CORE_MEMORY] Failed to get enhancement context: {e}")
307
  return "", "", {"error": str(e)}
308
 
309
  # ────────────────────────────── Private Helper Methods ──────────────────────────────
memo/history.py CHANGED
@@ -86,19 +86,8 @@ class HistoryManager:
86
 
87
  # ────────────────────────────── Legacy Functions (Backward Compatibility) ──────────────────────────────
88
 
89
- # async def summarize_qa_with_nvidia(question: str, answer: str, rotator) -> str:
90
- # """Legacy function - use HistoryManager.summarize_qa_with_nvidia() instead"""
91
- # return await summarize_qa(question, answer, rotator)
92
-
93
- # async def files_relevance_legacy(question: str, file_summaries: List[Dict[str, str]], rotator) -> Dict[str, bool]:
94
- # """Legacy function - use HistoryManager.files_relevance() instead"""
95
- # return await files_relevance(question, file_summaries, rotator)
96
-
97
- # async def related_recent_and_semantic_context(user_id: str, question: str, memory, embedder: EmbeddingClient, topk_sem: int = 3, nvidia_rotator=None) -> Tuple[str, str]:
98
- # """Legacy function - use HistoryManager.related_recent_and_semantic_context() instead"""
99
- # # Create a temporary history manager for legacy compatibility
100
- # history_manager = HistoryManager(memory)
101
- # return await history_manager.related_recent_and_semantic_context(user_id, question, embedder, topk_sem, nvidia_rotator)
102
 
103
  # ────────────────────────────── Global Instance ──────────────────────────────
104
 
 
86
 
87
  # ────────────────────────────── Legacy Functions (Backward Compatibility) ──────────────────────────────
88
 
89
+ # These legacy functions have been removed as they are no longer needed with the new memory planning system.
90
+ # Use the appropriate methods from the core memory system or memory planner instead.
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  # ────────────────────────────── Global Instance ──────────────────────────────
93
 
memo/planning.py ADDED
@@ -0,0 +1,770 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ────────────────────────────── memo/planning.py ──────────────────────────────
2
+ """
3
+ Memory Planning Strategy
4
+
5
+ Intelligent memory planning system that analyzes user intent and determines
6
+ the optimal memory retrieval strategy, especially for enhancement requests.
7
+ """
8
+
9
+ import re
10
+ from typing import List, Dict, Any, Tuple, Optional, Set
11
+ from enum import Enum
12
+
13
+ from utils.logger import get_logger
14
+ from utils.rag.embeddings import EmbeddingClient
15
+
16
+ logger = get_logger("MEMORY_PLANNER", __name__)
17
+
18
+ class QueryIntent(Enum):
19
+ """Types of user query intents"""
20
+ ENHANCEMENT = "enhancement" # User wants more details/elaboration
21
+ CLARIFICATION = "clarification" # User wants clarification
22
+ CONTINUATION = "continuation" # User is continuing previous topic
23
+ NEW_TOPIC = "new_topic" # User is starting a new topic
24
+ COMPARISON = "comparison" # User wants to compare with previous content
25
+ REFERENCE = "reference" # User is referencing specific past content
26
+
27
+ class MemoryStrategy(Enum):
28
+ """Memory retrieval strategies"""
29
+ FOCUSED_QA = "focused_qa" # Focus on past Q&A pairs
30
+ BROAD_CONTEXT = "broad_context" # Use broad semantic context
31
+ RECENT_FOCUS = "recent_focus" # Focus on recent memories
32
+ SEMANTIC_DEEP = "semantic_deep" # Deep semantic search
33
+ MIXED_APPROACH = "mixed_approach" # Combine multiple strategies
34
+
35
+ class MemoryPlanner:
36
+ """
37
+ Intelligent memory planning system that determines optimal memory retrieval
38
+ strategy based on user intent and query characteristics.
39
+ """
40
+
41
+ def __init__(self, memory_system, embedder: EmbeddingClient):
42
+ self.memory_system = memory_system
43
+ self.embedder = embedder
44
+
45
+ # Enhancement request patterns
46
+ self.enhancement_patterns = [
47
+ r'\b(enhance|elaborate|expand|detail|elaborate on|be more detailed|more details|more information)\b',
48
+ r'\b(explain more|tell me more|go deeper|dive deeper|more context)\b',
49
+ r'\b(what else|anything else|additional|further|supplement)\b',
50
+ r'\b(comprehensive|thorough|complete|full)\b',
51
+ r'\b(based on|from our|as we discussed|following up|regarding)\b'
52
+ ]
53
+
54
+ # Clarification patterns
55
+ self.clarification_patterns = [
56
+ r'\b(what do you mean|clarify|explain|what is|define)\b',
57
+ r'\b(how does|why does|when does|where does)\b',
58
+ r'\b(can you explain|help me understand)\b'
59
+ ]
60
+
61
+ # Comparison patterns
62
+ self.comparison_patterns = [
63
+ r'\b(compare|versus|vs|difference|similar|different)\b',
64
+ r'\b(like|unlike|similar to|different from)\b',
65
+ r'\b(contrast|opposite|better|worse)\b'
66
+ ]
67
+
68
+ # Reference patterns
69
+ self.reference_patterns = [
70
+ r'\b(you said|we discussed|earlier|before|previously)\b',
71
+ r'\b(that|this|it|the above|mentioned)\b',
72
+ r'\b(according to|based on|from|in)\b'
73
+ ]
74
+
75
+ async def plan_memory_strategy(self, user_id: str, question: str,
76
+ nvidia_rotator=None, project_id: Optional[str] = None) -> Dict[str, Any]:
77
+ """
78
+ Plan the optimal memory retrieval strategy based on user intent and context.
79
+
80
+ Args:
81
+ user_id: User identifier
82
+ question: Current user question/instruction
83
+ nvidia_rotator: NVIDIA API rotator for AI analysis
84
+ project_id: Project context
85
+
86
+ Returns:
87
+ Dictionary containing strategy, intent, and retrieval parameters
88
+ """
89
+ try:
90
+ # Detect user intent
91
+ intent = await self._detect_user_intent(question, nvidia_rotator)
92
+
93
+ # Get conversation context for better planning
94
+ conversation_context = await self._get_conversation_context(user_id, question)
95
+
96
+ # Determine memory strategy based on intent and context
97
+ strategy = self._determine_memory_strategy(intent, question, conversation_context)
98
+
99
+ # Plan specific retrieval parameters
100
+ retrieval_params = await self._plan_retrieval_parameters(
101
+ user_id, question, intent, strategy, conversation_context, nvidia_rotator
102
+ )
103
+
104
+ # Create execution plan
105
+ execution_plan = {
106
+ "intent": intent,
107
+ "strategy": strategy,
108
+ "retrieval_params": retrieval_params,
109
+ "conversation_context": conversation_context,
110
+ "enhancement_focus": intent == QueryIntent.ENHANCEMENT,
111
+ "qa_focus": intent in [QueryIntent.ENHANCEMENT, QueryIntent.CLARIFICATION, QueryIntent.REFERENCE]
112
+ }
113
+
114
+ logger.info(f"[MEMORY_PLANNER] Planned strategy: {strategy.value} for intent: {intent.value}")
115
+ return execution_plan
116
+
117
+ except Exception as e:
118
+ logger.error(f"[MEMORY_PLANNER] Memory planning failed: {e}")
119
+ return self._get_fallback_plan()
120
+
121
+ async def _detect_user_intent(self, question: str, nvidia_rotator) -> QueryIntent:
122
+ """Detect user intent from the question"""
123
+ try:
124
+ question_lower = question.lower()
125
+
126
+ # Check for enhancement patterns
127
+ if any(re.search(pattern, question_lower) for pattern in self.enhancement_patterns):
128
+ return QueryIntent.ENHANCEMENT
129
+
130
+ # Check for clarification patterns
131
+ if any(re.search(pattern, question_lower) for pattern in self.clarification_patterns):
132
+ return QueryIntent.CLARIFICATION
133
+
134
+ # Check for comparison patterns
135
+ if any(re.search(pattern, question_lower) for pattern in self.comparison_patterns):
136
+ return QueryIntent.COMPARISON
137
+
138
+ # Check for reference patterns
139
+ if any(re.search(pattern, question_lower) for pattern in self.reference_patterns):
140
+ return QueryIntent.REFERENCE
141
+
142
+ # Use AI for more sophisticated intent detection
143
+ if nvidia_rotator:
144
+ try:
145
+ return await self._ai_intent_detection(question, nvidia_rotator)
146
+ except Exception as e:
147
+ logger.warning(f"[MEMORY_PLANNER] AI intent detection failed: {e}")
148
+
149
+ # Default to continuation if no clear patterns
150
+ return QueryIntent.CONTINUATION
151
+
152
+ except Exception as e:
153
+ logger.warning(f"[MEMORY_PLANNER] Intent detection failed: {e}")
154
+ return QueryIntent.CONTINUATION
155
+
156
+ async def _ai_intent_detection(self, question: str, nvidia_rotator) -> QueryIntent:
157
+ """Use AI to detect user intent more accurately"""
158
+ try:
159
+ from utils.api.router import generate_answer_with_model
160
+
161
+ sys_prompt = """You are an expert at analyzing user intent in questions.
162
+
163
+ Classify the user's question into one of these intents:
164
+ - ENHANCEMENT: User wants more details, elaboration, or comprehensive information
165
+ - CLARIFICATION: User wants explanation or clarification of something
166
+ - CONTINUATION: User is continuing a previous topic or conversation
167
+ - NEW_TOPIC: User is starting a completely new topic
168
+ - COMPARISON: User wants to compare or contrast things
169
+ - REFERENCE: User is referencing specific past content or discussions
170
+
171
+ Respond with only the intent name (e.g., "ENHANCEMENT")."""
172
+
173
+ user_prompt = f"Question: {question}\n\nWhat is the user's intent?"
174
+
175
+ selection = {"provider": "nvidia", "model": "meta/llama-3.1-8b-instruct"}
176
+ response = await generate_answer_with_model(
177
+ selection=selection,
178
+ system_prompt=sys_prompt,
179
+ user_prompt=user_prompt,
180
+ gemini_rotator=None,
181
+ nvidia_rotator=nvidia_rotator
182
+ )
183
+
184
+ # Parse response
185
+ response_upper = response.strip().upper()
186
+ for intent in QueryIntent:
187
+ if intent.name in response_upper:
188
+ return intent
189
+
190
+ return QueryIntent.CONTINUATION
191
+
192
+ except Exception as e:
193
+ logger.warning(f"[MEMORY_PLANNER] AI intent detection failed: {e}")
194
+ return QueryIntent.CONTINUATION
195
+
196
+ def _determine_memory_strategy(self, intent: QueryIntent, question: str,
197
+ conversation_context: Dict[str, Any]) -> MemoryStrategy:
198
+ """Determine the optimal memory retrieval strategy"""
199
+ try:
200
+ # Enhancement requests need focused Q&A retrieval
201
+ if intent == QueryIntent.ENHANCEMENT:
202
+ return MemoryStrategy.FOCUSED_QA
203
+
204
+ # Clarification requests need recent context and Q&A
205
+ if intent == QueryIntent.CLARIFICATION:
206
+ return MemoryStrategy.RECENT_FOCUS
207
+
208
+ # Comparison requests need broad context
209
+ if intent == QueryIntent.COMPARISON:
210
+ return MemoryStrategy.BROAD_CONTEXT
211
+
212
+ # Reference requests need focused Q&A
213
+ if intent == QueryIntent.REFERENCE:
214
+ return MemoryStrategy.FOCUSED_QA
215
+
216
+ # New topics need semantic deep search
217
+ if intent == QueryIntent.NEW_TOPIC:
218
+ return MemoryStrategy.SEMANTIC_DEEP
219
+
220
+ # Continuation requests use mixed approach
221
+ if intent == QueryIntent.CONTINUATION:
222
+ return MemoryStrategy.MIXED_APPROACH
223
+
224
+ # Default to mixed approach
225
+ return MemoryStrategy.MIXED_APPROACH
226
+
227
+ except Exception as e:
228
+ logger.warning(f"[MEMORY_PLANNER] Strategy determination failed: {e}")
229
+ return MemoryStrategy.MIXED_APPROACH
230
+
231
+ async def _plan_retrieval_parameters(self, user_id: str, question: str, intent: QueryIntent,
232
+ strategy: MemoryStrategy, conversation_context: Dict[str, Any],
233
+ nvidia_rotator) -> Dict[str, Any]:
234
+ """Plan specific retrieval parameters based on strategy"""
235
+ try:
236
+ params = {
237
+ "recent_limit": 3,
238
+ "semantic_limit": 5,
239
+ "qa_focus": False,
240
+ "enhancement_mode": False,
241
+ "priority_types": ["conversation"],
242
+ "similarity_threshold": 0.15,
243
+ "use_ai_selection": False
244
+ }
245
+
246
+ # Adjust parameters based on strategy
247
+ if strategy == MemoryStrategy.FOCUSED_QA:
248
+ params.update({
249
+ "recent_limit": 5, # More recent Q&A pairs
250
+ "semantic_limit": 10, # More semantic Q&A pairs
251
+ "qa_focus": True,
252
+ "enhancement_mode": True,
253
+ "priority_types": ["conversation", "qa"],
254
+ "similarity_threshold": 0.1, # Lower threshold for more results
255
+ "use_ai_selection": True
256
+ })
257
+
258
+ elif strategy == MemoryStrategy.RECENT_FOCUS:
259
+ params.update({
260
+ "recent_limit": 5,
261
+ "semantic_limit": 3,
262
+ "qa_focus": True,
263
+ "priority_types": ["conversation"]
264
+ })
265
+
266
+ elif strategy == MemoryStrategy.BROAD_CONTEXT:
267
+ params.update({
268
+ "recent_limit": 3,
269
+ "semantic_limit": 15,
270
+ "qa_focus": False,
271
+ "priority_types": ["conversation", "general", "knowledge"],
272
+ "similarity_threshold": 0.2
273
+ })
274
+
275
+ elif strategy == MemoryStrategy.SEMANTIC_DEEP:
276
+ params.update({
277
+ "recent_limit": 2,
278
+ "semantic_limit": 20,
279
+ "qa_focus": False,
280
+ "priority_types": ["conversation", "general", "knowledge", "qa"],
281
+ "similarity_threshold": 0.1,
282
+ "use_ai_selection": True
283
+ })
284
+
285
+ elif strategy == MemoryStrategy.MIXED_APPROACH:
286
+ params.update({
287
+ "recent_limit": 4,
288
+ "semantic_limit": 8,
289
+ "qa_focus": True,
290
+ "priority_types": ["conversation", "qa"],
291
+ "use_ai_selection": True
292
+ })
293
+
294
+ # Special handling for enhancement requests
295
+ if intent == QueryIntent.ENHANCEMENT:
296
+ params["enhancement_mode"] = True
297
+ params["qa_focus"] = True
298
+ params["use_ai_selection"] = True
299
+ params["similarity_threshold"] = 0.05 # Very low threshold for maximum recall
300
+
301
+ return params
302
+
303
+ except Exception as e:
304
+ logger.warning(f"[MEMORY_PLANNER] Parameter planning failed: {e}")
305
+ return {
306
+ "recent_limit": 3,
307
+ "semantic_limit": 5,
308
+ "qa_focus": False,
309
+ "enhancement_mode": False,
310
+ "priority_types": ["conversation"],
311
+ "similarity_threshold": 0.15,
312
+ "use_ai_selection": False
313
+ }
314
+
315
+ async def _get_conversation_context(self, user_id: str, question: str) -> Dict[str, Any]:
316
+ """Get conversation context for better planning"""
317
+ try:
318
+ context = {
319
+ "has_recent_memories": False,
320
+ "memory_count": 0,
321
+ "conversation_depth": 0,
322
+ "last_question": "",
323
+ "is_continuation": False
324
+ }
325
+
326
+ if self.memory_system.is_enhanced_available():
327
+ # Get enhanced memory stats
328
+ stats = self.memory_system.get_memory_stats(user_id)
329
+ context["memory_count"] = stats.get("total_memories", 0)
330
+
331
+ # Get recent memories
332
+ recent_memories = self.memory_system.enhanced_memory.get_memories(
333
+ user_id, memory_type="conversation", limit=5
334
+ )
335
+ context["has_recent_memories"] = len(recent_memories) > 0
336
+
337
+ if recent_memories:
338
+ context["last_question"] = recent_memories[0].get("content", "")
339
+ else:
340
+ # Legacy memory stats
341
+ recent_memories = self.memory_system.recent(user_id, 3)
342
+ context["has_recent_memories"] = len(recent_memories) > 0
343
+ context["memory_count"] = len(self.memory_system.all(user_id))
344
+
345
+ if recent_memories:
346
+ context["last_question"] = recent_memories[0]
347
+
348
+ return context
349
+
350
+ except Exception as e:
351
+ logger.warning(f"[MEMORY_PLANNER] Context retrieval failed: {e}")
352
+ return {
353
+ "has_recent_memories": False,
354
+ "memory_count": 0,
355
+ "conversation_depth": 0,
356
+ "last_question": "",
357
+ "is_continuation": False
358
+ }
359
+
360
+ def _get_fallback_plan(self) -> Dict[str, Any]:
361
+ """Get fallback plan when planning fails"""
362
+ return {
363
+ "intent": QueryIntent.CONTINUATION,
364
+ "strategy": MemoryStrategy.MIXED_APPROACH,
365
+ "retrieval_params": {
366
+ "recent_limit": 3,
367
+ "semantic_limit": 5,
368
+ "qa_focus": False,
369
+ "enhancement_mode": False,
370
+ "priority_types": ["conversation"],
371
+ "similarity_threshold": 0.15,
372
+ "use_ai_selection": False
373
+ },
374
+ "conversation_context": {},
375
+ "enhancement_focus": False,
376
+ "qa_focus": False
377
+ }
378
+
379
+ async def execute_memory_plan(self, user_id: str, question: str, execution_plan: Dict[str, Any],
380
+ nvidia_rotator=None, project_id: Optional[str] = None) -> Tuple[str, str, Dict[str, Any]]:
381
+ """
382
+ Execute the planned memory retrieval strategy.
383
+
384
+ Returns:
385
+ Tuple of (recent_context, semantic_context, metadata)
386
+ """
387
+ try:
388
+ params = execution_plan["retrieval_params"]
389
+ strategy = execution_plan["strategy"]
390
+ intent = execution_plan["intent"]
391
+
392
+ # Execute based on strategy
393
+ if strategy == MemoryStrategy.FOCUSED_QA:
394
+ return await self._execute_focused_qa_retrieval(
395
+ user_id, question, params, nvidia_rotator, project_id
396
+ )
397
+ elif strategy == MemoryStrategy.RECENT_FOCUS:
398
+ return await self._execute_recent_focus_retrieval(
399
+ user_id, question, params, nvidia_rotator, project_id
400
+ )
401
+ elif strategy == MemoryStrategy.BROAD_CONTEXT:
402
+ return await self._execute_broad_context_retrieval(
403
+ user_id, question, params, nvidia_rotator, project_id
404
+ )
405
+ elif strategy == MemoryStrategy.SEMANTIC_DEEP:
406
+ return await self._execute_semantic_deep_retrieval(
407
+ user_id, question, params, nvidia_rotator, project_id
408
+ )
409
+ else: # MIXED_APPROACH
410
+ return await self._execute_mixed_approach_retrieval(
411
+ user_id, question, params, nvidia_rotator, project_id
412
+ )
413
+
414
+ except Exception as e:
415
+ logger.error(f"[MEMORY_PLANNER] Plan execution failed: {e}")
416
+ return "", "", {"error": str(e)}
417
+
418
+ async def _execute_focused_qa_retrieval(self, user_id: str, question: str, params: Dict[str, Any],
419
+ nvidia_rotator, project_id: Optional[str]) -> Tuple[str, str, Dict[str, Any]]:
420
+ """Execute focused Q&A retrieval for enhancement requests"""
421
+ try:
422
+ recent_context = ""
423
+ semantic_context = ""
424
+ metadata = {"strategy": "focused_qa", "qa_focus": True}
425
+
426
+ if self.memory_system.is_enhanced_available():
427
+ # Get Q&A focused memories
428
+ qa_memories = self.memory_system.enhanced_memory.get_memories(
429
+ user_id, memory_type="conversation", limit=params["recent_limit"]
430
+ )
431
+
432
+ if qa_memories:
433
+ # Use AI to select most relevant Q&A pairs for enhancement
434
+ if params["use_ai_selection"] and nvidia_rotator:
435
+ recent_context = await self._ai_select_qa_memories(
436
+ question, qa_memories, nvidia_rotator, "recent"
437
+ )
438
+ else:
439
+ recent_context = await self._semantic_select_qa_memories(
440
+ question, qa_memories, params["similarity_threshold"]
441
+ )
442
+
443
+ # Get additional semantic Q&A context
444
+ all_memories = self.memory_system.enhanced_memory.get_memories(
445
+ user_id, limit=params["semantic_limit"]
446
+ )
447
+
448
+ if all_memories:
449
+ if params["use_ai_selection"] and nvidia_rotator:
450
+ semantic_context = await self._ai_select_qa_memories(
451
+ question, all_memories, nvidia_rotator, "semantic"
452
+ )
453
+ else:
454
+ semantic_context = await self._semantic_select_qa_memories(
455
+ question, all_memories, params["similarity_threshold"]
456
+ )
457
+ else:
458
+ # Legacy fallback
459
+ recent_memories = self.memory_system.recent(user_id, params["recent_limit"])
460
+ rest_memories = self.memory_system.rest(user_id, params["recent_limit"])
461
+
462
+ if recent_memories:
463
+ recent_context = await self._semantic_select_qa_memories(
464
+ question, [{"content": m} for m in recent_memories], params["similarity_threshold"]
465
+ )
466
+
467
+ if rest_memories:
468
+ semantic_context = await self._semantic_select_qa_memories(
469
+ question, [{"content": m} for m in rest_memories], params["similarity_threshold"]
470
+ )
471
+
472
+ metadata["enhancement_focus"] = True
473
+ metadata["qa_memories_found"] = len(recent_context) > 0 or len(semantic_context) > 0
474
+
475
+ return recent_context, semantic_context, metadata
476
+
477
+ except Exception as e:
478
+ logger.error(f"[MEMORY_PLANNER] Focused Q&A retrieval failed: {e}")
479
+ return "", "", {"error": str(e)}
480
+
481
+ async def _execute_recent_focus_retrieval(self, user_id: str, question: str, params: Dict[str, Any],
482
+ nvidia_rotator, project_id: Optional[str]) -> Tuple[str, str, Dict[str, Any]]:
483
+ """Execute recent focus retrieval for clarification requests"""
484
+ try:
485
+ recent_context = ""
486
+ semantic_context = ""
487
+ metadata = {"strategy": "recent_focus"}
488
+
489
+ if self.memory_system.is_enhanced_available():
490
+ recent_memories = self.memory_system.enhanced_memory.get_memories(
491
+ user_id, memory_type="conversation", limit=params["recent_limit"]
492
+ )
493
+
494
+ if recent_memories:
495
+ recent_context = "\n\n".join([m["content"] for m in recent_memories])
496
+
497
+ # Get some semantic context
498
+ all_memories = self.memory_system.enhanced_memory.get_memories(
499
+ user_id, limit=params["semantic_limit"]
500
+ )
501
+
502
+ if all_memories:
503
+ semantic_context = await self._semantic_select_qa_memories(
504
+ question, all_memories, params["similarity_threshold"]
505
+ )
506
+ else:
507
+ # Legacy fallback
508
+ recent_memories = self.memory_system.recent(user_id, params["recent_limit"])
509
+ rest_memories = self.memory_system.rest(user_id, params["recent_limit"])
510
+
511
+ recent_context = "\n\n".join(recent_memories)
512
+
513
+ if rest_memories:
514
+ semantic_context = await self._semantic_select_qa_memories(
515
+ question, [{"content": m} for m in rest_memories], params["similarity_threshold"]
516
+ )
517
+
518
+ return recent_context, semantic_context, metadata
519
+
520
+ except Exception as e:
521
+ logger.error(f"[MEMORY_PLANNER] Recent focus retrieval failed: {e}")
522
+ return "", "", {"error": str(e)}
523
+
524
+ async def _execute_broad_context_retrieval(self, user_id: str, question: str, params: Dict[str, Any],
525
+ nvidia_rotator, project_id: Optional[str]) -> Tuple[str, str, Dict[str, Any]]:
526
+ """Execute broad context retrieval for comparison requests"""
527
+ try:
528
+ recent_context = ""
529
+ semantic_context = ""
530
+ metadata = {"strategy": "broad_context"}
531
+
532
+ if self.memory_system.is_enhanced_available():
533
+ # Get recent context
534
+ recent_memories = self.memory_system.enhanced_memory.get_memories(
535
+ user_id, memory_type="conversation", limit=params["recent_limit"]
536
+ )
537
+
538
+ if recent_memories:
539
+ recent_context = "\n\n".join([m["content"] for m in recent_memories])
540
+
541
+ # Get broad semantic context
542
+ all_memories = self.memory_system.enhanced_memory.get_memories(
543
+ user_id, limit=params["semantic_limit"]
544
+ )
545
+
546
+ if all_memories:
547
+ semantic_context = await self._semantic_select_qa_memories(
548
+ question, all_memories, params["similarity_threshold"]
549
+ )
550
+ else:
551
+ # Legacy fallback
552
+ recent_memories = self.memory_system.recent(user_id, params["recent_limit"])
553
+ rest_memories = self.memory_system.rest(user_id, params["recent_limit"])
554
+
555
+ recent_context = "\n\n".join(recent_memories)
556
+ semantic_context = "\n\n".join(rest_memories)
557
+
558
+ return recent_context, semantic_context, metadata
559
+
560
+ except Exception as e:
561
+ logger.error(f"[MEMORY_PLANNER] Broad context retrieval failed: {e}")
562
+ return "", "", {"error": str(e)}
563
+
564
+ async def _execute_semantic_deep_retrieval(self, user_id: str, question: str, params: Dict[str, Any],
565
+ nvidia_rotator, project_id: Optional[str]) -> Tuple[str, str, Dict[str, Any]]:
566
+ """Execute semantic deep retrieval for new topics"""
567
+ try:
568
+ recent_context = ""
569
+ semantic_context = ""
570
+ metadata = {"strategy": "semantic_deep"}
571
+
572
+ if self.memory_system.is_enhanced_available():
573
+ # Get all memories for deep semantic search
574
+ all_memories = self.memory_system.enhanced_memory.get_memories(
575
+ user_id, limit=params["semantic_limit"]
576
+ )
577
+
578
+ if all_memories:
579
+ if params["use_ai_selection"] and nvidia_rotator:
580
+ semantic_context = await self._ai_select_qa_memories(
581
+ question, all_memories, nvidia_rotator, "semantic"
582
+ )
583
+ else:
584
+ semantic_context = await self._semantic_select_qa_memories(
585
+ question, all_memories, params["similarity_threshold"]
586
+ )
587
+
588
+ # Get some recent context
589
+ recent_memories = self.memory_system.enhanced_memory.get_memories(
590
+ user_id, memory_type="conversation", limit=params["recent_limit"]
591
+ )
592
+
593
+ if recent_memories:
594
+ recent_context = "\n\n".join([m["content"] for m in recent_memories])
595
+ else:
596
+ # Legacy fallback
597
+ all_memories = self.memory_system.all(user_id)
598
+ recent_memories = self.memory_system.recent(user_id, params["recent_limit"])
599
+
600
+ if all_memories:
601
+ semantic_context = await self._semantic_select_qa_memories(
602
+ question, [{"content": m} for m in all_memories], params["similarity_threshold"]
603
+ )
604
+
605
+ recent_context = "\n\n".join(recent_memories)
606
+
607
+ return recent_context, semantic_context, metadata
608
+
609
+ except Exception as e:
610
+ logger.error(f"[MEMORY_PLANNER] Semantic deep retrieval failed: {e}")
611
+ return "", "", {"error": str(e)}
612
+
613
+ async def _execute_mixed_approach_retrieval(self, user_id: str, question: str, params: Dict[str, Any],
614
+ nvidia_rotator, project_id: Optional[str]) -> Tuple[str, str, Dict[str, Any]]:
615
+ """Execute mixed approach retrieval for continuation requests"""
616
+ try:
617
+ recent_context = ""
618
+ semantic_context = ""
619
+ metadata = {"strategy": "mixed_approach"}
620
+
621
+ if self.memory_system.is_enhanced_available():
622
+ # Get recent context
623
+ recent_memories = self.memory_system.enhanced_memory.get_memories(
624
+ user_id, memory_type="conversation", limit=params["recent_limit"]
625
+ )
626
+
627
+ if recent_memories:
628
+ if params["use_ai_selection"] and nvidia_rotator:
629
+ recent_context = await self._ai_select_qa_memories(
630
+ question, recent_memories, nvidia_rotator, "recent"
631
+ )
632
+ else:
633
+ recent_context = await self._semantic_select_qa_memories(
634
+ question, recent_memories, params["similarity_threshold"]
635
+ )
636
+
637
+ # Get semantic context
638
+ all_memories = self.memory_system.enhanced_memory.get_memories(
639
+ user_id, limit=params["semantic_limit"]
640
+ )
641
+
642
+ if all_memories:
643
+ if params["use_ai_selection"] and nvidia_rotator:
644
+ semantic_context = await self._ai_select_qa_memories(
645
+ question, all_memories, nvidia_rotator, "semantic"
646
+ )
647
+ else:
648
+ semantic_context = await self._semantic_select_qa_memories(
649
+ question, all_memories, params["similarity_threshold"]
650
+ )
651
+ else:
652
+ # Legacy fallback
653
+ recent_memories = self.memory_system.recent(user_id, params["recent_limit"])
654
+ rest_memories = self.memory_system.rest(user_id, params["recent_limit"])
655
+
656
+ if recent_memories:
657
+ recent_context = await self._semantic_select_qa_memories(
658
+ question, [{"content": m} for m in recent_memories], params["similarity_threshold"]
659
+ )
660
+
661
+ if rest_memories:
662
+ semantic_context = await self._semantic_select_qa_memories(
663
+ question, [{"content": m} for m in rest_memories], params["similarity_threshold"]
664
+ )
665
+
666
+ return recent_context, semantic_context, metadata
667
+
668
+ except Exception as e:
669
+ logger.error(f"[MEMORY_PLANNER] Mixed approach retrieval failed: {e}")
670
+ return "", "", {"error": str(e)}
671
+
672
+ async def _ai_select_qa_memories(self, question: str, memories: List[Dict[str, Any]],
673
+ nvidia_rotator, context_type: str) -> str:
674
+ """Use AI to select the most relevant Q&A memories"""
675
+ try:
676
+ from utils.api.router import generate_answer_with_model
677
+
678
+ if not memories:
679
+ return ""
680
+
681
+ sys_prompt = f"""You are an expert at selecting the most relevant Q&A memories for {context_type} context.
682
+
683
+ Given a user's question and a list of Q&A memories, select the most relevant ones that would help provide a comprehensive and detailed answer.
684
+
685
+ Focus on:
686
+ 1. Direct relevance to the question
687
+ 2. Q&A pairs that provide supporting information
688
+ 3. Memories that add context and depth
689
+ 4. Past discussions that relate to the current question
690
+
691
+ Return ONLY the selected Q&A memories, concatenated together. If none are relevant, return nothing."""
692
+
693
+ # Format memories for AI
694
+ formatted_memories = []
695
+ for i, memory in enumerate(memories):
696
+ content = memory.get("content", "")
697
+ if content:
698
+ formatted_memories.append(f"Memory {i+1}: {content}")
699
+
700
+ user_prompt = f"""Question: {question}
701
+
702
+ Available Q&A Memories:
703
+ {chr(10).join(formatted_memories)}
704
+
705
+ Select the most relevant Q&A memories:"""
706
+
707
+ selection = {"provider": "nvidia", "model": "meta/llama-3.1-8b-instruct"}
708
+ response = await generate_answer_with_model(
709
+ selection=selection,
710
+ system_prompt=sys_prompt,
711
+ user_prompt=user_prompt,
712
+ gemini_rotator=None,
713
+ nvidia_rotator=nvidia_rotator
714
+ )
715
+
716
+ return response.strip()
717
+
718
+ except Exception as e:
719
+ logger.warning(f"[MEMORY_PLANNER] AI Q&A selection failed: {e}")
720
+ return ""
721
+
722
+ async def _semantic_select_qa_memories(self, question: str, memories: List[Dict[str, Any]],
723
+ threshold: float) -> str:
724
+ """Use semantic similarity to select Q&A memories"""
725
+ try:
726
+ if not memories:
727
+ return ""
728
+
729
+ # Extract content from memories
730
+ memory_contents = [memory.get("content", "") for memory in memories if memory.get("content")]
731
+
732
+ if not memory_contents:
733
+ return ""
734
+
735
+ # Use semantic similarity
736
+ from memo.context import semantic_context
737
+ selected = await semantic_context(question, memory_contents, self.embedder, len(memory_contents))
738
+
739
+ return selected
740
+
741
+ except Exception as e:
742
+ logger.warning(f"[MEMORY_PLANNER] Semantic Q&A selection failed: {e}")
743
+ return ""
744
+
745
+
746
+ # ────────────────────────────── Global Instance ──────────────────────────────
747
+
748
+ _memory_planner: Optional[MemoryPlanner] = None
749
+
750
+ def get_memory_planner(memory_system=None, embedder: EmbeddingClient = None) -> MemoryPlanner:
751
+ """Get the global memory planner instance"""
752
+ global _memory_planner
753
+
754
+ if _memory_planner is None:
755
+ if not memory_system:
756
+ from memo.core import get_memory_system
757
+ memory_system = get_memory_system()
758
+ if not embedder:
759
+ from utils.rag.embeddings import EmbeddingClient
760
+ embedder = EmbeddingClient()
761
+
762
+ _memory_planner = MemoryPlanner(memory_system, embedder)
763
+ logger.info("[MEMORY_PLANNER] Global memory planner initialized")
764
+
765
+ return _memory_planner
766
+
767
+ # def reset_memory_planner():
768
+ # """Reset the global memory planner (for testing)"""
769
+ # global _memory_planner
770
+ # _memory_planner = None
memo/retrieval.py CHANGED
@@ -28,7 +28,7 @@ class RetrievalManager:
28
  nvidia_rotator=None, project_id: Optional[str] = None,
29
  conversation_mode: str = "chat") -> Tuple[str, str, Dict[str, Any]]:
30
  """
31
- Get intelligent context for conversation with enhanced edge case handling.
32
 
33
  Args:
34
  user_id: User identifier
@@ -40,6 +40,27 @@ class RetrievalManager:
40
  Returns:
41
  Tuple of (recent_context, semantic_context, metadata)
42
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  try:
44
  # Check for conversation session continuity
45
  from memo.sessions import get_session_manager
@@ -71,13 +92,14 @@ class RetrievalManager:
71
  "context_enhanced": context_used,
72
  "enhanced_input": enhanced_input,
73
  "conversation_depth": session_info["depth"],
74
- "last_activity": session_info["last_activity"]
 
75
  }
76
 
77
  return recent_context, semantic_context, metadata
78
 
79
  except Exception as e:
80
- logger.error(f"[RETRIEVAL_MANAGER] Smart context failed: {e}")
81
  return "", "", {"error": str(e)}
82
 
83
  async def _get_continuation_context(self, user_id: str, question: str,
@@ -308,6 +330,19 @@ Create an enhanced version that incorporates this context naturally."""
308
  except Exception as e:
309
  logger.warning(f"[RETRIEVAL_MANAGER] Instructions enhancement failed: {e}")
310
  return instructions, False
 
 
 
 
 
 
 
 
 
 
 
 
 
311
 
312
 
313
  # ────────────────────────────── Global Instance ──────────────────────────────
 
28
  nvidia_rotator=None, project_id: Optional[str] = None,
29
  conversation_mode: str = "chat") -> Tuple[str, str, Dict[str, Any]]:
30
  """
31
+ Get intelligent context for conversation with enhanced memory planning.
32
 
33
  Args:
34
  user_id: User identifier
 
40
  Returns:
41
  Tuple of (recent_context, semantic_context, metadata)
42
  """
43
+ try:
44
+ # Use the new memory planning system from core memory
45
+ return await self.memory_system.get_smart_context(
46
+ user_id, question, nvidia_rotator, project_id, conversation_mode
47
+ )
48
+
49
+ except Exception as e:
50
+ logger.error(f"[RETRIEVAL_MANAGER] Smart context failed: {e}")
51
+ # Fallback to legacy approach
52
+ try:
53
+ return await self._get_legacy_smart_context(
54
+ user_id, question, nvidia_rotator, project_id, conversation_mode
55
+ )
56
+ except Exception as fallback_error:
57
+ logger.error(f"[RETRIEVAL_MANAGER] Legacy fallback also failed: {fallback_error}")
58
+ return "", "", {"error": str(e)}
59
+
60
+ async def _get_legacy_smart_context(self, user_id: str, question: str,
61
+ nvidia_rotator=None, project_id: Optional[str] = None,
62
+ conversation_mode: str = "chat") -> Tuple[str, str, Dict[str, Any]]:
63
+ """Legacy smart context retrieval as fallback"""
64
  try:
65
  # Check for conversation session continuity
66
  from memo.sessions import get_session_manager
 
92
  "context_enhanced": context_used,
93
  "enhanced_input": enhanced_input,
94
  "conversation_depth": session_info["depth"],
95
+ "last_activity": session_info["last_activity"],
96
+ "legacy_mode": True
97
  }
98
 
99
  return recent_context, semantic_context, metadata
100
 
101
  except Exception as e:
102
+ logger.error(f"[RETRIEVAL_MANAGER] Legacy smart context failed: {e}")
103
  return "", "", {"error": str(e)}
104
 
105
  async def _get_continuation_context(self, user_id: str, question: str,
 
330
  except Exception as e:
331
  logger.warning(f"[RETRIEVAL_MANAGER] Instructions enhancement failed: {e}")
332
  return instructions, False
333
+
334
+ async def get_enhancement_context(self, user_id: str, question: str,
335
+ nvidia_rotator=None, project_id: Optional[str] = None) -> Tuple[str, str, Dict[str, Any]]:
336
+ """Get context specifically optimized for enhancement requests"""
337
+ try:
338
+ # Use the core memory system's enhancement context method
339
+ return await self.memory_system.get_enhancement_context(
340
+ user_id, question, nvidia_rotator, project_id
341
+ )
342
+
343
+ except Exception as e:
344
+ logger.error(f"[RETRIEVAL_MANAGER] Enhancement context failed: {e}")
345
+ return "", "", {"error": str(e)}
346
 
347
 
348
  # ────────────────────────────── Global Instance ──────────────────────────────