mirrors / conversation_manager.py
Shim
Add all project files with proper .gitignore for Hugging Face deployment
a67f1bb
# -*- coding: utf-8 -*-
"""
Conversation Manager for ΧžΧ¨ΧΧ•Χͺ (Mirrors) - Hebrew Self-Reflective AI Agent
Handles conversation context, history, and session state management
"""
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
import json
@dataclass
class ConversationState:
"""Tracks the current conversation state"""
user_context: Optional[str] = None
selected_part: Optional[str] = None
persona_name: Optional[str] = None
persona_age: Optional[str] = None
persona_style: Optional[str] = None
conversation_history: List[Dict] = None
initial_prompt_choice: Optional[str] = None
def __post_init__(self):
if self.conversation_history is None:
self.conversation_history = []
class ConversationManager:
"""Manages conversation flow and context for the ΧžΧ¨ΧΧ•Χͺ application"""
def __init__(self, max_history_length: int = 50):
"""
Initialize conversation manager
Args:
max_history_length: Maximum number of messages to keep in history
"""
self.max_history_length = max_history_length
def create_new_session(self) -> ConversationState:
"""Create a new conversation session"""
return ConversationState()
def set_initial_context(self, state: ConversationState, prompt_choice: str, user_response: str) -> ConversationState:
"""
Set the initial context based on user's choice and response
Args:
state: Current conversation state
prompt_choice: Which initial prompt was chosen
user_response: User's response to the initial prompt
"""
state.initial_prompt_choice = prompt_choice
state.user_context = user_response
return state
def set_selected_part(self, state: ConversationState, part_name: str,
persona_name: Optional[str] = None,
persona_age: Optional[str] = None,
persona_style: Optional[str] = None) -> ConversationState:
"""
Set the selected part and its customization
Args:
state: Current conversation state
part_name: Name of the selected part
persona_name: Custom name for the persona
persona_age: Custom age for the persona
persona_style: Custom speaking style
"""
state.selected_part = part_name
state.persona_name = persona_name
state.persona_age = persona_age
state.persona_style = persona_style
return state
def add_to_history(self, state: ConversationState, user_message: str, bot_response: str) -> ConversationState:
"""
Add a message exchange to conversation history
Args:
state: Current conversation state
user_message: User's message
bot_response: Bot's response
"""
# Add user message
state.conversation_history.append({
"role": "user",
"content": user_message
})
# Add bot response
state.conversation_history.append({
"role": "assistant",
"content": bot_response
})
# Trim history if too long
if len(state.conversation_history) > self.max_history_length:
# Remove oldest messages (keep pairs)
messages_to_remove = len(state.conversation_history) - self.max_history_length
# Make sure we remove in pairs
if messages_to_remove % 2 == 1:
messages_to_remove += 1
state.conversation_history = state.conversation_history[messages_to_remove:]
return state
def get_conversation_context(self, state: ConversationState) -> str:
"""
Get formatted conversation context for prompt generation
Args:
state: Current conversation state
Returns:
Formatted context string
"""
context_parts = []
if state.user_context:
context_parts.append(f"Χ”Χ§Χ©Χ¨ ראשוני: {state.user_context}")
if state.conversation_history:
context_parts.append("Χ”Χ™Χ‘Χ˜Χ•Χ¨Χ™Χ™Χͺ Χ”Χ©Χ™Χ—Χ”:")
for msg in state.conversation_history[-10:]: # Last 10 messages for context
role = "משΧͺמש" if msg["role"] == "user" else "Χ—ΧœΧ§ Χ€Χ Χ™ΧžΧ™"
context_parts.append(f"{role}: {msg['content']}")
return "\n".join(context_parts)
def format_history_for_display(self, state: ConversationState) -> List[Tuple[str, str]]:
"""
Format conversation history for Gradio display
Args:
state: Current conversation state
Returns:
List of (user_message, bot_response) tuples
"""
formatted_history = []
for i in range(0, len(state.conversation_history), 2):
if i + 1 < len(state.conversation_history):
user_msg = state.conversation_history[i]["content"]
bot_msg = state.conversation_history[i + 1]["content"]
formatted_history.append((user_msg, bot_msg))
return formatted_history
def get_session_summary(self, state: ConversationState) -> Dict:
"""
Get a summary of the current session
Args:
state: Current conversation state
Returns:
Dictionary with session summary
"""
return {
"has_context": bool(state.user_context),
"selected_part": state.selected_part,
"persona_name": state.persona_name,
"conversation_length": len(state.conversation_history),
"initial_choice": state.initial_prompt_choice
}
def clear_conversation(self, state: ConversationState) -> ConversationState:
"""
Clear conversation history while keeping context and part selection
Args:
state: Current conversation state
Returns:
State with cleared conversation history
"""
state.conversation_history = []
return state
def reset_session(self, state: ConversationState) -> ConversationState:
"""
Reset the entire session to start fresh
Args:
state: Current conversation state
Returns:
Fresh conversation state
"""
return ConversationState()
def is_session_ready(self, state: ConversationState) -> bool:
"""
Check if session is ready for conversation (has context and selected part)
Args:
state: Current conversation state
Returns:
True if ready for conversation
"""
return bool(state.user_context and state.selected_part)
def get_gradio_history(self, state: ConversationState) -> List[List[str]]:
"""
Format conversation history for Gradio ChatInterface
Args:
state: Current conversation state
Returns:
List of [user_message, bot_response] pairs for Gradio
"""
gradio_history = []
for i in range(0, len(state.conversation_history), 2):
if i + 1 < len(state.conversation_history):
user_msg = state.conversation_history[i]["content"]
bot_msg = state.conversation_history[i + 1]["content"]
gradio_history.append([user_msg, bot_msg])
return gradio_history