Voltar para todos os posts

Um Modelo de Decisão "System 1" para Atendimento em PT-BR — Parte 4: O Bake-off de Juízes e o v6 Híbrido

41 min de leitura
  • decisum
  • making-of
  • benchmarks

Decisum é o nome público do modelo que chamamos internamente de "decisor". Esta série de making-of preserva a nomenclatura interna usada durante o desenvolvimento.

Raphael Pizzo — Especialista em Machine Learning Outubro de 2026 · Série técnica, parte 4

Nota de anonimização: como nas partes anteriores, nenhum nome de empresa, produto ou plataforma aparece neste texto. O juiz da Parte 3 (modelo de chat de propósito geral) segue sendo "o juiz". O novo modelo avaliado aqui — um modelo de decisão de propósito específico, acessado por API tipada — será chamado de juiz-D. O único nome real é o do autor.


1. O problema que sobrou: o teto do juiz único

A Parte 3 prometeu que o próximo capítulo seria produto, não treino. Esta parte é a exceção que confirma a regra — uma última volta de treino, justificada por um fato novo: apareceu um professor melhor a preço de café.

A vitória do v5 tinha uma verdade incômoda embutida: todo o train tinha sido re-rotulado por um único juiz — o mesmo modelo de chat, com o mesmo guia de anotação e os mesmos few-shots. O ouro humano (999 chamados do núcleo) provou que esse juiz era muito melhor que a prata de regex que o antecedeu. Mas "melhor que a prata" não é "bom o bastante": o próprio ouro mede a concordância do juiz com o humano, e ela está longe de 100% — numa amostra estratificada de 76 casos do núcleo, o juiz concorda com o humano em 71% das respostas, somadas as três perguntas (seção 4).

A pergunta científica natural: existe um juiz melhor? E a pergunta de engenharia, igualmente importante: a quanto?

2. O candidato improvável: um modelo que não conversa

O juiz-D não é um modelo de chat. Ele não recebe prompt de sistema, não recebe few-shots, não gera texto livre. A API dele recebe um estado (o texto do chamado) e um conjunto de perguntas tipadas — choice (escolha entre opções, cada uma com uma descrição-critério) e score (escala ordenada) — e devolve, por pergunta: a opção vencedora, as probabilidades de cada opção e uma confiança.

Três propriedades mudam o jogo:

  1. Probabilidades por opção, nativamente. Um juiz de chat devolve um rótulo duro; pedir distribuição calibrada de um chat é teatro. O juiz-D devolve a distribuição de verdade — o que o torna um professor de destilação KL pronto, não só um rotulador.
  2. Preço de entrada irrisório e saída grátis. A chamada média saiu por ~US$ 0,00008. Rotular os 6.217 casos de CS do train custou US$ 0,49 no total — menos que o café da esquina.
  3. Sem few-shots. Todo o conhecimento de domínio tem que caber nas descrições-critério de cada opção — uma página de guia destilada em uma linha por categoria. Isso é uma limitação e um teste de pureza: mede o que o modelo sabe fazer por arquitetura, não por prompt.

O lado ruim, declarado antes dos números: o modelo não é determinístico (não há temperatura a fixar), e a própria documentação admite que abaixo de confiança 0,7 cerca de 40% das respostas mudam em repetição. Rótulo de treino não precisa ser perfeito — precisa ser melhor que a alternativa. É isso que o bake-off mede.

3. O desenho do bake-off

A régua é o ouro humano — o único conjunto em que confio cegamente, porque cada um dos 999 chamados do núcleo passou por olhos humanos (os meus), com adjudicação nos casos de baixa confiança.

  • Amostra: 76 casos do núcleo do ouro, estratificados por categoria (seed 42). Amostra pequena de propósito: este é um teste de fumaça barato antes de comprometer um treino de 4 horas, não um estudo clínico.
  • Juiz (chat): exatamente o pipeline da Parte 3 — guia de anotação completo + few-shots, temperatura 0. O melhor que o chat sabe fazer.
  • Juiz-D: o mesmo estado do chamado (truncado em 12.000 caracteres, confortavelmente abaixo do limite prático da API), as mesmas 3 perguntas, com os critérios de uma linha destilados do guia (incluindo os quatro desempates difíceis descobertos na adjudicação do ouro). Zero few-shots. Uma assimetria de protocolo declarada: urgência chega ao juiz-D como score ordenado (0–3) e vira rótulo pelo argmax das probabilidades; para o chat, é choice como sempre foi.
  • Métrica: acurácia contra o ouro, por pergunta (categoria, decisão, urgência) e geral.

4. Resultado do bake-off

perguntajuiz (chat, guia+few-shots)juiz-D (só critérios)
categoria0,7630,711
decisão0,6970,816
urgência0,6710,737
geral0,7110,754

E nos 14 desacordos de categoria entre os dois juízes, o ouro concordou com o chat 9 vezes e com o juiz-D 5.

Leitura honesta, sem torcida:

  1. Não existe vencedor único — existe divisão de trabalho. O juiz-D entende melhor o que fazer (decisão) e quão grave é (urgência); o chat entende melhor que tipo de caso é (categoria). Faz sentido: categoria é a pergunta com 17 opções e fronteiras sutis de domínio — onde o guia completo e os few-shots do chat mais pesam.
  2. A margem geral (4,4pp) não é conclusiva com n=76; as margens por pergunta são mais informativas. Decisão (+11,9pp) é o sinal mais forte do bake-off.
  3. O custo assimétrico muda a decisão mesmo sem vencedor claro. Se o juiz-D empatasse em tudo, ainda assim seria interessante: centavos por mil casos e probabilidades por opção de graça.

5. A destilação híbrida

A regra de montagem do train v6 cai direto da tabela acima — cada pergunta fica com o juiz que o ouro aprovou:

perguntarótulo do v6por quê
categoriajuiz (chat) — como já estava0,763 vs 0,711; ouro 9×5 nos desacordos
decisãojuiz-D (argmax)0,816 vs 0,697
urgênciajuiz-D (argmax)0,737 vs 0,671

Destilar os 6.217 casos de CS (3.982 do train re-rotulado da Parte 3 + 2.235 casos novos de abr–out, recuperados de exports antigos e dedupados contra corpus e ouro) levou ~7 minutos, zero falhas, US$ 0,49. As probabilidades por opção de cada caso ficaram arquivadas — são os soft targets de uma futura destilação KL, se o argmax desta rodada mostrar que a direção é boa.

5.1 O que a troca de juiz mudou nos rótulos

perguntarótulos trocadoso que mudou
decisão35,7%escalar 984 → 2.220; executar_acao 4.498 → 2.949; pedir_mais_info 464 → 933; rejeitar 208 → 22
urgência28,4%3 - crítica 703 → 271; 1 - moderada 2.177 → 2.502

O juiz-D é sistematicamente mais conservador: escala mais, executa menos no nível 1, e distribui muito menos "crítica". Como o ouro concorda mais com ele exatamente nessas duas perguntas, a leitura é que o juiz de chat estava super-resolvendo e super-dramatizando — comportamento coerente com um modelo treinado para agradar ("posso resolver isso pra você!").

5.2 O que NÃO mudou

  • Os dados externos de robustez (e-commerce público e tickets em inglês) seguem com os rótulos originais: o bake-off não mediu esse domínio, e não se troca o que não se mediu.
  • O ouro segue intocável como teste permanente. Nenhum rótulo do ouro participa de treino; nenhum juiz novo "vota" nele.
  • Config de treino: idêntica à do v5 (2 épocas, smoothing 0,05, sem class weighting). Duas variáveis mudam de uma vez — dados novos e rótulos novos — e a seção 6 vai precisar ser honesta sobre esse confundimento deliberado: esta é uma série de engenharia com GPU contada, não um delineamento fatorial.

6. Resultados do v6 contra o ouro

Protocolo: split por caso (seed 42) sobre o ouro (999 núcleo adversarial

  • 500 aleatórios não-enviesados; 1.499 casos × 3 perguntas), temperature scaling ajustado no split de calibração, métricas no teste. As ECEs abaixo são pós-temp.

Tabela principal (teste, n = 753 casos por pergunta):

métricav6v5v3
acc categoria0,55780,52990,3028
acc decisao0,59630,62020,6215
acc urgencia0,67460,63880,3240
acc geral0,60960,59630,4161
macro-F1 categoria0,41350,38590,1882
ECE pós-temp (cat / dec / urg)0,066 / 0,044 / 0,0280,046 / 0,052 / 0,0440,059 / 0,096 / 0,125

Breakdown por subset (acurácia, "todas" = média das 3 perguntas):

subsetv6v5v3
núcleo (n = 999 casos)0,58820,58350,4011
aleatorio (n = 500 casos)0,65100,62110,4453

Veredito pela regra fixada a priori: o v6 vence — 0,5882 contra 0,5835 do v5 no subset núcleo (+0,5 pp no critério acordado).

Leitura honesta. O híbrido ganhou onde o bake-off dizia que ganharia: a categoria (única pergunta em que o juiz-chat foi escolhido) subiu +2,8 pp no geral e +7,8 pp no subset aleatório, e a urgencia (juiz-D) subiu +3,6 pp, com macro-F1 de categoria também acima do v5. A perda ficou na decisao (−2,4 pp contra o v5), pergunta em que o juiz-D já empatava com o juiz-chat no bake-off — trocar o rotulador não comprou nada ali, e o v3 segue ligeiramente acima dos dois nessa pergunta, um sinal de que decisao pode ter um teto ligado à ambiguidade intrínseca dos casos, não ao rotulador. O confundimento de variáveis é declarado como foi planejado: mudamos dados novos e rótulos novos ao mesmo tempo, então não é possível atribuir o ganho isoladamente a um dos dois — o que a tabela permite dizer é que o pacote inteiro não degradou nenhuma pergunta além da margem acima e ainda entregou a maior cobertura de roteamento automático entre os candidatos (17,4% das linhas com acurácia 0,83 no auto). Sobre o subset aleatório, a ressalva de circularidade permanece: o juiz-chat rotulou o treino do v6, então os 0,651 devem ser lidos como teto otimista — foi exatamente por isso que o critério fixado a priori olha só o núcleo. A calibração pós-avaliação convergiu (T* = 1,15 / 1,35 / 1,30 para 4 / 5 / 17 opções; ECE no split de calibração 0,018 / 0,030 / 0,059) e está gravada no checkpoint.

Estado da API: o v5 segue em produção. O v6 está calibrado e apto ao swap — que fica pendente de autorização explícita do dono, dado que o v5 acabou de entrar.

7. Se o v6 vencer: o caminho da destilação de verdade

Esta rodada usou o juiz-D como rotulador de argmax. Mas ele devolve a distribuição inteira por opção — e isso habilita o passo que a literatura chama de destilação propriamente dita: treinar o aluno com KL divergence contra os soft targets do professor, em vez de entropia cruzada contra rótulos duros. Soft targets carregam a geometria do professor ("este caso é 52% bug e 45% dúvida" informa muito mais que "bug"), e é a técnica por trás de meia década de modelos pequenos que performam acima do que seu tamanho sugere. Os 6.217 conjuntos de probabilidades já estão arquivados esperando a decisão.

8. Lições da Parte 4

  1. Juiz também se audita. O bake-off de juízes contra o ouro custou centavos e 10 minutos — e evitou assumir que "o juiz que já temos" é o teto.
  2. Modelo especializado vence prompt engenhoso em 2 de 3 perguntas; na terceira (categoria, 17 opções de fronteira sutil), o guia completo e os few-shots do chat ainda pagam a diferença.
  3. Híbrido não é gambiarra, é alocação: cada pergunta com o juiz que o ouro aprovou — e o v6 confirmou no teste, ganhando exatamente nas perguntas onde trocou de juiz.
  4. Probabilidade por opção é o ativo subestimado. Rótulo duro todo mundo dá; distribuição calibrada, não.
  5. Vitória por critério a priori vale mais que vitória retórica. O ganho no núcleo foi de meio ponto percentual — real, mas dentro da margem de ruído; a região de decisao ainda regrediu. A destilação KL com os soft targets arquivados é o próximo alavancamento natural, não um luxo.
  6. Critério fixado antes de ver o número protege contra autoengano. O subset aleatório mostrou +3 pp a favor do v6, mas é circular (juiz-chat rotulou o treino); o critério legítimo foi o núcleo.

9. v8: a aposta multilíngue

O v6 tinha um teto óbvio: 6.217 casos, todos em português. A aposta do v8 foi destravar escala com o ativo mais barato do pipeline — o juiz-D — em outro idioma: 48.765 linhas de tickets em inglês (fontes públicas de suporte), rotuladas pelo juiz-D com os mesmos critérios de uma linha, somadas à receita inteira do v6. Treino e config idênticos; a única variável nova é o corpus EN.

Asterisco metodológico, declarado antes da tabela: o juiz-D foi validado por bake-off apenas em PT-BR. A transferência para o inglês foi assumida, não medida — a auditoria humana de 50 casos EN estava pendente no momento da escrita desta seção.

Tabela principal (teste, n = 753 casos por pergunta):

métricav8v6v5v3
acc categoria0,53390,55780,52990,3028
acc decisao0,59890,59630,62020,6215
acc urgencia0,67860,67460,63880,3240
acc geral0,60380,60960,59630,4161
macro-F1 categoria0,41130,41350,38590,1882
ECE pós-temp (cat / dec / urg)0,066 / 0,048 / 0,0330,066 / 0,044 / 0,0280,046 / 0,052 / 0,0440,059 / 0,096 / 0,125

Breakdown por subset (acurácia "todas"):

subsetv8v6v5v3
núcleo (n = 999 casos)0,58690,58820,58350,4011
aleatorio (n = 500 casos)0,63670,65100,62110,4453

Veredito pela regra fixada a priori (acc geral no núcleo): o v8 NÃO vence — 0,5869 contra 0,5882 do v6, uma derrota por 0,13 pp, dentro da margem de ruído do teste mas uma derrota pela régua acordada, e derrotas pela régua acordada se registram com o mesmo cuidado das vitórias (tradição do v4). Sem calibração, sem fila de produção.

Leitura honesta. O inglês não quebrou o modelo — 0,6038 no geral, acima do v5, e a urgencia até melhorou (0,6786, melhor marca da linhagem) —, mas também não moveu a régua que importa. No núcleo, o v8 ganhou a categoria (+0,6 pp sobre o v6) e a urgencia (+0,4 pp), e perdeu na decisao (−1,4 pp), pergunta que segue amaldiçoada: o v6 já havia regredido ali contra o v5 (0,5963 × 0,6202) e o v8 apenas recuperou parte do estrago (0,5989), permanecendo abaixo de um modelo três gerações mais velho. O padrão de confusão do v8 no núcleo (conta_config ↔ duvida_produto, bug_produto → incidente) é o mesmo de sempre, agora em versão bilíngue. Duas hipóteses ficam abertas, e nenhuma é inocente: ou o juiz-D em EN rotula com viés diferente do validado em PT (e a auditoria pendente de 50 casos humanos é exatamente o teste entre as duas), ou o ganho de escala em dados fora de domínio simplesmente dilui os 6.217 casos de CS que carregam a régua. Enquanto isso não se desfaz, o corpus EN é um ativo em observação, não um fato consumado.

Estado da API: o v5 segue em produção; o v6 segue calibrado e na fila do swap; o v8 fica sem calibração, checkpoint arquivado como candidato reprovado pelo critério. Por decisão do dono, o v9 (receita do v8 + 136.845 linhas de fontes públicas rotuladas pelo juiz-D) entrou na GPU logo após esta avaliação — os números do v8 foram analisados enquanto o v9 treinava, e a próxima seção tratará dele.


10. v9: a escala máxima — e o teto que ela não moveu

O v8 perdeu por 0,13 pp, um empate técnico. A leitura da seção 9 deixou duas hipóteses abertas — viés de rótulo do juiz-D em EN, ou diluição de domínio — e o v9 foi desenhado para testá-las à força: receita inteira do v8 mais 136.845 linhas novas de fontes públicas HF, todas rotuladas pelo juiz-D — twitter (74,6k, com oversampling de mensagens de raiva), bitext (55,5k, EN), openjev_cs (3,4k) e br_pt (2,8k). Treino e config idênticos; a variável nova é volume puro, o maior lote externo da linhagem.

Tabela principal (teste, n = 753 casos por pergunta):

métricav9v8v6v5v3
acc categoria0,53780,53390,55780,52990,3028
acc decisao0,58830,59890,59630,62020,6215
acc urgencia0,64540,67860,67460,63880,3240
acc geral0,59050,60380,60960,59630,4161
macro-F1 categoria0,41930,41130,41350,38590,1882
ECE pós-temp (cat / dec / urg)0,081 / 0,053 / 0,0450,066 / 0,048 / 0,0330,066 / 0,044 / 0,0280,046 / 0,052 / 0,0440,059 / 0,096 / 0,125

Breakdown por subset (acurácia "todas"):

subsetv9v8v6v5v3
núcleo (n = 999 casos)0,57750,58690,58820,58350,4011
aleatorio (n = 500 casos)0,61590,63670,65100,62110,4453

Veredito pela regra fixada a priori (acc geral no núcleo): o v9 PERDEU — 0,5775 contra 0,5882 do v6, uma derrota por 1,07 pp. Não é mais empate técnico: é a primeira regressão de mais de 1 ponto no núcleo desde o v4, e ela veio justamente do experimento de maior escala da linhagem. Sem calibração, sem fila.

Leitura honesta, ressalva por ressalva. (1) A auditoria EN do juiz-D segue pendente com o dono — e o v9 agravou exatamente a aposta não auditada, acrescentando 55,5k linhas bitext em inglês às 48,7k do v8. O sinal indireto aponta para ruído de rótulo: as duas perguntas que regrediram (decisao −1,1 pp sobre o v8, urgencia −3,3 pp) são as mais sensíveis ao tom do rótulo, enquanto categoria, a mais lexical, melhorou. Mas sem os 50 casos auditados isso é atribuição plausível, não medição — e agora há 184k linhas EN em dois checkpoints arquivados pousando nessa incógnita. (2) O oversampling de raiva do twitter foi checado na distribuição de erros e inocentado no mérito relevante: no núcleo, os erros que mais cresceram foram baixa → moderada (67 no v8, 80 no v9), não moderada → alta (18 → 16), e alta → moderada ficou estável (47 → 50). A regressão de urgência vem da fronteira baixa ↔ moderada — o modelo novo hesita mais entre "pode esperar" e "precisa de atenção" —, não de urgência inflada. Se o oversampling teve efeito, foi borrar essa fronteira, não empurrar o medidor para cima. (3) O "outro" não virou lixeira: F1 de 0,676 contra 0,689 do v8, estável, e nenhuma das 12 confusões mais frequentes do v9 termina em "outro" — os 16k de "outro" do bloco novo não contaminaram o comportamento no ouro. O que os dados novos de fato mudaram: a categoria subiu no núcleo (+0,6 pp sobre o v8) e o macro-F1 de categoria é o melhor da linhagem inteira — os volumes ajudam a separar o que o chamado é, mas cobram o preço em o que fazer com ele e com que pressa. Por fim, um dado que fecha qualquer atalho: o ECE de categoria do v9 (0,081) é o pior dos recentes — ele não seria promovido nem como calibrado. O teto do núcleo segue em 0,5882, marcado pelo v6, um modelo treinado só com os 6.217 casos de CS e zero volume externo.

Estado da API: o v5 segue em produção; o v6 segue calibrado e na fila do swap; o v8 e o v9 ficam sem calibração, checkpoints arquivados como reprovados pelo critério. O próximo candidato já tem dados prontos — o v7-KL, destilação com soft targets em data/processed_v7/ —, e o teto que o v9 não moveu define o que ele precisa quebrar.


11. v7-KL: soft targets contra rótulos duros — o experimento controlado

O v7 é o experimento mais limpo da linhagem: mesmos 18.651 exemplos do v6, mesmo backbone, mesma agenda — a única diferença é que decisão e urgência carregam a distribuição completa do juiz-D (probs_alvo, KL-divergência com alpha 1.0 e temperatura 2.0) em vez do rótulo duro. Categoria, que não recebeu soft target nenhum, funciona como controle negativo embutido no desenho. A pergunta é direta: a incerteza que o professor confessa (entropia normalizada média de 0,43 em decisão, 0,42 em urgência) chega ao aluno ou evapora no caminho?

Avaliação contra o ouro, mesma régua de sempre (split por caso seed 42, temperatura calibrada no calib, métricas no teste, n=753 linhas por modelo). O campeão vigente é o v6 (núcleo 0,5882); o v9 entrou na mesma rodada para referência.

11.1 Núcleo duro (subset adversarial, n=497 por pergunta)

perguntav7-KLv6 (campeão)v9 (referência)
categoria0,52720,51910,5372
decisao0,59960,57950,5533
urgencia0,66400,66600,6419
todas0,59690,58820,5775

11.2 Headline de produção (subset aleatório, n=256 por pergunta)

perguntav7-KLv6 (campeão)
categoria0,60160,6328
decisao0,65620,6289
urgencia0,70310,6914
todas0,65360,6510

11.3 Teste completo (n=2259 linhas)

métricav7-KLv6 (campeão)
acc geral0,61620,6096
ECE categoria0,07360,0656
ECE decisao0,06770,0440
ECE urgencia0,02460,0282
macro-F1 categoria0,38330,4135

11.4 Veredito do experimento

O KL venceu, com ressalvas que importam. No núcleo — o subset que decide promoção — o v7 marcou 0,5969 contra 0,5882 do v6 (+0,87 p.p.), novo teto da linhagem, e confirmou a direção no aleatório não-enviesado (0,6536 contra 0,6510). O ganho vem inteiro de decisão: +2,0 p.p. no núcleo e +2,7 p.p. no aleatório, exatamente a pergunta onde o professor mais confessa incerteza — a hipótese do apêndice A.3 se confirmou onde ela era testável. Urgência empatou dentro do ruído (0,6640 contra 0,6660 no núcleo), e categoria — o controle que não recebeu tratamento nenhum — ficou a meio ponto percentual do v6 no núcleo, o que é exatamente o esperado se a única coisa que mudou foi o alvo das duas perguntas tratadas. Em outras palavras: o experimento controlado se comportou como um experimento controlado. As ressalvas são honestas: o macro-F1 de categoria caiu de 0,4135 para 0,3833 (o soft target não explica categoria, mas o modelo compartilha tronco e o desgaste aparece ali), o ECE de decisão piorou de 0,0440 para 0,0677 — o aluno ficou mais acertivo e menos calibrado onde o professor era ambíguo — e no aleatório de categoria o v6 segue 3 pontos à frente. Soft targets não são mágica: são um ganho real e modesto, concentrado na pergunta certa, com custo de calibração que a temperatura por pergunta (T=1,25 nas 17 classes de categoria, 0,75 nas 4 de urgência, 1,10 nas 5 de decisão) absorve parcialmente. Para a próxima geração, a combinação óbvia é manter o KL em decisão/urgência e investigar de separadamente por que a categoria desgente quando os vizinhos mudam de alvo. Conclusão prática: neste regime de dados, soft target supera rótulo duro; o rótulo duro deixa de ser o padrão para decisão e urgência.

Estado da API: o v5 segue em produção, intocado. O v6 permanece calibrado e passa a ser o rollback imediato; o v7-KL está calibrado (temperaturas salvas em models/decisor-v7/temperaturas.pt) e é o novo campeão do núcleo — a promoção a produção fica condicionada ao swap via scripts/trocar_api_v5.sh, com rollback simétrico. O v8 e o v9 seguem arquivados como reprovados pelo critério.


Apêndice A — A destilação KL em carne e osso (engenharia)

A seção 7 conta o porquê; este apêndice conta o como, porque o diabo da destilação mora em três linhas de código.

A.1 A loss

O treinador do decisor usa uma cabeça de option-markers: cada pergunta gera logits sobre até 32 opções, com os slots de padding travados em −1e4 (softmax ali ≈ softmax só nas opções válidas). A loss por exemplo, antes, era CE dura com label smoothing manual mascarado (o smoothing padrão do PyTorch espalha massa nos slots de padding — o episódio da "loss 666" da Parte 3 nasceu disso).

A destilação entra por linha, não por dataset:

se a linha tem probs_alvo (veio do juiz-D):
    p_T  = normalize(p_alvo ** (1/T))          # professor suavizado
    KL   = Σ p_T · (log p_T − log_softmax(logits/T)) · T²
    per  = α · KL + (1−α) · NLL(argmax)        # âncora dura opcional
senão:
    per  = CE dura com smoothing (como sempre foi)

T = 2,0 e α = 1,0 no config v7. Três decisões de desenho, e o motivo de cada:

  1. α = 1,0 (KL puro, sem âncora dura). O rótulo duro da linha já é o argmax do próprio professor — a âncora estaria redundante com o pico da distribuição destilada. Se um dia desconfiarmos que o professor erra sistematicamente num nicho, α = 0,7 devolve 30% de peso ao argmax sem custo novo.
  2. Linhas destiladas não levam label smoothing. Smoothing espalha massa uniformemente; a distribuição do professor já codifica qual incerteza existe e onde (52% bug × 45% dúvida não é "40% em qualquer lugar"). Smoothing por cima seria dupla borragem.
  3. Professor renormalizado sobre as opções válidas da linha. A API devolve probs sobre as opções que recebeu; a renormalização defensiva cobre qualquer divergência de conjunto (e as 7 linhas em 12.434 — 0,06% — em que o campo choice diverge do argmax das probabilidades; ruído de desempate interno do professor, mantido como está: o choice é o rótulo oficial, as probs carregam a geometria).

A.2 O bug que era do teste, não do código

A verificação numérica da loss KL quase reprovou o treinador por um motivo instrutivo: o teste comparava contra torch.distributions.kl_divergence sobre logits sem mascarar os slots de padding. Sem o −1e4, o softmax do aluno espalha massa pelos 32 slots; com ele, concentra nas 5 opções reais. A "divergência" era o teste medindo uma distribuição que o modelo nunca vê. Replicada a máscara no teste, a loss confere com a referência do PyTorch até a 6ª casa decimal — e as linhas sem soft target saem bit a bit com a loss antiga, o que importa por um motivo operacional: o treino do v6 rodava na GPU enquanto o treinador era editado no disco. O container já tinha o código em memória, e mesmo numa re-execução hipotética o comportamento seria idêntico (sem probs_alvo nos dados, os ramos novos são inertes). Edição cirúrgica com padrões desligados é como se mexe num treinador em produção.

A.3 O que os dados já dizem antes do treino

A entropia normalizada média das distribuições do juiz-D é 0,43 em decisão e 0,42 em urgência (0 = professor decidido, 1 = dúvida total). Ou seja: em quase metade da massa de probabilidade o professor está confessando incerteza — exatamente o conhecimento que o rótulo duro joga fora e que o KL preserva. Se o v6-híbrido confirmar a direção no ouro, o v7 não precisa de um caso novo de dados: mesma base, alvo mais rico.


12. v10: a receita inteira — e o novo teto

O v10 não tem variável nova. Ele é o primeiro modelo da linhagem a combinar, num único treino, as três alavancas que as seções anteriores validaram isoladamente — e é exatamente por isso que ele fecha esta parte do artigo:

  1. O híbrido de juízes do v6 (seção 5): categoria pelo juiz de chat, decisão e urgência pelo juiz-D.
  2. A destilação KL do v7 (seção 11): decisão e urgência com soft targets completos do juiz-D (α = 1,0, T = 2,0), não rótulos duros.
  3. Casos novos de domínio: 234 casos minerados dos exports de ago→out (702 linhas), com o parsing corrigido do formato SELECT, dedupados contra corpus e ouro, rotulados pelo juiz-D por US$ 0,019 — o lote mais barato da linhagem.

Treino e agenda idênticos aos anteriores (37.645 steps, ~4 h na GPU de treino). A régua é a de sempre: acurácia geral no núcleo adversarial do ouro, split por caso seed 42, temperatura calibrada no split de calibração, métricas no teste. O campeão vigente é o v7-KL (0,5969); o v6 (0,5882) entra como referência da base comum.

12.1 Núcleo duro (subset adversarial, n=497 por pergunta)

perguntav10v7-KLv6
categoria0,52310,52720,5191
decisao0,60760,59960,5795
urgencia0,66600,66400,6660
todas0,59890,59690,5882

12.2 Headline de produção (subset aleatório, n=256 por pergunta)

perguntav10v7-KLv6
categoria0,59380,60160,6328
decisao0,71480,65620,6289
urgencia0,70310,70310,6914
todas0,67060,65360,6510

12.3 Teste completo (n=753 casos por pergunta)

métricav10v7-KLv6
acc geral0,62330,61620,6096
acc categoria0,54710,55250,5578
acc decisao0,64410,61890,5963
acc urgencia0,67860,67730,6746
macro-F1 categoria0,42150,38330,4135
ECE pós-temp (cat / dec / urg)0,049 / 0,043 / 0,0370,074 / 0,068 / 0,0250,066 / 0,044 / 0,028
roteamento linha (% auto @ acc)21,9% @ 0,85420,2% @ 0,81617,4% @ 0,832

12.4 Veredito do experimento

O v10 venceu pela regra fixada a priori — 0,5989 contra 0,5969 do v7-KL no núcleo (+0,2 p.p.) e é o novo teto da linhagem. A margem do critério é pequena, mas o v10 não é um empate envernizado: ele abre vantagem onde a régua não olha diretamente — 0,6233 no teste completo (melhor marca da linhagem), 0,6706 no aleatório não-enviesado (melhor marca), e o maior salto aparece na decisão: 0,6441 no teste completo, a pergunta que estava amaldiçoada desde o v3. Toda a linhagem v6 em diante havia regredido nessa pergunta (o v3 marcara 0,6215 e o v5, 0,6202); o v10 é o primeiro a superar os dois com folga — e com correção de prior por Bayes-EM chega a 0,6587, com macro-F1 de decisão saltando de 0,31 para 0,43 (nos predecessores, o mesmo ajuste mal movia o macro-F1: o v10 aprendeu classes de decisão que os outros nem tentam prever). No roteamento, a cobertura automática sobe para 21,9% das linhas com acurácia 0,854 no auto — mais cobertura e mais acurácia que qualquer antecessor, a combinação que normalmente troca uma pela outra.

As ressalvas, sem verniz nenhum. (1) Categoria puro regrediu — 0,5471 contra 0,5578 do v6, terceira geração seguida em que categoria fica aquém do v6-híbrido. Com vector scaling pós-hoc o v10 vai a 0,579, a melhor marca da mesa, mas isso é remendo de calibração, não aprendizado: a fronteira bug_produto ↔ incidente ↔ duvida_produto ↔ conta_config segue sendo o eixo cego do projeto, e nenhuma alavanca testada até aqui a atacou de frente. (2) As classes de cauda seguem sem dados — duvida_comercial (12 casos no ouro) tem F1 zero em todos os modelos da tabela; reembolso (3 casos) oscila ao sabor do split. Nenhum treino corrige o que o ouro mal mede. (3) A margem no critério (+0,2 p.p.) está dentro do ruído do teste — o que a sustenta é o conjunto da obra: vitória consistente nos três subsets, na pergunta mais difícil, e no roteamento. E uma nota de reprodutibilidade que vale mais que qualquer margem: o v6 e o v7 reavaliados nesta rodada reproduziram exatamente os números das seções 6 e 11 (0,5882 e 0,5969 no núcleo) — a régua é estável, o split não vaza, e as diferenças reportadas ao longo desta série são de modelo, não de medição.

A calibração pós-avaliação convergiu e está gravada no checkpoint (T* = 1,05 / 0,85 / 1,25 para decisão, urgência e categoria; ECE de calibração 0,018 / 0,024 / 0,041 — o ECE de categoria caiu de 0,114 para 0,041, o maior ganho de temperatura da linhagem).

Estado da API: o v10 está em produção desde 17/out — swap autorizado pelo dono e executado com rollback simétrico pronto (scripts/rollback_api_v5.sh recoloca o v5 no ar em ~1 min). O v7-KL é o rollback imediato; o v6, terceira linha.

12.5 A tabela consolidada — doze gerações contra o ouro

Para fechar a parte 4, a linhagem inteira na mesma régua (acurácia geral no teste completo; negrito no campeão de cada onda):

geraçãoo que mudougeraldestino
v3primeira receita KL-capaz, prata de regex0,4161arquivado
v5ouro de juiz de chat + hard labels0,5963produção até 17/out
v6híbrido de juízes (bake-off)0,6096rollback 2ª linha
v8+48,8k linhas EN (juiz-D)0,6038reprovado
v9+136,8k linhas HF (juiz-D)0,5905reprovado
v7-KLsoft targets KL do juiz-D0,6162rollback imediato
v10receita completa: híbrido + KL + casos novos0,6233membro da campeã
v11_cons+reclamações reais (curadoria conservadora)0,6127melhor macro-F1
v11eensemble v10+v11_cons0,6282campeã por 24h
v12stack+focal/R-Drop/FGM/SWA (pilha completa)0,5644❌ super-regulariza
swasó SWA isolado da pilha0,6242melhor single
v10+swaensemble do campeão0,6339🏆 EM PRODUÇÃO

As lições que atravessam as doze gerações:

  1. Escala de rótulo de juiz, sozinha, dilui (v8, v9, v12active) — volume sem curadoria é ruído, não sinal.
  2. O conhecimento do professor vale mais que o volume (KL com os mesmos dados vence volume novo 5× maior) — mas escolher O QUE destilar importa mais ainda (SWA do que o professor sabe; focal/R-Drop do que ele não sabe).
  3. A técnica campeã estava escondida dentro do fracasso — a pilha completa perdeu 4,8 p.p., mas a ablação revelou que SWA sozinho era ouro puro. Sem ablação componente-a-componente, o campeão teria sido descartado junto com o fracasso.
  4. Pré-treino adicional em encoder pequeno é bomba-relógio — DAPT over-trained destruiu o modelo (−20 p.p.); a janela entre "adaptado" e "esqueceu como classificar" é estreita e sem sinal de parada.

13. O v11: o programa de dados dirigido (síntese verificada + reclamações reais)

Depois do v10, a questão deixou de ser "mais dados" e passou a ser dados apontados para os erros medidos. O v11 nasce de quatro fontes novas, todas passando pelo mesmo funil (dedup contra o ouro e o treino, rotulagem híbrida — categoria por juiz de chat, decisão/urgência por juiz-D com probabilidades — e verificação):

  1. Corpus sintético verificado (~9,1 mil conversas): geração dirigida às caudas medidas (fraude, frete, prazos) e às fronteiras do eixo cego (bug × dúvida × conta × incidente), com pares contrastivos e pares de calibração de urgência (calmo-crítico × bravo-banal); tudo filtrado por juiz — 26% de rejeição, concentrada exatamente nas fronteiras visadas.
  2. Churn real (318 conversas reais de clientes, dedup por protocolo).
  3. Amostra do Consumidor.gov.br (portal público de reclamações): 30,2 mil reclamações reais com resposta da empresa e desfecho, das quais 22,2 mil do comércio eletrônico — 75% mapeando nas categorias-cauda (frete 5,2 mil, reembolso 5,1 mil, prazos 2,2 mil).
  4. Pacote externo híbrido (2 mil conversas com probabilidades do juiz-D já embutidas).

Duas dosagens foram montadas sobre a receita do v10 (mesma arquitetura, mesmos hiperparâmetros, KL ligado): conservadora (~1,3:1 novo:base) e agressiva (tudo). A conservadora treinou primeiro.

13.1 Resultado na régua oficial (conservadora)

métricav10v11Δ
núcleo (métrica oficial)0,59890,6009+0,20 p.p.
geral0,62330,6127−1,06 p.p.
categoria0,54710,5564+0,93 p.p.
macro-F1 categoria (17 classes)0,42150,5037+8,22 p.p.
decisão0,64410,6109−3,32 p.p.
urgência0,67860,6707−0,79 p.p.

13.2 Leitura

O programa venceu exatamente onde mirou: o subset núcleo — casos difíceis adjudicados por humanos, onde vivem as caudas — subiu, e o macro-F1 de categoria deu o maior salto da linhagem desde o v5 (+8,2 p.p., movido pelas classes que até aqui tinham F1 próximo de zero). O custo apareceu no subset aleatório e na decisão: a hipótese de trabalho é que o rótulo do juiz-D sobre reclamações (estilo "consumidor versus empresa") desloca o prior de decisão — o registro público de reclamações ensina "escalar/rejeitar" mais do que o chat de plataforma ensina. É a próxima fronteira de calibragem: correção de prior por origem do dado.

13.3 Dosagem agressiva (v11b) — o teste da escala com funil

O perfil agressivo (toda a amostra nova, ~575 mil linhas) respondeu a pergunta deixada em aberto — e a resposta confirmou a lição do v9, agora com funil de qualidade no caminho:

métricav10v11 (conservador)v11b (agressivo)
núcleo (oficial)0,59890,60090,5983
geral0,62330,61270,6144
categoria0,54710,55640,5671
decisão0,64410,61090,6003
macro-F1 categoria0,42150,50370,4771

O agressivo emplacou o melhor acerto bruto de categoria, mas o volume cheio do registro público de reclamações re-diluiu o equilíbrio das caudas (macro-F1 cai 2,7 p.p. frente ao conservador) e o núcleo ficou abaixo até do v10. Direção segue batendo escala — mesmo com dedup, dois juízes e KL. A conclusão operacional: o ganho sustentável mora na seleção (active learning), não no volume; e o conservador é a dosagem de referência para as próximas rodadas.

14. A regressão de decisão explicada (prior-por-origem)

A análise dos fluxos de erro na decisão revelou um padrão concentrado: das 69 respostas onde o v10 acertava e o v11 errou, 52 (75%) seguem um único fluxo: casos onde a resposta correta era executar_acao e o v11 passou a predizer escalar. A assinatura é inconfundível do professor: o registro público de reclamações (Consumidor.gov.br) ensina o estilo "consumidor versus empresa", onde a resposta certa é escalar para um humano — não executar uma ação automática. O dado é bom para categoria (caudas, macro-F1 +8,2 p.p.) mas desloca o prior de decisão.

A correção é treinável: distribution matching (casar a marginal do professor com a marginal do ouro por pergunta) ou simplesmente reduzir o peso da fatia consumidor na perda de decisão mantendo o peso cheio em categoria. Ambas entram como flags no v12.

14.1 Born-again: o núcleo afia, a cauda cai (v12ba)

O experimento de rede renascida (téc. 18) — o v11_cons rotulando com probs macias o próprio corpus de treino, aluno treinado do zero contra esses alvos — fechou com um resultado negativo instrutivo:

métricav12bav10v11_cons
núcleo adversarial0,60160,59890,6009
headline de produção0,62240,67060,6354
macro-F1 categoria0,41410,42150,5037

O born-again deu o melhor núcleo da história (+0,27 p.p. sobre o v10) e perdeu 4,8 p.p. no subset limpo de produção, com macro-F1 despencando. A autodestilação afia o que o professor já sabia (casos difíceis do próprio viés) e apaga a diversidade que o coletivo de professores originais (juiz de chat + juiz-D) carregava — sobretudo nas caudas de categoria. Ensembles não resgatam: média das três redes (v10 + v11_cons

  • v12ba) no núcleo cai para 0,6043 contra 0,6110 da dupla original. Veredito: técnica reprovada nesta família; o conhecimento que faltava ao v11 não estava dentro dele.

15. A campanha dos nove desafiantes — e o que ela delimita

Entre 18 e 19 de outubro executamos, na mesma régua e no mesmo protocolo (split por caso seed 42, temperature scaling no calib, métricas no teste), uma campanha completa contra o campeão vigente — o ensemble v11e (média das probs calibradas de v10 + v11_cons: núcleo 0,6110, geral 0,6282). A campanha abriu com seis desafiantes — e os seis foram reprovados:

desafianteideiageralleitura
v12ba (born-again)aluno do zero com as probs do próprio campeão0,6087§14.1: núcleo recorde, cauda destruída
v12imp (troca de professor)rótulos macios do Imperium 26B no lugar do juiz-D0,6184melhor single da linhagem v11, mas macro-F1 0,4002
v12stack (pilha de treino)focal + R-Drop + FGM + SWA + downweight consumidor0,5644super-regularização (−4,8 p.p.); melhor calibração da família (ECE 0,025–0,061)
v12active (active learning)+6k casos selecionados por incerteza×discordância0,5985a fatia rotulada pelo professor injeta viés, não informação
Veredicto 9Bescalar o classificador para um backbone de 9B0,3838reprovado como classificador; recorde de urgência 0,745
ensembles com os desafiantesmédia com o campeão≤0,6110 (núcleo)nenhum supera a dupla original

Três leções se consolidam. Primeira: o gargalo não é a técnica de treino — pilha de regularização, autodestilação e seleção ativa de dados com rótulo de LLM todas falharam em mover a régua, e a que chegou mais perto (troca de professor) ganhou no geral perdendo exatamente na cauda que já doía. Segunda: escala de backbone também não é — o 9B floreia em categoria e decisão no formato joint-schema, revelando que o formato de pergunta multiopção não transfere grátis para modelos maiores. Terceira, e a mais acionável: o conhecimento está nas perguntas certas dos modelos certos — o Veredicto responde urgência (0,745) melhor que qualquer Decisum (teto 0,6919, da campeã v10+swa), e o Imperium rotula melhor o conjunto do que o juiz-D (0,6184 contra 0,6127 no aluno). A agenda que sobra é cirúrgica: destilar urgência do Veredicto no 322M, levar representação (não só decisão) do 26B via hidden states, e engrossar a fronteira de categoria com dados — os três caminhos que a campanha deixou abertos e o stack de técnicas, fechado.

15.1 O oitavo desafiante: SWA sozinho, o campeão escondido

A campanha parecia fechada com o veredito de que "nenhuma técnica de treino move a régua" — até a ablação componente-a-componente da pilha revelar que o problema não era a SWA, mas a companhia dela. O v12stack (focal + R-Drop + FGM + SWA juntos) perdera 4,8 p.p.; removidos os três primeiros, o que sobrou foi o melhor modelo da história:

sistemageralcatdecurgmacro-F1
v11e (campeã até aqui)0,62820,56040,63750,68660,4223
swa sozinho (single)0,62420,55510,62950,68790,4693
v10+swa (ensemble)0,63390,56180,64810,69190,4301

O ensemble v10+swa desbanca a v11e por 0,57 p.p., com categoria e urgência recordes absolutos (0,5618 e 0,6919). A lição cirúrgica: SWA (média de pesos no último quarto do treino) estabiliza o checkpoint final numa região mais plana da paisagem de perda — sozinho, é ganho puro; combinado com focal/R-Drop/FGM (que também empurram pra zonas planas), o efeito composto super-regulariza e destrói a adaptação fina.

A campanha parecia fechar aí: oito desafiantes, sete reprovados, um campeão vindo de dentro da própria pilha que parecia reprovada. Faltava ainda o nono — a aposta "segura" do pré-treino de domínio (§15.3).

15.2 O professor medido na régua — e o aluno que o superou

Para fechar a comparação com referência única, rodamos o juiz-D (a API de decisões de fronteira, professor da linhagem) na régua oficial completa — mesmo split seed 42, mesmos 753 casos de teste:

sistemacategoriadecisãourgênciageral
juiz-D (API)0,72510,68920,72380,7127
v10+swa (campeã)0,56180,64810,69190,6339
Veredicto 9B (v4)0,24300,16330,74500,3838
Veredicto 9B (v5)0,09690,17000,72780,3316

Dois números valem o experimento. O teto honesto do professor é 0,7127 — a amostra antiga de 76 casos superestimava (0,754) por ser enviesada a caudas; o gap real para a campeã local é de 7,9 p.p., concentrado em categoria. E o achado da campanha se confirma com força total: na urgência, o aluno de 9B destilado do professor supera o próprio professor (0,745 contra 0,724) — especialização de domínio e média de professores compram mais que os parâmetros extras na pergunta certa. É o resultado que abre a próxima onda: destilar urgência do Veredicto no 322M.

O v5 (re-treino com dados limpos e deduplicados, 2 épocas) confirma que a limitação em categoria/decisão é arquitetural, não de dados: dado limpo deixou categoria ainda pior (0,097 contra 0,243), enquanto a urgência se manteve robusta (0,728 contra 0,745). O clef-flash não transfere classificação multiopção fina em PT-BR no formato joint-schema.

15.3 O nono desafiante: DAPT, o blefe do pré-treino

O experimento de adaptação de domínio (DAPT — 1,08M documentos de e-commerce PT-BR alimentando MLM no encoder por 11 horas) parecia a aposta mais segura de toda a campanha: técnica consolidada, literatura favorável, oceano de dados. O resultado: 0,4188 geral — perda de 20,5 p.p. para o mesmo modelo sem o encoder adaptado.

A explicação está no bug da retomada: o script de DAPT rodou 230k steps em vez dos 129k planejados (um erro de arredondamento em math.ceil(0.48) que executou a época inteira em vez de 48%). O encoder over-trained sofreu catastrophic forgetting — especializou-se tanto em prever palavras de ticket que perdeu a representação geral que o fine-tune supervisionado precisava recuperar.

A lição vai além do bug: DAPT em encoder de 322M com um corpus de 1M documentos é uma bomba-relógio de hiperparâmetros — a janela entre "adaptado ao domínio" e "esqueceu como classificar" é estreita e não tem sinal de parada óbvia. Com 476k linhas rotuladas de qualidade auditada, o encoder genérico já está saturado.

15.4 O placar final da campanha

#desafiantegeralveredito
1born-again (v12ba)0,6087❌ cauda destruída
2troca de professor (v12imp)0,6184❌ macro-F1 cai
3pilha completa (v12stack)0,5644❌ super-regulariza
4active learning (v12active)0,5985❌ injeta viés
5Veredicto 9B0,3838❌ como classificador; ✅ urgência
6Veredicto 9B v5 (limpo)0,3316❌ confirma limitação
7DAPT encoder (v12dapt)0,4188❌ catastrophic forgetting
8DAPT + pilhacancelado— (encoder comprometido)
9SWA isolado0,6242✅ melhor single
—v10+swa ensemble0,6339🏆 CAMPEÃ

Nove desafiantes, oito reprovados, um campeão. E o campeão estava escondido dentro do experimento que parecia o maior fracasso (a pilha completa com −4,8 p.p.). A técnica que moveu a régua não veio de literatura nova, nem de mais dados, nem de escala — veio de ablação cirúrgica: separar o que funcionava do que atrapalhava dentro de uma combinação que fracassou em conjunto.

15.5 O campeão está público

O ensemble v10+swa está público no Hugging Face — syvorai/decisum, sob Apache 2.0: pesos dos dois membros, calibração (temperature scaling), scripts de inferência e serving, e o benchmark de latência reproduzível usado na tabela de hardware do model card (ROCm, XPU e Apple Silicon, todos medidos com a mesma carga).


Raphael Pizzo é Especialista em Machine Learning. Este projeto foi desenvolvido em infraestrutura própria (AMD ROCm), com dados anonimizados e aprovados para uso em pesquisa.