en
· 3 min de leitura

O modelo vai mudar. A interface não deveria.

Projete a fronteira em volta do modelo para que trocar provedor, versão ou prompt seja mudança de config, não reescrita.

aiarchitecture

No tempo em que venho entregando features em cima de modelos de linguagem, todo modelo com que comecei já foi substituído. Descontinuado, superado, encarecido ou simplesmente batido por outro. Isso não vai parar. Se o comportamento do seu produto está ligado diretamente ao SDK de um provedor, a um formato de prompt e a um conjunto de manias, toda troca de modelo vira projeto de migração. A saída é a mesma que engenheiros de sistemas usam para bancos de dados e provedores de pagamento há décadas: coloque uma interface na frente da coisa que muda, e faça o resto do sistema depender da interface.

O que a interface controla

A interface que coloco em volta de um modelo é mais estreita do que a maioria dos SDKs. Ela recebe um request tipado: nome da tarefa, entradas estruturadas, um schema de saída, e restrições como latência máxima e custo máximo. Devolve um resultado tipado, validado contra o schema, com metadados: qual modelo respondeu, tokens usados, latência, e se houve fallback. Templates de prompt vivem atrás da interface, indexados por tarefa, versionados. Clientes de provedor vivem atrás dela. Retries, timeouts e rate limits vivem atrás dela. A aplicação nunca vê uma string de completion crua e nunca monta um prompt. Ela pede que uma tarefa seja feita e recebe uma resposta tipada ou um erro tipado.

Por que tarefas, e não prompts

Chamar a unidade de "tarefa" em vez de "prompt" é a decisão mais útil desse design. Uma tarefa como "classificar ticket de suporte" tem um contrato estável: estas entradas, este formato de saída, esta barra de qualidade. Como ela é cumprida é detalhe de implementação. Hoje pode ser um frontier model com um prompt longo. No próximo trimestre pode ser um modelo pequeno com fine-tuning nos seus próprios dados, ou uma consulta em cache para os noventa por cento de tickets que se repetem. O código da aplicação não muda. O conjunto de evals daquela tarefa também não muda, o que significa que você consegue medir se a nova implementação é tão boa quanto a antiga antes de virar a chave.

O conjunto de evals é o teste de contrato

Interface sem teste é esperança. Para cada tarefa atrás da fronteira mantenho um conjunto de evals: entradas reais, saídas esperadas ou uma regra de pontuação, e um limiar. Trocar o modelo significa rodar o conjunto contra a nova implementação e comparar. É exatamente o que um teste de contrato faz para uma API HTTP, e é a única coisa que torna trocas de modelo entediantes. Sem isso, todo upgrade é uma semana de verificação manual e uma regressão silenciosa em algum lugar onde ninguém olhou.

Coisas que vazam

  • Recursos específicos do provedor, como formatos de tool calling ou tokens especiais, usados direto no código da aplicação.
  • Parsing de saída que assume os hábitos de formatação de um modelo específico.
  • Prompts que citam o modelo pelo nome ou dependem da tolerância de um modelo a instruções ambíguas.
  • Premissas de custo embutidas em decisões de produto, como "dá para chamar a cada tecla digitada".

Cada um desses é um lugar onde o modelo escapou da fronteira e virou parte do produto. Procuro por eles em auditorias, e encontro em quase toda base de código que ganhou uma feature de IA às pressas.

Roteamento é a recompensa

Quando a interface existe, roteamento fica barato. Mande as entradas fáceis para um modelo pequeno e as difíceis para um frontier model. Mande uma porcentagem do tráfego para um candidato e compare. Caia para uma resposta em cache quando o provedor estiver fora. Nada disso é possível quando a aplicação fala direto com o provedor, e tudo isso são poucas linhas quando ela fala com uma interface. O modelo é a dependência que muda mais rápido que você tem. Trate como tal.