Um cliente escreve: "no dia 3, o assistente me disse que o meu contrato cobria X". Você abre o sistema e descobre que não tem como saber o que foi respondido, com qual prompt, com quais documentos recuperados nem com qual versão do modelo.

Aplicação de LLM é não determinística. Sem registro, ela é literalmente impossível de depurar — você não consegue nem reproduzir o caso. Isso não é um refinamento para a fase 2; é a primeira coisa a montar, e leva algumas horas.

A tabela

CREATE TABLE chamadas_ia (
  id                TEXT PRIMARY KEY,
  criado_em         TIMESTAMP NOT NULL,      -- em UTC, com fuso explícito
  usuario_id        TEXT,
  sessao_id         TEXT,                    -- agrupa a conversa
  fluxo             TEXT NOT NULL,           -- 'atendimento', 'resumo', 'classificacao'

  modelo            TEXT NOT NULL,
  versao_prompt     TEXT NOT NULL,           -- 'atendimento-v7'
  temperatura       REAL,

  entrada_hash      TEXT NOT NULL,           -- para agrupar repetidos
  entrada_texto     TEXT,                    -- conforme a política de retenção
  saida_texto       TEXT,
  documentos_ids    TEXT,                    -- o que a busca recuperou

  tokens_entrada    INTEGER NOT NULL,
  tokens_saida      INTEGER NOT NULL,
  custo_brl         REAL NOT NULL,

  ttft_ms           INTEGER,
  duracao_ms        INTEGER NOT NULL,

  status            TEXT NOT NULL,           -- ok | erro | bloqueado | timeout
  motivo_bloqueio   TEXT,
  feedback          INTEGER                  -- +1 / -1, quando o usuário der
);

CREATE INDEX idx_chamadas_data   ON chamadas_ia(criado_em);
CREATE INDEX idx_chamadas_fluxo  ON chamadas_ia(fluxo, criado_em);
CREATE INDEX idx_chamadas_status ON chamadas_ia(status, criado_em);

Dez minutos para criar, e ela responde praticamente toda pergunta que vai aparecer nos próximos dois anos.

🔍 As três colunas que ninguém coloca e todo mundo precisa

versao_prompt — sem ela, você não consegue relacionar uma piora com a mudança que a causou. Versione o prompt como código e grave a versão em cada chamada.

documentos_ids — quando a resposta estiver errada, a primeira pergunta é "o trecho certo foi recuperado?". Sem os identificadores, não há resposta.

fluxo — sem separar por fluxo, o custo total não diz nada. Com ela, você descobre em cinco minutos qual funcionalidade consome 80% da fatura.

O que NÃO guardar

Registro é dado pessoal quando contém conversa de usuário. Três decisões que evitam problema:

⚠️ Cuidado com o registro de erro

Bibliotecas costumam despejar a requisição inteira no traço da exceção — com prompt, dados do usuário e cabeçalho de autorização. Filtre o que vai para o registro de erro com o mesmo rigor do registro normal.

As cinco consultas que você vai rodar toda semana

Para onde vai o dinheiro

SELECT fluxo, modelo,
       COUNT(*) AS chamadas,
       ROUND(SUM(custo_brl), 2) AS custo,
       ROUND(AVG(tokens_entrada)) AS entrada_media
FROM chamadas_ia
WHERE criado_em > datetime('now', '-7 days')
GROUP BY fluxo, modelo
ORDER BY custo DESC;

Quase sempre revela um fluxo consumindo desproporcionalmente. E, com entrada_media na tabela, você já vê se a causa é contexto inflado.

O que está falhando

SELECT status, motivo_bloqueio, COUNT(*) AS n
FROM chamadas_ia
WHERE criado_em > datetime('now', '-1 day')
GROUP BY status, motivo_bloqueio
ORDER BY n DESC;

Latência sem a mentira da média

SELECT fluxo,
       COUNT(*) AS n,
       ROUND(AVG(ttft_ms)) AS ttft_medio,
       MAX(ttft_ms) AS ttft_pior
FROM chamadas_ia
WHERE criado_em > datetime('now', '-1 day') AND status = 'ok'
GROUP BY fluxo;

As perguntas que se repetem

SELECT entrada_hash, COUNT(*) AS n, ROUND(SUM(custo_brl), 2) AS custo
FROM chamadas_ia
WHERE criado_em > datetime('now', '-30 days')
GROUP BY entrada_hash
HAVING n > 20
ORDER BY custo DESC;

É a consulta que justifica cache: se vinte perguntas idênticas somam um custo relevante, você acabou de achar dinheiro parado.

O que o usuário reprovou

SELECT id, criado_em, versao_prompt, saida_texto
FROM chamadas_ia
WHERE feedback = -1 AND criado_em > datetime('now', '-7 days')
ORDER BY criado_em DESC;

Cada linha dessa consulta é candidata a caso no conjunto de avaliação. É o circuito que faz o sistema melhorar sozinho ao longo dos meses.

Colete o feedback — mas colete direito

Dois botões de polegar rendem pouco: a taxa de resposta fica abaixo de 2% e vem enviesada para o extremo negativo. Duas coisas que aumentam bastante o sinal:

Os sinais implícitos têm cobertura de 100% e, na prática, são mais informativos que o polegar.

Alarmes que valem a pena

AlarmeLimiar sugeridoPor que importa
Custo diário acima do normal2× a média de 7 diasCiclo de agente, abuso ou bug de contexto
Taxa de erro> 2% em 15 minProvedor instável ou falha do seu lado
Taxa de bloqueio> 5%O prompt ou o modelo regrediram
TTFT do percentil 95> 2× o normalFila no servidor ou contexto inflado
Um usuário sozinho> 10% do custo do diaAutomação de cliente ou uso indevido

O último merece nota: em produto com API, um único cliente integrando de forma ineficiente pode multiplicar o seu custo em um dia. Esse alarme paga o esforço de montar o registro sozinho.

O painel já mostra consumo por chave e por modelo

Custo em reais, no mesmo saldo das GPUs — e você complementa com o seu registro por fluxo para saber onde vaza.

Criar conta →

A investigação, quando alguém reclama

Com a tabela acima, o roteiro é mecânico:

  1. Ache a chamada por usuário e data.
  2. Olhe versao_prompt — era a versão atual ou uma anterior?
  3. Olhe documentos_ids — o trecho certo foi recuperado? Se não, o problema é a busca, não o modelo.
  4. Se foi recuperado e a resposta ignorou, o problema é a geração — vire o caso em teste.
  5. Reproduza com a mesma versão de prompt e temperatura zero. Se não reproduzir, foi variação aleatória: baixe a temperatura naquele fluxo.

Cinco minutos de trabalho, em vez de uma tarde de suposição. É exatamente essa diferença que o registro compra.

Conclusão

Uma tabela e cinco consultas. É o que separa "acho que ficou pior depois da última mudança" de "a versão 7 do prompt caiu 9 pontos no fluxo de atendimento, e a causa foram estes doze casos".

Monte antes de precisar. Quando o cliente reclamar da resposta de três semanas atrás, ou o dado está lá, ou a conversa acaba em "não temos como verificar" — que é a pior frase possível.

Continue: avaliação automática · onde vaza o custo · latência