Post
Um endpoint para modelos locais e cloud: por que usei LiteLLM como gateway
Como um gateway compatível com OpenAI reduz o acoplamento entre aplicações, modelos locais, provedores cloud e políticas de custo.
Quando uma aplicação chama um único modelo, apontar diretamente para o provedor parece a solução mais simples. O problema começa quando o mesmo ambiente passa a combinar um modelo local para tarefas baratas, um serviço remoto para demandas maiores e um provedor cloud para casos em que qualidade ou capacidade importam mais que o custo.
Sem uma camada intermediária, cada aplicação precisa saber qual URL chamar, como autenticar, qual SDK usar, quais nomes de modelo existem e o que fazer quando um provedor falha. A troca de modelo deixa de ser uma decisão operacional e passa a exigir mudanças distribuídas no código.
No meu homelab, a decisão foi colocar o LiteLLM Proxy entre as aplicações e os provedores. Ele oferece uma API compatível com OpenAI e pode encaminhar chamadas para modelos locais, outras instâncias do próprio LiteLLM e serviços cloud.
1
2
3
4
5
Aplicações, scripts e ferramentas
↓
LiteLLM local
↙ ↓ ↘
modelo local gateway remoto provedor cloud
O objetivo não era esconder a infraestrutura por completo. Era concentrar decisões que não deveriam estar espalhadas por cada cliente: qual modelo usar, onde ele está, quem pode chamá-lo, quanto custa e como observar o que está acontecendo.
O acoplamento aparece antes de percebermos
É comum uma aplicação começar com variáveis como estas:
1
2
3
export OPENAI_BASE_URL="https://provedor-a.exemplo/v1"
export OPENAI_API_KEY="..."
export DEFAULT_MODEL="modelo-do-provedor-a"
Para um experimento isolado, isso é adequado. Mas, quando existem vários consumidores, a configuração se multiplica:
- um script escolhe um modelo local;
- uma ferramenta de linha de comando aponta diretamente para a nuvem;
- um serviço usa outro SDK porque o provedor pede uma interface diferente;
- uma chave de alto privilégio aparece em mais ambientes do que deveria;
- mudar um modelo exige alterar configurações em vários repositórios.
O custo dessa dispersão não é apenas manutenção. Ela reduz a capacidade de responder a perguntas básicas: qual aplicação usou qual modelo? Quanto custou? O que falhou? Quais clientes ainda dependem do provedor antigo?
Um gateway não resolve automaticamente essas perguntas, mas cria o lugar onde elas podem ser tratadas de maneira consistente.
A fronteira que eu queria criar
O LiteLLM funciona como tradutor e proxy. A aplicação fala uma interface conhecida, e o gateway converte a chamada para o provedor configurado. A documentação do projeto descreve suporte a múltiplos provedores, respostas no formato OpenAI, roteamento, fallbacks e rastreamento de uso. A página oficial é a melhor referência para verificar a lista de integrações e recursos da versão em uso.
No meu caso, a fronteira ficou assim:
1
2
3
4
5
Cliente
→ POST /v1/chat/completions
→ alias de modelo
→ LiteLLM
→ implementação escolhida para aquele alias
O cliente não precisa saber se chat-rapido é atendido por uma instância local ou por um provedor externo. Ele precisa saber que há limites de capacidade e que o alias tem uma finalidade clara.
Essa última parte é importante. Eu evitaria expor aliases que apenas repetem o nome do fornecedor, como modelo-x-provedor-y. Isso só desloca o acoplamento de lugar.
Prefiro nomes ligados à intenção de uso:
1
2
3
4
chat-rapido
codigo-padrao
raciocinio
embedding-local
O alias é uma promessa operacional. chat-rapido, por exemplo, pode priorizar custo e tempo de resposta. Se o backend mudar, a promessa precisa continuar válida ou o alias deve ganhar uma nova versão.
Um arquivo de configuração torna a decisão visível
Uma configuração reduzida pode começar assim:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
model_list:
- model_name: chat-rapido
litellm_params:
model: ollama/modelo-local
api_base: os.environ/OLLAMA_BASE_URL
- model_name: raciocinio
litellm_params:
model: vertex_ai/modelo-gerenciado
vertex_ai_project: os.environ/VERTEX_PROJECT
vertex_ai_location: os.environ/VERTEX_LOCATION
- model_name: codigo-padrao
litellm_params:
model: openai/codigo-remoto
api_base: os.environ/REMOTE_GATEWAY_BASE_URL
api_key: os.environ/REMOTE_GATEWAY_API_KEY
Os valores são genéricos de propósito. O ponto é mostrar as três classes de destino que eu precisava tratar:
- um servidor local, apropriado quando a tarefa cabe no hardware disponível;
- um provedor cloud, para modelos que não fazem sentido hospedar;
- outro gateway compatível, que permite delegar uma parte do catálogo a uma instância remota.
O arquivo de configuração não deve carregar chaves reais. Ele referencia variáveis de ambiente ou um mecanismo de segredos. Assim, o mesmo manifesto pode ir para o controle de versão sem transformar credenciais em conteúdo do repositório.
Encadear gateways tem um uso específico
O LiteLLM também pode usar outra instância compatível com OpenAI como destino. Na configuração, isso aparece como um modelo com prefixo openai/, uma URL base e uma credencial limitada para o gateway remoto.
1
2
3
4
5
6
model_list:
- model_name: codigo-padrao
litellm_params:
model: openai/codigo-remoto
api_base: os.environ/REMOTE_GATEWAY_BASE_URL
api_key: os.environ/REMOTE_GATEWAY_API_KEY
Esse encadeamento é útil quando uma instância local precisa manter o contrato para seus clientes, mas não deve conhecer todos os provedores, políticas e credenciais disponíveis em outro ambiente.
Eu o usaria para separar responsabilidades, não para construir uma cadeia arbitrária de proxies. Cada salto adiciona latência, novos modos de falha e uma etapa extra de diagnóstico. Se o cliente pode chamar o destino certo com uma política clara, um proxy adicional talvez seja apenas complexidade.
A aplicação muda pouco
Depois de configurar o gateway, um cliente compatível com OpenAI aponta para uma única URL:
1
2
3
4
5
6
7
8
9
10
11
12
13
from openai import OpenAI
client = OpenAI(
base_url="https://llm.interno/v1",
api_key="chave-do-cliente"
)
response = client.chat.completions.create(
model="chat-rapido",
messages=[
{"role": "user", "content": "Resuma estes pontos."}
]
)
O ganho é que o código do cliente fica concentrado na interação: mensagem, resposta, streaming, ferramentas e tratamento de erro. Roteamento, chaves de provedores e escolha de backend ficam no gateway.
Isso também ajuda quando ferramentas antigas já entendem o protocolo OpenAI, mas não têm suporte nativo a um determinado provedor. Em vez de trocar a ferramenta, eu configuro a URL do gateway e um alias permitido para aquele uso.
Fallback não é sinônimo de trocar qualquer modelo
Um dos recursos mais atraentes de um gateway é poder configurar fallback. Quando um modelo fica indisponível, o proxy pode tentar outro destino. Essa capacidade é útil, mas precisa ser aplicada com critério.
Eu separaria as tarefas em dois grupos.
No primeiro, estão as operações que toleram variação: resumir texto, classificar conteúdo, extrair um campo simples, gerar uma primeira versão. Um fallback para um modelo equivalente pode reduzir indisponibilidade sem comprometer o resultado.
No segundo, estão tarefas em que o comportamento do modelo faz parte do requisito: uma resposta com ferramenta específica, uma análise que exige um contexto grande, uma decisão com política sensível ou uma geração de código que será aplicada automaticamente. Nesses casos, trocar o modelo sem avisar pode criar uma resposta formalmente bem-sucedida, mas errada para o produto.
Eu começaria com roteamento explícito e só adicionaria fallback depois de definir:
- quais modelos são realmente equivalentes para aquela tarefa;
- quais parâmetros e ferramentas precisam existir nos dois destinos;
- como o cliente será informado de que houve troca;
- qual teste de qualidade protege a mudança;
- quando a falha deve chegar ao usuário em vez de ser mascarada.
O gateway torna a mudança possível. Ele não transforma modelos diferentes em componentes intercambiáveis por definição.
A governança começa pela chave certa
Um erro comum é colocar a credencial administrativa do gateway em todos os consumidores. Isso transforma qualquer script em um cliente com poder de administrar modelos, chaves e orçamento.
Eu separaria pelo menos três níveis de acesso:
- uma credencial administrativa, reservada à operação do gateway;
- credenciais de aplicação, limitadas aos aliases e aos limites necessários;
- credenciais dos provedores, mantidas apenas pelo gateway.
O LiteLLM oferece recursos de chaves virtuais, limites e rastreamento por projeto; esses recursos são úteis quando há mais de um consumidor ou quando o custo precisa ser atribuído. Mesmo em um ambiente pequeno, a separação vale a pena porque reduz o impacto de um vazamento e deixa claro quem usa o quê.
Também decidiria com cuidado o que registrar. Logs de latência, status, modelo, contagem de tokens e custo costumam ser suficientes para operar o serviço. Registrar prompts e respostas integralmente pode ser útil para depurar, mas precisa de uma política de retenção e acesso compatível com o conteúdo processado.
O que eu observaria antes de adicionar mais modelos
Com muitos modelos disponíveis, o problema muda de integração para escolha. Colocar todos no catálogo não ajuda se ninguém sabe qual usar.
Eu acompanharia, por alias e por consumidor:
- taxa de sucesso e categorias de erro;
- latência, especialmente p50 e p95;
- tokens de entrada e saída;
- custo estimado para os destinos pagos;
- volume de fallbacks;
- concentração de uso em um único modelo;
- falhas por limite de taxa ou timeout.
Esses dados tornam uma conversa abstrata em uma decisão operacional. Se chat-rapido começa a receber solicitações que exigem contexto maior ou ferramentas indisponíveis localmente, isso aparece como erro, fallback ou latência. A resposta pode ser ajustar o alias, criar outro mais específico ou orientar o cliente a escolher uma capacidade diferente.
Quando eu não criaria esse gateway
Para uma aplicação pequena, um único provedor e uma única credencial bem protegida, adicionar LiteLLM pode ser mais infraestrutura do que benefício. O proxy precisa ser atualizado, monitorado, autenticado e incluído no caminho crítico da requisição.
Também não o trataria como substituto para avaliação de modelos. O gateway consegue encaminhar uma chamada; ele não demonstra que o modelo escolhido atende à qualidade, à privacidade ou ao custo necessário para a tarefa.
Eu consideraria introduzi-lo quando pelo menos uma destas condições aparecer:
- duas ou mais aplicações consomem modelos diferentes;
- existe intenção real de alternar entre local e cloud;
- custos precisam ser medidos por projeto ou cliente;
- a equipe quer retirar credenciais de provedores das aplicações;
- ferramentas distintas já suportam uma interface compatível com OpenAI.
Conclusão
O LiteLLM resolveu um problema de organização: separar o que a aplicação quer fazer da infraestrutura que executa o modelo.
Para começar, eu exporia dois ou três aliases com finalidades bem definidas, manteria as credenciais de provedores dentro do gateway e instrumentaria latência, erro e custo desde o primeiro cliente. Depois de observar o uso real, adicionaria roteamento, fallback ou novos destinos quando houvesse uma necessidade clara.
O endpoint único não elimina as escolhas de IA. Ele as coloca em um lugar onde podem ser revisadas, testadas e operadas sem modificar cada aplicação a cada mudança de modelo.