Módulo 5: OpenRouter - Introducción
Model Selection Automática
Descripción
Implementarás auto-selection inteligente de modelo según tipo de query (código, análisis, chat simple, etc.).
Tiempo: 25 minutos
Dificultad: Media-Alta
🎯 Objetivos
- ✅ Classifier para tipo de query
- ✅ Routing rules por tipo
- ✅ Machine learning (opcional)
- ✅ A/B testing
🧠 Rule-Based Selection
def classify_query(prompt: str) -> str:
"""Clasifica tipo de query."""
prompt_lower = prompt.lower()
# Código
if any(w in prompt_lower for w in ["código", "code", "function", "script", "python"]):
return "code"
# Análisis complejo
elif any(w in prompt_lower for w in ["analiza", "explica detalladamente", "razonamiento"]):
return "analysis"
# Traducción
elif any(w in prompt_lower for w in ["traduce", "translate"]):
return "translation"
# Creativo
elif any(w in prompt_lower for w in ["escribe", "redacta", "crea"]):
return "creative"
# Chat simple (default)
else:
return "simple"
def select_model(query_type: str) -> str:
"""Selecciona modelo según tipo."""
routing = {
"code": "mistralai/codestral-latest", # Especializado código
"analysis": "openai/gpt-4-turbo", # Razonamiento complejo
"translation": "google/gemini-pro", # Multilingüe
"creative": "anthropic/claude-3-opus", # Escritura creativa
"simple": "mistralai/mixtral-8x7b-instruct" # Barato para simple
}
return routing.get(query_type, "mistralai/mixtral-8x7b-instruct")
# Uso
prompt = "Escribe una función Python para fibonacci"
query_type = classify_query(prompt)
model = select_model(query_type)
print(f"Query type: {query_type}, Model: {model}")
🎯 Smart Router Class
from openai import OpenAI
import os
class SmartRouter:
"""Router inteligente multi-criterio."""
def __init__(self):
self.client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENROUTER_API_KEY")
)
def route(self, prompt: str, priority: str = "balanced") -> str:
"""
Selecciona modelo según prompt y prioridad.
Args:
prompt: Query del usuario
priority: "cost", "quality", "balanced", "speed"
"""
# Detecta tipo
query_type = self.classify(prompt)
# Routing según prioridad
if priority == "cost":
return self._route_cost(query_type)
elif priority == "quality":
return self._route_quality(query_type)
elif priority == "speed":
return self._route_speed(query_type)
else: # balanced
return self._route_balanced(query_type)
def classify(self, prompt: str) -> str:
"""Clasifica query."""
prompt_lower = prompt.lower()
if "code" in prompt_lower or "python" in prompt_lower:
return "code"
elif len(prompt) > 200:
return "complex"
else:
return "simple"
def _route_cost(self, query_type: str) -> str:
"""Prioriza costo."""
return "mistralai/mixtral-8x7b-instruct" # Siempre el más barato
def _route_quality(self, query_type: str) -> str:
"""Prioriza calidad."""
if query_type == "code":
return "openai/gpt-4-turbo"
else:
return "anthropic/claude-3-opus"
def _route_balanced(self, query_type: str) -> str:
"""Balance costo/calidad."""
routing = {
"simple": "mistralai/mixtral-8x7b-instruct",
"code": "mistralai/codestral-latest",
"complex": "openai/gpt-3.5-turbo"
}
return routing.get(query_type, "mistralai/mixtral-8x7b-instruct")
def _route_speed(self, query_type: str) -> str:
"""Prioriza velocidad."""
return "anthropic/claude-3-haiku" # Más rápido
def chat(self, prompt: str, priority: str = "balanced") -> str:
"""Chat con routing automático."""
model = self.route(prompt, priority)
print(f"[Using: {model}]")
response = self.client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
# Uso
router = SmartRouter()
print(router.chat("Hola", priority="cost")) # Mixtral (barato)
print(router.chat("Explica teoría cuántica en detalle", priority="quality")) # Claude Opus
print(router.chat("Quick question", priority="speed")) # Claude Haiku
📊 A/B Testing
import random
class ABTestRouter:
"""Router con A/B testing."""
def __init__(self):
self.client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENROUTER_API_KEY")
)
self.results = {"A": [], "B": []}
def chat(self, prompt: str) -> dict:
"""Chat con A/B test."""
# 50/50 split
variant = "A" if random.random() < 0.5 else "B"
# Variants
models = {
"A": "openai/gpt-3.5-turbo",
"B": "anthropic/claude-3-haiku"
}
model = models[variant]
response = self.client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}]
)
result = {
"variant": variant,
"model": model,
"response": response.choices[0].message.content,
"tokens": response.usage.total_tokens
}
self.results[variant].append(result)
return result
def analyze(self):
"""Analiza resultados A/B."""
print("=== A/B Test Results ===")
for variant in ["A", "B"]:
results = self.results[variant]
if not results:
continue
avg_tokens = sum(r["tokens"] for r in results) / len(results)
print(f"\nVariant {variant} ({results[0]['model']}):")
print(f" Queries: {len(results)}")
print(f" Avg tokens: {avg_tokens:.0f}")
# Test
tester = ABTestRouter()
for _ in range(20):
tester.chat("Test query")
tester.analyze()
🎯 Context-Aware Selection
def context_aware_route(
prompt: str,
conversation_history: list,
user_tier: str = "free"
) -> str:
"""Selección según contexto completo."""
# Tier-based (freemium model)
if user_tier == "free":
max_cost = 0.30 # Mixtral máximo
elif user_tier == "pro":
max_cost = 1.00 # GPT-3.5 máximo
else: # enterprise
max_cost = 100.0 # Sin límite
# Conversation length
total_messages = len(conversation_history)
# Si conversación larga → Modelo con context window grande
if total_messages > 20:
if max_cost >= 10.0:
return "anthropic/claude-3-opus" # 200k context
else:
return "openai/gpt-3.5-turbo" # 16k context
# Query length
elif len(prompt) > 500:
if max_cost >= 10.0:
return "openai/gpt-4-turbo"
else:
return "anthropic/claude-3-haiku"
# Default: Barato
else:
return "mistralai/mixtral-8x7b-instruct"
# Test
history = [] # Vacío
print(context_aware_route("Hola", history, "free")) # Mixtral
history = [{"role": "user", "content": "..."}] * 25 # Muchos mensajes
print(context_aware_route("Continúa", history, "enterprise")) # Claude Opus
📊 Machine Learning Selection (Avanzado)
# Placeholder para ML approach
def ml_route(prompt: str, historical_performance: dict) -> str:
"""
Usa ML para predecir mejor modelo.
Features:
- Prompt length
- Keywords
- Historical performance del modelo en queries similares
- Time of day (load balancing)
Requiere: scikit-learn, modelo entrenado
"""
# Simplified version (keyword-based como proxy)
features = {
"length": len(prompt),
"has_code": "code" in prompt.lower(),
"has_math": any(w in prompt.lower() for w in ["calcular", "matemáticas"]),
"is_creative": any(w in prompt.lower() for w in ["escribe", "crea"])
}
# Simple heuristic (placeholder para ML model)
if features["has_code"]:
return "mistralai/codestral-latest"
elif features["is_creative"]:
return "anthropic/claude-3-opus"
elif features["length"] > 300:
return "openai/gpt-4-turbo"
else:
return "mistralai/mixtral-8x7b-instruct"
✅ Resumen
Estrategias de selection:
- Rule-based (keywords, length)
- Priority-based (cost, quality, speed)
- Context-aware (history, user tier)
- A/B testing (experimentación)
- ML-based (avanzado)
Resultado: 80%+ queries usan modelo óptimo
Siguiente: 07-comparacion-providers.md
Compararás providers side-by-side (OpenAI vs Anthropic vs Google).
Tiempo: 15 min