Evaluation de LLMs em produção

TL;DR

LLM em produção sem evaluation é aposta. Não é tradeoff — é dívida. Práticas mínimas: golden set de 30-100 exemplos representativos rodado a cada mudança de prompt/modelo; LLM-as-judge para tarefas subjetivas (com cuidado de viés); traces e observabilidade instrumentando toda chamada (tokens, latência, custo, taxa de erro); A/B test em produção com métricas de negócio. Sem isso, “prompt engineering” vira superstição — mudou prompt, ninguém sabe se melhorou.

Por que eval é diferente em LLMs

Software tradicional:

Input X → função pura → Output Y → assert Y == esperado ✅

LLM:

Input X → função estocástica → Output Y (semanticamente similar a esperado, talvez)
→ ?? como medir ??

Não dá pra fazer assertEqual. Eval de LLM precisa de métricas semânticas, não exatas.

Os 4 pilares de eval

graph TB
    A["LLM em produção"] --> B["1️⃣ Golden set<br/>(testes regressão)"]
    A --> C["2️⃣ LLM-as-judge<br/>(tarefas subjetivas)"]
    A --> D["3️⃣ Traces + métricas<br/>(observabilidade)"]
    A --> E["4️⃣ A/B test<br/>(métricas negócio)"]

Cada pilar resolve uma pergunta diferente. Maturidade real é ter os 4.

Pilar 1 — Golden set

O que é: 30-100 exemplos representativos com resposta esperada (ou critério). Rodados a cada mudança de prompt ou modelo.

Conteúdo do golden set:

- id: classify_001
  input: "App crashou na inicialização após update"
  expected:
    category: "bug"
    severity: "high"
 
- id: classify_002
  input: "Pode adicionar dark mode?"
  expected:
    category: "feature"
    severity: "low"
 
- id: extract_003
  input: "Reunião amanhã às 14h com Maria"
  expected:
    type: "meeting"
    when: "tomorrow 14:00"
    with: "Maria"

Como avaliar:

Tipo de tarefaMétrica
ClassificaçãoEquality (actual.category == expected.category)
Extração estruturadaEquality + schema valid
Geração de textoEmbedding similarity (cosine) > threshold
Geração de códigoTest pass + linter pass
Resumo / criatividadeLLM-as-judge (Pilar 2)

Quanto eval custa:

100 exemplos × $0.01/exemplo (Sonnet) = $1 por rodada de eval
× 50 rodadas/mês (ajustes de prompt) = $50/mês

ROI: detectar 1 bug em prod paga o ano inteiro de evals.

Pilar 2 — LLM-as-judge

Quando usar: tarefas subjetivas onde equality não funciona (resumos, escrita criativa, conversação).

Como funciona: modelo (geralmente mais forte) avalia output de outro modelo.

JUDGE_PROMPT = """
Você é avaliador rigoroso. Dados:
- Pergunta: {question}
- Resposta correta: {expected}
- Resposta do modelo: {actual}
 
Avalie de 0-10 quão correta a resposta do modelo é. Seja estrito.
 
Output em JSON:
{{
  "score": <0-10>,
  "reason": "<justificativa curta>",
  "issues": ["<problema 1>", "<problema 2>"]
}}
"""
 
def llm_as_judge(question, expected, actual):
    response = client.messages.create(
        model="claude-opus-4",  # judge mais forte que o modelo avaliado
        max_tokens=300,
        messages=[{
            "role": "user",
            "content": JUDGE_PROMPT.format(
                question=question,
                expected=expected,
                actual=actual
            )
        }]
    )
    return parse_json(response.content[0].text)

Cuidados com LLM-as-judge

  • Viés do judge — se judge é Claude, ele tende a preferir respostas estilo Claude. Use judge diferente do avaliado quando possível.
  • Custo — judge é geralmente modelo grande. Eval com 100 exemplos × Opus é caro.
  • Position bias — em comparação A vs B, judges às vezes preferem o primeiro. Randomize ordem.
  • Calibração — score 7/10 do judge nem sempre é “bom”. Calibre com gabarito humano antes.

Pilar 3 — Traces e observabilidade

Instrumentar toda chamada:

MétricaO que medePor que importa
Input tokensTokens consumidosCusto + atenção dilui (03 - A janela de contexto)
Output tokensTokens geradosCusto principal
Total cost$ por chamadaDireto pro budget
TTFTTime to First TokenUX em streaming
Total latencyTTFT + decode timeUX geral
Error ratetimeout, rate limit, schema invalidReliability
User feedbackthumbs up/down, ratingsSinal de qualidade real

Ferramentas em 2026:

FerramentaForte em
LangfuseOpen source, self-hostable, rico em features
LangSmithIntegração nativa LangChain
HeliconeProxy + analytics, bom pra times sem instrumentação
Arize PhoenixSessions com timeline, debugging
BraintrustEval-first, comparação de versions

Pattern recomendado:

import langfuse
 
@langfuse.observe()
def classify_ticket(text: str):
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=200,
        messages=[{"role": "user", "content": text}]
    )
    # langfuse instrumenta automaticamente
    return response.content[0].text

Em 2-3 linhas de código você ganha trace completo + dashboard.

Pilar 4 — A/B test em produção

Por que: golden set + traces medem o sistema. A/B mede impacto no usuário.

# Pseudocode
def get_response(user_id, query):
    variant = ab_assign(user_id, "prompt_v2_test", split=0.5)
 
    if variant == "control":
        prompt = PROMPT_V1
    else:
        prompt = PROMPT_V2
 
    response = client.messages.create(
        system=prompt,
        messages=[{"role": "user", "content": query}]
    )
 
    log_event("ai_response", {
        "user_id": user_id,
        "variant": variant,
        "response": response.content[0].text,
    })
 
    return response.content[0].text

Métricas para comparar:

  • Métricas de negócio: conversion, resolution time, NPS
  • Métricas de uso: re-prompts, abandono
  • Métricas de custo: tokens médios por interação

A/B test > golden set para impacto real

Golden set diz “v2 é 5% mais preciso”. A/B test diz “v2 reduz tickets de suporte em 18%“. A segunda métrica vende para stakeholders.

Maturidade — onde você está?

Diagnóstico

NívelSinal
Nível 0 — Zero eval”Olhei e tá bom”
Nível 1 — Golden set ad-hocLista de exemplos em planilha; rodada manual eventual
Nível 2 — Eval em CIGolden set roda automaticamente em PR de prompt
Nível 3 — Eval + observabilidadeTraces de prod + LLM-as-judge para tarefas subjetivas
Nível 4 — A/B test em prodVariantes comparadas com métricas de negócio
Nível 5 — Eval continuousGolden set evolui com casos reais de prod, evaluation contínua

Maioria dos times está em Nível 0-1. Nível 2 é meta para 2026.

Anti-patterns

  • Eval só “no final” — após shippar, nunca mais
  • Golden set de 5 exemplos — não é representativo
  • Equality em tarefas abertas — sempre vai falhar; use embedding ou judge
  • Judge igual ao avaliado — viés de auto-aprovação
  • Métricas de modelo, não de negócio — “accuracy 92%” não é resolution rate
  • Mudar prompt sem rodar eval — cego total

Métricas-alvo em 2026

MétricaAlvo
Eval coverage (% prompts com golden set)>80%
Eval frequency (toda mudança rodada?)Sempre
Trace coverage100% das chamadas em prod
Custo de eval / custo total<5%
Time to detect prompt regression<1 dia
A/B test em features novasSempre

Veja também

Referências

  • Chip HuyenAI Engineering (2025), capítulo sobre evaluation.
  • LangfuseEvaluation patterns documentation (2026).
  • OpenAIEvals framework (github.com/openai/evals) (2024+).
  • Eugene YanPatterns for Building LLM-based Systems (2024).
  • BraintrustAI evaluation best practices (2026).