Multimodel systeemontwerp: wanneer één model niet genoeg is
Kies het eenvoudigste patroon dat werkt.
Systeem met één model zijn eenvoudig. Systemen met meerdere modellen zijn krachtig. De uitdaging ligt niet in het kiezen van modellen, maar in het ontwerpen van de architectuur die ze orchestreert.
Een systeem met meerdere modellen gaat niet over het hebben van meer modellen. Het gaat over het hebben van het juiste model voor de juiste taak op het juiste moment.

Architectuurpatronen
Vijf patronen dekken de meeste gebruiksscenario’s:
| Patroon | Complexiteit | Wanneer te gebruiken | Afweging |
|---|---|---|---|
| Enkel Model | Laagst | Prototyping, eenvoudige taken | Beperkte capaciteit |
| Sequentieel | Laag | Workflows met meerdere stappen | Hogere latentie |
| Parallel | Middel | Onafhankelijke taken | Hogere kosten |
| Hiërarchisch | Hoog | Complexe redenering | Complexe orchestratie |
| Ensemble | Hoogst | Kritieke beslissingen | Hoogste kosten |
Kies het eenvoudigste patroon dat werkt. Complexiteit is echt en deze cumuleert.
Sequentiële architectuur
Verwerk taken via een keten van modellen, elk gespecialiseerd in een stap.
Patroon 1: Pipeline
Pipelinepatroon — de output van elk model voert naar het volgende:
class ModelPipeline:
def __init__(self):
self.models = [
{"model": "qwen2.5-1.5b", "task": "classify"},
{"model": "qwen2.5-7b", "task": "extract"},
{"model": "qwen2.5-32b", "task": "reason"},
]
def process(self, input: str) -> str:
current = input
for model_config in self.models:
current = self.call_model(
model_config["model"],
self.create_prompt(model_config["task"], current)
)
return current
Latentie telt op. Drie modellen in serie betekent driemaal de latentie. Gebruik dit alleen wanneer elke stap daadwerkelijk een ander model nodig heeft.
Patroon 2: Router
Routerpatroon — classificeer de taak, routeer naar de specialist:
class ModelRouter:
def __init__(self):
self.classifier = "qwen2.5-1.5b"
self.specialists = {
"code": "qwen2.5-coder-7b",
"math": "qwen2.5-32b",
"creative": "claude-sonnet-4",
"general": "qwen2.5-7b",
}
def route(self, prompt: str) -> str:
task_type = self.classify(prompt)
model = self.specialists.get(task_type, self.specialists["general"])
return self.call_model(model, prompt)
De classifier is de zwakke schakel. Als deze verkeerd classificeert, wordt naar het verkeerde model geroet en gaat kwaliteit verloren. Gebruik een classifier die goed genoeg is — zelfs een kleine werkt als de categorieën duidelijk zijn.
Parallelle architectuur
Verwerk onafhankelijke taken gelijktijdig.
Patroon 1: Fan-Out
Fan-out — voer dezelfde prompt uit door meerdere modellen:
import asyncio
class ModelFanOut:
def __init__(self):
self.models = [
"qwen2.5-7b",
"qwen2.5-32b",
"claude-sonnet-4",
]
async def process(self, prompt: str) -> list[str]:
tasks = [self.call_model(model, prompt) for model in self.models]
return await asyncio.gather(*tasks)
Nuttig voor vergelijking, A/B-testen, of wanneer u de beste output wilt kiezen. Duur, maar de kwaliteitswinst is het waard voor kritieke beslissingen.
Patroon 2: Voting
Voting — combineer outputs via consensus:
class ModelVoting:
def __init__(self):
self.models = [
"qwen2.5-7b",
"qwen2.5-32b",
"claude-sonnet-4",
]
def vote(self, prompt: str) -> str:
responses = [self.call_model(model, prompt) for model in self.models]
from collections import Counter
votes = Counter(responses)
return votes.most_common(1)[0][0]
Meerderheidsstemmen werken voor classificatie. Voor generatietaken is het moeilijker — u hebt semantische similariteit nodig, geen exacte matches.
Hiërarchische architectuur
Gebruik modellen op verschillende niveaus van abstractie.
Patroon 1: Planner-Executor
Planner-executor — een sterk model plant, kleinere modellen voeren uit:
class PlannerExecutor:
def __init__(self):
self.planner = "qwen2.5-32b"
self.executors = {
"code": "qwen2.5-coder-7b",
"search": "qwen2.5-7b",
"math": "qwen2.5-7b",
}
def process(self, task: str) -> str:
plan = self.call_model(self.planner, f"Plan: {task}")
results = []
for step in self.parse_plan(plan):
executor = self.executors.get(step["type"], "qwen2.5-7b")
result = self.call_model(executor, step["prompt"])
results.append(result)
return self.call_model(self.planner, f"Synthesize: {results}")
De planner doet het zware werk. De executors hanteren specifieke taken. Dit patroon werkt goed wanneer de planstap duur is, maar de uitvoeringsstappen goedkoop.
Patroon 2: Supervisor-Worker
Supervisor-worker — een supervisor delegeert en reviewt:
class SupervisorWorker:
def __init__(self):
self.supervisor = "qwen2.5-32b"
self.workers = ["qwen2.5-7b", "qwen2.5-coder-7b"]
def process(self, task: str) -> str:
assignments = self.call_model(self.supervisor, f"Assign: {task}")
results = []
for assignment in self.parse_assignments(assignments):
result = self.call_model(
assignment["worker"], assignment["task"]
)
results.append(result)
return self.call_model(self.supervisor, f"Review: {results}")
De supervisor is de bottleneck. Deze plant, delegeert en reviewt. Zorg dat deze snel genoeg is, anders vertraagt het hele systeem.
Ensemble-architectuur
Combineer meerdere modellen voor kritieke beslissingen.
Patroon 1: Weighted Ensemble
Weighted ensemble — score de output van elk model, kies de hoogste:
class WeightedEnsemble:
def __init__(self):
self.models = {
"qwen2.5-32b": 0.5,
"claude-sonnet-4": 0.3,
"qwen2.5-7b": 0.2,
}
def decide(self, prompt: str) -> str:
responses = {
model: self.call_model(model, prompt)
for model in self.models
}
scores = {}
for model, response in responses.items():
score = self.evaluate(response) * self.models[model]
scores[response] = scores.get(response, 0) + score
return max(scores, key=scores.get)
Gewichten weerspiegelen uw vertrouwen in elk model. Pas ze aan op basis van daadwerkelijke prestaties, niet op benchmarks.
Patroon 2: Consensus Ensemble
Consensus ensemble — vereis overeenstemming, escaleer als deze ontbreekt:
class ConsensusEnsemble:
def __init__(self, threshold: float = 0.7):
self.threshold = threshold
self.models = [
"qwen2.5-32b",
"claude-sonnet-4",
"qwen2.5-7b",
]
def decide(self, prompt: str) -> str:
responses = [
self.call_model(model, prompt)
for model in self.models
]
from collections import Counter
votes = Counter(responses)
max_votes = max(votes.values())
if max_votes / len(self.models) >= self.threshold:
return votes.most_common(1)[0][0]
return self.call_model("qwen2.5-32b", prompt)
De drempel regelt hoe streng consensus is. 0,7 betekent twee derde overeenstemming. Verlaag deze voor snellere beslissingen, verhoog deze voor meer zekerheid.
Wanneer multi-model systemen zinvol zijn
Multi-model systemen zijn zinvol wanneer u gemengde werklasten heeft, hoge kwaliteit nodig heeft voor kritieke beslissingen, of optimaliseert voor kosten of latentie.
Ze zijn niet zinvol wanneer alle taken vergelijkbare complexiteit hebben, u prototyping doet, of wanneer eenvoud belangrijker is dan optimalisatie.
De vuistregel: begin met één model. Voeg er meer toe wanneer u tegen een echte beperking stoot — kosten, latentie of kwaliteit. Ontwerp complexiteit niet voordat u deze nodig heeft.
Afwegingen
| Patroon | Kosten | Latentie | Kwaliteit | Complexiteit |
|---|---|---|---|---|
| Enkel Model | Laagst | Laagst | Variabel | Laagst |
| Sequentieel | Middel | Hoog | Hoog | Middel |
| Parallel | Hoog | Laag | Hoog | Middel |
| Hiërarchisch | Hoog | Hoog | Hoogst | Hoog |
| Ensemble | Hoogst | Middel | Hoogst | Hoogst |
Elk patroon maakt een afweging. Kies degene die past bij uw beperkingen.
Gerelateerd
- Model Routing Strategies — routing op basis van capaciteit, kostenbewust en latentiebewust
- Cost Optimization for LLM Systems — tokenbudgettering, fallback-modellen, caching
- LLM Guardrails in Practice — validatie van invoer, filtering van uitvoer, veiligheid
- LLM Architecture — pijler van systeemontwerp: routing, kosten, guardrails en orchestratie