feat: Add database setup guide and local configuration files
- 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
This commit is contained in:
443
lyra/core/lyra_model.py
Normal file
443
lyra/core/lyra_model.py
Normal file
@@ -0,0 +1,443 @@
|
||||
"""
|
||||
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'}
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user