Design de Sistemas Multi-Modelos: Quando Um Único Modelo Não Basta

Escolha o padrão mais simples que funcione.

Conteúdo da página

Sistemas de modelo único são simples. Sistemas de multimodelo são poderosos. O desafio não é escolher os modelos — é projetar a arquitetura que os orquestra.

Um sistema de multimodelo não se trata de ter mais modelos. Trata-se de ter o modelo certo para a tarefa certa no momento certo.

Padrões de design de sistemas de LLM multimodelo

Padrões de arquitetura

Cinco padrões cobrem a maioria dos casos de uso:

Padrão Complexidade Quando usar Compensação (Tradeoff)
Modelo Único Mais baixa Prototipagem, tarefas simples Capacidade limitada
Sequencial Baixa Fluxos de trabalho em múltiplos passos Maior latência
Paralelo Média Tarefas independentes Maior custo
Hierárquico Alta Raciocínio complexo Orquestração complexa
Ensemble (Conjunto) Mais alta Decisões críticas Maior custo

Escolha o mais simples que funcione. A complexidade é real e ela se acumula.

Arquitetura sequencial

Processe tarefas através de uma cadeia de modelos, cada um especializado em uma etapa.

Padrão 1: Pipeline (Canalização)

Padrão de pipeline — a saída de cada modelo alimenta o próximo:

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

A latência acumula-se. Três modelos em sequência significam três vezes a latência. Use isto apenas quando cada etapa realmente precisar de um modelo diferente.

Padrão 2: Router (Encaminhador)

Padrão de roteamento — classifique a tarefa, encaminhe para o especialista:

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)

O classificador é o elo fraco. Se ele classificar incorretamente, você encaminha para o modelo errado e perde qualidade. Use um classificador que seja bom o suficiente — mesmo um pequeno funciona se as categorias forem claras.

Arquitetura paralela

Processe tarefas independentes simultaneamente.

Padrão 1: Fan-Out (Leque)

Fan-out — execute o mesmo prompt através de múltiplos modelos:

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)

Útil para comparação, testes A/B ou quando você deseja escolher a melhor saída. Caro, mas o ganho de qualidade vale a pena para decisões críticas.

Padrão 2: Voting (Votação)

Votação — combine saídas através de consenso:

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]

A votação pela maioria funciona para classificação. Para tarefas de geração, é mais difícil — você precisa de similaridade semântica, não de correspondências exatas.

Arquitetura hierárquica

Use modelos em diferentes níveis de abstração.

Padrão 1: Planner-Executor (Planejador-Executor)

Planejador-executor — um modelo forte planeja, modelos menores executam:

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}")

O planejador faz o trabalho pesado. Os executores lidam com tarefas específicas. Este padrão funciona bem quando a etapa de planejamento é cara, mas as etapas de execução são baratas.

Padrão 2: Supervisor-Worker (Supervisor-Trabalhador)

Supervisor-trabalhador — um supervisor delega e revisa:

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}")

O supervisor é o gargalo. Ele planeja, delega e revisa. Certifique-se de que ele seja rápido o suficiente, ou todo o sistema ficará lento.

Arquitetura de Ensemble (Conjunto)

Combine múltiplos modelos para decisões críticas.

Padrão 1: Weighted Ensemble (Ensemble Ponderado)

Ensemble ponderado — avalie a saída de cada modelo, escolha a mais alta:

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)

Os pesos refletem sua confiança em cada modelo. Ajuste-os com base no desempenho real, não em benchmarks.

Padrão 2: Consensus Ensemble (Ensemble de Consenso)

Ensemble de consenso — exija acordo, escale se não houver nenhum:

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)

O limite (threshold) controla quão rigoroso é o consenso. 0,7 significa dois terços de acordo. Reduza-o para decisões mais rápidas, aumente-o para maior confiança.

Quando os sistemas multimodelo fazem sentido

Os sistemas multimodelo fazem sentido quando você tem cargas de trabalho mistas, precisa de alta qualidade para decisões críticas ou está otimizando para custo ou latência.

Eles não fazem sentido quando todas as tarefas têm complexidade similar, você está prototipando ou a simplicidade é mais importante do que a otimização.

A regra geral: comece com um modelo. Adicione mais quando atingir uma restrição real — custo, latência ou qualidade. Não arquitecte complexidade antes de precisar dela.

Compensações (Tradeoffs)

Padrão Custo Latência Qualidade Complexidade
Modelo Único Mais baixo Mais baixa Variável Mais baixa
Sequencial Médio Alta Alta Média
Paralelo Alto Baixa Alta Média
Hierárquico Alto Alta Mais alta Alta
Ensemble (Conjunto) Mais alto Média Mais alta Mais alta

Cada padrão troca algo. Escolha aquele que corresponde às suas restrições.

Relacionados

Assinar

Receba novos artigos sobre sistemas, infraestrutura e engenharia de IA.