Voltar para todos os posts

Um Modelo de Decisão "System 1" para Atendimento em PT-BR — Parte 3: A Régua Estava Errada (Benchmark, Ouro e a Trilogia v3→v4→v5)

27 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 3

Nota de anonimização: como nas Partes 1 e 2, todos os nomes de empresas, produtos, plataformas e clientes foram omitidos ou generalizados. O canal de mensagens que domina o volume segue chamado de canal_msg. O único nome real neste texto é o do autor.


1. O incômodo que abriu esta parte

A Parte 2 terminou com o decisor-v3 recomendado para produção: acurácia geral 0,650 contra a prata corrigida, ECE pós-temperatura abaixo de 0,07 nas três perguntas, 30,9% das linhas roteáveis com 91% de acurácia no automático. Bons números — com uma ressalva que não saía da minha cabeça:

A prata continua prata. Regex melhorado ainda é regex.

Todo o edifício do v3 — treino, avaliação, o veredito negativo sobre o RLCD — estava apoiado em rótulos extraídos por regras determinísticas sobre os textos dos chamados. A adjudicação cega da Parte 2 já tinha mostrado que, nos pontos em que o v3 discorda da prata, a prata está errada em 63% dos casos de categoria. Ou seja: a régua não era só imperfeita, era imperfeita exatamente nos pontos que decidem a nota final.

Esta Parte 3 conta o que aconteceu quando paramos de discutir a régua e construímos uma nova — e o efeito dominó que isso provocou:

  1. Um benchmark pareado contra o próprio backbone em zero-shot, para isolar quanto do v3 é modelo e quanto é vazamento da régua;
  2. Uma adjudicação cega de 175 desacordos, para medir a acurácia real do v3 sem depender da prata;
  3. Um ouro de 1.000 chamados rotulado por leitura semântica (não por regex), mais 500 aleatórios — a primeira régua honesta do projeto;
  4. O v4, um resultado negativo curto e instrutivo: class weighting sobre rótulos ruidosos;
  5. O v5, a correção pela causa raiz: re-rotular o train inteiro com um juiz forte, e treinar de novo.

É a parte com mais reviravoltas por hora de GPU. E com o bug mais absurdo do projeto inteiro (seção 5.2 — envolve a loss chegar a 666).

2. Benchmark pareado: quanto do v3 é modelo?

2.1 Desenho

Antes de qualquer ouro, a primeira pergunta era de isolação: o v3 é um encoder mmBERT de 322M parâmetros com uma cabeça de classificação sobre option-markers. Se eu pegar o mesmo backbone, sem fine-tune, e fizer as mesmas três perguntas (categoria, decisão, urgência) em prompt zero-shot, quanto ele acerta? A diferença entre os dois é, por construção, o efeito do treinamento — nem mais, nem menos.

Protocolo idêntico ao da Parte 2 para os dois lados:

  • gold: 5.193 linhas / 1.731 casos da prata corrigida;
  • split por caso (seed 42): 862 casos para calibração, 869 para teste;
  • temperature scaling idêntico (grid 0,25–5,0, minimizando ECE, ajustado só no calib) — nenhum modelo ganha calibração de graça;
  • contexto de 1.024 tokens nos dois; limiar de roteamento 0,8 nos dois.

2.2 Resultado

métricadecisor-v3backbone zero-shot
acurácia categoria0,6030,131
acurácia decisão0,7500,196
acurácia urgência0,5970,267
acurácia geral0,6500,198
macro-F1 categoria0,2670,092
roteamento: % linhas no automático30,9%0,5%
roteamento: acurácia no automático0,9090,286

Leituras:

  1. O fine-tune é o modelo. +45 pontos percentuais de acurácia geral sobre o mesmo encoder. O backbone cru acerta 13% em categoria — menos do que chutar a classe majoritária com disciplina — e erra de um jeito específico e revelador: a confusão mais frequente dele é canal_msg → fraude_suspeita (155 vezes). Para quem conhece o vocabulário do domínio, faz sentido: os textos de canal_msg estão cheios de palavras como "bloqueio", "conta restrita", "não autorizado" — que, sem contexto de produto, parecem fraude. O fine-tune não ensinou só categorias; ensinou o que essas palavras significam dentro desta plataforma.
  2. O backbone cru é hiperconfiante. A temperatura ótima dele bateu no teto do grid (4,95) nas três perguntas, com ECE cru de até 0,545 — ele aposta tudo em respostas erradas. O v3, em contraste, calibra com T entre 1,3 e 1,8. Saber o que não sabe também é aprendido.
  3. Zero casos de concordância contra a prata. Em 2.117 linhas de desacordo entre v3 e backbone, não existe um único caso em que os dois concordem entre si divergindo da prata. Esse fato, curioso à primeira vista, é consistente com a hipótese de que os dois erram por mecanismos completamente diferentes — e montou o palco para a adjudicação da seção 3.

3. A adjudicação cega: quanto vale a prata nos pontos difíceis?

O benchmark mede concordância com a prata, não acurácia. Para medir acurácia de verdade sem esperar o ouro, desenhamos uma adjudicação:

  • 175 casos amostrados dos desacordos do benchmark, estratificados: para categoria, 40 casos em que todos divergem, 25 em que o v3 erra e o backbone acerta a prata, 30 em que o v3 acerta a prata e o backbone erra; para decisão e urgência, 40 aleatórios cada.
  • Juiz cego à procedência: o juiz via o estado do chamado e 2–3 respostas candidatas anonimizadas (A/B/C), sem saber qual era da prata, do v3 ou do backbone. Podia escolher uma letra, "nenhuma", ou propor um rótulo livre.
  • O gabarito (qual letra era qual fonte) só foi aberto depois do 175º veredito.

3.1 Resultado central

pergunta · estratonprata certav3 certobackbone certonenhum
categoria · todos divergem4035%28%8%30%
categoria · v3 erra, backbone=prata2540%28%40%*32%
categoria · v3=prata, backbone erra3080%80%7%13%
categoria · total9551%44%16%25%
decisão · total4065%75%20%5%
urgência · total4042%45%42%0%

* nesse estrato, backbone e prata são a mesma letra por construção.

Três conclusões:

1. A prata é mais ruidosa do que se assumia. Nos desacordos de categoria em que v3≠prata, a prata erra 63% (decisão: 75%; urgência: 65%). A régua contra a qual o v3 foi medido — e treinado — está errada na maioria dos pontos contestados.

2. A acurácia real do v3 é maior que a reportada. Corrigindo pelos desacordos adjudicados (acc_prata + (1 − acc_prata) × P(v3 certo | desacordo)):

perguntaacurácia vs prataacurácia real estimada
categoria0,603≈ 0,71
decisão0,750≈ 0,90
urgência0,597≈ 0,76

(O leitor atento vai segurar esta tabela até a seção 4 — o ouro contou uma história diferente, e a diferença entre as duas é uma das lições desta parte.)

3. A confiança do v3 separa acerto de erro. Quando o juiz concordou com o v3, a confiança média dele era 0,650; quando discordou, 0,349. A calibração não é só um número agregado bonito — ela é informativa caso a caso, que é o que o roteamento por limiar precisa.

3.2 Os 24 "nenhum": lacunas de esquema, não ruído

Nos casos de categoria em que nenhum candidato tinha a resposta, os rótulos livres propostos pelo juiz se concentraram em duvida_produto (6), bug_produto (5) e conta_config (4) — "onde fica o módulo de chamados?", erro 500 ao salvar usuário, troca de responsáveis de fila. Ou seja: os desacordos mais duros vivem fora do eixo incidente × canal_msg, nas fronteiras finas entre produto, dúvida e configuração — exatamente onde uma regex sobre palavras-chave é estruturalmente cega. Este parágrafo é a previsão que o ouro da seção 4 confirmou com força.

3.3 Urgência: o problema é a régua, não o modelo

Em urgência, a votação saiu quase em três vias (prata 42%, v3 45%, backbone 42%) e zero "nenhum": os três candidatos costumam ser defensáveis porque a urgência-prata é derivada de regex sobre palavras ("urgente", "erro", "parou"), sem noção de escopo. O cliente que escreve "é urgente" para uma dúvida de configuração recebe alta da prata e moderada do juiz; a plataforma "sem carregamento e sem gerar tickets" descrita sem ênfase recebe baixa da prata e alta do juiz. Urgência era, claramente, a pergunta que mais precisava de uma régua nova.

4. O ouro de 1.000 chamados

4.1 Desenho da amostra

O ouro foi desenhado para medir onde dói. Dos 1.731 casos do gold de prata, selecionamos 1.000 (999 válidos ao final) em três estratos:

  • T1 — erros confiantes do v3 em categoria (v3≠prata com confiança ≥ 0,70): os pontos em que o modelo "jura" que a prata erra;
  • T2 — qualquer desacordo (categoria, decisão ou urgência, incluindo v3×backbone);
  • T3 — concordância plena, aleatórios estratificados pela categoria-prata, para não esquecer o universo dos casos fáceis.

Os textos foram para uma planilha cega (sem os rótulos da prata, sem as respostas dos modelos), acompanhada de um guia de anotação com definições e exemplos por categoria.

4.2 Quem rotulou — e a honestidade sobre isso

A rotulagem foi feita por leitura semântica assistida por IA: três agentes leram os textos individualmente, cada lote passou por revisão do próprio agente e por revisão cruzada de outro agente (202 casos revistos na íntegra, 16 com rótulo alterado nessa etapa), com adjudicação final de ambiguidades por um coordenador. Sem regex, sem consulta à aba de referência da planilha. Revisão humana por amostragem sobre o resultado final.

Eu chamo isso de ouro de leitura, não de "gold humano puro" — e a distinção importa. 73 casos ficaram marcados como baixa confiança do anotador, pendentes de confirmação humana. É um ouro de qualidade muito acima da prata, com um processo de revisão documentado, mas não é um comitê de especialistas humanos. O preço dessa escolha aparece na seção 6, sob a forma de um risco de circularidade que precisa ser declarado.

(Anotação operacional: 7 chamados continham credenciais explícitas — chaves de API, tokens — que foram mascaradas antes de qualquer modelo ver os textos. Dez ocorrências. Se você opera dados de atendimento real, espere encontrar segredos vazados pelos próprios clientes nos textos.)

4.3 O susto: um bug de linhagem quase contaminou o ouro

No meio do processo, descobri que o sampler que gerou a planilha tinha lido o gold v1 — aquele, do capítulo da urgência degenerada — em vez do gold v3 corrigido. Por sorte, os campos que a planilha usa (o texto do chamado) são os mesmos nos dois; o estrago seria nos estratos de amostragem. A correção foi apontar o sampler para o arquivo certo e regenerar. Fica o registro porque é o terceiro bug de dados do projeto que só foi pego porque alguém olhou o arquivo, não o nome do arquivo: depois do <mask> e da urgência constante, o critério de verificação de linhagem (hash do arquivo + contagem de linhas + spot check de três casos) virou passo obrigatório de todo pipeline deste projeto.

4.4 O que o ouro revelou

A concordância da prata com o ouro, nos 997 casos válidos:

perguntaconcordância prata×ouro
categoria0,327
decisão0,566
urgência0,345

Uma em cada três etiquetas de categoria da prata não sobreviveu à leitura. As confusões mais frequentes (prata → ouro) são exatamente as fronteiras previstas pelos "nenhum" da adjudicação:

confusão prata → ouron
canal_msg → bug_produto78
canal_msg → conta_config69
canal_msg → duvida_produto54
incidente → bug_produto44
outro → duvida_produto39
canal_msg → integracao29
canal_msg → plano_creditos27

A distribuição de categorias mudou de figura. Na prata, canal_msg respondia por cerca de 49% dos casos do gold; no ouro (núcleo), canal_msg cai para 19,6%, incidente despenca para 0,6% (6 casos em 999!), e as três categorias que a prata mal conhecia — bug_produto (19,4%), duvida_produto (16,3%), conta_config (16,4%) — passam a dominar. A prata não errava aleatoriamente: ela super-etiquetava sistematicamente as duas classes do seu vocabulário e sub-etiquetava tudo o que exigia leitura.

Urgência, a suspeita da Parte 2, confirmou-se: o ouro distribui 498 baixa / 365 moderada / 112 alta / 24 crítica no núcleo — enquanto a prata inflava alta (a confusão alta → moderada sozinha responde por 228 casos; alta → baixa, mais 125). E decisão, a pergunta mais "estável", mostrou um deslocamento conceitual importante: a prata dizia executar_acao onde o ouro diz pedir_mais_info (136 casos) ou escalar (123) — a regex via uma ação mencionada e concluía que ela devia ser executada; a leitura percebia que o caso não estava pronto para agir.

E onde fica o v3 nessa régua nova? Contra o ouro, a acurácia dele cai para 0,317 em categoria (vs 0,603 contra a prata), 0,569 em decisão e 0,330 em urgência. A estimativa da adjudicação (≈0,71) não se confirmou — porque adjudicação e ouro discordam entre si nas fronteiras finas: dois juízes, dois desenhos, duas definições implícitas de fronteira. A lição não é que uma das duas medidas "mente"; é que abaixo de certa granularidade, a fronteira entre bug_produto, duvida_produto e conta_config é uma decisão de taxonomia, não um fato da natureza — e quem define a taxonomia é o guia de anotação mais a consistência do anotador. O v3 aprendeu a taxonomia da prata; o ouro carrega a taxonomia do guia. O próximo modelo precisava aprender a taxonomia certa.

5. v4: o resultado negativo (class weighting não conserta rótulo)

5.1 A hipótese, o experimento, o veredito

Antes do ouro ficar pronto, a hipótese na mesa era: as categorias órfãs do v3 (macro-F1 de 0,267, com conta_config em 0,133 e duvida_produto em 0,048) sofriam de desbalanceamento — canal_msg tinha ~49% do train. A resposta padrão de manual é class weighting. Treinamos o v4 com pesos sqrt(1/freq) limitados a um teto de 5×, mais label smoothing 0,1, tudo o mais igual ao v3.

Resultado na mesma régua (gold prata, split idêntico, temperaturas recalibradas no calib):

métricav4v3
acurácia geral0,6600,650
acurácia categoria0,5850,603
macro-F1 categoria (a métrica-alvo!)0,2220,267
F1 bug_produto0,1110,289
F1 conta_config0,0000,133
F1 pagamento0,2000,519

A acurácia geral "subiu" um ponto — e a métrica que o experimento existia para melhorar piorou, com as classes-minoria que o peso deveria proteger sendo destruídas (conta_config zerou). A explicação ficou óbvia depois que o ouro saiu: peso de classe amplifica o rótulo que existe, não o rótulo certo. Dar 5× de peso a exemplos de conta_config cujos rótulos estavam errados em grande proporção é pagar 5× mais atenção ao ruído. Class weighting é uma ferramenta de frequência; o problema era de veracidade.

5.2 O interlúdio da loss 666

O v4 ainda rendeu o bug mais exótico do projeto. O log do primeiro treino mostrava a loss abrir em ~666 e descer devagar — três ordens de grandeza acima do esperado para uma cross-entropy de 17 classes. A causa: o label_smoothing do PyTorch espalha a massa de probabilidade uniformemente por todos os logits da camada — e a cabeça do decisor tem espaço para 17 opções, mas cada exemplo só apresenta as opções válidas da sua pergunta, com os slots de padding mascarados a −1e4. Espalhar 10% de massa por slots que valem −1e4 produz um termo de loss gigante (e gradientes absurdos apontando para opções inexistentes). A correção foi reescrever o smoothing manualmente, restrito às opções válidas de cada exemplo — e a loss passou a abrir em ~1,3. Fica a vacina: smoothing e máscara de padding não se combinam de graça; se a sua loss abre num valor que parece uma piada numerológica, provavelmente é um bug, não uma coincidência.

6. v5: corrigir a causa raiz — re-rotular o train inteiro

Se o problema era a taxonomia dos rótulos de treino, a solução era trocar os rótulos de treino. Com o ouro provando que leitura semântica em lote era viável, o passo seguinte foi escalar a mesma ideia para o train completo.

6.1 O juiz e o protocolo

Juiz: um modelo de linguagem grande de raciocínio, servido em endpoint dedicado (sem custo de GPU local — as duas placas ficaram livres para o treino). Protocolo desenhado para minimizar contaminação:

  • uma chamada por caso, com o texto integral do chamado;
  • o juiz recebe o guia de anotação e few-shots no system prompt;
  • o juiz não vê o rótulo da prata — cego à régua antiga, para não herdar o viés dela;
  • saída estruturada com o rótulo das três perguntas + confiança do juiz;
  • 16 workers paralelos.

Resultado da operação: 3.982 casos re-rotulados, zero falhas, ~18 minutos (3,7 casos/segundo). Mais 500 casos aleatórios do universo (sem estratificação por desacordo) re-rotulados pelo mesmo juiz, para compor o ouro de avaliação com um subset não-enviesado. Dedup final contra o conjunto de teste: 2 casos vazados removidos (6 linhas), train final de 11.946 linhas / 3.982 casos, zero sobreposição com o teste.

6.2 O train mudou de cara

A re-rotulagem redistribuiu o train na mesma direção do ouro:

categoriatrain v3 (prata)train v5 (juiz forte)
incidenteclasse gigante935
bug_produtosub-representada605
duvida_produtoquase órfã590
conta_configquase órfã573
canal_msg~metade do train475
outro—348
integracao—176

E urgência, que na prata era uma classe quase única com variação por palavra-gatilho, virou uma distribuição de verdade no train: 1.256 baixa / 1.330 moderada / 736 alta / 660 crítica.

6.3 Config do v5

Com o v4 provando que peso de classe é veneno sobre rótulo ruidoso e o log do v4 mostrando platô de loss já na transição época 2→3, a config do v5 é o v3 com duas mudanças conservadoras: 2 épocas (em vez de 3) e smoothing 0,05 (a versão corrigida, restrita às opções válidas). Sem pesos de classe. Batch 24, padding dinâmico, mesmo encoder mmBERT, mesmo split por caso, mesma seed. O v5 é um experimento de uma variável: só mudaram os rótulos do train.

7. Resultados do v5 contra o ouro

A avaliação definitiva rodou ao fim do treino: v5 × v3 × backbone zero-shot contra o ouro de 1.499 casos (999 núcleo + 500 aleatórios), protocolo idêntico ao do benchmark — split por caso seed 42, temperature scaling ajustado só no calib, métricas no teste (753 casos), limiar 0,8. O critério de promoção, fixado antes dos números, era a acurácia geral no subset núcleo.

Tabela principal (teste, 753 casos)

métricadecisor-v5decisor-v3backbone zero-shot
acurácia categoria0,5300,3030,100
acurácia decisão0,6200,6220,191
acurácia urgência0,6390,3240,311
acurácia geral0,5960,4160,201
macro-F1 categoria0,3860,1880,089
ECE categoria (pós-temp)0,0460,0590,086
ECE decisão (pós-temp)0,0520,0960,092
ECE urgência (pós-temp)0,0440,1250,037
roteamento: % linhas no automático10,8%0,0%0,4%
roteamento: acurácia no automático0,848— (vazio)0,300

Headline: o subset aleatório (amostragem não-enviesada do universo; o desconto de circularidade da seção 7.1 aplica-se a ele, nunca ao núcleo)

perguntav5v3backbone
categoria0,5550,3050,113
decisão0,7030,6840,223
urgência0,6060,3480,328
todas0,6210,4450,221

Núcleo duro (999 adversariais, juiz independente — o critério)

perguntav5v3backbone
categoria0,5170,3020,093
decisão0,5780,5900,175
urgência0,6560,3120,302
todas0,5840,4010,190

F1 por categoria (teste) — onde o redesenho do train apareceu

categorianv5v3
canal_msg1380,6590,450
outro690,6340,495
conta_config1220,5780,048
plano_creditos460,5370,254
integracao480,5240,366
duvida_produto1310,4710,058
bug_produto1460,4590,142
pagamento150,4440,286
incidente220,3250,161
duvida_comercial120,0000,000

Leitura honesta:

  1. A causa raiz era mesmo a taxonomia. +18,2 pontos no núcleo, +17,6 no aleatório, com a maior subida exatamente nas três categorias que a prata sub-etiquetava (conta_config 0,048→0,578, duvida_produto 0,058→0,471, bug_produto 0,142→0,459). O único ponto em que o v5 perde para o v3 é decisão no núcleo (0,578 vs 0,590) — empate técnico dentro do ruído, mais que coberto pela urgência (+34 pontos no mesmo subset). Na tabela principal, decisão é literalmente um empate (0,620 vs 0,622): a pergunta que a prata menos distorcia é a que mais o v3 já acertava, e a re-rotulagem não tinha muito o que consertar lá.
  2. Onde o v5 não ganhou: cobertura. 10,8% das linhas no automático (a 84,8% de acurácia) contra os 30,9% que o v3 alcançava na régua de prata. Parte é régua mais dura com todo mundo — o v3, contra o ouro, não coloca uma única linha acima do limiar 0,8: a confiança dele foi aprendida sobre a taxonomia da prata e não sobreviveu à régua nova. Parte é o limiar conservador da Parte 2, que segue valendo até haver motivo para mexer. E duvida_comercial continua zerada nos dois modelos (n=12, amostra pequena demais para qualquer conclusão).
  3. A calibração acompanhou a acurácia. ECE pós-temperatura do v5 abaixo de 0,06 nas três perguntas (a do v3 chega a 0,125 em urgência), com temperaturas estáveis (T entre 1,05 e 1,70). O único ECE melhor do backbone (urgência, 0,037) vem acompanhado de 31% de acurácia — estar calibrado no errado não é calibração útil.

Pelo critério fixado antes dos números — acurácia geral no subset núcleo — o v5 venceu, e a troca da API de produção foi feita na mesma execução que gerou esta tabela.

7.1 A ressalva de circularidade (escrita antes dos números, de propósito)

Registro aqui, antes de ver os resultados, a limitação que esta avaliação carrega, para que ela não seja "descoberta" depois caso os números venham bonitos: o subset aleatório do ouro foi rotulado pelo mesmo juiz que re-rotulou o train do v5. Uma acurácia alta do v5 nesse subset mede, em parte, concordância com o juiz — o que é exatamente o que o treino otimizou. O subset núcleo (999 casos) foi rotulado por um pipeline de leitura independente (três agentes + revisão cruzada), o que o torna a medida menos contaminada do par — mas ele é enviesado para casos difíceis (estratos T1/T2) por desenho. A leitura honesta será: o núcleo mede qualidade em regime duro com juiz independente; o aleatório mede o universo real, com o desconto da circularidade. Se o v5 vencer nos dois, a evidência é forte. Se vencer só no aleatório, o veredito fica em aberto e o próximo passo é a confirmação humana dos 73 casos de baixa confiança mais uma rodada de adjudicação cega v3×v5.

Desfecho real: o v5 venceu nos dois subsets — a previsão a priori se confirmou, e esta ressalva permanece como desconto honesto sobre o aleatório, não como desculpa para ignorá-lo.

7.2 O v5 em carne e osso

Tabelas dizem quanto; casos dizem o quê. Rodei os dois modelos sobre os 1.499 casos do ouro e separei os desacordos: v3 e v5 divergem em 61% dos casos — e, nesses desacordos, o v5 acerta 448 contra 107 do v3 (razão 4,2:1), com 360 em que ambos erram. Quando os dois concordam, acertam apenas 59%: a discordância concentra exatamente os casos difíceis. Cinco casos reais (textos anonimizados; o rótulo canal_msg segue a convenção da série):

Caso 1 — o vício da prata, desaprendido. Cliente pede backup dos dados da conta para migração ("Solicitar Backup / Para migração de dados / Regularmente"). Ouro: conta_config. O v3 diz canal_msg com confiança 0,95 — qualquer menção a número ou exportação de conversas, ele jogava na classe que a prata super-etiquetava, com certeza absoluta. O v5 diz conta_config com 0,88, e ainda acerta a urgência (baixa, onde o v3 dizia alta). Este padrão se repete em dezenas de casos: o v5 não decorou novas palavras — desaprendeu um reflexo.

Caso 2 — a fronteira que a regex não via. Cliente pergunta por que a atribuição de uma mensagem a um vendedor aparece no histórico com outro nome. Ouro: duvida_produto, urgência moderada. O v3 diz incidente (0,56) — "apareceu algo errado" virava incidente. O v5 diz duvida_produto (0,75) e moderada — entendeu que é uma pergunta sobre como o produto funciona, não uma falha.

Caso 3 — bug de verdade, enfim reconhecido. "Pesquisa em campo de ticket de lista de subníveis não localiza as classificações" — um relato de comportamento quebrado na v2 do helpdesk. Ouro: bug_produto. O v3 diz canal_msg com 0,96 (!). O v5 diz bug_produto com 0,73. O F1 de bug_produto ter saltado de 0,142 para 0,459 é feito de centenas de casos assim.

Caso 4 — onde o v5 perde (honestidade). Cliente pergunta da nova política de cobrança da provedora do canal e do recurso de otimização de bot para reduzir custos. Ouro: canal_msg. O v3 crava canal_msg (0,98) ✅; o v5 diz conta_config (0,35) ❌. O pêndulo balançou: quem antes super-etiquetava a classe do canal agora às vezes a sub-etiqueta. Mas note a confiança: 0,35 está muito abaixo do limiar de 0,8 — o erro do v5 vai para a fila humana, não vira decisão automática errada. Perder com confiança baixa é o jeito certo de perder.

Caso 5 — a fronteira que resta (ambos erram). "Os clientes estão ficando presos no bot, está dando erro de envio das mensagens, estou com 850 conversas no bot." Ouro: duvida_produto (o juiz leu como dúvida de configuração do bot). v3: canal_msg (0,98); v5: bug_produto (0,56). Razoável dos dois lados e errado nos dois — é exatamente a fronteira bug_produto × duvida_produto × conta_config que a seção 4.4 identificou como decisão de taxonomia. Esses casos não se resolvem com mais GPU; se resolvem com guia de anotação mais afiado e mais exemplos rotulados exatamente nessa fronteira.

O mapa completo de 20 casos (14 vitórias do v5, 3 do v3, 3 empates no erro) está em docs/comparativo_v3_v5.md, com textos, confianças e os comentários do juiz do ouro.

8. O que separa isto de "um modelo que as pessoas queiram usar"

Inventário honesto do que resta, em ordem de alavanca:

  1. Cobertura no automático: 10,8% das linhas a 84,8% de acurácia (v5, régua nova) é um produto menor do que os 30,9% do v3 na régua de prata — e mais honesto. O caminho para 60–80% passa por mais dados de domínio nas categorias duras — agora, com rótulos de leitura, cada novo lote rotulado vale mais do que valia na era da prata.
  2. Ouro ampliado e com confirmação humana: 1.499 casos é uma régua; 5.000 é um ativo. E os 73 casos de baixa confiança precisam de olhos humanos.
  3. Serving: o decisor-v5 já responde em API local (as três perguntas, probabilidades calibradas, roteamento por limiar de confiança) — a "configuração, não um projeto" prometida acima foi exatamente o que aconteceu: temperaturas recalibradas no ouro, checkpoint trocado, smoke test, ~5 segundos de indisponibilidade. O v3 permanece no host intocado como rollback.
  4. Revisita ao RL? A Parte 2 encerrou o assunto com "inócuo não é útil". Com rótulos de leitura e uma régua confiável, a recompensa do RLCD deixaria de ser ruidosa — mas o baseline escalar (temperature scaling) continua capturando o ganho fácil. RL volta à mesa só quando houver evidência de que a fronteira restante é de calibração fina, não de rótulo.

9. Lições da Parte 3

  1. Meça a régua antes de medir o modelo. O benchmark contra o backbone zero-shot isolou o efeito do treino; a adjudicação cega mediu o erro da régua (63% nos pontos contestados); o ouro mediu o resto. Cada camada de medição mudou a conclusão anterior.
  2. Régua errada em duas direções. A prata não só inflava a nota do v3 (0,603 contra ela vs 0,317 contra o ouro) como também escondia acertos (a adjudicação estimava 0,71). Ruído de régua não "se cancela" — ele distorce o ranking dos modelos e o mapa de onde investir.
  3. Resultado negativo com mecanismo claro vale mais que positivo confuso. O v4 falhou por uma razão identificável — peso amplifica ruído de rótulo — e essa razão apontou diretamente para o v5.
  4. Conserte a causa raiz, não o sintoma. O sintoma era macro-F1 baixo; a causa era a taxonomia dos rótulos. Class weighting tratou o sintoma e piorou o quadro; re-rotular o train tratou a causa.
  5. Juiz cego à régua antiga. O re-rotulador não viu a prata de propósito — herdar o viés da régua anterior na régua nova teria invalidado o exercício inteiro.
  6. Declare a circularidade antes dos números. A seção 7.1 foi escrita antes da avaliação rodar. Limitação declarada a priori é método; declarada a posteriori é desculpa.
  7. Todo pipeline precisa de verificação de linhagem. Três bugs de dados (<mask>, urgência constante, sampler lendo o gold v1) foram pegos olhando o arquivo, não o nome do arquivo. Hash, contagem e spot check — sempre.

Na sequência

A seção 7 foi preenchida assim que o treino saiu: o v5 venceu o v3 no subset núcleo (0,584 vs 0,401 na acurácia geral — o critério fixado a priori) e no aleatório (0,621 vs 0,445), e a API de produção já roda o v5 — calibrado no ouro, com o v3 preservado no host como rollback e ~5 segundos de indisponibilidade no swap. A ressalva de circularidade do subset aleatório foi declarada antes dos números e segue valendo como desconto, não como veto. O próximo capítulo não é mais treino — é produto: subir a cobertura do automático além dos 10,8% atuais, confirmar os 73 casos de baixa confiança com olhos humanos, e medir latência e a experiência de quem usa.


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.