7. OptimizationIntermédiaire

Routage LLM : L'Architecture Secrète qui Réduit vos Coûts IA de 60% (Sans Perte de Qualité)

3 août 2026
24 min de lecture
Équipe Ailog

Guide complet sur le routage LLM pour optimiser les coûts : routage par complexité, cascade, consensus. Comparatif Martian, Unify, OpenRouter. Code et architecture pour un router custom.

Routage LLM : L'Architecture Secrète qui Réduit vos Coûts IA de 60%

Imaginez un monde où chaque requête utilisateur est envoyée au modèle LLM parfait pour la tâche : GPT-4o mini pour les questions simples, Claude 3.5 Sonnet pour l'analyse complexe, Mistral Large pour les tâches en français. Sans que l'utilisateur ne remarque la différence.

C'est exactement ce que fait le routage LLM. Et les entreprises qui l'adoptent réduisent leurs coûts de 50 à 70% avec moins de 2% de perte de qualité.

TL;DR

  • Routage LLM = envoyer chaque requête au modèle le plus adapté (rapport qualité/coût optimal)
  • 3 stratégies principales : routage par complexité, routage en cascade, routage par consensus
  • Économies typiques : 50-70% de réduction des coûts LLM avec < 2% de dégradation qualité
  • Outils : Martian, Unify, OpenRouter pour le routage managé ; classifier custom pour le contrôle total
  • Pour le RAG : combiner le routage LLM avec le prompt caching pour des économies > 80%

Pourquoi le Routage LLM est Indispensable

Le problème : un seul modèle pour tout

La plupart des entreprises utilisent un seul modèle pour toutes les requêtes :

Toutes les requêtes → GPT-4o → Réponses
                      $$$$$

Le problème ? 80% des requêtes sont simples et ne nécessitent pas la puissance (et le coût) d'un GPT-4o.

La distribution typique des requêtes

Complexité% requêtesExempleModèle optimalCoût relatif
Triviale30%"Bonjour", "Merci"Règle simple (pas de LLM)$0
Simple35%"Quels sont vos horaires ?"GPT-4o mini / Mistral Small$0,001
Moyenne25%"Comparez les offres Pro et Business"Claude 3.5 Haiku / GPT-4o mini$0,005
Complexe8%"Analysez les tendances de mes ventes Q3"GPT-4o / Claude 3.5 Sonnet$0,03
Expert2%"Rédigez un contrat adapté à mon cas"Claude Opus 4 / GPT-5$0,08

L'impact financier

Pour 100 000 requêtes/mois :

ApprocheCoût mensuelQualité moyenne
Tout sur GPT-4o$3 0009,2/10
Tout sur GPT-4o mini$1507,8/10
Avec routage intelligent$6009,0/10
Économie vs GPT-4o-80%-0,2 point

Les 3 Stratégies de Routage

Stratégie 1 : Routage par complexité

Le plus courant. Un classifier analyse la requête et l'envoie au bon modèle.

                    ┌─────────────────┐
                    │   Classifier    │
                    │  (complexité)   │
                    └───┬──────┬──────┘
                        │      │
              ┌─────────┼──────┼──────────┐
              ▼         ▼      ▼          ▼
         ┌────────┐ ┌──────┐ ┌──────┐ ┌───────┐
         │Trivial │ │Simple│ │Medium│ │Complex│
         │(règle) │ │(mini)│ │(std) │ │(pro)  │
         └────────┘ └──────┘ └──────┘ └───────┘
         $0         $0,001   $0,005   $0,03

Implémentation :

DEVELOPERpython
from openai import OpenAI import anthropic client_openai = OpenAI() client_anthropic = anthropic.Anthropic() # Classifier de complexité (lui-même un LLM léger) CLASSIFIER_PROMPT = """Analyse la complexité de cette requête utilisateur. Réponds UNIQUEMENT par un des niveaux suivants : - TRIVIAL : salutations, remerciements, confirmations - SIMPLE : question factuelle directe, info de base - MEDIUM : comparaison, synthèse, question multi-facettes - COMPLEX : analyse, rédaction longue, raisonnement multi-étapes - EXPERT : tâche créative complexe, analyse de données, juridique Requête : {query} Niveau :""" async def classify_complexity(query: str) -> str: """Classifier la complexité avec un modèle léger.""" response = client_openai.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "user", "content": CLASSIFIER_PROMPT.format(query=query)} ], max_tokens=10, temperature=0, ) return response.choices[0].message.content.strip() # Mapping complexité → modèle MODEL_ROUTING = { "TRIVIAL": None, # Réponse template, pas de LLM "SIMPLE": {"provider": "openai", "model": "gpt-4o-mini"}, "MEDIUM": {"provider": "anthropic", "model": "claude-3-5-haiku-20241022"}, "COMPLEX": {"provider": "openai", "model": "gpt-4o"}, "EXPERT": {"provider": "anthropic", "model": "claude-sonnet-4-20250514"}, } TRIVIAL_RESPONSES = { "bonjour": "Bonjour ! Comment puis-je vous aider ?", "merci": "Je vous en prie ! N'hésitez pas si vous avez d'autres questions.", } async def route_and_generate(query: str, context: str) -> dict: """Route la requête vers le bon modèle et génère la réponse.""" complexity = await classify_complexity(query) config = MODEL_ROUTING[complexity] if config is None: # Requête triviale → réponse template for keyword, response in TRIVIAL_RESPONSES.items(): if keyword in query.lower(): return {"response": response, "model": "template", "cost": 0} if config["provider"] == "openai": response = client_openai.chat.completions.create( model=config["model"], messages=[ {"role": "system", "content": f"Contexte:\n{context}"}, {"role": "user", "content": query}, ], ) return { "response": response.choices[0].message.content, "model": config["model"], "cost": estimate_cost(response.usage, config["model"]), } elif config["provider"] == "anthropic": response = client_anthropic.messages.create( model=config["model"], max_tokens=2048, system=f"Contexte:\n{context}", messages=[{"role": "user", "content": query}], ) return { "response": response.content[0].text, "model": config["model"], "cost": estimate_cost_anthropic(response.usage, config["model"]), }

Stratégie 2 : Routage en cascade

Commence par le modèle le moins cher. Si la confiance est trop faible, escalade vers un modèle supérieur.

Query → GPT-4o mini → Confiance > 80% ? → Oui → Réponse ✓
                           │
                           Non
                           ↓
              Claude 3.5 Sonnet → Confiance > 80% ? → Oui → Réponse ✓
                                       │
                                       Non
                                       ↓
                              GPT-4o → Réponse (forcée) ✓

Implémentation :

DEVELOPERpython
import re CASCADE_MODELS = [ {"provider": "openai", "model": "gpt-4o-mini", "threshold": 0.8}, {"provider": "anthropic", "model": "claude-sonnet-4-20250514", "threshold": 0.7}, {"provider": "openai", "model": "gpt-4o", "threshold": 0.0}, # Fallback ] CONFIDENCE_PROMPT_SUFFIX = """ Après ta réponse, ajoute sur la dernière ligne : CONFIDENCE: X.XX (entre 0 et 1, ta confiance dans la réponse)""" async def cascade_route(query: str, context: str) -> dict: """Routage en cascade avec évaluation de confiance.""" for config in CASCADE_MODELS: response, confidence = await generate_with_confidence( query, context, config ) if confidence >= config["threshold"]: return { "response": response, "model": config["model"], "cascade_level": CASCADE_MODELS.index(config) + 1, } # Fallback : dernière réponse return { "response": response, "model": CASCADE_MODELS[-1]["model"], "cascade_level": len(CASCADE_MODELS), } async def generate_with_confidence(query, context, config): """Génère une réponse et extrait le score de confiance.""" full_query = query + CONFIDENCE_PROMPT_SUFFIX if config["provider"] == "openai": resp = client_openai.chat.completions.create( model=config["model"], messages=[ {"role": "system", "content": f"Contexte:\n{context}"}, {"role": "user", "content": full_query}, ], ) text = resp.choices[0].message.content else: resp = client_anthropic.messages.create( model=config["model"], max_tokens=2048, system=f"Contexte:\n{context}", messages=[{"role": "user", "content": full_query}], ) text = resp.content[0].text # Extraire la confiance confidence_match = re.search(r"CONFIDENCE:\s*([\d.]+)", text) confidence = float(confidence_match.group(1)) if confidence_match else 0.5 clean_response = re.sub(r"\nCONFIDENCE:.*$", "", text).strip() return clean_response, confidence

Stratégie 3 : Routage par consensus

Pour les requêtes critiques : interroger plusieurs modèles et prendre la réponse majoritaire ou la combiner.

Query → ┌─ GPT-4o mini ──────────┐
        ├─ Claude 3.5 Haiku ─────┤→ Comparateur → Réponse finale
        └─ Mistral Small ────────┘

Implémentation :

DEVELOPERpython
import asyncio async def consensus_route(query: str, context: str) -> dict: """Interroge 3 modèles et combine les réponses.""" models = [ {"provider": "openai", "model": "gpt-4o-mini"}, {"provider": "anthropic", "model": "claude-3-5-haiku-20241022"}, {"provider": "openai", "model": "gpt-4o-mini"}, # Mistral via OpenAI-compatible ] # Appels parallèles tasks = [generate(query, context, m) for m in models] responses = await asyncio.gather(*tasks) # Combiner les réponses combined = await synthesize_responses(query, responses) return { "response": combined, "models_used": [m["model"] for m in models], "individual_responses": responses, } async def synthesize_responses(query, responses): """Un modèle synthétise les réponses des autres.""" synthesis_prompt = f"""Voici 3 réponses à la même question. Synthétise la meilleure réponse en combinant les points forts de chacune. Si les réponses se contredisent, privilégie le consensus. Question : {query} Réponse 1 : {responses[0]} Réponse 2 : {responses[1]} Réponse 3 : {responses[2]} Synthèse :""" resp = client_openai.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": synthesis_prompt}], ) return resp.choices[0].message.content

Comparatif des Solutions de Routage

Outils de routage managés

OutilTypeModèles supportésPrixLatence ajoutéeProduction-ready
MartianRouter ML20+Usage-based~50msOui
UnifyRouter + benchmark50+Gratuit (pay LLM)~30msOui
OpenRouterProxy + routage100++5,5% sur recharge (pas de markup au token)~20msOui
RouteLLMOpen-sourceConfigurableGratuitVariablePartiellement
CustomDIYIllimitéDev time~10msDépend

Martian : Le router ML

DEVELOPERpython
import requests def route_with_martian(query: str, context: str) -> dict: """Routage via Martian - sélection automatique du meilleur modèle.""" response = requests.post( "https://api.withmartian.com/v1/chat/completions", headers={"Authorization": "Bearer MARTIAN_API_KEY"}, json={ "messages": [ {"role": "system", "content": context}, {"role": "user", "content": query}, ], "model": "router", # Martian choisit le modèle "max_tokens": 1024, "route_params": { "max_cost": 0.01, # Budget max par requête "min_quality": 0.85, # Qualité minimum } } ) result = response.json() return { "response": result["choices"][0]["message"]["content"], "model_used": result["model"], # Quel modèle a été choisi "cost": result["usage"]["total_cost"], }

OpenRouter : L'agrégateur universel

DEVELOPERpython
from openai import OpenAI # OpenRouter est compatible OpenAI SDK client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key="OPENROUTER_API_KEY", ) def route_with_openrouter(query: str, context: str) -> dict: """Routage via OpenRouter avec sélection par prix.""" response = client.chat.completions.create( model="openrouter/auto", # Routage automatique messages=[ {"role": "system", "content": context}, {"role": "user", "content": query}, ], max_tokens=1024, extra_body={ "route": "cost", # Optimiser pour le coût # Options : "cost", "quality", "balanced" } ) return { "response": response.choices[0].message.content, "model_used": response.model, }

Unify : Le benchmarker

DEVELOPERpython
import unify client = unify.Unify(api_key="UNIFY_API_KEY") def route_with_unify(query: str, context: str) -> dict: """Routage via Unify - benchmark-driven.""" response = client.generate( messages=[ {"role": "system", "content": context}, {"role": "user", "content": query}, ], # Syntaxe : model@provider ou "router" model="router", routing_strategy="lowest_cost", # ou "highest_quality", "balanced" ) return { "response": response, "model_used": client.last_model_used, }

Routage LLM pour le RAG

Architecture RAG avec routage

┌────────────────────────────────────────────────────────┐
│                  RAG + LLM ROUTING                      │
├────────────────────────────────────────────────────────┤
│                                                         │
│  Query utilisateur                                      │
│       │                                                 │
│       ▼                                                 │
│  ┌──────────────┐                                      │
│  │  Classifier  │  ← Analyse complexité + intent        │
│  │  (GPT-4o     │                                      │
│  │   mini)      │                                      │
│  └──────┬───────┘                                      │
│         │                                               │
│    ┌────┴────┐                                          │
│    ▼         ▼                                          │
│  Simple    Complexe                                     │
│    │         │                                          │
│    ▼         ▼                                          │
│  ┌──────┐  ┌──────────┐                                │
│  │Light │  │  Full    │                                │
│  │ RAG  │  │  RAG     │                                │
│  │(top3)│  │  (top10  │                                │
│  └──┬───┘  │  +rerank)│                                │
│     │      └────┬─────┘                                │
│     ▼           ▼                                      │
│  GPT-4o     Claude 3.5                                  │
│  mini       Sonnet                                      │
│  ($0,001)   ($0,015)                                    │
│     │           │                                      │
│     └─────┬─────┘                                      │
│           ▼                                             │
│      Réponse finale                                     │
└────────────────────────────────────────────────────────┘

Combiner routage et prompt caching

Le combo ultime pour réduire les coûts :

OptimisationÉconomieCumulé
Baseline (GPT-4o pour tout)0%$3 000/mois
+ Routage par complexité-60%$1 200/mois
+ Prompt caching (Anthropic)-85% sur cached$480/mois
+ Cache sémantique RAG-30% requêtes$336/mois
Total-89%$336/mois

Métriques et Monitoring

KPIs de routage

DEVELOPERpython
# Métriques essentielles à tracker routing_metrics = { # Distribution "requests_per_model": "Counter par modèle", "complexity_distribution": "Histogram des niveaux", # Qualité "user_satisfaction_per_model": "Score moyen par modèle", "cascade_escalation_rate": "% de requêtes escaladées", "consensus_disagreement_rate": "% de désaccords", # Coûts "cost_per_request_avg": "Coût moyen par requête", "cost_savings_vs_single_model": "Économie vs modèle unique", "classifier_cost_overhead": "Surcoût du classifier", # Performance "routing_latency_p50": "< 50ms", "total_latency_p50": "< 2s", "cache_hit_rate": "> 70%", }

Dashboard type

MétriqueCibleAlerte si
Coût moyen / requête< $0,008> $0,015
Qualité moyenne> 8,5/10< 8,0/10
% requêtes vers modèle cher< 15%> 25%
Latence routage< 50ms> 100ms
Cache hit rate> 70%< 50%
Taux d'escalade cascade< 20%> 35%

ROI du Routage LLM

Calculateur ROI

Profil entrepriseVolumeSans routageAvec routageÉconomie annuelle
Startup50K req/mois$1 500/mois$450/mois$12 600/an
PME300K req/mois$9 000/mois$2 700/mois$75 600/an
Enterprise2M req/mois$60 000/mois$18 000/mois$504 000/an
E-commerce1M req/mois$30 000/mois$9 000/mois$252 000/an

Temps de mise en place

ApprocheTemps devMaintenanceRecommandation
OpenRouter auto1 jourAucunePOC / startup
Martian / Unify2-3 joursFaiblePME
Custom classifier1-2 semainesMoyenneEnterprise
Custom ML router1-2 moisÉlevéeTrès gros volumes

Ailog et le Routage LLM

Le pipeline RAG d'Ailog intègre nativement le routage intelligent :

  • Classifier automatique qui analyse la complexité de chaque question
  • Multi-modèles avec fallback automatique en cas d'erreur
  • Prompt caching combiné pour des économies maximales
  • Dashboard de suivi des coûts et de la qualité par modèle

Découvrez aussi le prompt caching pour aller encore plus loin dans l'optimisation, ou explorez les stratégies de caching RAG pour réduire la latence.

FAQ

Le routage LLM ajoute-t-il de la latence ?

Oui, mais très peu. Le classifier ajoute typiquement 30-80ms (un appel GPT-4o mini avec 50 tokens). Pour un budget total de 2-3 secondes de latence, c'est négligeable. L'astuce : utilisez un classifier basé sur des règles (regex, longueur) pour les cas triviaux, et un LLM classifier uniquement pour les cas ambigus.

Comment mesurer la qualité pour ajuster le routage ?

Trois approches complémentaires : (1) feedback utilisateur (pouce haut/bas), (2) LLM-as-judge qui note les réponses sur 10, (3) métriques RAG (faithfulness, relevance) avec des frameworks comme RAGAS. Comparez les scores par modèle pour ajuster les seuils de routage.

Faut-il un router managé ou custom ?

Pour démarrer, un router managé (OpenRouter, Martian) suffit : mise en place en 1 jour, pas de maintenance. Quand votre volume dépasse 500K requêtes/mois ou que vous avez des besoins spécifiques (modèles privés, latence ultra-basse), passez à un classifier custom.

Le routage fonctionne-t-il avec le streaming ?

Oui. Le classifier décide du modèle avant la génération. La réponse est ensuite streamée depuis le modèle choisi, comme d'habitude. La seule contrainte : le routage en cascade avec évaluation de confiance est incompatible avec le streaming pur (il faut attendre la réponse complète pour évaluer la confiance).

Quel est le risque de dégradation de qualité ?

Avec un routage bien calibré, la dégradation est minime : < 2% en moyenne. Le risque principal est un classifier mal entraîné qui envoie des requêtes complexes vers un modèle léger. Solution : commencez conservateur (seuils hauts) et baissez progressivement en monitorant la qualité.


Prêt à diviser vos coûts IA par 3 ? Créez votre compte Ailog et bénéficiez d'un routage LLM intelligent intégré à votre pipeline RAG, hébergé en France.

Tags

RAGLLM routingoptimisationcoûtsMartianOpenRouterUnifyarchitecture

Articles connexes

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !