Skip to main content
Glama
claudia_learning_plugin.py23.2 kB
#!/usr/bin/env python3 """ Claudia Voice Assistant Learning Integration Plugin Provides learning capabilities to enhance Claudia's voice interactions """ import asyncio import json import logging from typing import Dict, List, Optional, Any, Callable from datetime import datetime import sys import os # Add the parent directory to the path to import the client library sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'lib')) from self_learning_client import SelfLearningClient, ClaudiaLearningIntegration class ClaudiaLearningPlugin: """ Learning plugin for Claudia Voice Assistant This plugin integrates with the MCP Self-Learning Server to: - Learn from voice interactions - Improve intent recognition - Optimize response generation - Predict user needs """ def __init__(self, claudia_instance, config: Dict[str, Any] = None): self.claudia = claudia_instance self.config = config or {} self.logger = logging.getLogger(__name__) # Initialize learning integration mcp_url = self.config.get('mcp_server_url', 'http://localhost:8765') self.learning_integration = ClaudiaLearningIntegration(mcp_url) # Learning settings self.learning_enabled = self.config.get('learning_enabled', True) self.auto_optimize = self.config.get('auto_optimize', True) self.prediction_enabled = self.config.get('prediction_enabled', True) # Statistics tracking self.stats = { 'interactions_learned': 0, 'predictions_made': 0, 'optimizations_applied': 0, 'session_start': datetime.now() } # Current session tracking self.current_session = None self.session_interactions = [] self.is_initialized = False async def initialize(self): """Initialize the learning plugin""" if self.is_initialized: return try: await self.learning_integration.start() self.is_initialized = True self.logger.info("Claudia learning plugin initialized successfully") # Start periodic optimization if enabled if self.auto_optimize: asyncio.create_task(self._periodic_optimization()) except Exception as e: self.logger.error(f"Failed to initialize learning plugin: {e}") raise async def shutdown(self): """Shutdown the learning plugin""" try: # Learn from current session if active if self.current_session and self.session_interactions: await self._finalize_session() await self.learning_integration.stop() self.is_initialized = False self.logger.info("Claudia learning plugin shutdown complete") except Exception as e: self.logger.error(f"Error during learning plugin shutdown: {e}") def start_session(self, session_id: str = None) -> str: """Start a new learning session""" if not session_id: session_id = f"claudia-{datetime.now().strftime('%Y%m%d-%H%M%S')}" self.current_session = session_id self.session_interactions = [] self.logger.debug(f"Started learning session: {session_id}") return session_id async def end_session(self, session_success: bool = True, user_satisfaction: float = None): """End the current learning session""" if not self.current_session: return try: # Analyze the complete session if self.session_interactions: await self._analyze_session(session_success, user_satisfaction) await self._finalize_session() except Exception as e: self.logger.error(f"Error ending learning session: {e}") finally: self.current_session = None self.session_interactions = [] async def learn_from_interaction(self, user_input: str, assistant_response: str, intent: str, confidence: float, success: bool = True, metadata: Dict[str, Any] = None) -> Dict[str, Any]: """ Learn from a voice interaction Args: user_input: What the user said assistant_response: How Claudia responded intent: Detected intent confidence: Confidence in intent detection success: Whether the interaction was successful metadata: Additional interaction metadata Returns: Learning results and recommendations """ if not self.learning_enabled or not self.is_initialized: return {'learned': False, 'reason': 'Learning disabled or not initialized'} try: # Learn from the interaction result = await self.learning_integration.log_voice_command( user_input, assistant_response, intent, confidence, success ) # Track the interaction in current session if self.current_session: interaction_data = { 'user_input': user_input, 'assistant_response': assistant_response, 'intent': intent, 'confidence': confidence, 'success': success, 'timestamp': datetime.now().isoformat(), 'metadata': metadata or {} } self.session_interactions.append(interaction_data) self.stats['interactions_learned'] += 1 # Get immediate insights if this was a significant interaction if confidence < 0.5 or not success: insights = await self.get_learning_insights() result['insights'] = insights return result except Exception as e: self.logger.error(f"Failed to learn from interaction: {e}") return {'learned': False, 'error': str(e)} async def predict_user_intent(self, partial_input: str, context: Dict[str, Any] = None) -> Dict[str, Any]: """ Predict user intent from partial input Args: partial_input: Partial user input (e.g., from ongoing speech recognition) context: Current conversation context Returns: Predicted intent and confidence """ if not self.prediction_enabled or not self.is_initialized: return {'predictions': [], 'confidence': 0.0} try: result = await self.learning_integration.predict_user_intent(partial_input) self.stats['predictions_made'] += 1 # Format predictions for Claudia formatted_predictions = self._format_predictions_for_claudia(result) return formatted_predictions except Exception as e: self.logger.error(f"Failed to predict user intent: {e}") return {'predictions': [], 'confidence': 0.0, 'error': str(e)} async def get_voice_optimizations(self) -> Dict[str, Any]: """Get optimization suggestions for voice interactions""" if not self.is_initialized: return {'optimizations': [], 'recommendations': []} try: result = await self.learning_integration.get_voice_optimizations() # Format optimizations for Claudia formatted_optimizations = self._format_optimizations_for_claudia(result) return formatted_optimizations except Exception as e: self.logger.error(f"Failed to get voice optimizations: {e}") return {'optimizations': [], 'recommendations': [], 'error': str(e)} async def get_learning_insights(self) -> Dict[str, Any]: """Get learning insights and statistics""" if not self.is_initialized: return {'insights': {}, 'stats': self.stats} try: # Get insights from the learning server status = await self.learning_integration.client.get_status() insights = await self.learning_integration.client.get_insights() # Combine with local stats combined_insights = { 'server_status': { 'running': status.running, 'learning_active': status.learning_status.value, 'patterns': status.patterns_count, 'knowledge': status.knowledge_count }, 'learning_insights': { 'top_patterns': insights.top_patterns[:5], # Top 5 patterns 'performance': insights.performance_metrics, 'recommendations': insights.recommendations }, 'plugin_stats': self.stats, 'session_info': { 'current_session': self.current_session, 'session_interactions': len(self.session_interactions) } } return combined_insights except Exception as e: self.logger.error(f"Failed to get learning insights: {e}") return {'insights': {}, 'stats': self.stats, 'error': str(e)} async def improve_intent_recognition(self, training_data: List[Dict[str, Any]]) -> Dict[str, Any]: """ Improve intent recognition using training data Args: training_data: List of training examples with 'input', 'intent', 'confidence' Returns: Training results and improvements """ if not self.learning_enabled or not self.is_initialized: return {'improved': False, 'reason': 'Learning disabled or not initialized'} try: results = [] for example in training_data: # Create interaction for learning interaction = { 'type': 'intent_training', 'input': example['input'], 'output': example['intent'], 'success': True, 'context': { 'confidence': example.get('confidence', 1.0), 'training_mode': True, 'expected_intent': example['intent'] } } result = await self.learning_integration.client.analyze_pattern(interaction) results.append(result) # Trigger learning cycle after batch training await self.learning_integration.client.trigger_learning() return { 'improved': True, 'examples_processed': len(training_data), 'results': results, 'message': 'Intent recognition training completed' } except Exception as e: self.logger.error(f"Failed to improve intent recognition: {e}") return {'improved': False, 'error': str(e)} async def get_conversation_suggestions(self, conversation_history: List[Dict[str, Any]], user_profile: Dict[str, Any] = None) -> Dict[str, Any]: """ Get suggestions for continuing the conversation Args: conversation_history: Recent conversation turns user_profile: Known information about the user Returns: Conversation suggestions and predictions """ if not self.prediction_enabled or not self.is_initialized: return {'suggestions': [], 'confidence': 0.0} try: # Build context from conversation history context = { 'conversation_history': conversation_history[-5:], # Last 5 turns 'user_profile': user_profile or {}, 'conversation_length': len(conversation_history), 'prediction_type': 'conversation_continuation' } # Get predictions predictions = await self.learning_integration.client.predict_next_action(context) # Format as conversation suggestions suggestions = self._format_conversation_suggestions(predictions) return suggestions except Exception as e: self.logger.error(f"Failed to get conversation suggestions: {e}") return {'suggestions': [], 'confidence': 0.0, 'error': str(e)} async def _analyze_session(self, session_success: bool, user_satisfaction: float = None): """Analyze the complete session for learning""" if not self.session_interactions: return try: # Create a session summary interaction session_summary = { 'type': 'claudia_session', 'input': f"Session with {len(self.session_interactions)} interactions", 'output': f"Session {'successful' if session_success else 'unsuccessful'}", 'success': session_success, 'context': { 'session_id': self.current_session, 'total_interactions': len(self.session_interactions), 'user_satisfaction': user_satisfaction, 'average_confidence': sum(i.get('confidence', 0) for i in self.session_interactions) / len(self.session_interactions), 'intents': list(set(i.get('intent') for i in self.session_interactions if i.get('intent'))) }, 'performance': { 'duration': (datetime.now() - self.stats['session_start']).total_seconds() * 1000 } } # Learn from the session await self.learning_integration.client.analyze_pattern(session_summary) self.logger.info(f"Analyzed session {self.current_session} with {len(self.session_interactions)} interactions") except Exception as e: self.logger.error(f"Failed to analyze session: {e}") async def _finalize_session(self): """Finalize the current session""" if self.session_interactions: # Export session data for potential future analysis session_data = { 'session_id': self.current_session, 'interactions': self.session_interactions, 'stats': { 'total_interactions': len(self.session_interactions), 'successful_interactions': sum(1 for i in self.session_interactions if i.get('success', True)), 'average_confidence': sum(i.get('confidence', 0) for i in self.session_interactions) / len(self.session_interactions), 'session_duration': (datetime.now() - self.stats['session_start']).total_seconds() } } self.logger.debug(f"Session {self.current_session} finalized with {len(self.session_interactions)} interactions") async def _periodic_optimization(self): """Periodic optimization task""" while self.is_initialized: try: await asyncio.sleep(300) # Every 5 minutes if self.auto_optimize: optimizations = await self.get_voice_optimizations() # Apply automatic optimizations if available if optimizations.get('optimizations'): auto_applicable = [opt for opt in optimizations['optimizations'] if opt.get('auto_applicable', False)] for optimization in auto_applicable: await self._apply_optimization(optimization) self.stats['optimizations_applied'] += 1 except asyncio.CancelledError: break except Exception as e: self.logger.error(f"Error in periodic optimization: {e}") def _format_predictions_for_claudia(self, predictions: Dict[str, Any]) -> Dict[str, Any]: """Format predictions for Claudia's usage""" formatted = { 'predictions': [], 'confidence': predictions.get('confidence', 0.0) } suggestions = predictions.get('suggestions', []) for suggestion in suggestions: formatted_suggestion = { 'intent': suggestion.get('action', 'unknown'), 'confidence': suggestion.get('confidence', 0.0), 'reasoning': suggestion.get('reasoning', ''), 'parameters': suggestion.get('parameters', {}) } formatted['predictions'].append(formatted_suggestion) return formatted def _format_optimizations_for_claudia(self, optimizations: Dict[str, Any]) -> Dict[str, Any]: """Format optimizations for Claudia's usage""" formatted = { 'optimizations': [], 'recommendations': [] } opts = optimizations.get('optimizations', []) for opt in opts: formatted_opt = { 'type': opt.get('type', 'general'), 'description': opt.get('description', ''), 'impact': opt.get('impact', 'low'), 'auto_applicable': opt.get('type') in ['response_timing', 'confidence_threshold'], 'parameters': opt.get('parameters', {}) } formatted['optimizations'].append(formatted_opt) # Add general recommendations if optimizations.get('recommendations'): formatted['recommendations'] = optimizations['recommendations'] return formatted def _format_conversation_suggestions(self, predictions: Dict[str, Any]) -> Dict[str, Any]: """Format predictions as conversation suggestions""" suggestions = { 'suggestions': [], 'confidence': predictions.get('confidence', 0.0) } for prediction in predictions.get('suggestions', []): suggestion = { 'type': 'conversation_move', 'action': prediction.get('action', 'continue'), 'text': prediction.get('suggested_response', ''), 'confidence': prediction.get('confidence', 0.0), 'intent': prediction.get('suggested_intent', 'unknown') } suggestions['suggestions'].append(suggestion) return suggestions async def _apply_optimization(self, optimization: Dict[str, Any]): """Apply an optimization to Claudia""" try: opt_type = optimization.get('type') params = optimization.get('parameters', {}) if opt_type == 'response_timing': # Adjust response timing if Claudia supports it if hasattr(self.claudia, 'set_response_timing'): self.claudia.set_response_timing(params.get('timing', 1.0)) self.logger.info("Applied response timing optimization") elif opt_type == 'confidence_threshold': # Adjust confidence threshold if Claudia supports it if hasattr(self.claudia, 'set_confidence_threshold'): self.claudia.set_confidence_threshold(params.get('threshold', 0.7)) self.logger.info("Applied confidence threshold optimization") # Add more optimization types as needed except Exception as e: self.logger.error(f"Failed to apply optimization {optimization.get('type')}: {e}") def get_stats(self) -> Dict[str, Any]: """Get plugin statistics""" current_time = datetime.now() uptime = (current_time - self.stats['session_start']).total_seconds() return { **self.stats, 'uptime_seconds': uptime, 'uptime_formatted': f"{int(uptime // 3600)}h {int((uptime % 3600) // 60)}m", 'learning_rate': self.stats['interactions_learned'] / max(uptime / 3600, 1), # Per hour 'prediction_rate': self.stats['predictions_made'] / max(uptime / 3600, 1), # Per hour 'is_initialized': self.is_initialized, 'current_session': self.current_session } # Integration helper functions for easy setup async def setup_claudia_learning(claudia_instance, config: Dict[str, Any] = None) -> ClaudiaLearningPlugin: """ Set up learning integration for a Claudia instance Args: claudia_instance: Instance of Claudia voice assistant config: Configuration dictionary Returns: Initialized learning plugin """ plugin = ClaudiaLearningPlugin(claudia_instance, config) await plugin.initialize() return plugin def create_learning_config(mcp_server_url: str = "http://localhost:8765", learning_enabled: bool = True, auto_optimize: bool = True, prediction_enabled: bool = True) -> Dict[str, Any]: """Create a learning configuration dictionary""" return { 'mcp_server_url': mcp_server_url, 'learning_enabled': learning_enabled, 'auto_optimize': auto_optimize, 'prediction_enabled': prediction_enabled } # Example usage in Claudia's main loop: """ # In Claudia's initialization: learning_config = create_learning_config() learning_plugin = await setup_claudia_learning(self, learning_config) # In Claudia's interaction handler: async def handle_user_input(self, user_input, intent, confidence): # Process the interaction normally response = await self.generate_response(user_input, intent) # Learn from the interaction learning_result = await self.learning_plugin.learn_from_interaction( user_input, response, intent, confidence, success=True ) # Get predictions for better responses if confidence < 0.7: predictions = await self.learning_plugin.predict_user_intent(user_input) if predictions['predictions'] and predictions['confidence'] > confidence: # Use the predicted intent instead better_intent = predictions['predictions'][0]['intent'] response = await self.generate_response(user_input, better_intent) return response """

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/saralegui-solutions/mcp-self-learning-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server