"""Intent recognition system for routing user requests.""" import json import logging from enum import Enum from typing import Any logger = logging.getLogger(__name__) class IntentType(Enum): """Types of user intents.""" SIMPLE = "simple" # Simple Q&A, no tools needed TOOL = "tool" # Needs tools (search, code, files, etc.) SKILL = "skill" # Needs specific domain skill TEAM = "team" # Needs multi-agent collaboration UNKNOWN = "unknown" # Cannot determine # Intent recognition prompt template INTENT_PROMPT = """Analyze the user's message and classify their intent. Intent Types: - simple: General knowledge questions, greetings, casual conversation, simple Q&A Examples: "你好", "介绍一下武汉", "什么是AI", "今天天气怎么样" - tool: Requires external tools - web search, code execution, file operations, calculations Examples: "搜索最新的AI新闻", "帮我运行这段代码", "读取文件内容", "计算这个表达式" - skill: Requires specific domain skill (coding, design, analysis, etc.) Examples: "用Python写一个排序算法", "分析这段代码的性能", "创建一个网页" - team: Requires multiple agents working together Examples: "让设计agent和开发agent一起完成这个任务", "创建一个团队来完成这个项目" Guidelines: - For greetings and simple questions, prefer "simple" - Only use "tool" when user explicitly asks for search, execution, or file operations - "introduce Wuhan" in Chinese is general knowledge - prefer "simple" unless user specifically asks for latest/current information - If ambiguous, prefer "simple" to avoid unnecessary tool calls User message: {message} Respond with only the intent type (simple/tool/skill/team), no explanation:""" class IntentRecognizer: """Recognizes user intent to route requests appropriately.""" def __init__(self, llm_provider=None): """Initialize intent recognizer. Args: llm_provider: LLM provider for intent recognition """ self._llm_provider = llm_provider self._cache = {} # Simple cache for recent intents def recognize( self, message: str, available_tools: list[str] | None = None, available_skills: list[str] | None = None, ) -> IntentType: """Recognize user intent. Args: message: User message available_tools: List of available tool names available_skills: List of available skill names Returns: Recognized intent type """ # Simple heuristics for common cases (fast path) intent = self._heuristic_recognition(message) if intent != IntentType.UNKNOWN: logger.info(f"Intent recognized (heuristic): {intent.value} for message: {message[:50]}...") return intent # Use LLM for complex cases if self._llm_provider: return self._llm_recognition(message) # Default to simple if no LLM return IntentType.SIMPLE def _heuristic_recognition(self, message: str) -> IntentType: """Fast heuristic-based intent recognition. Args: message: User message Returns: Recognized intent or UNKNOWN """ if not message: return IntentType.UNKNOWN message_lower = message.lower().strip() # Greetings greetings = ["你好", "hello", "hi", "嗨", "您好", "hey"] if any(g in message_lower for g in greetings) and len(message_lower) < 20: return IntentType.SIMPLE # Simple questions patterns simple_patterns = [ "什么是", "什么叫", "什么是", "介绍一下", "请介绍", "解释一下", "解释", "怎么样", "好不好", "是什么意思", "who are", "what is", "what's", "tell me about", ] # Check for simple patterns that don't require tools for pattern in simple_patterns: if pattern in message_lower: # But exclude if explicitly asking for current/latest/real-time if any(kw in message_lower for kw in ["最新", "现在", "current", "latest", "实时"]): return IntentType.UNKNOWN # Might need web search return IntentType.SIMPLE # Explicit tool request patterns tool_patterns = [ "搜索", "查找", "search", "执行", "运行", "run", "计算", "calculate", "帮我写代码", "write code", "读取", "读取", "read file", "创建文件", "write file", ] for pattern in tool_patterns: if pattern in message_lower: return IntentType.TOOL # Skill patterns skill_patterns = [ "用python", "用java", "用js", "写一个算法", "实现", "创建一个", "开发", "分析", "优化", ] for pattern in skill_patterns: if pattern in message_lower: return IntentType.SKILL # Team patterns team_patterns = [ "团队", "协作", "多个agent", "team", "collaborate", "一起", ] for pattern in team_patterns: if pattern in message_lower: return IntentType.TEAM return IntentType.UNKNOWN def _llm_recognition(self, message: str) -> IntentType: """LLM-based intent recognition. Args: message: User message Returns: Recognized intent type """ try: prompt = INTENT_PROMPT.format(message=message) # Use the LLM to classify intent response = self._llm_provider.chat( messages=[{"role": "user", "content": prompt}], max_tokens=50, ) content = response.content.strip().lower() # Parse the response if "simple" in content: return IntentType.SIMPLE elif "tool" in content: return IntentType.TOOL elif "skill" in content: return IntentType.SKILL elif "team" in content: return IntentType.TEAM else: logger.warning(f"Unexpected intent response: {content}") return IntentType.SIMPLE # Default to simple except Exception as e: logger.error(f"LLM intent recognition failed: {e}") return IntentType.SIMPLE # Default to simple on error class IntentRouter: """Routes requests based on recognized intent.""" def __init__( self, intent_recognizer: IntentRecognizer | None = None, use_llm_recognition: bool = True, ): """Initialize intent router. Args: intent_recognizer: Intent recognizer instance use_llm_recognition: Whether to use LLM for complex cases """ self._recognizer = intent_recognizer self._use_llm = use_llm_recognition def route( self, message: str, available_tools: list[str] | None = None, available_skills: list[str] | None = None, ) -> dict[str, Any]: """Route the user message based on intent. Args: message: User message available_tools: List of available tool names available_skills: List of available skill names Returns: Routing decision with intent type and suggested action """ # Recognize intent intent = self._recognizer.recognize( message, available_tools, available_skills, ) # Build routing decision decision = { "intent": intent.value, "action": self._get_action(intent), "message": message, } logger.info(f"Routed message to {intent.value}: {message[:50]}...") return decision def _get_action(self, intent: IntentType) -> str: """Get the action to take based on intent. Args: intent: Recognized intent type Returns: Action name """ return { IntentType.SIMPLE: "direct_response", IntentType.TOOL: "execute_tools", IntentType.SKILL: "execute_skill", IntentType.TEAM: "team_collaboration", IntentType.UNKNOWN: "direct_response", # Default to direct response }.get(intent, "direct_response") def create_intent_router(llm_provider=None) -> IntentRouter: """Create an intent router with default settings. Args: llm_provider: LLM provider for intent recognition Returns: Configured IntentRouter instance """ recognizer = IntentRecognizer(llm_provider=llm_provider) return IntentRouter(intent_recognizer=recognizer)