| | """ |
| | Intent Recognition Agent |
| | Specialized in understanding user goals using Chain of Thought reasoning |
| | """ |
| |
|
| | import logging |
| | from typing import Dict, Any, List |
| | import json |
| |
|
| | logger = logging.getLogger(__name__) |
| |
|
| | class IntentRecognitionAgent: |
| | def __init__(self, llm_router=None): |
| | self.llm_router = llm_router |
| | self.agent_id = "INTENT_REC_001" |
| | self.specialization = "Multi-class intent classification with context awareness" |
| | |
| | |
| | self.intent_categories = [ |
| | "information_request", |
| | "task_execution", |
| | "creative_generation", |
| | "analysis_research", |
| | "casual_conversation", |
| | "troubleshooting", |
| | "education_learning", |
| | "technical_support" |
| | ] |
| | |
| | async def execute(self, user_input: str, context: Dict[str, Any] = None, **kwargs) -> Dict[str, Any]: |
| | """ |
| | Execute intent recognition with Chain of Thought reasoning |
| | """ |
| | try: |
| | logger.info(f"{self.agent_id} processing user input: {user_input[:100]}...") |
| | |
| | |
| | if self.llm_router: |
| | intent_result = await self._llm_based_intent_recognition(user_input, context) |
| | else: |
| | |
| | intent_result = await self._rule_based_intent_recognition(user_input, context) |
| | |
| | |
| | intent_result.update({ |
| | "agent_id": self.agent_id, |
| | "processing_time": intent_result.get("processing_time", 0), |
| | "confidence_calibration": self._calibrate_confidence(intent_result) |
| | }) |
| | |
| | logger.info(f"{self.agent_id} completed with intent: {intent_result['primary_intent']}") |
| | return intent_result |
| | |
| | except Exception as e: |
| | logger.error(f"{self.agent_id} error: {str(e)}") |
| | return self._get_fallback_intent(user_input, context) |
| | |
| | async def _llm_based_intent_recognition(self, user_input: str, context: Dict[str, Any]) -> Dict[str, Any]: |
| | """Use LLM for sophisticated intent classification with Chain of Thought""" |
| | |
| | try: |
| | cot_prompt = self._build_chain_of_thought_prompt(user_input, context) |
| | |
| | logger.info(f"{self.agent_id} calling LLM for intent recognition") |
| | llm_response = await self.llm_router.route_inference( |
| | task_type="intent_classification", |
| | prompt=cot_prompt, |
| | max_tokens=1000, |
| | temperature=0.3 |
| | ) |
| | |
| | if llm_response and isinstance(llm_response, str) and len(llm_response.strip()) > 0: |
| | |
| | parsed_result = self._parse_llm_intent_response(llm_response) |
| | parsed_result["processing_time"] = 0.8 |
| | parsed_result["method"] = "llm_enhanced" |
| | return parsed_result |
| | |
| | except Exception as e: |
| | logger.error(f"{self.agent_id} LLM intent recognition failed: {e}") |
| | |
| | |
| | logger.info(f"{self.agent_id} falling back to rule-based classification") |
| | return await self._rule_based_intent_recognition(user_input, context) |
| | |
| | async def _rule_based_intent_recognition(self, user_input: str, context: Dict[str, Any]) -> Dict[str, Any]: |
| | """Rule-based fallback intent classification""" |
| | |
| | primary_intent, confidence = self._analyze_intent_patterns(user_input) |
| | secondary_intents = self._get_secondary_intents(user_input, primary_intent) |
| | |
| | return { |
| | "primary_intent": primary_intent, |
| | "secondary_intents": secondary_intents, |
| | "confidence_scores": {primary_intent: confidence}, |
| | "reasoning_chain": ["Rule-based pattern matching applied"], |
| | "context_tags": [], |
| | "processing_time": 0.02 |
| | } |
| | |
| | def _build_chain_of_thought_prompt(self, user_input: str, context: Dict[str, Any]) -> str: |
| | """Build Chain of Thought prompt for intent recognition""" |
| | |
| | |
| | |
| | context_info = "" |
| | if context: |
| | |
| | combined_context = context.get('combined_context', '') |
| | if combined_context: |
| | |
| | context_info = f"\n\nAvailable Context:\n{combined_context[:1000]}..." |
| | else: |
| | |
| | session_context = context.get('session_context', {}) |
| | session_summary = session_context.get('summary', '') if isinstance(session_context, dict) else "" |
| | interaction_contexts = context.get('interaction_contexts', []) |
| | user_context = context.get('user_context', '') |
| | |
| | context_parts = [] |
| | if session_summary: |
| | context_parts.append(f"Session Context: {session_summary[:300]}...") |
| | if user_context: |
| | context_parts.append(f"User Context: {user_context[:300]}...") |
| | |
| | if interaction_contexts: |
| | |
| | recent_contexts = interaction_contexts[-2:] |
| | context_parts.append("Recent Interactions:") |
| | for idx, ic in enumerate(recent_contexts, 1): |
| | summary = ic.get('summary', '') |
| | if summary: |
| | context_parts.append(f" {idx}. {summary}") |
| | |
| | if context_parts: |
| | context_info = "\n\nAvailable Context:\n" + "\n".join(context_parts) |
| | |
| | if not context_info: |
| | context_info = "\n\nAvailable Context: No previous context available (first interaction in session)." |
| | |
| | return f""" |
| | Analyze the user's intent step by step: |
| | |
| | User Input: "{user_input}" |
| | {context_info} |
| | |
| | Step 1: Identify key entities, actions, and questions in the input |
| | Step 2: Map to intent categories: {', '.join(self.intent_categories)} |
| | Step 3: Consider the conversation flow and user's likely goals (if context available) |
| | Step 4: Assign confidence scores (0.0-1.0) for each relevant intent |
| | Step 5: Provide reasoning for the classification |
| | |
| | Respond with JSON format containing primary_intent, secondary_intents, confidence_scores, and reasoning_chain. |
| | """ |
| | |
| | def _analyze_intent_patterns(self, user_input: str) -> tuple: |
| | """Analyze user input patterns to determine intent""" |
| | user_input_lower = user_input.lower() |
| | |
| | |
| | patterns = { |
| | "information_request": [ |
| | "what is", "how to", "explain", "tell me about", "what are", |
| | "define", "meaning of", "information about" |
| | ], |
| | "task_execution": [ |
| | "do this", "make a", "create", "build", "generate", "automate", |
| | "set up", "configure", "execute", "run" |
| | ], |
| | "creative_generation": [ |
| | "write a", "compose", "create content", "make a story", |
| | "generate poem", "creative", "artistic" |
| | ], |
| | "analysis_research": [ |
| | "analyze", "research", "compare", "study", "investigate", |
| | "data analysis", "find patterns", "statistics" |
| | ], |
| | "troubleshooting": [ |
| | "error", "problem", "fix", "debug", "not working", |
| | "help with", "issue", "broken" |
| | ], |
| | "technical_support": [ |
| | "how do i", "help me", "guide me", "tutorial", "step by step" |
| | ] |
| | } |
| | |
| | |
| | for intent, pattern_list in patterns.items(): |
| | for pattern in pattern_list: |
| | if pattern in user_input_lower: |
| | confidence = min(0.9, 0.6 + (len(pattern) * 0.1)) |
| | return intent, confidence |
| | |
| | |
| | return "casual_conversation", 0.7 |
| | |
| | def _get_secondary_intents(self, user_input: str, primary_intent: str) -> List[str]: |
| | """Get secondary intents based on input complexity""" |
| | user_input_lower = user_input.lower() |
| | secondary = [] |
| | |
| | |
| | if "research" in user_input_lower and primary_intent != "analysis_research": |
| | secondary.append("analysis_research") |
| | if "help" in user_input_lower and primary_intent != "technical_support": |
| | secondary.append("technical_support") |
| | |
| | return secondary[:2] |
| | |
| | def _extract_context_tags(self, user_input: str, context: Dict[str, Any]) -> List[str]: |
| | """Extract relevant context tags from user input""" |
| | tags = [] |
| | user_input_lower = user_input.lower() |
| | |
| | |
| | if "research" in user_input_lower: |
| | tags.append("research") |
| | if "technical" in user_input_lower or "code" in user_input_lower: |
| | tags.append("technical") |
| | if "academic" in user_input_lower or "study" in user_input_lower: |
| | tags.append("academic") |
| | if "quick" in user_input_lower or "simple" in user_input_lower: |
| | tags.append("quick_request") |
| | |
| | return tags |
| | |
| | def _calibrate_confidence(self, intent_result: Dict[str, Any]) -> Dict[str, Any]: |
| | """Calibrate confidence scores based on various factors""" |
| | primary_intent = intent_result["primary_intent"] |
| | confidence = intent_result["confidence_scores"][primary_intent] |
| | |
| | calibration_factors = { |
| | "input_length_impact": min(1.0, len(intent_result.get('user_input', '')) / 100), |
| | "context_enhancement": 0.1 if intent_result.get('context_tags') else 0.0, |
| | "reasoning_depth_bonus": 0.05 if len(intent_result.get('reasoning_chain', [])) > 2 else 0.0 |
| | } |
| | |
| | calibrated_confidence = min(0.95, confidence + sum(calibration_factors.values())) |
| | |
| | return { |
| | "original_confidence": confidence, |
| | "calibrated_confidence": calibrated_confidence, |
| | "calibration_factors": calibration_factors |
| | } |
| | |
| | def _parse_llm_intent_response(self, response: str) -> Dict[str, Any]: |
| | """Parse LLM response for intent classification""" |
| | try: |
| | import json |
| | import re |
| | |
| | |
| | json_match = re.search(r'\{.*\}', response, re.DOTALL) |
| | if json_match: |
| | parsed = json.loads(json_match.group()) |
| | return parsed |
| | except json.JSONDecodeError: |
| | logger.warning(f"{self.agent_id} Failed to parse LLM intent JSON") |
| | |
| | |
| | response_lower = response.lower() |
| | primary_intent = "casual_conversation" |
| | confidence = 0.7 |
| | |
| | |
| | if any(word in response_lower for word in ['question', 'ask', 'what', 'how', 'why']): |
| | primary_intent = "information_request" |
| | confidence = 0.8 |
| | elif any(word in response_lower for word in ['task', 'action', 'do', 'help', 'assist']): |
| | primary_intent = "task_execution" |
| | confidence = 0.8 |
| | elif any(word in response_lower for word in ['create', 'generate', 'write', 'make']): |
| | primary_intent = "creative_generation" |
| | confidence = 0.8 |
| | |
| | return { |
| | "primary_intent": primary_intent, |
| | "secondary_intents": [], |
| | "confidence_scores": {primary_intent: confidence}, |
| | "reasoning_chain": [f"LLM response parsed: {response[:100]}..."], |
| | "context_tags": ["llm_parsed"], |
| | "method": "llm_parsed" |
| | } |
| | |
| | def _get_fallback_intent(self, user_input: str, context: Dict[str, Any]) -> Dict[str, Any]: |
| | """Provide fallback intent when processing fails""" |
| | return { |
| | "primary_intent": "casual_conversation", |
| | "secondary_intents": [], |
| | "confidence_scores": {"casual_conversation": 0.5}, |
| | "reasoning_chain": ["Fallback: Default to casual conversation"], |
| | "context_tags": ["fallback"], |
| | "processing_time": 0.01, |
| | "agent_id": self.agent_id, |
| | "error_handled": True |
| | } |
| |
|
| | |
| | def create_intent_agent(llm_router=None): |
| | return IntentRecognitionAgent(llm_router) |
| |
|
| |
|