Português

Colocando Modelos em Produção Sem Quebrá-los

O notebook marcou 0,91 de AUC no seu laptop. O modelo agora está no ar, retornando -infinito para 3% das requisições, o engenheiro de plantão foi acionado às 2h da manhã e você não consegue reproduzir o treinamento original porque nunca fixou o random seed. Bem-vindo à lacuna entre "modelo funciona" e "modelo é publicado."

Assisti a essa cena se repetir em seis empresas, com cinco stacks de ML diferentes, e o padrão não muda. As perdas não são algorítmicas. São operacionais. A discrepância entre treinamento e serviço silenciosamente reduz o AUC em produção em 4 a 7 pontos. Um pipeline de atributos que funcionou ontem emite NaNs hoje porque alguém alterou um schema upstream e não avisou você. A engenharia trata seu modelo como uma caixa-preta porque você tratou o serviço deles da mesma forma.

Este é o playbook que eu gostaria que alguém tivesse me entregado antes do meu primeiro incidente em produção. Ele cobre as sete coisas que decidem se o seu modelo vira uma linha de receita silenciosa ou um tópico recorrente de análise pós-incidente.

Por Que Isso Importa Agora

A maioria das equipes de data science perde de 30 a 50% do valor do modelo entre o AUC offline e o impacto no negócio online. Esse não é um número que inventei. Faça as contas dos seus últimos três modelos publicados: ganho offline, ganho online, tempo de "merged" para "totalmente em produção." A lacuna quase sempre tem o formato de staffing, não de algoritmo.

O DS que tem disciplina de reversão, monitoramento e interface com engenharia entrega 5 vezes mais valor do que o DS com uma arquitetura de modelo marginalmente melhor. Prontidão para produção é uma disciplina, não uma escolha de ferramenta. Você pode fazer isso com AWS Batch e uma tabela no Postgres. Você também pode falhar espetacularmente com o repositório de atributos mais caro do mercado.

Pipeline de Atributos: Feast vs Tecton vs DIY

Toda falha em ML em produção que causei pessoalmente remonta a atributos. Especificamente: os atributos com que o modelo foi treinado não eram os atributos que o modelo via no momento da pontuação. Chamamos isso de discrepância entre treinamento e serviço, e é o exterminador silencioso.

Três opções:

DIY (tabela no Postgres ou view no warehouse). Funciona bem quando você tem um modelo, pontuação em lote e o mesmo SQL produz tanto os dados de treinamento quanto os dados de serviço. A maioria das empresas deveria começar aqui e permanecer aqui por mais tempo do que pensa. A armadilha: quando você começa a adicionar atributos em tempo real, o SQL que escreveu para o treinamento (uma soma acumulada de 7 dias do warehouse) não é o SQL que o serviço de disponibilização executa (um agregado em streaming do Redis). Eles divergem. Silenciosamente.

Feast (open source). Gratuito, você o hospeda. Vale o investimento quando você tem 3 ou mais modelos compartilhando atributos, quer a mesma definição usada tanto no treinamento quanto na disponibilização online, e está disposto a operar Redis/DynamoDB e um pipeline de Spark ou Flink. O custo honesto: você vai gastar um trimestre no onboarding antes de os atributos começarem a fluir. Vale a pena se você já passou da fase de um único modelo.

Tecton (gerenciado). Compre quando a engenharia de atributos for um gargalo real, você tiver orçamento para R$ 400 mil a R$ 1 milhão por ano e preferir não operar infraestrutura de streaming. O Tecton resolve a discrepância entre treinamento e serviço fazendo uma única definição produzir tanto backfills quanto valores online. O rastreamento de linhagem deles detecta "esse atributo mudou na última terça-feira" antes de você notar.

A decisão não é "qual ferramenta é melhor." É: tenho um modelo ou vários, lote ou tempo real, e o desvio de atributos está invisível para mim agora? Se sim-sim-sim, você precisa de um repositório. Se não-não-não, uma view no warehouse e um arquivo feature_definitions.py que você importa tanto no treinamento quanto na disponibilização é mais do que suficiente.

Reprodutibilidade do Pipeline de Treinamento

Se eu pedisse que você reexecutasse agora o job de treinamento exato que produziu o modelo em produção, a partir dos dados brutos, com os mesmos splits e as mesmas métricas, você conseguiria fazer isso em 30 minutos?

Se a resposta for não, você não tem um pipeline reprodutível. Você tem uma lembrança.

O que a reprodutibilidade de fato requer:

  1. Fixe todos os seeds. Não apenas random_state=42 no split treino/teste. Fixe o numpy, o PyTorch/TensorFlow, o seu sampler, o seu embaralhador de dados, qualquer augmentation. Já depurei um modelo em que dois engenheiros obtiveram AUC de 0,86 e 0,91 "do mesmo notebook" porque o RNG de CUDA do torch estava sem seed. Três dias perdidos.

  2. Faça hash dos seus splits. Não confie que train_test_split seja determinístico entre versões do pandas. Calcule um hash estável a partir de um identificador de linha (user_id, transaction_id) módulo a proporção do split. Mesma linha, mesmo split, para sempre. Bônus: quando você retreinar em novos dados, as linhas antigas do conjunto de teste permanecem no conjunto de teste.

  3. Registre o SHA do dataset no artefato do modelo. A ficha do modelo deve incluir: SHA-256 do dataset de treinamento (pós-engenharia de atributos), janela de treinamento (2025-10-01 a 2026-03-31), versão do schema de atributos, commit do código, hash do lockfile de bibliotecas, métricas de avaliação no holdout, métricas de avaliação em um conjunto de referência congelado. Isso vai no mesmo artefato do Git LFS ou MLflow que os pesos do modelo.

  4. Trave o runtime. Um requirements.lock, poetry.lock ou uv.lock commitado junto com o modelo. O desvio de versão de biblioteca quebra a reprodutibilidade silenciosamente. A diferença entre scikit-learn 1.3 e 1.4 é suficiente para alterar as previsões.

O teste de "reexecutar o treinamento de 6 semanas atrás" é inegociável. Se você não consegue passar nele, não pode depurar uma regressão de forma credível. Você está adivinhando.

Disponibilização em Lote vs Tempo Real: Quando Usar Cada Uma

A maioria dos modelos "em tempo real" deveria ser em lote. Vou dizer duas vezes porque é ignorado toda vez. A maioria dos modelos "em tempo real" deveria ser em lote.

A árvore de decisão:

  • Orçamento de latência maior que 1 hora, previsão muda lentamente: lote noturno. Pontue todos às 2h, escreva em uma tabela, o produto lê da tabela. Lead scoring, risco de churn, recomendações de conteúdo para usuários sem cold start. Latência p99: um SELECT.
  • Orçamento de latência de 5 a 60 minutos, previsão precisa de atualização horária: lote horário. Mesmo formato, mais frequente. Previsão de estoque, sinais de demanda.
  • Orçamento de latência de 30 segundos a 5 minutos, depende da atividade da sessão: microlote. Um consumidor de streaming pontua em lotes de 100 a 1.000 registros a cada 30 segundos. Sinais de fraude, detecção de anomalias onde a ação pode esperar um minuto.
  • Orçamento de latência abaixo de 200ms, requisição é imprevisível: tempo real. Ranking de anúncios, relevância de busca, bloqueios de fraude no checkout, personalização em tempo real. Essa é a opção cara. O orçamento de latência p99 deve ser definido no contrato de interface antes do treinamento, não depois do deploy.

A diferença de custo é enorme. Um job de lote noturno roda em uma única instância grande por uma hora. Um serviço em tempo real precisa de autoscaling, warm pools, monitoramento de p99 e um SRE em rotação. Escolha lote a menos que tenha uma razão real.

Uma história de guerra: publicamos um modelo de recomendação "em tempo real" que chamava o Postgres de forma síncrona para três buscas de atributos por requisição. O p99 chegou a 4 segundos antes de detectarmos. A correção não foi um Postgres mais rápido. Foi admitir que o modelo não precisava ser em tempo real, migrá-lo para lote e disponibilizar a partir de uma tabela pré-calculada. A latência caiu para 8ms. A equipe de produto não percebeu a mudança porque as recomendações não dependiam de sessão.

Monitoramento do Modelo: Desvio, Mudança de Conceito, Métrica de Negócio

Quatro coisas a monitorar. Três delas são diagnósticas. Apenas uma paga as contas.

Desvio de entrada. Os atributos que o modelo vê hoje estão distribuídos como os atributos com que ele foi treinado? Acompanhe o Population Stability Index (PSI) por atributo, diariamente. PSI maior que 0,1: investigue. PSI maior que 0,25: a sua distribuição de treinamento e a sua distribuição em produção não são mais as mesmas. Alerte. Para atributos contínuos, execute também um teste de Kolmogorov-Smirnov contra uma janela de referência. Barato, rápido, detecta quebras de schema antes que as previsões piorem.

Desvio de previsão. As saídas do modelo estão distribuídas como estavam na semana passada? Às vezes o desvio de entrada é invisível (interações de atributos mudam) mas o desvio de previsão é evidente. Acompanhe p10/p50/p90 da saída do modelo diariamente.

Desvio de conceito (com consciência de delay no label). A relação entre atributos e o label mudou? Você só pode verificar isso quando os labels chegam, o que para muitos modelos é dias ou semanas depois. Construa um pipeline de avaliação com delay: quando os labels chegarem, recalcule AUC/MAE nessas linhas e plote ao longo do tempo. A armadilha é alertar sobre AUC no dia seguinte ao deploy quando você ainda não tem labels. Você vai ficar olhando para zero.

A métrica de negócio. Receita. Taxa de conversão. CAC. Lifetime value. O que o modelo existe para mover. Essa é a única métrica que decide se o modelo permanece ativo. Limiares de alerta sobre desvio de entrada e previsão são diagnósticos. Limiares de alerta sobre a métrica de negócio são existenciais.

Já vi equipes publicarem um modelo com dashboards de desvio belamente calibrados e zero visibilidade sobre se a receita se moveu. Não seja essa equipe. O primeiro dashboard é o de negócio. Os dashboards de desvio existem para explicar por que a métrica de negócio se moveu, não para substituí-la.

O Lançamento em Modo Sombra

Pontuar sem agir. Por uma a duas semanas. No mesmo tráfego. Compare as previsões do novo modelo com as previsões do modelo atual e com os resultados reais quando os labels chegarem.

Essa é a prática de maior alavancagem que conheço em ML em produção, e a maioria das equipes a pula.

O fluxo do lançamento em modo sombra:

  1. Faça o deploy do novo modelo ao lado do atual. Ambos pontuam cada requisição. Apenas as previsões do modelo atual afetam o comportamento do produto.
  2. Registre ambas as previsões mais todos os atributos usados.
  3. Após 7 a 14 dias, compare:
    • Sobreposição de distribuição: os dois modelos fazem previsões semelhantes para as mesmas entradas? Se 30% divergem, descubra o motivo antes de fazer a troca.
    • Correspondência com expectativas offline: o comportamento online do novo modelo corresponde ao que a sua avaliação no holdout previa? Se offline disse +5% de ganho e o modo sombra diz que são idênticos, seus dados de treinamento tinham vazamento.
    • Latência, taxa de erro, casos extremos (entradas NaN, atributos ausentes): o novo modelo lida bem com a cauda longa?
  4. Só faça a troca quando os dados do modo sombra confirmarem a história offline.

Campeão/desafiante é a mesma ideia, formalizada. O modelo atual é o campeão. O novo modelo é o desafiante. Você não promove o desafiante até que ele tenha vencido sob tráfego real, não apenas em um conjunto de teste.

O próprio lançamento deve ser gradual: 1% para 5% para 25% para 50% para 100%, com pelo menos 24 a 48 horas entre etapas e a métrica de negócio monitorada em cada estágio. Se qualquer coisa se mover na direção errada, pause. Não racionalze.

Padrões de Parceria com Engenharia: Contratos de Interface

O modelo de "jogar o pickle por cima do muro" falha toda vez. Veja o que funciona em vez disso.

Antes de começar o treinamento, sente-se com o engenheiro de plataforma e escreva um contrato de interface de uma página. Ele cobre:

  • Schema da API. Campos de entrada, tipos, nulos permitidos, regras de validação. Campos de saída, tipos, intervalos. Como é a resposta quando o modelo não consegue pontuar (atributos ausentes, servidor do modelo fora do ar)?
  • SLO de latência. p50, p95, p99 em milissegundos. Isso determina se você pode fazer buscas de atributos em tempo real, quais arquiteturas de modelo estão descartadas, se a inferência em GPU é necessária.
  • SLO de throughput. Requisições por segundo no pico. Orienta a configuração de autoscaling.
  • Orçamento de erro. Qual porcentagem das requisições o serviço pode falhar? 0,1%? 1%? Isso define o nível de rigor para validação de entrada.
  • Limite de responsabilidade. Quem é acionado quando o modelo retorna previsões erradas versus quando o serviço retorna erros 500? DS é dono do primeiro. Engenharia é dona do segundo. Ambos são donos do terceiro (modelo está no ar mas as previsões estão ruins).
  • Autoridade de reversão. Quem pode acionar o interruptor de emergência sem escalonar? Às 3h da manhã, a resposta deveria ser "o engenheiro de plantão," não "acione a Camellia."

Escreva isso. Assine. Fixe. Quando o inevitável incidente em produção acontecer, o contrato é o que mantém a conversa focada em resolver o problema em vez de negociar responsabilidade.

O DS que chega a essa reunião com um rascunho de contrato conquista confiança no momento em que entra. O DS que chega com um notebook e pergunta "como fazemos o deploy disso?" começa do zero.

Disciplina de Reversão

Todo deploy inclui um caminho de reversão testado. Não documentado. Testado.

Três componentes:

  1. Versionamento. Cada modelo recebe uma versão (pricing-model-v23). Cada previsão registrada inclui a versão que a pontuou. Quando você investiga uma regressão, pode filtrar por versão.
  2. O interruptor de emergência. Um sinalizador de configuração que redireciona o tráfego do novo modelo de volta para o anterior em menos de 60 segundos. Não um redeploy. Uma troca de sinalizador. O serviço de disponibilização lê o sinalizador no momento da requisição.
  3. Exercícios de reversão. A cada trimestre, execute a reversão em produção por 5 minutos durante uma janela de baixo tráfego. Se você não acionou o gatilho em 90 dias, a reversão é teórica, o que significa que não funciona.

A primeira vez que você precisar de uma reversão não é o momento para descobrir que o artefato do modelo anterior foi deletado do S3, que o pipeline de atributos foi refatorado ou que o interruptor de emergência nunca funcionou. Já vivi os três pessoalmente.

Erros Comuns

  • Treinar em dados que o modelo não consegue ver no momento da disponibilização. Vazamento de dados. A forma mais comum: um atributo que só é computável após o evento que você está prevendo. Um atributo de "dias desde o último login" calculado a partir do warehouse vai incluir logins posteriores ao timestamp da previsão, a menos que você o corte explicitamente.
  • Fixar random_state=42 mas não fixar o seed do sampler upstream. Seus splits são determinísticos; seu treinamento não é.
  • Fazer deploy sem campeão/desafiante. Você está adivinhando se o novo modelo é melhor.
  • Alertar sobre AUC em vez de receita. AUC foi de 0,84 para 0,82: é ruim? Você não sabe. Talvez a receita tenha subido.
  • Sem teste de reversão em 90 dias. Você não tem uma reversão. Você tem um desejo.
  • Tratar engenharia como um balcão de atendimento em vez de um parceiro. Eles vão tratar seu modelo da mesma forma.

Templates e Ferramentas

Os quatro documentos que todo modelo publicado deve ter:

  • Ficha do modelo. SHA do dataset, janela de treinamento, seed, versão do schema de atributos, métricas de avaliação no holdout e em referência congelada, SLO de disponibilização, responsável, data de deploy, procedimento de reversão.
  • Checklist de comparação em modo sombra. Sobreposição de distribuição, correspondência offline-online, latência, taxa de erro, tratamento de casos extremos, requisitos de aprovação por parte interessada.
  • Runbook de reversão. Passo a passo para acionar o interruptor de emergência, como verificar que o modelo anterior está servindo tráfego, a quem notificar, template de análise pós-incidente.
  • Contrato de interface DS/Engenharia. Uma página. Schema da API, SLOs, orçamento de erro, limite de responsabilidade, autoridade de reversão. Assinado pelo DS, pelo líder de engenharia e pela rotação de plantão.

Medindo o Sucesso

Você está fazendo isso certo quando:

  • Você consegue reexecutar o treinamento exato de qualquer modelo em produção a partir dos dados brutos em menos de 30 minutos.
  • Todo deploy tem uma reversão testada que foi exercida nos últimos 90 dias.
  • O monitoramento detecta o desvio antes que a métrica de negócio se mova, não depois.
  • Seu engenheiro de plataforma diz "trabalhar com você é fácil" sem ser provocado.
  • Os últimos três deploys foram entediantes.

Deploys entediantes são o objetivo. Drama é falha. O DS que publica de forma entediante é o DS que publica com frequência, e o DS que publica com frequência compõe valor mais rápido do que qualquer um com uma arquitetura de modelo marginalmente melhor.

Saiba Mais