Documentation Index
Fetch the complete documentation index at: https://docs.praison.ai/llms.txt
Use this file to discover all available pages before exploring further.
Advanced Multi-Provider Patterns
While basic multi-provider support allows you to use different LLMs for different agents, PraisonAI’s ModelRouter and RouterAgent provide sophisticated patterns for dynamic provider switching, cost optimization, and resilience.
Overview
The advanced multi-provider system enables:
- Dynamic model selection based on task requirements
- Automatic fallback when providers fail
- Cost-optimized routing for different task complexities
- Performance-based routing for critical operations
- Load balancing across providers
- Circuit breaker patterns for provider health
RouterAgent with ModelRouter
The RouterAgent uses the ModelRouter to intelligently select models based on task analysis:
from praisonaiagents import RouterAgent
# Configure router with multiple models
router_agent = RouterAgent(
models=[
"gpt-4o", # High capability, higher cost
"gpt-4o-mini", # Balanced capability and cost
"gemini/gemini-1.5-flash", # Fast and cost-effective
"deepseek/deepseek-chat" # Very cost-effective
],
routing_strategy="auto", # or "cost-optimized", "performance-optimized"
fallback_model="gpt-4o-mini"
)
# The router automatically selects appropriate models based on task complexity
response = router_agent.run("Analyze this complex financial report...") # Uses GPT-4
response = router_agent.run("What's the weather today?") # Uses cheaper model
Routing Strategies
1. Automatic Routing (“auto”)
Analyzes task complexity and requirements to select the best model:
router_agent = RouterAgent(
models=["gpt-4o", "claude-3-opus-20240229", "gemini/gemini-1.5-pro"],
routing_strategy="auto"
)
# Complex analysis task → Premium model
# Simple query → Cost-effective model
# Tool usage → Model with function calling support
2. Cost-Optimized Routing
Prioritizes cheaper models while ensuring task completion:
router_agent = RouterAgent(
models=["gpt-4o", "gpt-4o-mini", "gemini/gemini-1.5-flash"],
routing_strategy="cost-optimized",
cost_threshold=0.005 # Max cost per 1k tokens
)
# Get usage report with cost estimates
usage = router_agent.get_usage_summary()
print(f"Total cost: ${usage['total_cost']:.4f}")
Prioritizes capability and reliability for critical tasks:
router_agent = RouterAgent(
models=["gpt-4o", "claude-3-opus-20240229"],
routing_strategy="performance-optimized"
)
# Always uses the most capable model available
Advanced Patterns
Fallback Mechanism
Automatic fallback when primary model fails:
from praisonaiagents import RouterAgent, Agent
router = RouterAgent(
models=["gpt-4o", "claude-3-haiku-20240307", "gemini/gemini-1.5-flash"],
fallback_model="gpt-4o-mini",
routing_strategy="auto"
)
# If primary model fails, automatically tries next model
# If all models fail, uses fallback_model
agent = Agent(name="Resilient Agent", router=router)
Task-Based Routing
Route specific task types to specific providers:
from praisonaiagents import ModelRouter
class CustomRouter(ModelRouter):
def select_model(self, task_description: str, **kwargs):
# Code generation → Specialized model
if any(keyword in task_description.lower()
for keyword in ["code", "programming", "function"]):
return "deepseek/deepseek-coder"
# Creative tasks → Creative model
if any(keyword in task_description.lower()
for keyword in ["creative", "story", "poem"]):
return "claude-3-opus-20240229"
# Default to cost-effective model
return "gemini/gemini-1.5-flash"
router_agent = RouterAgent(router=CustomRouter())
Provider Health Monitoring
Track provider performance and route accordingly:
from praisonaiagents import RouterAgent
import time
class MonitoredRouter(RouterAgent):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.provider_stats = {}
def track_performance(self, model, latency, success):
if model not in self.provider_stats:
self.provider_stats[model] = {
"total_calls": 0,
"failures": 0,
"avg_latency": 0
}
stats = self.provider_stats[model]
stats["total_calls"] += 1
if not success:
stats["failures"] += 1
# Update average latency
stats["avg_latency"] = (
(stats["avg_latency"] * (stats["total_calls"] - 1) + latency)
/ stats["total_calls"]
)
def get_health_score(self, model):
if model not in self.provider_stats:
return 1.0
stats = self.provider_stats[model]
failure_rate = stats["failures"] / stats["total_calls"]
return 1.0 - failure_rate
# Use monitored router
router = MonitoredRouter(
models=["gpt-4o", "claude-3-haiku-20240307", "gemini/gemini-1.5-flash"]
)
Load Balancing
Distribute load across multiple providers:
from praisonaiagents import RouterAgent
import random
class LoadBalancedRouter(RouterAgent):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.model_usage = {model: 0 for model in self.models}
def select_model_balanced(self):
# Find least used model
min_usage = min(self.model_usage.values())
candidates = [m for m, u in self.model_usage.items() if u == min_usage]
selected = random.choice(candidates)
self.model_usage[selected] += 1
return selected
router = LoadBalancedRouter(
models=["gpt-4o-mini", "gemini/gemini-1.5-flash", "claude-3-haiku"]
)
Circuit Breaker Pattern
Temporarily disable failing providers:
from praisonaiagents import RouterAgent
import time
class CircuitBreakerRouter(RouterAgent):
def __init__(self, *args, failure_threshold=5, timeout=300, **kwargs):
super().__init__(*args, **kwargs)
self.failure_threshold = failure_threshold
self.timeout = timeout
self.failures = {}
self.circuit_open = {}
def is_available(self, model):
if model in self.circuit_open:
if time.time() - self.circuit_open[model] > self.timeout:
# Reset circuit after timeout
del self.circuit_open[model]
self.failures[model] = 0
return True
return False
return True
def record_failure(self, model):
self.failures[model] = self.failures.get(model, 0) + 1
if self.failures[model] >= self.failure_threshold:
self.circuit_open[model] = time.time()
print(f"Circuit breaker opened for {model}")
def get_available_models(self):
return [m for m in self.models if self.is_available(m)]
Integration with AutoAgents
Use RouterAgent with AutoAgents for dynamic teams:
from praisonaiagents import AutoAgentTeam, RouterAgent
# Create router for the team
router = RouterAgent(
models=["gpt-4o", "claude-3-haiku-20240307", "gemini/gemini-1.5-flash"],
routing_strategy="cost-optimized"
)
# AutoAgents will use the router for all agents
auto_agents = AutoAgentTeam(
instructions="Create a research team",
router=router
)
# Each agent gets optimal model based on their tasks
agents = auto_agents.create_agents()
Best Practices
1. Model Profiles
Configure accurate model profiles for better routing:
router = RouterAgent(
model_profiles={
"gpt-4o": {
"cost_per_1k_tokens": 0.03,
"strengths": ["reasoning", "analysis", "coding"],
"supports_tools": True,
"context_window": 128000
},
"gemini/gemini-1.5-flash": {
"cost_per_1k_tokens": 0.0001,
"strengths": ["speed", "simple_tasks"],
"supports_tools": True,
"context_window": 1000000
}
}
)
2. Cost Monitoring
Track and limit costs:
router = RouterAgent(
models=["gpt-4o", "gpt-4o-mini"],
cost_threshold=0.01, # Max per request
daily_budget=10.0 # Max daily spend
)
# Monitor usage
usage = router.get_usage_summary()
if usage["total_cost"] > 5.0:
router.routing_strategy = "cost-optimized"
3. Error Handling
Implement robust error handling:
try:
response = router_agent.run(task)
except ProviderError as e:
# Log provider-specific errors
logger.error(f"Provider {e.provider} failed: {e}")
# Router automatically handles fallback
except MaxRetriesError:
# All providers and fallback failed
logger.critical("All providers failed")
Common Use Cases
1. Development vs Production
# Development: Use cost-effective models
dev_router = RouterAgent(
models=["gpt-4o-mini", "gemini/gemini-1.5-flash"],
routing_strategy="cost-optimized"
)
# Production: Use high-performance models
prod_router = RouterAgent(
models=["gpt-4o", "claude-3-opus-20240229"],
routing_strategy="performance-optimized"
)
2. Specialized Routing
# Route by capability
coding_router = RouterAgent(
models=["deepseek/deepseek-coder", "gpt-4o"],
task_filter=lambda t: "code" in t.lower()
)
creative_router = RouterAgent(
models=["claude-3-opus-20240229", "gpt-4o"],
task_filter=lambda t: any(w in t.lower() for w in ["creative", "write", "story"])
)
3. A/B Testing
# Test different models for same tasks
ab_router = RouterAgent(
models=["gpt-4o", "claude-3-opus-20240229"],
routing_strategy="random", # 50/50 split
track_performance=True
)
# Analyze results
performance = ab_router.get_performance_comparison()
Next Steps