Um Modelo de Decisão "System 1" para Atendimento em PT-BR — Parte 2: Resultados, Calibração e o Veredito sobre RL
- 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 2
Nota de anonimização: como na Parte 1, todos os nomes de empresas, produtos, plataformas e clientes foram omitidos ou generalizados. "A plataforma de atendimento", "o dataset público de e-commerce brasileiro" e "o helpdesk" referem-se a sistemas reais em operação.
1. Recap: onde a Parte 1 parou
Resumo em três linhas para quem chegou agora:
- Construímos um decisor System 1 (encoder mmBERT de 322M parâmetros, option-markers, 17 categorias) que decide categoria/decisão/urgência de chamados em PT-BR, com probabilidades calibradas, rodando em CPU.
- O primeiro treino (v1) saiu degenerado por um bug de tokenização —
[MASK]hardcoded em vez do<mask>real do ModernBERT; 100% dos exemplos sem máscara; o "modelo" respondia sempre a opção 0. - A correção + a vacina (
checa_trunc.py, 0% de perda de máscara em todos os conjuntos) abriram caminho para o v2, treinado sobre ~444 mil exemplos com padding dinâmico e batch 24.
Esta Parte 2 responde quatro perguntas:
- O v2 aprendeu de verdade? (acurácia no gold set intocável)
- As probabilidades dele significam alguma coisa? (calibração)
- O RLCD melhora a honestidade das probabilidades? (e quanto)
- Quantas rodadas de RLCD valem a pena? (análise de ganho marginal)
Spoiler honesto: a resposta da pergunta 4 virou uma das descobertas mais interessantes do projeto — e não é a que eu esperava.
2. O protocolo de avaliação (antes dos números)
Uma decisão metodológica tomada antes de ver qualquer resultado, para não cair na armadilha do v1 (ECE bonito sobre comportamento degenerado):
- Gold set intocável: 5.244 exemplos dos últimos 60 dias, nunca vistos em nenhuma fase de treino (split temporal, não aleatório).
- Ordem das métricas: primeiro acurácia, depois calibração. ECE só é reportado para modelos que passam no gate de sanidade (acurácia muito acima do baseline aleatório).
- Tudo por pergunta: categoria (17 opções), decisão (5 opções) e urgência (4 opções) são avaliadas separadamente — um modelo pode ser bom numa e ruim noutra.
- Roteamento simulado: a métrica que paga as contas. Com threshold de confiança 0,8, medimos (a) que fração do gold o System 1 decidiria sozinho e (b) qual a acurácia dentro desse subconjunto. Objetivo do projeto: cobertura 80–90% com acurácia visivelmente maior que a acurácia global.
- Reprodutibilidade: a avaliação é um script (
avaliar_decisor.py) que salva JSON + Markdown por checkpoint; a comparação entre fases é outro script (comparar_checkpoints.py) que lê os artefatos e emite a tabela de evolução. Nenhum número deste artigo foi copiado à mão de log. - Gate anti-degradação: nenhuma fase nova (RL, novo treino) é aceita se piorar acurácia geral > 1 p.p., acurácia no roteamento automático > 1 p.p., ou ECE > 0,01. Autorização de experimento nunca atropela qualidade.
3. Resultados do v2 (supervised, pós-correção)
3.1 Treinamento
- 55.500 steps, 3 épocas sobre ~444 mil exemplos (dataset público de e-commerce BR + tickets de suporte EN + chamados próprios), batch 24 com padding dinâmico, max_len 1024, em uma das GPUs AMD de 24 GB a ~3,2 steps/s — pouco menos de 5 horas de treino.
- Loss final 0,122 · acurácia de treino 0,959 (época 3/3: loss 0,1219, acc 0,959). A curva estabilizou na época 2 (acc 0,958) — sinal de que 3 épocas foram suficientes e uma 4ª não agregaria.
A comparação que importa: o v1 bugado reportava "acurácia de treino" de 27% — a frequência exata da opção 0 no dataset. O v2 saiu de 47,3% no step 1.000 para 95,9% no final. Dessa vez, o gradiente tinha para onde ir.
3.2 Acurácia no gold set
| pergunta | v1 (bugado) | baseline aleatório | v2 |
|---|---|---|---|
| categoria (17 opções) | 1,8% | 5,9% | 53,7% |
| decisão (5 opções) | 0,0% | 20% | 74,4% |
| urgência (4 opções) | 0,0% | 25% | 100,0% ⚠️ |
| geral (5.244 ex.) | 0,6% | — | 76,0% |
Leitura honesta, número a número:
- Decisão (74,4%) é o resultado mais valioso: é a pergunta que o negócio mais precisa (resolver, escalar, pedir info...) e o modelo acerta 3,7× o baseline em dados que nunca viu.
- Categoria (53,7%) é 9× o aleatório, mas está longe do confortável. A seção 3.4 mostra que boa parte do "erro" mora na fronteira semântica entre categorias vizinhas, não em ignorância do modelo.
- Urgência (100,0%) é bom demais para ser verdade — e mereceu o mesmo
ceticismo que aplicamos ao v1. A auditoria (seção 10) confirmou que havia
algo errado, mas com um desfecho diferente da hipótese inicial: não era
vazamento de features — era pior. O rótulo de urgência é 100%
degenerado: todos os 1.748 exemplos do gold (e todos os 3.967 do
treino) são da classe "3 - crítica". O modelo acerta 100% respondendo
sempre a mesma coisa — o v1 das probabilidades se repetindo como v1 das
classes. A causa raiz estava na linha de derivação do rótulo: a urgência
era calculada a partir da "confiança" do rótulo SFT, que o pipeline
fixa em 0,9 para todo chamado resolvido por humano →
conf >= 0.9 → urgência 3para todo mundo, sempre. Uma métrica perfeita sobre uma pergunta vazia. A correção está na seção 10.
3.3 P/R/F1 das categorias
O gold set cobre 14 das 17 categorias (3 não aparecem nos últimos 60 dias — sem suporte, sem julgamento):
| categoria | N | P | R | F1 |
|---|---|---|---|---|
| canal_msg | 643 | 0,679 | 0,692 | 0,686 |
| outro | 245 | 0,497 | 0,616 | 0,550 |
| incidente | 409 | 0,435 | 0,626 | 0,514 |
| plano_creditos | 75 | 0,473 | 0,467 | 0,470 |
| integracao | 81 | 0,625 | 0,370 | 0,465 |
| bug_produto | 102 | 0,298 | 0,167 | 0,214 |
| pagamento | 30 | 0,429 | 0,100 | 0,162 |
| conta_config | 56 | 0,333 | 0,036 | 0,065 |
| duvida_comercial | 28 | 0,000 | 0,000 | 0,000 |
| duvida_produto | 64 | 0,000 | 0,000 | 0,000 |
| prazo_envio | 9 | 0,000 | 0,000 | 0,000 |
| produto_defeito | 2 | 0,000 | 0,000 | 0,000 |
| reembolso | 1 | 0,000 | 0,000 | 0,000 |
| troca_devolucao | 3 | 0,000 | 0,000 | 0,000 |
Padrões claros:
- Volume ajuda, mas não garante: as três categorias mais frequentes
(
canal_msg,incidente,outro) concentram os únicos F1 razoáveis — e também a maioria das confusões (elas se confundem entre si, ver 3.4). - As 6 categorias de e-commerce quase zeradas (
reembolso,troca,prazo_envio...) têm suporte ínfimo no gold (1–9 exemplos) porque o gold vem dos chamados próprios dos últimos 60 dias, não do dataset público. Ou seja: o gold atual não mede o domínio e-commerce — para ele, o teste real continua sendo o split temporal do próprio dataset público. Não concluir "o modelo esqueceu e-commerce" por esta tabela. duvida_produtoeduvida_comercialcom F1 0 e suporte real (64 e 28) são o fracasso genuíno da tabela: o modelo nunca as prediz — tudo escorre paraincidente,outroecanal_msg. Candidatas claras a oversampling ou a revisão de rótulo na próxima iteração.
3.4 Anatomia das confusões
As top confusões (real → predita) contam uma história muito específica:
- 128× canal_msg → incidente · 114× incidente → canal_msg
- 59× outro → incidente · 58× bug_produto → incidente
- 27× canal_msg → outro · 24× outro → canal_msg · 23× incidente → outro
Leitura preliminar (a confirmar na auditoria manual): o eixo incidente ↔ canal_msg domina — 242 exemplos, ~14% do gold de categoria. É exatamente a fronteira semântica que já apareceu na auditoria de vocabulário da Parte 1: quando a mensageria corporativa é o canal da conversa e também o assunto da falha ("as mensagens não estão saindo"), o mesmo chamado é legitimamente os dois. Se a regra de rotulagem original usava o canal como sinal, o rótulo carrega ambiguidade estrutural — e o modelo "errando" 50/50 entre as duas pode estar é reproduzindo a incerteza do próprio processo de rotulagem. O remédio aqui é uma regra de desempate no vocabulário (ex.: "se a falha reportada é no canal X, a categoria é incidente, não canal_msg"), não mais GPU.
Esta distinção muda o roadmap: se a auditoria confirmar que uma fatia grande das confusões é de rótulo/fronteira, a próxima alavanca é higiene de dados, não mais treino.
4. Calibração: as probabilidades significam alguma coisa?
4.1 Metodologia
Temperature scaling por número de opções (uma temperatura por tamanho de lista de opções), ajustado e medido sobre o gold por ECE (Expected Calibration Error), reportado separadamente por pergunta.
E o lembrete que virou regra da casa depois do v1: ECE sem acurácia não valida nada. O v1 bugado tinha ECE de categoria de 0,041 — "excelente" — porque sempre dizia a mesma coisa com confiança uniforme. Calibração só é reportada aqui porque o v2 passou pelo gate de acurácia.
4.2 Resultados
| pergunta (n° opções) | ECE antes | ECE depois | temperatura |
|---|---|---|---|
| urgência (4) | 0,001 | 0,000 | 0,25 |
| decisão (5) | 0,111 | 0,019 | 1,65 |
| categoria (17) | 0,120 | 0,041 | 1,35 |
Três leituras:
- O modelo saía do supervised superconfiante nas duas perguntas que importam (ECE ~0,11–0,12, acima do alvo de 0,10): as temperaturas > 1 (1,65 e 1,35) "achatam" a distribuição e derrubam o ECE para 0,019 e 0,041 — ambos confortavelmente abaixo do alvo.
- A temperatura de 0,25 da urgência é outro sintoma do rótulo degenerado discutido em 3.2: classe única no treino → o modelo aprendeu a ter certeza absoluta de uma resposta só. Calibração perfeita sobre pergunta vazia não é mérito — é advertência.
- Diferente do v1, aqui o ECE baixo acompanha acurácia real — é o primeiro modelo do projeto cujas probabilidades podem ser usadas para rotear tráfego de verdade. E é exatamente aí que o RLCD entra: se o temperature scaling corrigiu a média, o RL deveria corrigir a forma da distribuição, exemplo a exemplo. "Deveria" — a seção 5 conta o que aconteceu de fato.
5. RLCD: três rodadas, três resultados, um veredito
5.1 Por que RL depois do supervised
Cross-entropy ensina a acertar a resposta; não ensina a distribuir a probabilidade de forma honesta. Um modelo supervised tende a concentrar massa na opção argmax além do que sua taxa real de acerto justificaria — superconfiança clássica, confirmada na seção 4.2 (ECE ~0,12 antes do scaling). O RLCD (Reinforcement Learning for Calibrated Decisions) ataca exatamente isso:
- REINFORCE com baseline estilo GRPO: para cada exemplo, amostramos G decisões da política; a vantagem é a recompensa menos a média do grupo — sem crítico aprendido, sem PPO, variância controlada pelo grupo.
- Recompensa = strictly proper scoring rules (log score + spherical score sobre a distribuição reportada). A propriedade matemática que importa: uma scoring rule strictly proper só é maximizada em esperança quando a distribuição reportada é a crença verdadeira do modelo. Ou seja: a recompensa ótima não é "acerte sempre com 100%" — é "reporte exatamente a incerteza que você tem". O RL literalmente paga o modelo para ser honesto.
5.2 O desenho do experimento: uma curva dose-resposta em 3 pontos
Em vez de uma única rodada "no feeling", rodamos três configurações que varrem o espaço de doses — e isso fez toda a diferença na conclusão:
| RLCD-1 (quente demais) | RLCD-2 (fria demais) | RLCD-3 (intermediária) | |
|---|---|---|---|
| parâmetros treinados | encoder + cabeça (322M) | só cabeça | só cabeça |
| LR | 5e-6 | 1e-6 | 5e-6 |
| épocas | 2 | 1 | 1 |
| grupo G | 4 | 8 | 8 |
| recompensa medida em | política com ruído | política limpa | política limpa |
| vantagem | sem clip | clip ±2 | clip ±2 |
| weight decay | 0,01 (padrão) | 0 | 0 |
| dropout nos rollouts | ligado | desligado | desligado |
| dados | 11.901 chamados próprios | idem | idem |
O RLCD-1 foi o primeiro a rodar — e falhou de forma instrutiva. A auditoria pós-falha (antes de qualquer re-tentativa) encontrou sete problemas empilhados, não um:
- Recompensa medida na política com ruído (σ=0,5): o log score pune sem limite inferior; com ruído grande, a vantagem passa a medir o azar do sorteio do ruído, não a qualidade da política.
- Encoder inteiro treinando: RL de calibração deveria ajustar a cabeça; mover 322M parâmetros com gradiente de alta variância é pedir deriva catastrófica.
- Grupo G=4 pequeno demais para o baseline amortecer a variância.
- Vantagem sem clip: um único caso com log p ≈ -18 dita o gradiente do lote.
- Dropout ligado nos rollouts (modelo em modo treino): mais uma fonte de ruído invisível para a recompensa e o baseline.
- Weight decay padrão do AdamW (0,01): encolhe os pesos da cabeça a cada step independentemente do sinal — confiança drenada "de graça".
- Recompensa/baseline dentro do grafo de autograd: desperdício de VRAM e risco de vazamento de gradiente por caminho lateral.
A correção virou a config do RLCD-2/3: encoder congelado, recompensa na política limpa (ruído só para amostrar a ação), G=8, clip ±2, decay 0, dropout off, mais uma guarda anti-divergência: se a recompensa móvel cai > 0,75 abaixo da melhor vista, o treino aborta sem salvar checkpoint — modelo degradado nunca mais chega ao disco.
5.3 Trajetórias de recompensa: o sinal que conta a história
| rodada | início | fim | leitura |
|---|---|---|---|
| RLCD-1 | -0,38 | -2,21 | recompensa caindo por 3.900 steps seguidos — o treino estava ativamente piorando a política |
| RLCD-2 | -0,17 | -0,17 | oscilação ±0,1 em torno da média, sem tendência — política praticamente parada |
| RLCD-3 | -0,19 | -0,19 | idem — nenhuma direção |
Detalhe forense curioso: as trajetórias das rodadas 2 e 3 são quase idênticas ponto a ponto (mesma seed → mesma ordem de batches e mesma sequência de ruído; com os pesos quase parados, a recompensa é dominada pela sequência aleatória, não pela política). É a assinatura de um treino que não está se movendo.
5.4 O que cada rodada fez no gold set
| métrica | supervised v2 | RLCD-1 | RLCD-2 | RLCD-3 |
|---|---|---|---|---|
| acurácia geral | 0,760 | 0,658 ❌ | 0,760 | 0,760 |
| categoria | 0,537 | 0,234 ❌ | 0,537 | 0,536 |
| decisão | 0,744 | 0,739 | 0,744 | 0,745 |
| cobertura S1 (conf≥0,8) | 52,5% | 33,3% ❌ | 52,5% | 49,7% |
| acurácia no auto | 0,945 | 1,000* | 0,945 | 0,955 |
| ECE categoria (pós-scaling) | 0,041 | 0,073 | 0,040 | 0,041 |
| ECE decisão (pós-scaling) | 0,019 | 0,039 | 0,019 | 0,019 |
| temperatura necessária (17 op) | 1,35 | 4,95 | 1,35 | 1,40 |
* acurácia de 100% sobre apenas 33% do volume — o modelo só "confia" nos casos triviais; sintoma da calibração destruída (ECE pré-scaling de 0,764).
E o dado mais frio de todos: a diferença máxima de peso da cabeça entre supervised e RLCD-2 foi de 1,2e-4 — com encoder congelado e LR 1e-6, o RL literalmente não saiu do lugar. O RLCD-3 (LR 5× maior) moveu a cabeça o suficiente para trocar meia dúzia de predições: +0,1 p.p. em decisão, -0,1 p.p. em categoria, -2,8 p.p. de cobertura, +1,0 p.p. de acurácia no auto. Tudo dentro do ruído.
6. Quantas rodadas de RLCD valem a pena?
6.1 Critério de parada (definido antes de rodar)
Uma rodada adicional só se justificaria se a anterior trouxesse ganho marginal mensurável: ΔECE ≥ 0,01 em alguma pergunta, ou Δacurácia no auto ≥ 0,5 p.p., sem perda de acurácia geral.
6.2 O veredito: zero rodadas — e isso é um resultado, não um fracasso
Aplicando o critério às três rodadas:
- RLCD-1: degradou (reprovada no gate anti-degradação, -10,3 p.p. de acurácia geral).
- RLCD-2: ΔECE = 0,000–0,001; Δacc = 0,000. Nada.
- RLCD-3: ΔECE = 0,000; Δacc ≤ 0,1 p.p. Nada além do ruído.
A dose-resposta é plana nos dois extremos úteis e catastrófica no extremo quente: não existe dose deste RLCD que melhore o que o temperature scaling já entrega. A recomendação de produção é o checkpoint supervised puro + temperaturas (1,35/1,65) — o componente mais barato do pipeline.
Isso não contradiz a literatura de RL para calibração — contextualiza: o RLCD foi proposto para corrigir superconfiança quando não há um método mais simples. Aqui havia. O temperature scaling por número de opções capturou praticamente toda a superconfiança sistemática (ECE 0,12 → 0,02– 0,04); o que sobrou de erro de calibração é condicional (depende do exemplo), e sobre ele o RL com recompensa de scoring rule média tem gradiente fraco demais para agir — como mostram as trajetórias sem tendência. A lição metodológica: rodar o baseline escalar primeiro e o RL depois teria poupado uma rodada de GPU; a ordem correta de complexidade crescente deveria ter sido norma desde o início.
6.3 O teto que nenhuma rodada furaria
Mesmo que o RL tivesse funcionado, havia um teto baixo esperando: o gold de categoria carrega ambiguidade estrutural (a fronteira incidente↔canal_msg da seção 3.4 afeta ~14% dos exemplos) e, muito provavelmente, rótulos derivados por regra com ruído próprio. Contra um chão de irredutibilidade dessa ordem, a distância entre "ECE 0,041" e "calibração perfeita" é curta demais para pagar horas de GPU. O ganho marginal real de mais rodadas seria decimal — o critério de parada existia exatamente para dizer isso com dados, e disse.
7. A simulação de roteamento: o número que paga as contas
Com threshold de confiança 0,8 e probabilidades pós-temperature-scaling:
| cenário | cobertura S1 | acurácia no auto | acurácia global |
|---|---|---|---|
| supervised v2 (recomendado) | 52,5% | 94,5% | 76,0% |
| RLCD-1 | 33,3% | 100%* | 65,8% |
| RLCD-2 | 52,5% | 94,5% | 76,0% |
| RLCD-3 | 49,7% | 95,5% | 76,0% |
Leitura operacional: hoje, metade do volume cairia no automático acertando 19 de cada 20 — já é um produto útil. O objetivo de 80–90% de cobertura, porém, não será alcançada por calibração: o que separa 52,5% de 80% é acurácia de categoria (53,7%), e isso é problema de dados e vocabulário (seção 3.4), não de distribuição de probabilidade. O RLCD-3 mostra o trade-off no osso: -2,8 p.p. de cobertura comprando +1,0 p.p. de acurácia no auto — a curva cobertura×acurácia existe, e o ponto de operação é uma decisão de negócio (custo do erro vs. custo da escalada humana).
8. Evolução de qualidade por fase (visão única)
Tabela gerada pelo comparar_checkpoints.py diretamente dos artefatos de
avaliação — uma linha por checkpoint, todas as fases lado a lado:
| checkpoint | acc geral | acc categ. | acc decisão | roteamento S1 | acc no auto | ECE 17-op | ECE 5-op |
|---|---|---|---|---|---|---|---|
| decisor-v1 (supervised) | 0,760 | 0,537 | 0,744 | 52,5% | 0,945 | 0,041 | 0,019 |
| decisor-rlcd (RLCD-1) | 0,657 ❌ | 0,234 ❌ | 0,739 | 33,3% | 1,000* | 0,073 | 0,039 |
| decisor-rlcd2 | 0,760 | 0,537 | 0,744 | 52,5% | 0,945 | 0,040 | 0,019 |
| decisor-rlcd3 | 0,760 | 0,536 | 0,745 | 49,7% | 0,955 | 0,041 | 0,019 |
Cada fase do pipeline deixou um rastro medível, comparável e reproduzível — nenhuma "melhora" foi declarada sem delta. Incluindo a que não melhorou.
9. A auditoria de rótulos: ouro, prata e o que estava quebrado
Depois do veredito do RLCD, a pergunta que ficou na mesa era: se a calibração está resolvida, por que a acurácia de categoria estaciona em 53,7%? A resposta exigiu descer um nível abaixo do modelo — na linhagem dos rótulos.
9.1 A descoberta desconfortável: o "gold" era prata
Os rótulos dos chamados próprios (treino e gold) não vêm de humanos: são derivados por regras de palavra-chave sobre a conversa inteira — primeira regra que casa vence, numa ordem fixa. Isso vale para categoria (regex sobre o texto), decisão (regex sobre o comportamento do atendente) e urgência (que deveria medir severidade). Ou seja: o modelo foi treinado e avaliado contra a saída de uma família de regexes. O teto real do modelo não é 100% — é a qualidade dessas regras. Três evidências de que elas eram o gargalo:
- A confusão nº 1 era erro de rótulo, não do modelo. A fronteira
incidente↔canal_msgconcentrava 242 casos (~14% do gold de categoria). Lendo os casos contestados (142 exemplos com keywords das duas regras), o padrão é claro: o cliente relata "mensagem não enviada no canal_msg" ou "nosso contato caiu" — o assunto é o canal de mensageria, mas a regra deincidente("caiu", "mensagem não enviada") vinha antes na ordem e engolia o caso. O modelo que previacanal_msgestava, frequentemente, mais certo que o rótulo. - Urgência 100% degenerada (seção 3.2): a "urgência" era derivada da confiança do rótulo SFT, que o pipeline fixa em 0,9 para todo chamado resolvido por humano → classe única, treino e gold. Pergunta vazia.
- Categorias órfãs com suporte real:
duvida_produto(135 exemplos de treino, 64 no gold) eduvida_comercial(41/28) têm F1 = 0 — o modelo nunca as prevê. Padrão típico de rótulo indistinguível da classe vizinha nos dados (o regex que geraduvida_produtoquase nunca dispara antes deincidente/outro), não de falta de exemplos.
E um quarto achado, sobre a pergunta de decisão: acurácia de 74,4% contra
73,9% de baseline da classe majoritária (executar_acao é o rótulo
default da regra quando nada dispara). O modelo agregava +0,5 p.p. sobre
"sempre executar" — a pergunta mais importante do sistema era, também ela,
quase vazia de sinal discriminativo.
9.2 A correção (v3 dos dados)
Duas mudanças cirúrgicas, ambas documentadas em código:
- Regra de desempate de categoria:
canal_msg(e as demais categorias específicas de canal/produto) passam a vir antes deincidente, que fica residual para indisponibilidade sistêmica sem canal específico nomeado. Efeito na distribuição:incidente38,8% → 23%,canal_msg24,6% → 40% — a zona contestada migrou para onde a leitura humana apontava. - Urgência heurística real: substituída a regra da confiança por padrões sobre o texto do chamado (impacto: "fora do ar", "equipe parada", "prejuízo" → 3; bloqueio de fluxo: "não consigo", "erro" → 2; dúvida de uso → 0; resto → 1). Ainda é prata — mas prata sobre urgência, não sobre confiança de rotulador. Distribuição resultante: 4 classes vivas (treino: 16% / 49% / 22% / 4%; gold: 15% / 46% / 21% / 3%).
O gold foi regerado com as mesmas regras novas — e, para a comparação ser justa, o v2 será reavaliado no gold novo lado a lado com o v3 (seção 11). Trocar o rótulo e a régua ao mesmo tempo sem reavaliar o modelo antigo na régua nova seria o erro clássico de medida.
9.3 O resultado do v3: a régua honesta reescreve o placar
O v3 foi treinado com exatamente os mesmos hiperparâmetros do v2 — o que mudou foram os rótulos (seção 9.2). E ambos foram avaliados no mesmo gold novo (5.193 exemplos, categorias com desempate corrigido, urgência com 4 classes reais):
| métrica | v2 no gold novo | v3 no gold novo | leitura |
|---|---|---|---|
| acurácia geral | 0,435 | 0,646 | +21,1 p.p. |
| categoria | 0,529 | 0,593 | +6,4 p.p. |
| decisão | 0,741 | 0,745 | estável (regra não mudou) |
| urgência | 0,034 | 0,600 | o v2 não sabia urgência — respondia sempre "crítica"; com 3% de críticos no gold novo, quebrou |
| cobertura S1 (conf≥0,8) | 52,5% | 30,2% | cobertura caiu… |
| acurácia no auto | 0,330 | 0,913 | …mas a do v2 era conforto falso: confiante e errando 2/3 |
| ECE (cat/dec/urg, pós-scaling) | — | 0,050 / 0,027 / 0,042 | v3 calibrado nas 3 perguntas reais |
Três destaques:
- O número mais importante desta Parte não é do v3 — é o 0,330 do v2. No gold velho (prata), o v2 roteava 52,5% do volume com "94,5% de acurácia no automático". Na régua honesta, esse mesmo subconjunto confiante acerta um terço. A urgência degenerada inflava a acurácia e as categorias trocadas inflavam a confiança. A régua errada fazia um modelo mediano parecer produto pronto. Esta é a lição mais cara do projeto inteiro: quem avalia errado, entrega errado.
- A fronteira incidente↔canal_msg encolheu de 242 para 131 confusões
(-46%), e o F1 de
canal_msgsubiu de 0,686 para 0,769 — a regra de desempate fez pelo dado o que nenhuma GPU faria pelo modelo. - Urgência existe agora: 60% de acurácia em 4 classes (baseline 25%) com ECE real de 0,042. Não é excelente — é a primeira medida real.
E o trade-off honesto: a cobertura caiu de 52,5% para 30,2% porque o modelo agora sabe o que não sabe (a confiança parou de ser inflada por rótulo fácil). 30% de cobertura com 91,3% de acurácia é um produto menor, mas é um produto de verdade — e a fronteira seguinte (recuperar cobertura sem perder a honestidade) passa por mais dados de domínio e pelo System 2, não por métrica inflada.
Decisão de produção: decisor-v3, sem discussão — supera o v2 em todas as métricas na mesma régua, e a única métrica em que "perde" (cobertura) é exatamente aquela em que o v2 estava trapaceando sem saber.
Duas ressalvas que sobrevivem ao v3:
- A prata continua prata: regex melhorado ainda é regex. A medida definitiva exige um gold humano (ou de juiz forte, o System 2) sobre uma amostra — o número 0,646 também é uma cota inferior da qualidade percebida, porque uma fatia das "confusões" restantes ainda pode ser erro de régua.
pedir_mais_info(10 exemplos de treino) e as categorias de e-commerce nos chamados próprios seguem sub-representadas — o próximo salto de qualidade de decisão virá daí e do gold humano, não de mais treino sobre estes rótulos.
10. Lições da Parte 2
- Acurácia primeiro, calibração depois, sempre nesta ordem. (Repetida de propósito: é a lição mais cara do projeto.)
- Desconfie do 100%. A urgência perfeita era o sinal de fumaça de um
rótulo degenerado (classe única por uma confiança hardcoded) — o mesmo
ceticismo que pegou o bug do
<mask>pega prata mal-extraída. Métrica perfeita em tarefa imperfeita é diagnóstico, não troféu. - Toda confusão recorrente tem dono: rótulo, vocabulário ou modelo. A fronteira incidente↔canal_msg sugere que a próxima alavanca de qualidade é uma regra de desempate no vocabulário, não GPU.
- RL não é varinha: é bisturi. Sete problemas de configuração empilhados transformaram a ferramenta mais sofisticada do projeto na única que destruiu valor. Congelar o encoder, medir recompensa na política limpa e clipar vantagens transformaram-na em inócua — mas inócua não é útil.
- O baseline escalar primeiro. Temperature scaling (uma linha de código, um escalar por pergunta) capturou todo o ganho de calibração disponível. Complexidade crescente só se justifica quando a simples esgota — e deve-se provar que ela esgotou antes de escalar.
- Ganho marginal decrescente é a regra. O critério de parada, definido antes da primeira rodada, transformou "será que mais uma rodada ajuda?" em uma pergunta com resposta objetiva: não.
- A métrica de negócio é cobertura × acurácia no automático. O resto é instrumentação.
Na sequência
O roadmap de qualidade, ordenado por evidência (o item 1 já saiu do papel nesta edição — seção 9):
Treino v3 sobre os rótulos corrigidosfeito — v3 recomendado para produção (seção 9.3).- Gold humano de verdade: uma amostra de algumas centenas de chamados rotulados à mão para medir quanto da "prata" resiste — e, com o System 2, um juiz forte para escalar essa rotulagem.
- Recuperar cobertura sem perder honestidade: 30% → 80% é o desafio central; passa por mais dados de domínio (decisão e categorias órfãs) e pelo System 2 absorvendo a cauda difícil com justificativa.
- Só então: quem sabe uma revisita ao RL — com um baseline simples já esgotado de propósito para medir o que o RL realmente acrescenta.
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.