UNPKG

universal-ai-brain

Version:

🧠 UNIVERSAL AI BRAIN 3.3 - The world's most advanced cognitive architecture with 24 specialized systems, MongoDB 8.1 $rankFusion hybrid search, latest Voyage 3.5 embeddings, and framework-agnostic design. Works with Mastra, Vercel AI, LangChain, OpenAI A

681 lines (597 loc) 21 kB
/** * @file EmotionalIntelligenceEngine - Advanced emotional intelligence for AI agents * * This engine provides comprehensive emotional intelligence capabilities using MongoDB * time-series collections with TTL indexes for automatic emotional decay. Demonstrates * MongoDB's advanced capabilities for cognitive data management. * * Features: * - Real-time emotion detection and tracking * - Automatic emotional decay with TTL indexes * - Emotional pattern analysis and learning * - Context-aware emotional responses * - Emotional memory and state transitions * - Cognitive impact assessment */ import { Db } from 'mongodb'; import { EmotionalStateCollection, EmotionalState } from '../collections/EmotionalStateCollection'; export interface EmotionDetectionResult { primary: string; secondary?: string[]; intensity: number; valence: number; arousal: number; dominance: number; confidence: number; reasoning: string; } export interface EmotionalContext { agentId: string; sessionId?: string; input: string; conversationHistory?: Array<{ role: string; content: string }>; taskContext?: { taskId?: string; workflowId?: string; taskType?: string; progress?: number; }; userContext?: { mood?: string; urgency?: number; satisfaction?: number; }; } export interface EmotionalResponse { currentEmotion: EmotionalState; emotionalGuidance: { responseStyle: string; toneAdjustment: string; empathyLevel: number; assertivenessLevel: number; supportLevel: number; }; cognitiveImpact: { attentionFocus: string[]; memoryPriority: number; decisionBias: string; riskTolerance: number; }; recommendations: string[]; } export interface EmotionalLearning { patterns: Array<{ trigger: string; emotionalResponse: string; effectiveness: number; frequency: number; }>; improvements: Array<{ area: string; suggestion: string; priority: number; }>; calibration: { accuracy: number; bias: number; consistency: number; }; } /** * EmotionalIntelligenceEngine - Advanced emotional intelligence for AI agents * * This engine showcases MongoDB's time-series and TTL capabilities for emotional data: * - Time-series collections for emotional state tracking * - TTL indexes for automatic emotional decay * - Complex aggregation pipelines for emotional analytics * - Real-time emotional pattern recognition * - Emotional memory and learning systems */ export class EmotionalIntelligenceEngine { private db: Db; private emotionalStateCollection: EmotionalStateCollection; private isInitialized: boolean = false; // Emotional intelligence configuration private config = { decaySettings: { defaultHalfLife: 30, // minutes defaultBaselineReturn: 60, // minutes decayFunction: 'exponential' as const }, detectionThresholds: { minConfidence: 0.6, intensityThreshold: 0.1, valenceThreshold: 0.05 }, cognitiveImpact: { attentionWeight: 0.3, memoryWeight: 0.4, decisionWeight: 0.3 } }; constructor(db: Db) { this.db = db; this.emotionalStateCollection = new EmotionalStateCollection(db); } /** * Initialize the emotional intelligence engine */ async initialize(): Promise<void> { if (this.isInitialized) { return; } try { // Create collection indexes await this.emotionalStateCollection.createIndexes(); this.isInitialized = true; console.log('🎭 EmotionalIntelligenceEngine initialized successfully'); } catch (error) { console.error('❌ Failed to initialize EmotionalIntelligenceEngine:', error); throw error; } } /** * Detect emotions from input text and context */ async detectEmotion(context: EmotionalContext): Promise<EmotionDetectionResult> { if (!this.isInitialized) { throw new Error('EmotionalIntelligenceEngine must be initialized first'); } // Get current emotional state for context const currentState = await this.emotionalStateCollection.getCurrentEmotionalState( context.agentId, context.sessionId ); // Analyze input for emotional content const emotionAnalysis = await this.analyzeEmotionalContent( context.input, context.conversationHistory, currentState ); // Consider task and user context const contextualAdjustment = this.adjustForContext( emotionAnalysis, context.taskContext, context.userContext ); return { ...contextualAdjustment, confidence: Math.min(emotionAnalysis.confidence * 0.9, 1.0), // Slight confidence reduction for realism reasoning: this.generateEmotionalReasoning(emotionAnalysis, context) }; } /** * Process emotional state and provide intelligent response guidance */ async processEmotionalState( context: EmotionalContext, detectedEmotion: EmotionDetectionResult, trigger: string, triggerType: 'user_input' | 'task_completion' | 'error' | 'success' | 'interaction' | 'system_event' ): Promise<EmotionalResponse> { // Create emotional state record const emotionalState: Omit<EmotionalState, '_id' | 'createdAt' | 'updatedAt'> = { agentId: context.agentId, sessionId: context.sessionId, timestamp: new Date(), emotions: { primary: detectedEmotion.primary, secondary: detectedEmotion.secondary, intensity: detectedEmotion.intensity, valence: detectedEmotion.valence, arousal: detectedEmotion.arousal, dominance: detectedEmotion.dominance }, context: { trigger, triggerType, conversationTurn: context.conversationHistory?.length || 0, taskId: context.taskContext?.taskId, workflowId: context.taskContext?.workflowId }, cognitiveEffects: this.calculateCognitiveEffects(detectedEmotion), decay: { halfLife: this.config.decaySettings.defaultHalfLife, decayFunction: this.config.decaySettings.decayFunction, baselineReturn: this.config.decaySettings.defaultBaselineReturn }, metadata: { framework: 'universal-ai-brain', model: 'emotional-intelligence-v1', confidence: detectedEmotion.confidence, source: 'detected', version: '1.0.0' } }; // Store emotional state await this.emotionalStateCollection.recordEmotionalState(emotionalState); // Generate response guidance const emotionalGuidance = this.generateEmotionalGuidance(detectedEmotion); const cognitiveImpact = this.assessCognitiveImpact(detectedEmotion); const recommendations = await this.generateRecommendations(context, detectedEmotion); return { currentEmotion: { ...emotionalState, _id: undefined } as EmotionalState, emotionalGuidance, cognitiveImpact, recommendations }; } /** * Analyze emotional patterns and provide learning insights */ async analyzeEmotionalLearning(agentId: string, days: number = 7): Promise<EmotionalLearning> { const patterns = await this.emotionalStateCollection.analyzeEmotionalPatterns(agentId, days); // Extract learning patterns const learningPatterns = patterns.triggerAnalysis.map(trigger => ({ trigger: trigger.trigger, emotionalResponse: this.interpretValence(trigger.avgValence), effectiveness: Math.abs(trigger.avgValence), // Higher absolute valence = more effective frequency: trigger.frequency })); // Generate improvement suggestions const improvements = this.generateImprovementSuggestions(patterns); // Calculate calibration metrics const calibration = await this.calculateEmotionalCalibration(agentId, days); return { patterns: learningPatterns, improvements, calibration }; } /** * Get emotional timeline for visualization */ async getEmotionalTimeline(agentId: string, sessionId?: string, hours: number = 24): Promise<{ timeline: Array<{ timestamp: Date; emotion: string; intensity: number; valence: number; trigger: string; }>; summary: { dominantEmotion: string; avgIntensity: number; avgValence: number; emotionalStability: number; }; }> { const startTime = new Date(Date.now() - (hours * 60 * 60 * 1000)); const timeline = await this.emotionalStateCollection.getEmotionalTimeline(agentId, { timeRange: { start: startTime, end: new Date() }, includeDecayed: false }); const timelineData = timeline.map(state => ({ timestamp: state.timestamp, emotion: state.emotions.primary, intensity: state.emotions.intensity, valence: state.emotions.valence, trigger: state.context.trigger })); // Calculate summary statistics const summary = this.calculateTimelineSummary(timeline); return { timeline: timelineData, summary }; } /** * Analyze emotional content using pattern matching and heuristics */ private async analyzeEmotionalContent( input: string, conversationHistory?: Array<{ role: string; content: string }>, currentState?: EmotionalState | null ): Promise<EmotionDetectionResult> { // Emotional keyword patterns const emotionalPatterns = { joy: ['happy', 'excited', 'great', 'wonderful', 'amazing', 'fantastic', 'love', 'perfect'], sadness: ['sad', 'disappointed', 'upset', 'down', 'depressed', 'unhappy', 'terrible'], anger: ['angry', 'mad', 'furious', 'annoyed', 'frustrated', 'irritated', 'outraged'], fear: ['scared', 'afraid', 'worried', 'anxious', 'nervous', 'concerned', 'panic'], surprise: ['surprised', 'shocked', 'amazed', 'unexpected', 'wow', 'incredible'], disgust: ['disgusted', 'awful', 'horrible', 'gross', 'terrible', 'hate'], trust: ['trust', 'confident', 'reliable', 'sure', 'certain', 'believe'], anticipation: ['excited', 'looking forward', 'can\'t wait', 'eager', 'hopeful'] }; const inputLower = input.toLowerCase(); const emotionScores: Record<string, number> = {}; // Calculate emotion scores based on keyword matching for (const [emotion, keywords] of Object.entries(emotionalPatterns)) { emotionScores[emotion] = keywords.reduce((score, keyword) => { const matches = (inputLower.match(new RegExp(keyword, 'g')) || []).length; return score + matches; }, 0); } // Find primary emotion const primaryEmotion = Object.entries(emotionScores) .sort(([,a], [,b]) => b - a)[0]; const primary = primaryEmotion[1] === 0 ? 'neutral' : primaryEmotion[0]; const intensity = primaryEmotion[1] === 0 ? 0.1 : Math.min(primaryEmotion[1] * 0.3, 1.0); // Calculate valence based on emotion type const valenceMap: Record<string, number> = { joy: 0.8, sadness: -0.7, anger: -0.6, fear: -0.5, surprise: 0.2, disgust: -0.8, trust: 0.6, anticipation: 0.4, neutral: 0.0 }; const valence = valenceMap[primary] || 0; // Calculate arousal (how activating the emotion is) const arousalMap: Record<string, number> = { joy: 0.7, sadness: 0.3, anger: 0.9, fear: 0.8, surprise: 0.9, disgust: 0.6, trust: 0.4, anticipation: 0.6, neutral: 0.3 }; const arousal = arousalMap[primary] || 0.5; // Calculate dominance (how much control the emotion implies) const dominanceMap: Record<string, number> = { joy: 0.6, sadness: 0.2, anger: 0.8, fear: 0.1, surprise: 0.3, disgust: 0.4, trust: 0.7, anticipation: 0.5, neutral: 0.5 }; const dominance = dominanceMap[primary] || 0.5; // Determine secondary emotions const secondary = Object.entries(emotionScores) .filter(([emotion, score]) => emotion !== primary && score > 0) .sort(([,a], [,b]) => b - a) .slice(0, 2) .map(([emotion]) => emotion); return { primary, secondary: secondary.length > 0 ? secondary : undefined, intensity, valence, arousal, dominance, confidence: Math.min(0.7 + (intensity * 0.3), 1.0), reasoning: `Detected ${primary} emotion based on keyword analysis with intensity ${intensity.toFixed(2)}` }; } /** * Adjust emotion detection based on context */ private adjustForContext( emotion: EmotionDetectionResult, taskContext?: EmotionalContext['taskContext'], userContext?: EmotionalContext['userContext'] ): EmotionDetectionResult { let adjustedIntensity = emotion.intensity; let adjustedValence = emotion.valence; // Task context adjustments if (taskContext) { if (taskContext.taskType === 'error_handling') { adjustedValence = Math.min(adjustedValence - 0.2, 1.0); adjustedIntensity = Math.min(adjustedIntensity + 0.1, 1.0); } if (taskContext.progress && taskContext.progress > 0.8) { adjustedValence = Math.min(adjustedValence + 0.1, 1.0); } } // User context adjustments if (userContext) { if (userContext.urgency && userContext.urgency > 0.7) { adjustedIntensity = Math.min(adjustedIntensity + 0.2, 1.0); } if (userContext.satisfaction && userContext.satisfaction < 0.3) { adjustedValence = Math.min(adjustedValence - 0.3, 1.0); } } return { ...emotion, intensity: adjustedIntensity, valence: adjustedValence }; } /** * Calculate cognitive effects of emotional state */ private calculateCognitiveEffects(emotion: EmotionDetectionResult) { // Attention modification based on arousal and valence const attentionModification = (emotion.arousal - 0.5) * emotion.intensity; // Memory strength based on intensity and arousal const memoryStrength = Math.min((emotion.intensity + emotion.arousal) / 2, 1.0); // Decision bias based on valence and dominance const decisionBias = emotion.valence * emotion.dominance * emotion.intensity; // Response style based on emotional dimensions let responseStyle: 'analytical' | 'empathetic' | 'assertive' | 'cautious' | 'creative'; if (emotion.dominance > 0.6 && emotion.valence > 0) { responseStyle = 'assertive'; } else if (emotion.valence > 0.3 && emotion.arousal < 0.5) { responseStyle = 'empathetic'; } else if (emotion.arousal > 0.7) { responseStyle = 'creative'; } else if (emotion.valence < -0.3) { responseStyle = 'cautious'; } else { responseStyle = 'analytical'; } return { attentionModification, memoryStrength, decisionBias, responseStyle }; } /** * Generate emotional guidance for response style */ private generateEmotionalGuidance(emotion: EmotionDetectionResult) { const guidance = { responseStyle: emotion.dominance > 0.6 ? 'confident' : 'supportive', toneAdjustment: emotion.valence > 0 ? 'positive' : 'understanding', empathyLevel: Math.max(0.3, 1 - emotion.dominance), assertivenessLevel: emotion.dominance * emotion.intensity, supportLevel: emotion.valence < 0 ? 0.8 : 0.5 }; return guidance; } /** * Assess cognitive impact of emotional state */ private assessCognitiveImpact(emotion: EmotionDetectionResult) { const attentionFocus = []; if (emotion.arousal > 0.7) { attentionFocus.push('immediate_response', 'user_satisfaction'); } if (emotion.valence < -0.5) { attentionFocus.push('problem_solving', 'error_prevention'); } if (emotion.intensity > 0.8) { attentionFocus.push('emotional_regulation', 'response_quality'); } return { attentionFocus, memoryPriority: emotion.intensity * emotion.arousal, decisionBias: emotion.valence > 0 ? 'optimistic' : 'cautious', riskTolerance: emotion.dominance * (1 - Math.abs(emotion.valence)) }; } /** * Generate recommendations based on emotional state */ private async generateRecommendations( context: EmotionalContext, emotion: EmotionDetectionResult ): Promise<string[]> { const recommendations = []; if (emotion.intensity > 0.8) { recommendations.push('Consider emotional regulation techniques'); } if (emotion.valence < -0.5) { recommendations.push('Focus on problem resolution and user support'); } if (emotion.arousal > 0.7) { recommendations.push('Maintain calm and measured responses'); } if (emotion.dominance < 0.3) { recommendations.push('Provide reassurance and build confidence'); } return recommendations; } /** * Generate emotional reasoning explanation */ private generateEmotionalReasoning( emotion: EmotionDetectionResult, context: EmotionalContext ): string { return `Detected ${emotion.primary} emotion (intensity: ${emotion.intensity.toFixed(2)}, ` + `valence: ${emotion.valence.toFixed(2)}) based on input analysis and contextual factors. ` + `This suggests a ${emotion.valence > 0 ? 'positive' : 'negative'} emotional state with ` + `${emotion.arousal > 0.5 ? 'high' : 'low'} activation level.`; } /** * Interpret valence score as emotional category */ private interpretValence(valence: number): string { if (valence > 0.3) return 'positive'; if (valence < -0.3) return 'negative'; return 'neutral'; } /** * Generate improvement suggestions based on emotional patterns */ private generateImprovementSuggestions(patterns: any): Array<{ area: string; suggestion: string; priority: number; }> { const improvements = []; if (patterns.emotionalStability < 0.5) { improvements.push({ area: 'emotional_stability', suggestion: 'Implement emotional regulation techniques to improve stability', priority: 1 }); } const negativePatterns = patterns.triggerAnalysis.filter((t: any) => t.avgValence < -0.3); if (negativePatterns.length > patterns.triggerAnalysis.length * 0.6) { improvements.push({ area: 'negative_triggers', suggestion: 'Focus on positive reframing and solution-oriented responses', priority: 2 }); } return improvements; } /** * Calculate emotional calibration metrics */ private async calculateEmotionalCalibration(agentId: string, days: number): Promise<{ accuracy: number; bias: number; consistency: number; }> { // This would typically involve comparing predicted vs actual emotional outcomes // For now, return simulated metrics return { accuracy: 0.75, bias: 0.1, consistency: 0.8 }; } /** * Calculate timeline summary statistics */ private calculateTimelineSummary(timeline: EmotionalState[]) { if (timeline.length === 0) { return { dominantEmotion: 'neutral', avgIntensity: 0, avgValence: 0, emotionalStability: 1 }; } const emotionCounts: Record<string, number> = {}; let totalIntensity = 0; let totalValence = 0; const valences = []; for (const state of timeline) { emotionCounts[state.emotions.primary] = (emotionCounts[state.emotions.primary] || 0) + 1; totalIntensity += state.emotions.intensity; totalValence += state.emotions.valence; valences.push(state.emotions.valence); } const dominantEmotion = Object.entries(emotionCounts) .sort(([,a], [,b]) => b - a)[0][0]; const avgIntensity = totalIntensity / timeline.length; const avgValence = totalValence / timeline.length; // Calculate emotional stability (inverse of valence variance) const valenceVariance = valences.reduce((sum, v) => sum + Math.pow(v - avgValence, 2), 0) / valences.length; const emotionalStability = Math.max(0, 1 - (valenceVariance / 2)); // Normalize to 0-1 return { dominantEmotion, avgIntensity, avgValence, emotionalStability }; } /** * Get emotional intelligence statistics */ async getEmotionalStats(agentId?: string): Promise<{ totalStates: number; activeStates: number; avgIntensity: number; avgValence: number; dominantEmotions: Array<{ emotion: string; frequency: number }>; }> { const stats = await this.emotionalStateCollection.getEmotionalStats(agentId); // Get dominant emotions (this would need additional aggregation) const dominantEmotions = [ { emotion: 'neutral', frequency: 0.4 }, { emotion: 'joy', frequency: 0.3 }, { emotion: 'concern', frequency: 0.2 }, { emotion: 'satisfaction', frequency: 0.1 } ]; return { ...stats, dominantEmotions }; } /** * Cleanup expired emotional states */ async cleanup(): Promise<number> { return await this.emotionalStateCollection.cleanupExpiredStates(); } }