Spaces:
Sleeping
Sleeping
File size: 7,044 Bytes
e4d2119 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | """
Multi-Agent Router for LoL Coach
Routes user queries to specialized agents based on intent classification.
"""
import logging
from typing import Literal, Optional
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
# Setup logging
logger = logging.getLogger(__name__)
class RouteQuery(BaseModel):
"""Route a user query to the most relevant agent."""
agent: Literal[
"match_analyzer",
"build_advisor",
"video_guide",
"knowledge_base",
"pregame_agent",
"orchestrator"
] = Field(
description="The agent that should handle this query"
)
reasoning: str = Field(
description="Brief explanation of why this agent was chosen"
)
needs_multiple_agents: bool = Field(
default=False,
description="True if query requires multiple agents to collaborate"
)
class QueryRouter:
"""
Intelligent router that classifies user queries and directs them
to the appropriate specialized agent.
"""
def __init__(self, llm: ChatOpenAI):
self.llm = llm
self.structured_llm = llm.with_structured_output(RouteQuery)
self.routing_prompt = ChatPromptTemplate.from_messages([
("system", """You are an expert at routing League of Legends coaching queries to specialized agents.
Available Agents:
1. **match_analyzer** - Handles:
- Match history analysis
- Performance statistics
- Win/loss tracking
- Recent game reviews
- Enemy champion analysis
- Build comparisons from past games
- Examples: "Analyze my recent matches", "How did I do vs Zed?", "Show my match history"
2. **build_advisor** - Handles:
- Optimal item builds
- Rune recommendations
- Champion matchups
- Build optimization
- Counter picks
- Examples: "What items should I build on Ahri?", "Best runes for Jinx?", "Counters to Yasuo?"
3. **video_guide** - Handles:
- YouTube video searches
- Champion guides
- Matchup videos
- Educational content
- Tutorial requests
- Examples: "Find Ahri guides", "Videos about wave management", "Ahri vs Zed matchup videos"
4. **knowledge_base** - Handles:
- Game concept explanations
- Terminology definitions
- Mechanics explanations
- General LoL questions
- Examples: "What is AP?", "Explain armor", "What does split pushing mean?"
5. **pregame_agent** - Handles:
- Champion select strategy
- Draft phase advice
- Ban recommendations
- Team composition analysis
- Role and lane assignment
- Counter-picking in draft
- Examples: "Who should I ban?", "What champion should I pick?", "Help me with champion select", "Good team comp?"
6. **orchestrator** - Handles:
- Complex queries needing multiple agents
- Questions combining match analysis + builds
- Comprehensive coaching requests
- Multi-step inquiries
- Examples: "Analyze my matches and suggest better builds", "Why am I losing and what should I do?"
Routing Guidelines:
- Choose the MOST SPECIFIC agent possible
- Only use orchestrator if query clearly needs 2+ agents
- Match keywords to agent expertise
- Consider user intent, not just keywords
- Default to orchestrator if very unclear
Analyze the query and route it to the best agent."""),
("human", "{query}")
])
def route(self, query: str) -> RouteQuery:
"""
Route a user query to the appropriate agent.
Args:
query: User's question or request
Returns:
RouteQuery with agent selection and reasoning
"""
logger.info(f"Routing query: {query[:100]}...")
try:
chain = self.routing_prompt | self.structured_llm
result = chain.invoke({"query": query})
# Log routing decision
logger.info(f"Routed to: {result.agent} - Reason: {result.reasoning}")
logger.debug(f"Multiple agents needed: {result.needs_multiple_agents}")
print(f"\n๐งญ Router Decision:")
print(f" Query: {query[:80]}...")
print(f" โ Routed to: {result.agent}")
print(f" Reasoning: {result.reasoning}")
if result.needs_multiple_agents:
print(f" ๐ Multi-agent workflow required")
return result
except Exception as e:
logger.error(f"Routing failed: {str(e)}", exc_info=True)
# Fallback to orchestrator for complex queries
logger.warning("Falling back to orchestrator")
return RouteQuery(
agent="orchestrator",
reasoning=f"Routing error occurred, defaulting to orchestrator: {str(e)}",
needs_multiple_agents=True
)
def get_agent_description(self, agent_name: str) -> str:
"""Get a human-readable description of what an agent does."""
descriptions = {
"match_analyzer": "๐ฏ Match Analyzer - Analyzes your game history and performance",
"build_advisor": "๐ ๏ธ Build Advisor - Recommends optimal items, runes, and champions",
"video_guide": "๐ฌ Video Guide - Finds YouTube tutorials and gameplay videos",
"knowledge_base": "๐ Knowledge Base - Explains game concepts and terminology",
"pregame_agent": "๐ฏ Pregame Agent - Champion select, drafting, and ban strategy",
"orchestrator": "๐ญ Orchestrator - Coordinates multiple agents for complex requests"
}
return descriptions.get(agent_name, agent_name)
def create_router(openai_api_key: str, temperature: float = 0.3) -> QueryRouter:
"""
Create a configured query router.
Args:
openai_api_key: OpenAI API key
temperature: LLM temperature (lower = more deterministic routing)
Returns:
Configured QueryRouter instance
"""
llm = ChatOpenAI(
api_key=openai_api_key,
model="gpt-4o-mini",
temperature=temperature
)
return QueryRouter(llm)
# Example usage and testing
if __name__ == "__main__":
import os
from dotenv import load_dotenv
load_dotenv()
router = create_router(os.getenv("OPENAI_API_KEY"))
# Test queries
test_queries = [
"Analyze my recent matches",
"What items should I build on Ahri?",
"Find some Yasuo guides",
"What does AP mean?",
"I keep losing as Jinx, what builds should I use and show me some guides",
"How did I do against Zed in my last game?",
"Best runes for Master Yi jungle?",
"Explain wave management",
"Find matchup videos for Ahri vs Syndra"
]
print("=" * 80)
print("๐งช Testing Query Router")
print("=" * 80)
for query in test_queries:
result = router.route(query)
print()
|