Roteamento de Modelos: Pare de Usar Um Único Modelo para Tudo
O modelo certo para a tarefa certa.
Executar um modelo de 70 bilhões de parâmetros para resumir um e-mail de 200 palavras é um desperdício. Executar um modelo de 3 bilhões de parâmetros para revisar código de produção é imprudente. A maioria dos sistemas fica em algum ponto intermediário — e é aí que o roteamento de modelos entra.
Ele alinha a complexidade da tarefa à capacidade do modelo. Os compromissos (trade-offs) são reais, mas as economias também.

O problema do roteamento
As pessoas geralmente começam com um modelo e se mantêm nele. Isso funciona até que você perceba o custo, ou a latência, ou ambos. A alternativa é construir um roteador — algo que decida qual modelo lida com qual solicitação.
Quatro estratégias funcionam na prática:
- Baseado em capacidade — rotear pelo que o modelo pode fazer
- Com consciência de custo — rotear pelo quanto você está disposto a gastar
- Com consciência de latência — rotear pela velocidade necessária
- Híbrido — combiná-los
Cada uma otimiza algo diferente. Escolher uma geralmente é uma decisão sobre o que mais dói.
Roteamento baseado em capacidade
A abordagem mais simples. Classifique a tarefa, envie-a para o modelo que a lida.
| Tarefa | Tamanho do modelo | Exemplos |
|---|---|---|
| Classificação, etiquetagem | 1-3B | Qwen2.5-1.5B, Gemma-2-2B |
| Resumo, extração | 3-7B | Qwen2.5-7B, Llama-3.1-8B |
| Geração de código | 7-14B | Qwen2.5-Coder-7B, DeepSeek-Coder-V2 |
| Raciocínio complexo | 14-32B | Qwen2.5-32B, Llama-3.1-70B |
| Escrita criativa, análise | 32B+ | Qwen2.5-72B, Claude, GPT-4 |
Se a tarefa não precisa do modelo maior, não o use. Um modelo de 1.5B lida bem com classificação de sentimento. Ele simplesmente não escreverá um ensaio coerente.
A implementação é direta:
REGRAS_DE_ROTEAMENTO = {
"classificar": {"modelo": "qwen2.5-1.5b", "max_tokens": 100},
"resumir": {"modelo": "qwen2.5-7b", "max_tokens": 500},
"revisao_de_codigo": {"modelo": "qwen2.5-coder-7b", "max_tokens": 2000},
"raciocinar": {"modelo": "qwen2.5-32b", "max_tokens": 4000},
"criativo": {"modelo": "claude-sonnet-4", "max_tokens": 8000},
}
def rotear_solicitacao(tipo_tarefa: str) -> dict:
return REGRAS_DE_ROTEAMENTO.get(tipo_tarefa, REGRAS_DE_ROTEAMENTO["raciocinar"])
O problema é a própria classificação. Se você errar o tipo de tarefa, roteará para o modelo errado. Vi sistemas classificar revisão de código como “resumo” e perder qualidade silenciosamente.
Roteamento com consciência de custo
A inferência local brilha aqui. Modelos locais são efetivamente gratuitos após a amortização do hardware. Uma RTX 5080 se paga em cerca de seis meses com um uso moderado de API.
| Modelo | Entrada ($/M tokens) | Saída ($/M tokens) | Custo local/hora |
|---|---|---|---|
| GPT-4o | $2.50 | $10.00 | — |
| Claude Sonnet 4 | $3.00 | $15.00 | — |
| Qwen2.5-72B (API) | $0.50 | $2.00 | — |
| Qwen2.5-32B (local) | $0.00 | $0.00 | ~$0.10 |
| Qwen2.5-7B (local) | $0.00 | $0.00 | ~$0.05 |
Se você está processando milhares de solicitações por sessão, até $0.05 em eletricidade supera $15/M tokens.
O roteamento baseado em orçamento recua conforme você gasta:
class RoteadorComConscienciaDeCusto:
def __init__(self, orcamento_por_sessao: float = 0.10):
self.orcamento = orcamento_por_sessao
self.gasto = 0.0
self.modelos = {
"barato": {"modelo": "qwen2.5-7b", "custo": 0.0},
"medio": {"modelo": "qwen2.5-32b", "custo": 0.0},
"caro": {"modelo": "claude-sonnet-4", "custo": 0.000015},
}
def rotear(self, tarefa: str) -> str:
proporcao = self.gasto / self.orcamento
if proporcao < 0.5:
return self.modelos["caro"]["modelo"]
elif proporcao < 0.8:
return self.modelos["medio"]["modelo"]
return self.modelos["barato"]["modelo"]
A qualidade se degrada conforme você recua. Você começa com Claude, move-se para Qwen-32B, depois para Qwen-7B. No final de uma sessão longa, a saída é notavelmente pior. Se isso importa depende do que você está construindo.
Roteamento com consciência de latência
Ferramentas interativas precisam de primeiros tokens rápidos. Tarefas em lote podem esperar. A diferença geralmente é um fator de cinco no tamanho do modelo.
| Caso de uso | Primeiro token | Completo | Tamanho máximo do modelo |
|---|---|---|---|
| Chat em tempo real | < 200ms | < 2s | < 7B |
| Ferramentas interativas | < 500ms | < 5s | < 14B |
| Processamento em lote | < 1s | < 30s | Qualquer |
| Pesquisa/análise | < 2s | < 60s | Qualquer |
Quando você está transmitindo tokens para um usuário, a latência do primeiro token é o que eles sentem. Um modelo de 32B levando meio segundo para começar parece lento em comparação com um modelo de 1.5B que dispara instantaneamente.
class RoteadorComConscienciaDeLatencia:
def __init__(self):
self.latencias_modelos = {
"qwen2.5-1.5b": {"primeiro_token": 0.05, "completo": 0.5},
"qwen2.5-7b": {"primeiro_token": 0.15, "completo": 2.0},
"qwen2.5-32b": {"primeiro_token": 0.5, "completo": 10.0},
"claude-sonnet-4": {"primeiro_token": 0.3, "completo": 5.0},
}
def rotear(self, latencia_alvo: float) -> str:
for modelo, latencias in sorted(
self.latencias_modelos.items(),
key=lambda x: x[1]["completo"]
):
if latencias["completo"] <= latencia_alvo:
return modelo
return "qwen2.5-1.5b"
Os números de latência são aproximados — eles dependem do seu hardware, quantização e tamanho do lote. Meça na sua própria configuração.
Estratégias de fallback
Modelos falham. APIs limitam taxa. Timeouts acontecem. O padrão que funciona é uma cadeia de fallback, ordenada do melhor ao mais confiável:
class RoteadorComFallback:
def __init__(self):
self.cadeia_fallback = [
{"modelo": "claude-sonnet-4", "timeout": 30},
{"modelo": "qwen2.5-72b", "timeout": 60},
{"modelo": "qwen2.5-32b", "timeout": 120},
{"modelo": "qwen2.5-7b", "timeout": 300},
]
def rotear_com_fallback(self, prompt: str) -> str:
for config in self.cadeia_fallback:
try:
return self.chamar_modelo(
config["modelo"], prompt,
timeout=config["timeout"]
)
except (TimeoutError, APIError) as e:
log.warning(f"Modelo {config['modelo']} falhou: {e}")
continue
raise RuntimeError("Todos os modelos de fallback falharam")
O último modelo na cadeia deve ser local. É mais lento, mas não falhará devido a um problema de rede ou chave de API.
Quando o roteamento ajuda
O roteamento faz sentido quando sua carga de trabalho é mista. Se você está fazendo classificação, resumo e raciocínio no mesmo sistema, um roteador economiza dinheiro e latência.
Não faz sentido quando tudo o que você faz tem a mesma complexidade. Apenas use o modelo que é bom nessa tarefa. O roteador adiciona complexidade que você não precisa.
Prototipagem inicial é outra razão para ignorá-lo. Faça a tarefa funcionar com um modelo, então adicione roteamento quando custo ou latência realmente se tornarem um problema.
Compromissos (Trade-offs)
Cada estratégia de roteamento otimiza algo e sacrifica outra coisa:
- Modelo único — mais simples, mais caro, qualidade consistente
- Baseado em capacidade — melhor custo, qualidade mais alta por tarefa, complexidade moderada
- Com consciência de custo — mais barato, qualidade varia, complexidade moderada
- Com consciência de latência — mais rápido, pode sacrificar qualidade, complexidade moderada
- Híbrido — o melhor de todos, mais complexo de implementar
Sistemas de produção geralmente convergem para híbrido. Comece com roteamento baseado em capacidade, adicione consciência de custo quando a conta chegar, adicione consciência de latência quando os usuários reclamarem da lentidão.
Relacionado
- Otimização de Custos para Sistemas LLM — orçamento de tokens, cache, modelos de fallback
- Guardrails LLM na Prática — validação de entrada, filtragem de saída, segurança
- Design de Sistema Multi-Modelo — arquitetura para múltiplos modelos
- Arquitetura LLM — pilar de design de sistema: roteamento, custo, guardrails e orquestração