Conversation Analysis · Teste de paridade

O payload único do V4 deteriora a qualidade?

Rodamos os dois pipelines lado a lado, na mesma conversa, no mesmo momento, sem alterar nenhum dado de cliente. Diff automático nos campos que têm resposta certa; juiz cego nos textos livres.

30 conversas reais host cruzeiroec > 10 mensagens 13/jul/2026 escrita zero verificada

Os números foram colhidos antes das correções dos dois bugs de engenharia, que entraram no branch logo depois. As conclusões de qualidade não dependem deles; as de custo descrevem o estado pré-correção e precisam ser re-medidas.

Não virar ainda

A consolidação não é o problema. A configuração é.

O payload único não derruba a qualidade de forma geral — sentimento fica em paridade, o V4 alucina metade do que o V2 alucina e obedece muito mais às regras. Mas dois campos regridem (heat_score e pending), e o levantamento achou três bugs — um deles fazia o V4 custar mais caro que o V2, e já drenava dinheiro em produção pelo formFlow.

Dois desses bugs já foram corrigidos. O que ainda bloqueia o go/no-go é uma decisão de produto: o que o heat_score deve significar.

Os quatro números que decidem

Divergência real = 2 pontos ou mais. O piso de ruído medido é ±1: rodando o mesmo motor duas vezes na mesma conversa, ele já discorda de si mesmo em 1 ponto.

Sentimento 5/30 divergências reais. Juiz cego: empate (8 × 8). Paridade
Heat score 17/30 divergências reais. Juiz cego preferiu o V2 em 13 de 16 decididas. V4 pior
Pendências 15×1 o juiz preferiu o V2. Foi o veredito mais estável de todos. V4 pior
Alucinações 11 vs 22 o V4 inventa metade do que o V2 inventa. V4 melhor

O balanço, em uma tela

Onde o V4 ganha

  • +Metade das alucinações. 11 contra 22 apontadas pelo juiz.
  • +Obedece às regras. 27% dos resumos passam de 80 palavras, contra 53% do V2. Nenhum main_topic estourou o limite (o V2 estourou 5).
  • +3,6× mais rápido. 17s contra 61s por conversa.
  • +Sentimento em paridade. Empate técnico no juiz e no diff.
  • +4× mais barato — depois de corrigido o bug do sumarizador.

Onde o V4 perde

  • heat_score: 17 de 30 conversas divergem de verdade. Não é ruído, não é compressão de contexto, e não se resolve mudando o prompt de lugar.
  • pending: o V4 perde pendências. É o campo que dispara follow-up.
  • Falha inteiro. Quando a resposta estoura o teto de tokens, perde-se a análise toda — não um campo. Aconteceu em 1 de 30. O V2 nunca falhou.
  • Tags só coincidem 44%. O juiz achou as duas escolhas igualmente boas — mas os dashboards mudariam.

Campo a campo

30 conversas. O juiz cego avaliou cada par duas vezes, com as posições trocadas; vereditos que viraram ao inverter foram contados como empate.

Campo Igual No ruído (±1) Divergência real Juiz cego
sentiment_score 9 15 5 Empate — 8 × 8
heat_score 5 7 17 V2 vence — 13 × 3
smart_tags Jaccard 0,44 Empate — 6 × 6
dialogue_summary V2 9 × V4 0 — mas 21 empates
main_topic Empate em 25 de 30
pending V2 vence — 15 × 1

O custo, hoje, está invertido

Custo médio de IA por conversa, medido dentro do processo — não lido do banco.

Análise Resumo do smartContext (fallback)
V2 — 4 chamadas de IA US$ 0,00305
V4 como está — 1,5 chamadas US$ 0,00467
85% do custo é o bug, não a análise.
V4 com o bug corrigido (estimado) US$ 0,00083
3,6× mais barato que o V2 — a tese do desenho, confirmada.

A análise consolidada custa US$ 0,00071 — exatamente o que o desenho prometia. O que estoura a conta é o resumo do smartContext caindo num modelo 30× mais caro.

Três bugs no caminho

Crítico Corrigido

O resumo caía num modelo 30× mais caro — e isso já acontecia em produção

O sumarizador pede gpt-5-nano mandando temperature: 0.3. Só que gpt-5-nano é um modelo de reasoning e aceita apenas temperature: 1:

400 Unsupported value: 'temperature' does not support 0.3
    with this model. Only the default (1) value is supported.

O sistema então caía, silenciosamente, para o gemini-3.5-flashUS$ 1,50 por milhão de tokens contra US$ 0,05 do modelo pedido. Aconteceu em 100% das 14 conversas que dispararam resumo. O smartContext também alimenta o formFlow, que já está em produção: essa conta já estava sendo paga.

✅ Corrigido durante o levantamento: o temperature saiu, entrou reasoning_effort. O custo pós-correção ainda precisa ser confirmado numa nova rodada.

Grave Mitigado

O payload único pode falhar inteiro

A resposta consolidada tinha teto de 2.048 tokens. Quando estoura, o JSON vem cortado e perde-se a análise toda — não um campo, todos. Aconteceu em 1 de 30 conversas (e em 3 de 30 quando mandamos o diálogo inteiro). O V2 não falhou nenhuma vez: lá, um estouro derruba só um grupo de campos.

✅ Mitigado por um orçamento de payload. Mas o raio de dano continua tudo-ou-nada — é a fragilidade estrutural do payload único, ele concentra o risco.

Atenção

Dois campos são calculados e jogados fora

critical e user_authorization não existem como colunas na tabela de conversas. Os dois motores pedem esses campos ao modelo, pagam pelos tokens, e o código descarta o resultado na hora de gravar. O critical é o sinalizador de ameaça, assédio e risco — hoje ele não chega a lugar nenhum.

Por que o heat diverge: os dois estão certos

Mesma conversa (cancelamento de plano por motivo financeiro), mesmo critério do gestor, entregue aos dois motores. As justificativas são deles próprios.

V2 8
“a demanda é crítica e com alta probabilidade de resolução rápida”

Ancora em “resolução de demandas críticas”.

V4 2
“não existe interesse em compra/upgrade/regularização; o potencial comercial é baixo”

Ancora em “potencial de conversão”.

O critério do host mistura duas coisas — potencial comercial e prioridade de atendimento. O V2 se apoia numa; o V4, na outra. Testamos as duas explicações alternativas e as duas caem: não é a compressão de contexto (o braço com o diálogo inteiro mostra o mesmo gap) e não é onde o critério está escrito (movê-lo para a instrução de sistema não resolveu). Isto é uma decisão de produto, não um bug.

O que fazer, nesta ordem

  1. Decidir o que é o heat_score Bloqueia o go/no-go

    Decisão de produto. Prioridade de atendimento ou potencial comercial? Enquanto o critério escrito abrigar as duas leituras, qualquer modelo vai oscilar entre elas — e então reescrever o critério do host à luz da decisão.

  2. Investigar a perda de pending

    Único campo com regressão consistente e sem causa identificada.

  3. Re-rodar este teste sobre o código corrigido

    Confirma o custo pós-correção e a taxa de falha. O ferramental está versionado e é reprodutível. Se heat e pending não fecharem, o desenho já prevê o plano B: dividir em 2 chamadas, a ~US$ 0,0004 a mais por rodada — ainda muito abaixo do teto acordado.

Os dois bugs de engenharia (temperature do sumarizador e teto de tokens) já foram corrigidos durante o levantamento e saíram desta lista.

Como foi medido — e o que não vale generalizar

  • Escrita zero. O V2 rodou só a fase de captura; o V4 com persist: false. Um snapshot antes e depois provou que nenhuma coluna de análise e nenhuma tag mudou nas 30 conversas.
  • Três braços na mesma conversa: o V2 de hoje; o V4 como vai subir; e o V4 com o diálogo inteiro — este último existe para separar o efeito do payload único do efeito da compressão de contexto.
  • O juiz concordou consigo mesmo em 63% das inversões de posição. Os vereditos de pending, sentiment e main_topic são confiáveis; o de tip foi descartado por inconsistência. O placar geral é indicativo, não sentença.
  • Um host só. O cruzeiroec tem critérios customizados de sentimento e heat. Hosts com critério mais objetivo podem não ter o gap.
  • Os prompts do V4 eram provisórios e foram reconciliados com os prompts vivos do banco antes de medir — inclusive corrigindo três desvios que teriam punido o V4 injustamente. O mais grave: o V4 não enviava as descrições das tags ao modelo, só os nomes.