Model Router System

Intelligent LLM selection based on task requirements and model capabilities for optimal performance and cost efficiency.

python
from praisonaiagents import Agent

agent = Agent(name="router-demo", instructions="Pick the best model for each task.")
agent.start("Summarise this long document cheaply")

The user submits a task; the router picks the model that best matches requirements and cost.

Diagram

Model Router

📋 Task

🧠 Router

🔍 Select Model

✅ Result

Quick Start

  1. Install Package

    First, install the PraisonAI Agents package:

    bash
    pip install praisonaiagents
  2. Set API Keys

    Set your API keys as environment variables:

    bash
    export OPENAI_API_KEY="${OPENAI_API_KEY:?Set OPENAI_API_KEY in your shell}"
    export ANTHROPIC_API_KEY=your_anthropic_key_here
    export GOOGLE_API_KEY=your_google_key_here
  3. Create a file

    Create a new file model_router_example.py:

    python
    from praisonaiagents import Agent, Task, AgentTeam
    from praisonaiagents.llm import ModelRouter
    
    # Initialize the model router
    router = ModelRouter()
    
    # Analyze task complexity and select appropriate model
    task_description = "Calculate the sum of 15 + 27"
    complexity = router.analyze_task_complexity(task_description)
    selected_model = router.select_model(task_description)
    
    print(f"Task complexity: {complexity}")
    print(f"Selected model: {selected_model}")
    
    # Create an agent with the selected model
    smart_agent = Agent(
        name="Smart Assistant",
        role="Adaptive AI Assistant",
        goal="Complete tasks using the most appropriate model",
        instructions="Analyze task requirements and provide accurate results",
        llm=selected_model  # Use the model selected by router
    )
    
    # Create a simple task
    simple_task = Task(
        name="simple_calculation",
        description=task_description,
        expected_output="The numerical result",
        agent=smart_agent
    )
    
    # Create and run workflow
    workflow = AgentTeam(
        agents=[smart_agent],
        tasks=[simple_task]
    )
    
    print("Starting Model Router Workflow...")
    print("=" * 50)
    
    results = workflow.start()
    print("Done!")
  4. Run the Example

    Execute your model router example:

    bash
    python model_router_example.py

Which Strategy Should I Use?

Pick a routing_strategy based on whether you optimise for cost, quality, or let the router decide.

Diagram

Lowest cost

Best quality

Let router decide

What matters most?

Priority?

cost-optimized
cheapest model that fits

performance-optimized
most capable model

auto
match to task complexity


YAML-Based Model Configuration

You can configure custom models directly in your agents.yaml or workflow.yaml files. This allows you to define model profiles with costs, capabilities, and complexity levels without writing Python code.

Basic Configuration

Add a models section to your YAML file:

yaml
# agents.yaml or workflow.yaml
name: My Workflow

# Custom models configuration
models:
  cheap-fast:
    provider: openai
    complexity: [simple]
    cost_per_1k: 0.0001
    capabilities: [text]
    context_window: 16000

  balanced:
    provider: openai
    complexity: [moderate]
    cost_per_1k: 0.001
    capabilities: [text, function-calling]
    context_window: 128000

  premium:
    provider: anthropic
    complexity: [complex, very_complex]
    cost_per_1k: 0.015
    capabilities: [text, vision, function-calling]
    context_window: 200000
    strengths: [reasoning, analysis, code-generation]

agents:
  researcher:
    name: Researcher
    role: Research Analyst
    goal: Research topics
    llm: balanced  # Use specific model

Quick per-agent model (no router needed)

For simple per-agent model assignment without configuring the full Model Router system, use these direct forms:

yaml
roles:
  researcher:
    role: Researcher
    goal: Research {topic}
    llm: gpt-4o-mini            # string form

  writer:
    role: Writer  
    goal: Write about {topic}
    llm:
      model: groq/llama3-70b-8192   # dict form

Precedence: per-agent llm > manager_llm (for hierarchical process) > global model resolved from llm_config[0].model / CLI / env.

Framework support: Per-agent llm is honored by both crewai and the praisonai-native adapter.

Model Configuration Fields

FieldTypeDescription
providerstringProvider name: openai, anthropic, google, openrouter, etc.
complexitylistComplexity levels: simple, moderate, complex, very_complex
cost_per_1kfloatCost per 1,000 tokens in USD
capabilitieslistModel capabilities: text, vision, function-calling, streaming
context_windowintMaximum context window size in tokens
supports_toolsboolWhether the model supports tool/function calling
supports_streamingboolWhether the model supports streaming responses
strengthslistModel strengths: reasoning, code-generation, analysis, etc.

Per-Agent LLM Configuration (Named Models)

Each agent can specify its own LLM configuration using named models defined in the models: block above:

yaml
agents:
  # Fixed model assignment
  classifier:
    name: Classifier
    role: Request Classifier
    goal: Classify requests
    llm: cheap-fast  # Always use cheap model

  # Auto-routing based on task complexity
  researcher:
    name: Researcher
    role: Research Analyst
    goal: Research topics
    llm_routing: auto  # Enable auto-routing
    llm_models: [balanced, premium]  # Models to choose from

  # Premium model for quality output
  writer:
    name: Writer
    role: Content Writer
    goal: Write high-quality content
    llm: premium  # Always use premium

Routing Strategies

Configure routing strategy in the workflow section:

yaml
workflow:
  verbose: true
  router: true  # Enable model routing
  routing_strategy: cost-optimized  # Options: auto, cost-optimized, performance-optimized
StrategyDescription
autoAutomatically select based on task complexity
cost-optimizedPrefer cheaper models while meeting requirements
performance-optimizedPrefer more capable models for quality

Complete Example

yaml
name: Cost-Optimized Model Routing Workflow
description: Uses custom models with automatic routing

models:
  gpt-4o-mini:
    provider: openai
    complexity: [simple, moderate]
    cost_per_1k: 0.00075
    capabilities: [text, function-calling]

  claude-3-5-sonnet:
    provider: anthropic
    complexity: [moderate, complex, very_complex]
    cost_per_1k: 0.009
    capabilities: [text, vision, function-calling]
    strengths: [reasoning, code-generation, analysis]

workflow:
  verbose: true
  router: true
  routing_strategy: cost-optimized

agents:
  classifier:
    name: Classifier
    role: Request Classifier
    goal: Classify incoming requests
    llm: gpt-4o-mini

  researcher:
    name: Researcher
    role: Research Analyst
    goal: Research topics thoroughly
    llm_routing: auto
    llm_models: [gpt-4o-mini, claude-3-5-sonnet]

steps:
  - agent: classifier
    action: "Classify: {{input}}"

  - name: routing
    route:
      simple: [researcher]
      complex: [researcher]
      default: [researcher]

CLI Usage

Create a workflow from template:

bash
praisonai workflow create --template model-routing --output my_workflow.yaml

Run with the --router flag for automatic model selection:

bash
praisonai "Your task here" --router
praisonai "Your task here" --router --router-provider anthropic

How It Works

The user submits a task; the router analyses complexity, selects the best-matching model, and the agent runs on it.

Diagram
ModelAgentRouterUserModelAgentRouterUserTask descriptionAnalyze complexity + costSelected modelRun taskCompletionResult

Understanding Model Router

What is Model Router?

The Model Router: – Automatically selects the best LLM for each task – Considers task complexity, context length, and requirements – Optimizes for performance and cost – Supports fallback options if primary model fails – Provides detailed routing history and analytics

Features

Configuration Options

python
# Initialize router with custom configuration
router = ModelRouter(
    config={
        # Model selection preferences
        "prefer_cost_effective": True,
        "max_cost_per_token": 0.001,

        # Model capabilities
        "model_capabilities": {
            "gpt-4": {
                "max_tokens": 128000,
                "strengths": ["reasoning", "coding", "analysis"],
                "cost_per_1k_tokens": 0.03
            },
            "gpt-3.5-turbo": {
                "max_tokens": 16000,
                "strengths": ["general", "fast"],
                "cost_per_1k_tokens": 0.001
            },
            "claude-3-sonnet": {
                "max_tokens": 200000,
                "strengths": ["long_context", "writing"],
                "cost_per_1k_tokens": 0.015
            }
        },

        # Routing rules
        "routing_rules": {
            "complex_reasoning": ["gpt-4", "claude-3-opus"],
            "simple_tasks": ["gpt-3.5-turbo", "llama-3"],
            "long_context": ["claude-3-sonnet", "gpt-4-turbo"],
            "coding": ["gpt-4", "deepseek-coder"],
            "multimodal": ["gpt-4-vision", "gemini-pro-vision"]
        },

        # Fallback configuration
        "fallback_enabled": True,
        "fallback_models": ["gpt-3.5-turbo", "llama-3"]
    }
)

# Use router with specific task hints
result = router.route_task(
    task_description="Analyze complex financial data",
    requirements={
        "complexity": "high",
        "domain": "finance",
        "expected_tokens": 2000
    }
)

Advanced Usage

Custom Routing Logic

python
from praisonaiagents.llm import ModelRouter, RoutingCriteria

class CustomRouter(ModelRouter):
    def custom_routing_logic(self, task, criteria):
        # Add custom logic for specific use cases
        if "legal" in task.description.lower():
            return "claude-3-opus"  # Better for legal documents

        if criteria.urgency == "high":
            return "gpt-3.5-turbo"  # Fastest response

        return super().route(task, criteria)

# Use custom router
custom_router = CustomRouter()

Routing Analytics

python
# Get routing statistics
stats = router.get_statistics()
print(f"Total tasks routed: {stats['total_tasks']}")
print(f"Model usage breakdown: {stats['model_usage']}")
print(f"Average cost per task: ${stats['avg_cost']}")
print(f"Performance metrics: {stats['performance']}")

# Export routing history
router.export_history("routing_history.json")

Model Selection Criteria

The router considers multiple factors when selecting models:

Best Practices

Define Clear Requirements

Provide specific task requirements to help the router make better decisions:

python
task = Task(
    description="...",
    requirements={
        "complexity": "high",
        "context_length": 10000,
        "domain": "technical",
        "quality_priority": 0.8
    }
)
Monitor Performance

Regularly review routing decisions and performance:

python
# Enable detailed logging
router = ModelRouter(output="verbose", log_decisions=True)

# Review performance after execution
performance_report = router.generate_performance_report()
Set Cost Limits

Configure budget constraints to control costs:

python
router = ModelRouter(
    max_cost_per_task=0.50,
    daily_budget=100.00,
    alert_on_threshold=True
)

Troubleshooting

Next Steps

Related