# 🧠 AKIRA Memory + Emotional Intelligence Architecture ## 1. Overview: 3-Layer System ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ LAYER 1: User Message Input β”‚ β”‚ (agressivo, pergunta, pedido, etc) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ LAYER 2: AKIRA Internal Processing β”‚ β”‚ β”œβ”€ Detect Emotion β”‚ β”‚ β”œβ”€ Search Memory Graph (with connections) β”‚ β”‚ β”œβ”€ THINK/Reasoning (INTERNAL - never vaza) β”‚ β”‚ β”œβ”€ Inject Emotional Tag in Prompt β”‚ β”‚ β”œβ”€ Generate Response (uses tag + thinking) β”‚ β”‚ └─ Clean Response (_remove_ tags + thinking) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ LAYER 3: User Sees (Clean) β”‚ β”‚ (no thinking, no tags, no internal context) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ LAYER 4: Internal Storage (Never Shown) β”‚ β”‚ β”œβ”€ Save to MemoryNode β”‚ β”‚ β”œβ”€ Create/Update Connections β”‚ β”‚ β”œβ”€ Update Emotional State β”‚ β”‚ └─ Index in Graph (for next session) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## 2. Phase 2: Emotional State System ### 2.1 Flow with Example **Scenario: Aggressive user** ```python # INPUT user_message = "vocΓͺ Γ© inΓΊtil! essa resposta Γ© ridΓ­cula" numero_usuario = "5531988776655" # LAYER 2: INTERNAL PROCESSING # Step 1: Detect Emotion emotion = BART_emotion_analyzer(user_message) # Result: "agressivo" (confidence: 0.92) # Step 2: Search Memory Graph context = memory_graph.search_with_connections(user_message, numero_usuario) # Returns: [previous messages about same topic with connections] # Step 3: Create Prompt WITH TAG config_emotional_state = { "agressivo": { "tag": "", "instruction": "User is HOSTILE. Be firm, professional, NOT rude. Maintain boundaries..." } } prompt = f""" {config_emotional_state['agressivo']['tag']} Previous context: {context} {config_emotional_state['agressivo']['instruction']} User message: {user_message} """ # Step 4: Generate (INTERNAL - thinking allowed to be verbose) thinking = model.think(prompt) # Can have multiple thinking attempts response_with_thinking = model.generate(prompt) # Example thinking (INTERNAL, never shown): # # User is angry about response quality. They think I'm useless. # Need to: # 1. Acknowledge their frustration without being defensive # 2. Show I understand the issue # 3. Provide concrete solution # 4. Maintain firm tone (they're hostile) # # Sua resposta anterior realmente nΓ£o foi clara... # LAYER 3: CLEAN BEFORE SENDING cleaned_response = _clean_response(response_with_thinking) # Removes: , , # Result: "Sua resposta anterior realmente nΓ£o foi clara..." # OUTPUT TO USER user_sees = cleaned_response # "Sua resposta anterior realmente nΓ£o foi clara..." # (Firm tone because tag influenced thinking, but tag is removed) # LAYER 4: SAVE INTERNALLY profile_update = { "numero_usuario": "5531988776655", "emotional_state": "agressivo", "emotion_history": [..., "agressivo"], "is_hostile": True, "aggressive_count": 5 } memory_node = MemoryNode( id=uuid(), timestamp=now(), content=user_message, user_id="5531988776655", type="user_message", tags=["angry", "complaint", "quality"], emotion="agressivo", connections=[ {node_id: "prev_msg_id", relation: "follow_up", strength: 0.8} ] ) memory_graph.add_node(memory_node) save_to_profile(profile_update) ``` **7 Days Later: Same User Returns** ```python # INPUT user_message = "como faΓ§o isso funcionar?" numero_usuario = "5531988776655" # LAYER 2: INTERNAL PROCESSING # Step 1: Load Profile profile = load_profile(numero_usuario) # Result: emotional_state = "agressivo", aggressive_count = 5 # Step 2: Search + Connections context = memory_graph.search_with_connections(user_message, numero_usuario) # Returns: [messages from 7 days ago + connections] # AKIRA remembers: "Este usuΓ‘rio estava furioso hΓ‘ 7 dias" # Step 3: Create Prompt WITH TAG (REUSE EMOTIONAL STATE) prompt = f""" Previous context: [7 days ago user was angry about...] User has history of being demanding. Maintain firm professional tone. User message: como faΓ§o isso funcionar? """ # Step 4: Generate response = model.generate(prompt) # LAYER 3: CLEAN cleaned = _clean_response(response) # OUTPUT user_sees = cleaned # (Maintains firm tone from tag influence) # Result: βœ… "GUARDOU RANCOR" - Remembered user was aggressive! ``` ### 2.2 Implementation Details #### File: config.py ```python EMOTIONAL_STATES = { "agressivo": { "tag": "", "instruction": """ User is HOSTILE or AGGRESSIVE. Maintain these principles: - Be firm and professional - Don't match their aggression - Set clear boundaries - Provide concrete help - Never apologize excessively - Be direct and honest """, "response_style": "defensive", "memory_days": 30 # Remember 30 days }, "feliz": { "tag": "", "instruction": """ User is HAPPY and POSITIVE. Match their energy: - Be warm and encouraging - Use friendly language - Share enthusiasm - Build on their positive momentum - Celebrate their wins """, "response_style": "warm", "memory_days": 15 }, "triste": { "tag": "", "instruction": """ User is SAD or FRUSTRATED. Show empathy: - Acknowledge their feelings - Be supportive, not dismissive - Provide actionable help - Offer encouragement - Don't minimize their concerns """, "response_style": "supportive", "memory_days": 20 }, "confuso": { "tag": "", "instruction": """ User is CONFUSED. Simplify: - Break down complex ideas - Use examples and analogies - Be patient - Confirm understanding - Offer step-by-step guidance """, "response_style": "patient", "memory_days": 10 }, "neutro": { "tag": "", "instruction": "Standard professional tone", "response_style": "neutral", "memory_days": 0 } } ``` #### File: persona_tracker.py (Add Fields) ```python def create_user_profile(numero_usuario): return { # ... existing fields ... # PHASE 2: Emotional State Fields "emotional_state": "neutro", # Current emotion "emotion_history": [], # [timestamp, emotion] "is_hostile": False, # Flag for security "aggressive_count": 0, # Tracks patterns "last_emotion_change": None, # When state changed "emotion_confidence_score": 0.0, # How sure are we? # PHASE 3: Memory Graph Fields "memory_nodes": [], # Node IDs related to this user "favorite_topics": {}, # topic β†’ frequency "communication_style": "neutral", # Learned style } ``` #### File: api.py - New Methods ```python def _detect_and_store_emotional_state(self, message, numero_usuario): """ Detect emotion from message and save to profile Returns: emotion_state (str) """ # Use existing BART emotion analyzer emotion = self.emotion_analyzer(message) # emotion = {"label": "agressivo", "score": 0.92} if emotion["score"] < 0.5: return "neutro" emotion_state = emotion["label"] # Load profile profile = self.persona_tracker.get_profile(numero_usuario) # Update emotion profile["emotional_state"] = emotion_state profile["emotion_history"].append({ "timestamp": datetime.now(), "emotion": emotion_state, "confidence": emotion["score"] }) profile["last_emotion_change"] = datetime.now() profile["emotion_confidence_score"] = emotion["score"] # Track aggression pattern if emotion_state == "agressivo": profile["is_hostile"] = True profile["aggressive_count"] += 1 elif profile["aggressive_count"] > 0 and emotion_state in ["feliz", "neutro"]: # User calmed down profile["is_hostile"] = False # But aggressive_count stays for history # Save updated profile self.persona_tracker.save_profile(numero_usuario, profile) return emotion_state def _inject_emotional_tag_in_prompt(self, prompt, numero_usuario): """ Inject emotional state tag into prompt Returns: modified_prompt (str with tag prepended) """ profile = self.persona_tracker.get_profile(numero_usuario) emotion_state = profile.get("emotional_state", "neutro") # Check memory retention (should we keep old emotion?) if emotion_state != "neutro": last_change = profile.get("last_emotion_change") if last_change: memory_days = EMOTIONAL_STATES[emotion_state].get("memory_days", 7) age = (datetime.now() - last_change).days if age > memory_days: emotion_state = "neutro" # Get tag and instruction config = EMOTIONAL_STATES.get(emotion_state, EMOTIONAL_STATES["neutro"]) tag = config["tag"] instruction = config["instruction"] # Prepend to prompt modified_prompt = f"{tag}\n\nEmotional Context Instructions:\n{instruction}\n\n{prompt}" return modified_prompt ``` #### File: api.py - Modify generate() ```python def generate(self, prompt, numero_usuario, ...): """ Modified generate to include emotional state """ # PHASE 2: NEW - Detect and store emotion emotion_state = self._detect_and_store_emotional_state( user_message, numero_usuario ) # PHASE 2: NEW - Inject emotional tag in prompt prompt = self._inject_emotional_tag_in_prompt(prompt, numero_usuario) # Generate response (thinking allowed internally) response = self._call_provider(prompt) # Clean response (removes tag + thinking) cleaned = self._clean_response(response) # PHASE 3: NEW - Save to memory graph # (to be implemented next) return cleaned ``` --- ## 3. Phase 3: Memory Graph System ### 3.1 Why Memory Graph? **Without Graph** (Current): ``` User Session 1: "Tenho dor de cabeΓ§a" Memory: [msg1] User Session 2: "Tomo remΓ©dio?" Memory: [msg1, msg2] Problem: AKIRA doesn't know msg2 is related to msg1 User Session 3 (next month): "Ficou melhor?" Memory: [msg1, msg2, msg3] Problem: AKIRA doesn't know msg3 is asking about msg1 Result: "Melhorou o quΓͺ?" (Lost context!) ``` **With Graph** (Proposed): ``` MemoryNode(msg1): "Tenho dor de cabeΓ§a" tags: [health, pain, symptom] MemoryNode(msg2): "Tomo remΓ©dio?" tags: [medicine, treatment] connections: [(msg1, "follow_up_question", strength=0.9)] MemoryNode(msg3): "Ficou melhor?" tags: [status, improvement] connections: [(msg1, "status_update", strength=0.95)] Result: search("Ficou melhor?") finds: - msg3 (direct match) - msg1 (connected: status_update) - msg2 (connected: related_problem) AKIRA now knows: "MΓͺs atrΓ‘s vocΓͺ tinha dor de cabeΓ§a. Melhorou?" ``` ### 3.2 Data Structure ```python class MemoryNode: """Represents a single message/thought in the graph""" id: str # UUID timestamp: datetime # When created content: str # Message text user_id: str # Isolation type: str # "user_message", "akira_response", "observation" tags: List[str] # [health, pain, question] emotion: str # "agressivo", "feliz", etc connections: List[Connection] # Links to other nodes class Connection: node_id: str # Points to which node relation_type: str # "follow_up", "related", "solution_for", "reference" strength: float # 0.0-1.0 (relevance score) explanation: str # Why connected? class MemoryGraph: """Graph of user memories with logical connections""" nodes: Dict[str, MemoryNode] # All nodes user_index: Dict[str, List[str]] # user_id β†’ [node_ids] def add_node(node: MemoryNode) β†’ str: """Add new node to graph""" def connect(from_id, to_id, relation, strength, explanation) β†’ None: """Create connection between nodes""" def search(query, user_id, limit=10) β†’ List[MemoryNode]: """Search with BFS through connections""" def get_context(node_id, depth=2) β†’ enriched_context: """Get node with all connected nodes up to depth""" ``` ### 3.3 Connection Detection ```python def detect_connections(new_message, user_id, existing_nodes): """ Detect if new message relates to existing nodes Returns: [(node_id, relation_type, strength), ...] """ connections = [] # Strategy 1: Keyword matching for node in existing_nodes: common_tags = set(new_message.tags) & set(node.tags) if common_tags: strength = len(common_tags) / max(len(new_message.tags), len(node.tags)) connections.append(( node.id, "related_by_tags", strength )) # Strategy 2: Temporal proximity (follow-up detection) recent_nodes = [n for n in existing_nodes if (now - n.timestamp) < timedelta(hours=2)] if recent_nodes: # Likely follow-up connections.append(( recent_nodes[0].id, "immediate_follow_up", 0.95 )) # Strategy 3: Embedding similarity new_embedding = embed(new_message.content) for node in existing_nodes: node_embedding = embed(node.content) similarity = cosine_similarity(new_embedding, node_embedding) if similarity > 0.7: connections.append(( node.id, "similar_topic", similarity )) return connections ``` ### 3.4 Smart Search ```python def search_with_connections(query, user_id, depth=3): """ BFS search that follows connections Returns: List[MemoryNode] with relevant nodes """ queue = [] visited = set() results = [] # Start: find nodes matching query initial_nodes = [n for n in graph.nodes.values() if n.user_id == user_id and query in n.content] for node in initial_nodes: queue.append((node, depth)) # BFS: follow connections while queue: current_node, remaining_depth = queue.pop(0) if current_node.id in visited: continue visited.add(current_node.id) results.append(current_node) if remaining_depth > 0: # Add connected nodes to queue for connection in current_node.connections: if connection.node_id not in visited: next_node = graph.nodes[connection.node_id] queue.append((next_node, remaining_depth - 1)) return results ``` --- ## 4. Integration Timeline ### Phase 1 βœ… Done - Context isolation - Recursion protection - User validation ### Phase 2 (30-40 min) - Emotional detection + storage - Tag injection - Profile persistence ### Phase 3 (2-3 hours) - MemoryNode + MemoryGraph - Connection detection - Smart search - Integration into generate() --- ## 5. Security Guarantees βœ… **Thinking never shown** - Removed by _clean_response() before sending - Tags removed - Internal context removed βœ… **Context always preserved** - MemoryNodes save everything - Graph persists across sessions - Connections maintained βœ… **User isolation** - Every node has user_id - Search filters by user_id - No cross-user leakage βœ… **Emotional state private** - Profile only for that user - Historical emotions saved - Pattern tracking for safety (aggressive_count) --- ## 6. Example: Full Flow **Day 1, User A** ``` Input: "Tenho ansiedade social" β†’ Detect: neutro (baseline) β†’ MemoryNode_1: tags=[mental_health, anxiety] β†’ No connections (first message) β†’ Save to profile β†’ Output: "Entendo... ansiedade social Γ©..." ``` **Day 1, 5 min later, User A** ``` Input: "Fico nervoso em grupos" β†’ Detect: confuso (from word analysis) β†’ Tag: β†’ Search finds: MemoryNode_1 (similar topic) β†’ Connect: MemoryNode_2 β†’ MemoryNode_1 (related_by_tags, 0.85) β†’ Add context: "VocΓͺ mencionou ansiedade social... fico nervoso em grupos Γ© relacionado?" β†’ Output: "Sim, isso estΓ‘ muito relacionado. Aqui estΓ£o estratΓ©gias... [patient tone]" β†’ Save: MemoryNode_2 with connection ``` **Day 30, User A** ``` Input: "Como faΓ§o para melhorar minha sociabilidade?" β†’ Detect: neutro (but check profile) β†’ Profile shows: emotion_history = [confuso] β†’ Search with connections finds: - MemoryNode_1: "Tenho ansiedade social" - MemoryNode_2: "Fico nervoso em grupos" β†’ AKIRA context: "VocΓͺ tem trabalhado na sua ansiedade social. Aqui estΓ£o 5 tΓ©cnicas prΓ‘ticas..." β†’ Output: Highly relevant because graph understood multi-turn journey ``` Result: βœ… Context improved automatically. Graph made AKIRA smarter! --- ## 7. Deployment Checklist - [ ] Phase 1 deployed to production - [ ] Phase 2 code written and tested - [ ] Phase 2 deployed - [ ] Phase 3 design reviewed - [ ] Phase 3 code written and tested - [ ] Phase 3 deployed - [ ] Monitor: emotional detection accuracy - [ ] Monitor: graph connection quality - [ ] Collect user feedback