Pular para o conteúdo
IAIntermediário

Observabilidade de LLM: tokens, custo, latência e qualidade

Monte a observabilidade de uma aplicação com LLM: registre tokens, custo, TTFT e recusas, avalie qualidade por amostragem e responda 'por que o custo subiu?'.

Por Equipe IAUAI Estudos · 3 de julho de 2026 · 9 min de leitura

Nesta página

Neste artigo você vai montar a observabilidade de uma aplicação com LLM: o que registrar em cada chamada, como medir latência e custo, como acompanhar qualidade sem gastar uma fortuna avaliando tudo, e como organizar um painel que responde "por que a conta subiu?". Os exemplos são em Python e independem de provedor.

O problema real

O painel de infraestrutura está verde, as chamadas ao provedor retornam 200 e ninguém reclamou. Mesmo assim, a fatura do mês veio bem maior. Depois de muita investigação, descobre-se que uma alteração no prompt passou a produzir respostas bem mais longas, ou que uma nova funcionalidade manda um histórico enorme a cada requisição.

Numa aplicação comum, "respondeu 200" quase sempre significa que deu certo. Com LLM, não. A resposta pode ser cara, lenta, incorreta ou uma recusa educada, e tudo isso volta como sucesso HTTP. Por isso a observabilidade precisa olhar para tokens, custo, latência percebida e qualidade.

O que registrar em cada chamada

O núcleo é um evento estruturado por chamada, com um identificador para correlacionar com o resto do sistema.

import json, time, uuid
from dataclasses import dataclass, asdict

@dataclass
class EventoLLM:
    request_id: str
    feature: str            # ex.: "resumo-de-contrato"
    modelo: str
    tokens_entrada: int
    tokens_saida: int
    tokens_cache: int       # tokens lidos do cache de prompt, se o provedor reportar
    ttft_ms: float | None
    latencia_ms: float
    motivo_parada: str      # fim normal, limite de tokens, recusa, erro
    custo_usd: float

Os números de tokens vêm do campo de uso que o próprio provedor devolve na resposta, e o nome do campo muda de um para outro (input_tokens/output_tokens, prompt_tokens/completion_tokens). Não estime por contagem de caracteres: use o que a API informa.

O custo é tokens vezes o preço do modelo. Não coloque preços fixos no código. Guarde numa tabela de configuração com a data de vigência, alimentada a partir da página de preços do provedor, e calcule o custo no momento da consulta ou do registro. Assim, quando o preço mudar, você corrige em um lugar só.

PRECOS = {  # USD por milhão de tokens. Preencha com os valores atuais do seu provedor.
    "modelo-pequeno": {"entrada": 0.0, "saida": 0.0},
    "modelo-de-ponta": {"entrada": 0.0, "saida": 0.0},
}

def calcular_custo(modelo: str, tokens_entrada: int, tokens_saida: int) -> float:
    p = PRECOS[modelo]
    return (tokens_entrada * p["entrada"] + tokens_saida * p["saida"]) / 1_000_000

Os zeros acima são de propósito: o preço certo é o que está na página do provedor hoje, não o que está num artigo.

Medindo latência: TTFT e tempo total

Em respostas com streaming, o usuário sente duas coisas. Quanto tempo leva até o primeiro token aparecer (TTFT, time to first token) e quanto leva para terminar. Meça as duas.

def chamar_com_stream(cliente, **kwargs):
    inicio = time.perf_counter()
    ttft = None
    partes = []
    for pedaco in cliente.stream(**kwargs):   # adapte ao SDK que você usa
        if ttft is None:
            ttft = (time.perf_counter() - inicio) * 1000
        partes.append(pedaco.texto)
    total = (time.perf_counter() - inicio) * 1000
    return "".join(partes), ttft, total

Acompanhe mediana e p95 ou p99, não a média. Não existe um valor mágico de TTFT, ele depende do modelo, do tamanho do prompt e da carga do provedor. O que importa é a tendência: se o p95 sobe de repente, investigue prompts maiores, limites de taxa e mudanças no provedor.

Recusas e erros

Muitos provedores informam o motivo de parada da geração (fim natural, limite de tokens, bloqueio por política). Registre esse campo em vez de procurar frases como "não posso" no texto, o que é frágil e erra em português, inglês e todo o resto. Acompanhe também a proporção de respostas cortadas por limite de tokens, que costuma indicar um max_tokens baixo demais.

Um aumento súbito de recusas pode ter origem num novo texto de prompt, numa troca de modelo ou num tipo de entrada que chegou com um novo cliente. Segmente por funcionalidade para achar a causa.

Qualidade: avaliação online e offline

Latência e custo são fáceis de medir. Qualidade é o difícil, e vale combinar três camadas.

Verificações automáticas baratas rodam em todas as respostas: o JSON é válido, os campos obrigatórios existem, a resposta cita uma fonte que realmente estava no contexto, o tamanho está na faixa esperada.

Um modelo avaliador (LLM-as-judge) pontua uma amostra, digamos de 1% a 10% do tráfego, segundo critérios claros, como "a resposta se apoia só no contexto fornecido?". Ele é útil para tendências, e não para sentenciar uma resposta isolada. Calibre o juiz contra avaliações humanas numa amostra e meça a concordância, porque juízes têm vieses próprios, como preferir respostas longas.

Revisão humana de uma amostra pequena e regular mantém todo o resto honesto. Alimente seu conjunto de testes com os casos ruins que aparecerem em produção, o que fecha o ciclo com avaliação de LLM com evals.

import random

def deve_avaliar(taxa: float = 0.05) -> bool:
    return random.random() < taxa

if deve_avaliar():
    fila_de_avaliacao.enqueue(avaliar_resposta, request_id)  # fora do caminho da requisição

Rode a avaliação de forma assíncrona, numa fila, para não somar latência à resposta do usuário. Veja filas e workers.

Traces e padrões abertos

Uma requisição de usuário em um sistema com LLM costuma atravessar busca de contexto, uma ou mais chamadas de modelo, ferramentas e validações. Um trace mostra essa cadeia com os tempos de cada etapa. O OpenTelemetry tem convenções semânticas para IA generativa (atributos gen_ai.*), que ajudam a manter nomes consistentes, e o projeto ainda evolui, então confira a versão atual na documentação. Existem também plataformas especializadas em traces de LLM, como Langfuse, LangSmith e Arize Phoenix. Escolha pelo que já combina com o resto da sua stack.

Por privacidade, trate prompts e respostas como dados sensíveis: eles podem conter dados pessoais. Registre o conteúdo completo só quando necessário, com retenção curta, mascaramento e acesso restrito, de acordo com a LGPD.

O painel que responde "por que subiu?"

Pergunta Visão
Quanto gastamos? Custo por dia, por modelo e por funcionalidade
O que mudou? Tokens de entrada e de saída por requisição, ao longo do tempo
Está lento? TTFT e latência total, mediana e p95
Está pior? Nota média do avaliador e taxa de falha das verificações
Estão recusando? Proporção por motivo de parada
Está sendo reaproveitado? Fração de tokens vindos do cache de prompt

Para investigar um aumento de custo, comece decompondo: foi mais requisições, mais tokens de entrada por requisição, mais tokens de saída, ou troca para um modelo mais caro? Quase sempre a causa está num desses quatro.

Para consultar os eventos, qualquer agregação simples serve:

import pandas as pd

df = pd.DataFrame(eventos)
df["dia"] = pd.to_datetime(df["timestamp"]).dt.date
print(df.groupby(["dia", "feature"]).agg(
    custo=("custo_usd", "sum"),
    requisicoes=("request_id", "count"),
    tokens_saida_medio=("tokens_saida", "mean"),
))

Defina alertas de variação, por exemplo "tokens de entrada por requisição subiram bem acima da média da semana" ou "custo diário passou do orçamento", em vez de valores absolutos que envelhecem rápido.

Armadilhas comuns

  • Guardar o texto completo de todas as chamadas indefinidamente. Amostre e defina retenção.
  • Avaliar tudo com um modelo juiz caro. Amostre.
  • Olhar só o TTFT. Resposta rápida e errada continua errada.
  • Deixar a instrumentação para depois. Ela é bem mais simples no começo do projeto, e é a base para controlar custos, como mostra FinOps para IA.

Checklist

  • Cada chamada registra modelo, tokens, custo, latência, motivo de parada e request_id.
  • Existe tabela de preços versionada fora do código de negócio.
  • TTFT e tempo total aparecem em percentis.
  • Há verificações automáticas em todas as respostas e avaliação por amostragem.
  • Conteúdo sensível tem retenção e acesso controlados.
  • O painel decompõe o custo por funcionalidade e por modelo.

Próximos passos

Leia FinOps para IA para transformar essas métricas em controle de orçamento e Segurança em aplicações com LLM para registrar sem vazar dados.

Quer aplicar isso na sua empresa? Marque uma conversa de 45 minutos em https://iauaicloud.com.br/consultoria

Teste seu conhecimento

Teste o que você aprendeu sobre observabilidade de LLM

Pergunta 1 de 5

A fatura de uma aplicação com LLM subiu bastante, mas o número de requisições ficou estável e todas retornam 200. Qual é o primeiro passo de investigação mais útil?

Um conteúdo prático por quinzena

Deixe o seu e-mail para receber um conteúdo prático de IA e cloud a cada quinzena. Sem spam, e você pede a exclusão quando quiser.

Continue lendo