- Added DATABASE_SETUP.md with comprehensive guide for PostgreSQL and Redis installation on Windows - Created .claude/settings.local.json with permission settings for pytest and database fix scripts - Updated .gitignore to exclude .env.backup file - Included database connection test utilities in lyra/database_setup.py - Added environment variable configuration examples for local development
443 lines
16 KiB
Python
443 lines
16 KiB
Python
"""
|
|
Main Lyra model that integrates all AI components.
|
|
|
|
This is the central coordinator that brings together the transformer,
|
|
personality matrix, emotional system, and thinking agent.
|
|
"""
|
|
|
|
import torch
|
|
import torch.nn as nn
|
|
import logging
|
|
from typing import Dict, List, Any, Optional, Tuple
|
|
from datetime import datetime
|
|
|
|
from .transformer import LyraTransformer
|
|
from .self_evolution import SelfEvolutionEngine
|
|
from .thinking_agent import ThinkingAgent
|
|
from ..personality.matrix import PersonalityMatrix
|
|
from ..emotions.system import EmotionalSystem
|
|
from ..emotions.expressions import EmotionalExpressionEngine
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class LyraModel(nn.Module):
|
|
"""
|
|
Complete Lyra AI model integrating all cognitive systems.
|
|
|
|
This model combines:
|
|
- Self-evolving transformer for language generation
|
|
- Personality matrix for trait-based behavior
|
|
- Emotional intelligence for natural responses
|
|
- Behind-the-scenes thinking for human-like reasoning
|
|
- Self-evolution for continuous improvement
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
vocab_size: int = 50000,
|
|
embed_dim: int = 768,
|
|
num_layers: int = 12,
|
|
num_heads: int = 12,
|
|
ff_dim: int = 3072,
|
|
max_len: int = 2048,
|
|
device: Optional[torch.device] = None,
|
|
enable_evolution: bool = True
|
|
):
|
|
super().__init__()
|
|
|
|
self.vocab_size = vocab_size
|
|
self.embed_dim = embed_dim
|
|
self.device = device or torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
self.enable_evolution = enable_evolution
|
|
|
|
# Core transformer for language generation
|
|
self.transformer = LyraTransformer(
|
|
vocab_size=vocab_size,
|
|
embed_dim=embed_dim,
|
|
num_layers=num_layers,
|
|
num_heads=num_heads,
|
|
ff_dim=ff_dim,
|
|
max_len=max_len,
|
|
use_evolution=enable_evolution
|
|
)
|
|
|
|
# Personality system
|
|
self.personality_matrix = PersonalityMatrix(
|
|
device=self.device,
|
|
enable_self_modification=True
|
|
)
|
|
|
|
# Emotional intelligence
|
|
self.emotional_system = EmotionalSystem(
|
|
input_dim=embed_dim,
|
|
emotion_dim=19,
|
|
memory_capacity=1000,
|
|
device=self.device
|
|
)
|
|
|
|
# Thinking agent for internal reasoning
|
|
self.thinking_agent = ThinkingAgent(
|
|
model_dim=embed_dim,
|
|
thought_types=8,
|
|
max_thought_depth=5,
|
|
device=self.device
|
|
)
|
|
|
|
# Self-evolution engine
|
|
if enable_evolution:
|
|
self.evolution_engine = SelfEvolutionEngine(
|
|
model_dim=embed_dim,
|
|
evolution_rate=0.001,
|
|
adaptation_threshold=0.7,
|
|
device=self.device
|
|
)
|
|
else:
|
|
self.evolution_engine = None
|
|
|
|
# Emotional expression engine
|
|
self.expression_engine = EmotionalExpressionEngine(
|
|
vocab_size=vocab_size,
|
|
expression_dim=128,
|
|
device=self.device
|
|
)
|
|
|
|
# Integration layers
|
|
self.context_integrator = nn.Sequential(
|
|
nn.Linear(embed_dim + 19 + 24, embed_dim), # context + emotions + personality
|
|
nn.LayerNorm(embed_dim),
|
|
nn.ReLU(),
|
|
nn.Linear(embed_dim, embed_dim)
|
|
)
|
|
|
|
# Conversation state
|
|
self.conversation_history = []
|
|
self.current_user_id = None
|
|
self.interaction_count = 0
|
|
|
|
self.to(self.device)
|
|
|
|
def forward(
|
|
self,
|
|
input_ids: torch.Tensor,
|
|
attention_mask: Optional[torch.Tensor] = None,
|
|
user_id: Optional[str] = None,
|
|
conversation_context: Optional[str] = None
|
|
) -> Tuple[torch.Tensor, Dict[str, Any]]:
|
|
"""
|
|
Forward pass through complete Lyra model.
|
|
|
|
Args:
|
|
input_ids: Input token IDs
|
|
attention_mask: Attention mask
|
|
user_id: Current user ID for personalization
|
|
conversation_context: Context description
|
|
|
|
Returns:
|
|
output_logits: Language model logits
|
|
lyra_info: Comprehensive information about Lyra's processing
|
|
"""
|
|
batch_size, seq_len = input_ids.shape
|
|
|
|
# Create context embedding from input
|
|
with torch.no_grad():
|
|
# Get initial embeddings
|
|
input_embeddings = self.transformer.token_embedding(input_ids)
|
|
context_embedding = input_embeddings.mean(dim=1, keepdim=True) # [batch, 1, embed_dim]
|
|
|
|
# Update current user
|
|
self.current_user_id = user_id
|
|
|
|
# Process through emotional system
|
|
emotional_state, emotion_info = self.emotional_system(
|
|
context_embedding=context_embedding,
|
|
social_context={
|
|
'user_id': user_id,
|
|
'context': conversation_context,
|
|
'interaction_count': self.interaction_count
|
|
}
|
|
)
|
|
|
|
# Process through personality matrix
|
|
personality_weights, personality_info = self.personality_matrix(
|
|
context_embedding=context_embedding,
|
|
emotional_state=emotional_state.to_tensor(self.device).unsqueeze(0),
|
|
user_id=user_id
|
|
)
|
|
|
|
# Generate internal thoughts
|
|
if conversation_context:
|
|
thought_chain, thinking_info = self.thinking_agent(
|
|
context_embedding=context_embedding,
|
|
personality_state=personality_weights,
|
|
emotional_state=emotional_state.to_tensor(self.device).unsqueeze(0),
|
|
user_message=conversation_context
|
|
)
|
|
else:
|
|
thought_chain, thinking_info = [], {}
|
|
|
|
# Integrate all contexts
|
|
integrated_context = self._integrate_contexts(
|
|
context_embedding, emotional_state, personality_weights
|
|
)
|
|
|
|
# Apply self-evolution if enabled
|
|
if self.enable_evolution and self.evolution_engine:
|
|
evolved_context, evolution_info = self.evolution_engine(
|
|
current_state=integrated_context,
|
|
context=context_embedding,
|
|
feedback_signal=None # Will be provided after generation
|
|
)
|
|
else:
|
|
evolved_context = integrated_context
|
|
evolution_info = {}
|
|
|
|
# Generate response through transformer
|
|
logits, model_info = self.transformer(
|
|
input_ids=input_ids,
|
|
attention_mask=attention_mask,
|
|
emotional_state=emotional_state.to_tensor(self.device).unsqueeze(0),
|
|
evolve=self.enable_evolution
|
|
)
|
|
|
|
# Compile comprehensive information
|
|
lyra_info = {
|
|
'emotional_state': emotion_info,
|
|
'personality_state': personality_info,
|
|
'thinking_process': thinking_info,
|
|
'model_processing': model_info,
|
|
'thought_chain': [
|
|
{
|
|
'type': thought.thought_type,
|
|
'content': thought.content,
|
|
'confidence': thought.confidence,
|
|
'reasoning': thought.reasoning
|
|
}
|
|
for thought in thought_chain
|
|
],
|
|
'interaction_count': self.interaction_count,
|
|
'current_user': user_id
|
|
}
|
|
|
|
if self.enable_evolution:
|
|
lyra_info['evolution'] = evolution_info
|
|
|
|
self.interaction_count += 1
|
|
|
|
return logits, lyra_info
|
|
|
|
def _integrate_contexts(
|
|
self,
|
|
context_embedding: torch.Tensor,
|
|
emotional_state: Any,
|
|
personality_weights: torch.Tensor
|
|
) -> torch.Tensor:
|
|
"""Integrate context, emotional, and personality information."""
|
|
batch_size = context_embedding.shape[0]
|
|
|
|
# Get emotional tensor
|
|
emotional_tensor = emotional_state.to_tensor(self.device).unsqueeze(0)
|
|
if emotional_tensor.shape[0] != batch_size:
|
|
emotional_tensor = emotional_tensor.repeat(batch_size, 1)
|
|
|
|
# Ensure personality weights have correct batch size
|
|
if personality_weights.shape[0] != batch_size:
|
|
personality_weights = personality_weights.repeat(batch_size, 1)
|
|
|
|
# Combine all contexts
|
|
combined_input = torch.cat([
|
|
context_embedding.squeeze(1), # Remove sequence dimension
|
|
emotional_tensor[:, :19], # Take only emotion dimensions
|
|
personality_weights[:, :24] # Take personality dimensions
|
|
], dim=1)
|
|
|
|
# Integrate through neural network
|
|
integrated = self.context_integrator(combined_input)
|
|
|
|
return integrated.unsqueeze(1) # Add sequence dimension back
|
|
|
|
async def generate_response(
|
|
self,
|
|
user_message: str,
|
|
user_id: Optional[str] = None,
|
|
max_new_tokens: int = 100,
|
|
temperature: float = 1.0,
|
|
top_k: int = 50,
|
|
top_p: float = 0.9
|
|
) -> Tuple[str, Dict[str, Any]]:
|
|
"""
|
|
Generate a complete response to user input.
|
|
|
|
This is the main interface for having conversations with Lyra.
|
|
"""
|
|
# For now, create a simple response (will be enhanced with tokenizer)
|
|
# This is a placeholder until we implement the full training pipeline
|
|
|
|
# Process through thinking and emotional systems
|
|
context_embedding = torch.randn(1, 10, self.embed_dim, device=self.device)
|
|
|
|
# Get Lyra's thoughts about the message
|
|
thought_chain, thinking_info = self.thinking_agent(
|
|
context_embedding=context_embedding,
|
|
personality_state=torch.rand(1, 24, device=self.device),
|
|
emotional_state=torch.rand(1, 19, device=self.device),
|
|
user_message=user_message
|
|
)
|
|
|
|
# Process emotional response
|
|
emotional_state, emotion_info = self.emotional_system(
|
|
context_embedding=context_embedding,
|
|
social_context={
|
|
'user_id': user_id,
|
|
'context': user_message,
|
|
'trigger': 'user_message'
|
|
}
|
|
)
|
|
|
|
# Generate personality-influenced response
|
|
personality_weights, personality_info = self.personality_matrix(
|
|
context_embedding=context_embedding,
|
|
emotional_state=emotional_state.to_tensor(self.device).unsqueeze(0),
|
|
user_id=user_id
|
|
)
|
|
|
|
# Create a response based on current emotional and personality state
|
|
base_response = self._generate_contextual_response(
|
|
user_message, emotional_state, personality_info, thought_chain
|
|
)
|
|
|
|
# Apply emotional expression
|
|
expressed_response, expression_info = self.expression_engine(
|
|
text=base_response,
|
|
emotional_state=emotional_state,
|
|
intensity_multiplier=1.0
|
|
)
|
|
|
|
# Compile response information
|
|
response_info = {
|
|
'thoughts': [
|
|
{
|
|
'type': thought.thought_type,
|
|
'content': thought.content,
|
|
'confidence': thought.confidence
|
|
}
|
|
for thought in thought_chain
|
|
],
|
|
'emotional_state': {
|
|
'dominant_emotion': emotional_state.get_dominant_emotion(),
|
|
'valence': emotional_state.get_emotional_valence(),
|
|
'arousal': emotional_state.get_emotional_arousal()
|
|
},
|
|
'personality_influence': personality_info,
|
|
'expression_modifications': expression_info,
|
|
'response_generation_method': 'contextual_template' # Will change after training
|
|
}
|
|
|
|
return expressed_response, response_info
|
|
|
|
def _generate_contextual_response(
|
|
self,
|
|
user_message: str,
|
|
emotional_state: Any,
|
|
personality_info: Dict[str, Any],
|
|
thought_chain: List[Any]
|
|
) -> str:
|
|
"""Generate contextual response based on Lyra's current state."""
|
|
# This is a simplified response generation for testing
|
|
# Will be replaced with proper transformer generation after training
|
|
|
|
dominant_emotion, intensity = emotional_state.get_dominant_emotion()
|
|
mb_type = personality_info.get('myers_briggs', 'ENFP')
|
|
|
|
# Basic response templates based on emotional state and personality
|
|
responses = {
|
|
'joy': [
|
|
"That's wonderful! I'm really excited about this.",
|
|
"This makes me so happy! Tell me more!",
|
|
"I love hearing about this kind of thing!"
|
|
],
|
|
'curiosity': [
|
|
"That's really interesting! I'm curious to learn more.",
|
|
"Fascinating! How does that work exactly?",
|
|
"I wonder about the implications of this..."
|
|
],
|
|
'empathy': [
|
|
"I can understand how you might feel about that.",
|
|
"That sounds like it could be challenging.",
|
|
"I appreciate you sharing this with me."
|
|
],
|
|
'analytical': [
|
|
"Let me think about this systematically.",
|
|
"There are several factors to consider here.",
|
|
"From an analytical perspective..."
|
|
]
|
|
}
|
|
|
|
# Select response based on thinking and emotional state
|
|
if thought_chain and len(thought_chain) > 0:
|
|
primary_thought_type = thought_chain[0].thought_type
|
|
if primary_thought_type in responses:
|
|
response_options = responses[primary_thought_type]
|
|
else:
|
|
response_options = responses.get(dominant_emotion, responses['empathy'])
|
|
else:
|
|
response_options = responses.get(dominant_emotion, responses['empathy'])
|
|
|
|
import random
|
|
base_response = random.choice(response_options)
|
|
|
|
return base_response
|
|
|
|
def evolve_from_feedback(
|
|
self,
|
|
user_feedback: float,
|
|
conversation_success: float,
|
|
user_id: Optional[str] = None
|
|
):
|
|
"""Update Lyra based on conversation feedback."""
|
|
if not self.enable_evolution:
|
|
return
|
|
|
|
# Evolve personality
|
|
self.personality_matrix.evolve_from_interaction(
|
|
interaction_type='conversation',
|
|
user_feedback=user_feedback,
|
|
emotional_context=self.emotional_system.get_emotional_context_for_response(),
|
|
user_id=user_id,
|
|
conversation_success=conversation_success
|
|
)
|
|
|
|
# Evolve transformer
|
|
self.transformer.evolve_from_conversation(feedback_signal=user_feedback)
|
|
|
|
# Evolve emotional system (implicit through usage)
|
|
|
|
# Evolve self-evolution engine
|
|
if self.evolution_engine:
|
|
context_embedding = torch.randn(10, self.embed_dim, device=self.device)
|
|
emotional_context = self.emotional_system.get_emotional_context_for_response()
|
|
self.evolution_engine.evolve_from_conversation(
|
|
conversation_embedding=context_embedding,
|
|
user_satisfaction=user_feedback,
|
|
emotional_context=emotional_context
|
|
)
|
|
|
|
def get_lyra_status(self) -> Dict[str, Any]:
|
|
"""Get comprehensive status of all Lyra systems."""
|
|
return {
|
|
'model_info': {
|
|
'vocab_size': self.vocab_size,
|
|
'embed_dim': self.embed_dim,
|
|
'device': str(self.device),
|
|
'evolution_enabled': self.enable_evolution,
|
|
'interaction_count': self.interaction_count
|
|
},
|
|
'personality': self.personality_matrix.get_personality_summary(),
|
|
'emotions': self.emotional_system.get_emotional_summary(),
|
|
'thinking': self.thinking_agent.get_thinking_summary(),
|
|
'transformer_stats': self.transformer.get_model_stats(),
|
|
'evolution': (
|
|
self.evolution_engine.get_evolution_summary()
|
|
if self.evolution_engine else {'status': 'disabled'}
|
|
)
|
|
} |