Modellrouting: Stop met het gebruik van één model voor alles

Het juiste model voor de juiste taak.

Inhoud

Het draaien van een model met 70 miljard parameters om een e-mail van 200 woorden samen te vatten, is zonde van de middelen. Het gebruiken van een model van 3 miljard parameters om productiecode te reviewen, is roekeloos. De meeste systemen zitten ergens daar tussenin — en daar komt modelrouting om de hoek kijken.

Het koppelt taakcomplexiteit aan modelcapaciteit. De afwegingen zijn reëel, maar de besparingen ook.

Diagram van LLM-modelroutingstrategieën

Het routingprobleem

Mensen beginnen meestal met één model en blijven daar bij. Dat werkt tot je merkt dat de kosten, de latentie, of beide, een probleem worden. Het alternatief is het bouwen van een router — iets dat beslist welk model welk verzoek afhandelt.

In de praktijk werken vier strategieën:

  1. Op capaciteit gebaseerd — routeer op basis van wat het model kan
  2. Kostenbewust — routeer op basis van wat je wilt uitgeven
  3. Latentiebewust — routeer op basis van hoe snel je het nodig hebt
  4. Hybride — combineer ze

Elke strategie optimaliseert iets anders. Het kiezen van één is meestal een beslissing over wat het meest pijn doet.

Routing op basis van capaciteit

De eenvoudigste aanpak. Classificeer de taak, stuur het naar het model dat het afhandelt.

Taak Modelgrootte Voorbeelden
Classificatie, tagging 1-3B Qwen3-1.7B, Gemma-2-2B
Samenvatten, extractie 3-7B Qwen3-8B, Llama-3.1-8B
Codegeneratie 7-14B Qwen2.5-Coder-7B, DeepSeek-Coder-V2
Complexe redenering 14-32B Qwen3-32B, Llama-3.1-70B
Creatief schrijven, analyse 32B+ Qwen2.5-72B, Claude, GPT-4

Als de taak het grotere model niet nodig heeft, gebruik het dan niet. Een model van 1,5B parameters handelt sentimentclassificatie prima af. Het schrijft echter geen coherent betoog.

De implementatie is eenvoudig:

ROUTING_RULES = {
    "classify": {"model": "qwen3-1.7B", "max_tokens": 100},
    "summarize": {"model": "qwen3-8B", "max_tokens": 500},
    "code_review": {"model": "qwen2.5-coder-7b", "max_tokens": 2000},
    "reason": {"model": "qwen3-32b", "max_tokens": 4000},
    "creative": {"model": "claude-sonnet-4", "max_tokens": 8000},
}

def route_request(task_type: str) -> dict:
    return ROUTING_RULES.get(task_type, ROUTING_RULES["reason"])

De valkuil is de classificatie zelf. Als je de taaktype verkeerd classificeert, routeer je naar het verkeerde model. Ik heb systemen zien classificeren code-review als “samenvatten” en daardoor stilsgaand in kwaliteit verliezen.

Kostenbewuste routing

Lokale inferentie blinkt hier uit. Lokale modellen zijn effectief gratis na afschrijving van de hardware. Een RTX 5080 heeft zich binnen ongeveer zes maanden terugverdiend bij matig API-gebruik.

Model Input ($/M tokens) Output ($/M tokens) Lokale kosten/uur
GPT-4o $2.50 $10.00
Claude Sonnet 4 $3.00 $15.00
Qwen2.5-72B (API) $0.50 $2.00
Qwen3-32B (lokaal) $0.00 $0.00 ~$0.10
Qwen3-8B (lokaal) $0.00 $0.00 ~$0.05

Als je duizenden verzoeken per sessie verwerkt, wint zelfs $0,05 aan elektriciteit het van $15/M tokens.

Budgetgebaseerde routing valt terug naarmate je meer uitgeeft:

class CostAwareRouter:
    def __init__(self, budget_per_session: float = 0.10):
        self.budget = budget_per_session
        self.spent = 0.0
        self.models = {
            "cheap": {"model": "qwen3-8B", "cost": 0.0},
            "medium": {"model": "qwen3-32b", "cost": 0.0},
            "expensive": {"model": "claude-sonnet-4", "cost": 0.000015},
        }

    def route(self, task: str) -> str:
        ratio = self.spent / self.budget
        if ratio < 0.5:
            return self.models["expensive"]["model"]
        elif ratio < 0.8:
            return self.models["medium"]["model"]
        return self.models["cheap"]["model"]

De kwaliteit daalt naarmate je terugvalt. Je begint met Claude, gaat over naar Qwen3-32B, en dan naar Qwen3-8B. Aan het einde van een lange sessie is de output merkbaar slechter. Of dat uitmaakt, hangt af van wat je bouwt.

Latentiebewuste routing

Interactieve tools hebben snelle eerste tokens nodig. Batchtaken kunnen wachten. Het verschil is meestal een factor vijf in modelgrootte.

Geval van toepassing Eerste token Volledig Max modelgrootte
Realtime chat < 200ms < 2s < 7B
Interactieve tools < 500ms < 5s < 14B
Batchverwerking < 1s < 30s Elk
Onderzoek/analyse < 2s < 60s Elk

Wanneer je tokens naar een gebruiker streamt, is de latentie van het eerste token wat ze voelen. Een model van 32B dat een halve seconde nodig heeft om te starten, voelt traag vergeleken met een model van 1,5B dat direct reageert.

class LatencyAwareRouter:
    def __init__(self):
        self.model_latencies = {
            "qwen3-1.7b": {"first_token": 0.05, "complete": 0.5},
            "qwen3-8B": {"first_token": 0.15, "complete": 2.0},
            "qwen3-32b": {"first_token": 0.5, "complete": 10.0},
            "claude-sonnet-4": {"first_token": 0.3, "complete": 5.0},
        }

    def route(self, target_latency: float) -> str:
        for model, latencies in sorted(
            self.model_latencies.items(),
            key=lambda x: x[1]["complete"]
        ):
            if latencies["complete"] <= target_latency:
                return model
        return "qwen3-1.7b"

De latentiecijfers zijn ruw — ze hangen af van je hardware, kwantisatie en batchgrootte. Meet ze op je eigen setup.

Terugvalstrategieën

Modellen falen. API’s rate-limiten. Time-outs treden op. Het patroon dat werkt, is een terugvalketen, gerangschikt van beste naar meest betrouwbaar:

class FallbackRouter:
    def __init__(self):
        self.fallback_chain = [
            {"model": "claude-sonnet-4", "timeout": 30},
            {"model": "qwen2.5-72b", "timeout": 60},
            {"model": "qwen3-32b", "timeout": 120},
            {"model": "qwen3-8b", "timeout": 300},
        ]

    def route_with_fallback(self, prompt: str) -> str:
        for config in self.fallback_chain:
            try:
                return self.call_model(
                    config["model"], prompt,
                    timeout=config["timeout"]
                )
            except (TimeoutError, APIError) as e:
                log.warning(f"Model {config['model']} failed: {e}")
                continue
        raise RuntimeError("All fallback models failed")

Het laatste model in de keten zou lokaal moeten zijn. Het is langzamer, maar het faalt niet door een netwerkprobleem of een API-sleutel.

Wanneer routing helpt

Routing heeft zin wanneer je werklast gemengd is. Als je classificatie, samenvatting en redenering in hetzelfde systeem doet, bespaart een router geld en latentie.

Het heeft geen zin als alles wat je doet dezelfde complexiteit heeft. Gebruik gewoon het model dat goed is in die taak. De router voegt complexiteit toe die je niet nodig hebt.

Vroeg prototypen is nog een reden om het te laten. Laat de taak werken met één model, en voeg routing toe wanneer kosten of latentie daadwerkelijk een probleem worden.

Afwegingen

Elke routingstrategie optimaliseert iets en offert iets anders op:

  • Enkel model — eenvoudigst, duurste, consistente kwaliteit
  • Op capaciteit gebaseerd — betere kosten, hogere kwaliteit per taak, matige complexiteit
  • Kostenbewust — goedkoopst, variabele kwaliteit, matige complexiteit
  • Latentiebewust — snelst, kan kwaliteit offeren, matige complexiteit
  • Hybride — het beste van alle, meest complex om te implementeren

Productiesystemen convergeren meestal naar hybride. Begin met routing op basis van capaciteit, voeg kostenbewustzijn toe wanneer de rekening binnenkomt, en voeg latentiebewustzijn toe wanneer gebruikers klagen over trage prestaties.

Gerelateerd

Abonneren

Ontvang nieuwe berichten over systemen, infrastructuur en AI-engineering.