Os motivos para trocar são quase sempre os mesmos três: custo que cresceu junto com o uso, preço em dólar que oscila com o câmbio, ou a necessidade de manter o processamento numa instância que você controla.
E o medo é sempre o mesmo: quebrar o que funciona. Ele é justificado — mas o risco vem quase todo de como se migra, não de para onde.
A boa notícia técnica
O formato de chamada virou padrão de fato. A maioria absoluta dos servidores de modelo aberto expõe os mesmos endpoints — /v1/chat/completions, /v1/models —, aceita os mesmos campos e responde na mesma estrutura, inclusive em fluxo contínuo.
Na prática, isso costuma significar duas linhas:
from openai import OpenAI
cliente = OpenAI(
base_url="https://gpubrasil.com.br/v1",
api_key="gpub_live_...",
)
r = cliente.chat.completions.create(
model="gpub-plus",
messages=[{"role": "user", "content": "Resuma este texto: ..."}],
)
O mesmo SDK, o mesmo código, o mesmo tratamento de erro. É por isso que a migração é factível — e é exatamente por isso que ela costuma ser feita mal: parece tão simples que as pessoas trocam a URL, testam três perguntas e sobem.
O mesmo prompt não produz o mesmo resultado. Modelos diferentes têm vieses de formato diferentes: um responde com lista quando você pediu parágrafo, outro é mais verboso, outro obedece melhor a restrição de tamanho.
A migração é um problema de qualidade, não de integração. Quem trata como troca de URL descobre a diferença pelo cliente.
Os sete passos
1. Crie a camada de abstração (antes de qualquer coisa)
Se o seu código chama a API direto de doze lugares, a migração vira caça ao tesouro e o caminho de volta não existe. Centralize:
PROVEDORES = {
"atual": {"url": "https://api.provedor-a.exemplo/v1", "chave": CH_A},
"novo": {"url": "https://gpubrasil.com.br/v1", "chave": CH_B},
}
MAPA_MODELO = {
("atual", "rapido"): "modelo-pequeno-a",
("atual", "capaz"): "modelo-grande-a",
("novo", "rapido"): "gpub-mini",
("novo", "capaz"): "gpub-base",
}
def chamar(perfil, mensagens, provedor=None, **kw):
p = provedor or roteamento_do_fluxo(perfil)
cfg = PROVEDORES[p]
cli = OpenAI(base_url=cfg["url"], api_key=cfg["chave"])
return cli.chat.completions.create(
model=MAPA_MODELO[(p, perfil)], messages=mensagens, **kw
)
Repare que o resto da aplicação passa a pedir "rápido" ou "capaz", não um nome de modelo. Essa indireção é o que torna toda decisão futura reversível — inclusive a de voltar atrás.
2. Monte a avaliação com o modelo atual
Antes de trocar qualquer coisa, você precisa saber quanto o sistema atual acerta. Trinta a cinquenta casos reais, rodados no que está em produção hoje. Esse número é a linha de base — sem ele, "o novo modelo está pior" é opinião.
Se você ainda não tem, comece por montar isso. É meio dia de trabalho e serve para tudo depois.
3. Rode os dois em paralelo, com os dois resultados guardados
Em produção, sem mostrar o novo a ninguém: para uma amostra do tráfego real, chame os dois modelos e grave as duas respostas. Custa o dobro nessa amostra e vale cada centavo.
import random, threading
def responder(perfil, mensagens, contexto):
resposta = chamar(perfil, mensagens, provedor="atual")
if random.random() < 0.10: # 10% do tráfego, em sombra
threading.Thread(target=comparar_em_segundo_plano,
args=(perfil, mensagens, resposta, contexto),
daemon=True).start()
return resposta
Depois de alguns dias você tem centenas de pares de respostas ao mesmo pedido real. É a evidência mais forte que existe — muito melhor que qualquer teste sintético.
4. Ajuste o prompt para o novo modelo
Esta é a etapa que quase todo mundo pula, e é onde a maior parte da diferença de qualidade se resolve. Prompts são afinados, ao longo de meses, para as manias do modelo que você usava. O novo tem outras.
O que costuma precisar de ajuste:
- Tamanho da resposta. Se o novo é mais prolixo, seja explícito: "no máximo 3 frases".
- Formato. Se você dependia de o modelo devolver JSON por hábito, passe a exigir por esquema.
- Exemplos. Um ou dois exemplos no prompt corrigem viés de formato melhor que qualquer instrução.
- Raciocínio. Se o novo modelo pensa antes de responder e o antigo não, o comportamento e o custo mudam — decida se você quer isso naquele fluxo.
Depois do ajuste, rode a avaliação de novo. É comum o novo modelo sair de "3 pontos abaixo" para "2 pontos acima" só com o prompt adaptado.
5. Migre por fluxo, do mais fácil ao mais crítico
| Ordem | Fluxo | Por quê |
|---|---|---|
| 1º | Classificação, extração, tarefas fechadas | Verificáveis por código; erro aparece na hora |
| 2º | Processamento em lote, relatórios internos | Sem usuário esperando; dá tempo de conferir |
| 3º | Resumos e reescritas voltados ao usuário | Impacto visível, mas reversível |
| 4º | Atendimento a cliente, código, decisão | Só depois que os anteriores estabilizaram |
A primeira faixa costuma ser a maior parte do volume e a menor parte do risco. Migrando só ela, muita gente já captura o grosso da economia e pode decidir com calma sobre o resto.
6. Mantenha o caminho de volta ligado
Não desligue a conta antiga no dia da migração. Deixe a chave viva e o roteamento capaz de voltar por configuração — sem novo deploy — por pelo menos trinta dias.
def roteamento_do_fluxo(perfil):
if config.get("forcar_provedor"): # botão de emergência
return config["forcar_provedor"]
return config["provedor_por_perfil"].get(perfil, "atual")
Melhor ainda: caminho alternativo automático em caso de erro, que também protege contra instabilidade de qualquer um dos dois lados.
7. Acompanhe por duas semanas
O que olhar, no seu registro: taxa de erro, latência no percentil 95, custo por fluxo, taxa de bloqueio do filtro de saída e sinais implícitos de insatisfação — pergunta refeita, pedido de atendente, conversa abandonada.
Regressão de qualidade raramente aparece como erro. Aparece como pessoas repetindo a pergunta.
O que muda de verdade na conta
Além do preço por token, três diferenças costumam pesar mais que a tabela:
- Moeda. Cobrança em reais elimina a variação cambial e o custo de operação financeira do pagamento internacional. Numa conta que oscila com o dólar, isso é previsibilidade, não só desconto.
- Saldo único. Quando a API por token e as GPUs por hora saem do mesmo saldo, o controle orçamentário some da planilha e vira um número só.
- Instância dedicada, quando necessário. Para o fluxo em que você precisa controlar modelo, registros e retenção, dá para sair da API e subir a sua própria máquina — sem trocar de fornecedor nem de código, graças à camada do passo 1.
Teste com 10% do tráfego, em paralelo
API compatível com o formato da OpenAI, cobrada em reais no mesmo saldo das GPUs. Você troca a base_url e compara com o que já tem.
Criar conta →Quando não migrar
- Você depende de um recurso específico que só aquele provedor tem, e ele é central no produto.
- O seu fluxo mais crítico está no limite da qualidade — se hoje acerta 82% e o mínimo aceitável é 80%, não há margem para experimentar em produção.
- O gasto é pequeno. Abaixo de algumas centenas de reais por mês, a economia não paga o tempo de engenharia. Faça a camada de abstração assim mesmo — ela é barata e prepara o terreno.
Conclusão
Migração de modelo não é troca de URL, e também não é reescrita. É camada de abstração, linha de base medida, comparação em sombra com tráfego real, prompt readaptado e migração por fluxo, do mais fácil ao mais crítico — com o caminho de volta ligado o tempo todo.
Feita assim, ela deixa de ser um evento arriscado e vira uma configuração. E, uma vez que o produto sabe falar com dois provedores, você nunca mais fica preso a nenhum dos dois.
Continue: avaliação automática · comparativo de preços · servidor próprio