04 - LLM-as-judge — quando e como

TL;DR

LLM-as-judge é usar um modelo (geralmente forte) pra avaliar output de outro modelo aplicando uma rubrica. Resolve o gargalo de eval subjetivo em escala — humano não revisa 1000 outputs por iteração; judge sim. Funciona bem em tarefas subjetivas calibradas; falha silenciosamente em domínios especializados, em tarefas novas, e por causa de vieses sistemáticos: posicional (prefere primeira opção em A/B), verbosidade (prefere resposta mais longa), self-preference (modelo prefere o próprio estilo). Mitigações: chain-of-thought judging, pairwise em vez de score absoluto, randomização de posição, swap-judge check, e — sempre — calibração contra humano antes de confiar. Verbete: LLM-as-judge.

Quando faz sentido

Aplica:

  • Tarefas subjetivas em escala — resumo, escrita, chat, helpfulness — onde human-only não dá conta
  • Pipelines com muitos exemplos — golden set de 500+ itens
  • Iteração frequente — você quer rodar eval a cada PR
  • Tarefa com rubrica clara — judge precisa de critério, não de intuição

Não aplica (ou aplica com extremo cuidado):

  • Domínios especializados — legal, médico, científico de fronteira — judge não tem expertise
  • Tarefas novas — quando o próprio time não sabe ainda o que é “bom”
  • Quando o objetivo é precisão > 95% — judge tem teto de calibração realista
  • Quando avaliado e judge são o mesmo modelo — self-preference garantido

Como funciona — anatomia mínima

JUDGE_PROMPT = """
Você é avaliador rigoroso. Não é simpático, é objetivo.
 
Tarefa: {task_description}
Critério a avaliar: {criterion}
Escala: 1 (muito ruim) a 5 (excelente)
 
Definições de cada nível:
1 - {anchor_1}
2 - {anchor_2}
3 - {anchor_3}
4 - {anchor_4}
5 - {anchor_5}
 
Input do usuário: {input}
Resposta do modelo: {output}
 
Primeiro, raciocine sobre cada nível.
Depois, atribua o score final.
 
Output em JSON:
{{
  "reasoning": "<análise dimensão por dimensão>",
  "score": <1-5>,
  "issues": ["<problema 1>", "<problema 2>"]
}}
"""
 
def llm_judge(task, input_, output, criterion, anchors):
    response = client.messages.create(
        model="claude-opus-4-6",  # judge >= modelo avaliado
        max_tokens=600,
        messages=[{
            "role": "user",
            "content": JUDGE_PROMPT.format(
                task_description=task,
                criterion=criterion,
                anchor_1=anchors[1], anchor_2=anchors[2],
                anchor_3=anchors[3], anchor_4=anchors[4],
                anchor_5=anchors[5],
                input=input_,
                output=output,
            )
        }]
    )
    return parse_json(response.content[0].text)

Três decisões críticas aqui:

  1. Judge >= avaliado. Judge fraco não distingue bom de excelente.
  2. CoT antes do score. Pedir reasoning antes força calibração; pular vai direto pro chute. (Base do paper G-Eval.)
  3. Anchors no prompt do judge. Sem isso, judge inventa a própria escala.

Os 4 vieses canônicos

1. Position bias

Em comparação A vs B, judges tendem a preferir o que aparece primeiro (ou último, dependendo do modelo).

"Qual resposta é melhor?
A: <resposta X>
B: <resposta Y>"

→ judge marca A em ~57% mesmo quando X é objetivamente pior

Mitigação: randomize ordem em todo eval pairwise. Em N rodadas, A aparece 50% das vezes em cima.

2. Verbosity bias

Resposta mais longa tende a ser avaliada como melhor — mesmo quando é prolixa.

Resposta A (concisa, 50 palavras, correta)
Resposta B (verbosa, 300 palavras, mesma info diluída)

→ judge prefere B em ~62% dos casos

Mitigação:

  • Score conciseness explicitamente na rubrica
  • Normalizar comprimento antes de mostrar pro judge (truncar B ao tamanho de A)
  • Penalty automática por comprimento desproporcional

3. Self-preference bias

GPT como judge prefere outputs gerados por GPT. Claude como judge prefere Claude. Isso foi documentado em múltiplos papers (G-Eval, Judging-LLM-as-Judge).

Modelos avaliados: GPT-5, Claude Opus 4
Judge: GPT-5
→ GPT-5 vence em ~58% dos pareamentos blind

Mesmo experimento, judge: Claude Opus 4
→ Claude vence em ~55%

Mitigações:

  • Cross-judge: rode com 2 judges de famílias diferentes. Discordância sinaliza item ambíguo.
  • Judge diferente do modelo em produção.
  • Em produção, use ensemble: 2-3 judges, mediana do score.

4. Bandwagon / chain-of-thought leakage

Se você mostra o score do judge anterior, novo judge tende a concordar (bandwagon). Se você mostra reasoning de outro judge, vira anchor demais.

Mitigação: cada judge avalia isolado. Agregação acontece depois.

Técnicas de mitigação

CoT judging — G-Eval

Em vez de pedir score direto, peça reasoning estruturado:

1. Identifique pontos fortes da resposta
2. Identifique pontos fracos
3. Aplique a rubrica dimensão por dimensão
4. SÓ ENTÃO atribua score

Por que funciona: judge sem CoT é prompt completion — vê output, devolve número. Judge com CoT é forçado a justificar. A justificativa expõe o que ele está medindo de fato.

Citação direta do paper G-Eval (Liu et al., 2023): “forcing the model to generate a step-by-step evaluation rationale significantly improves correlation with human judgment.”

Pairwise em vez de absoluto

Score absoluto: “essa resposta é 4 de 5?” Pairwise: “A é melhor que B, B é melhor que A, ou empate?”

Por que pairwise é mais robusto:

  • Humanos (e modelos) são melhores em comparar do que em pontuar absoluto
  • Reduz central tendency bias (todo mundo tende a dar 3)
  • Permite Elo rating (Chatbot Arena usa)
  • Position bias mitiga com randomização

Quando pairwise não dá:

  • Você tem só um output (não dois pra comparar)
  • Custo computacional (N(N-1)/2 pares)

Solução híbrida: usa absoluto pra triagem ampla, pairwise pros top-K candidatos.

Swap-judge consistency check

1. Pede judge pra avaliar A vs B → resultado R1
2. Inverte ordem: avalie B vs A → resultado R2
3. Se R1 == invert(R2): consistente
4. Se R1 != invert(R2): item ambíguo, descarta ou envia pra humano

Custo: 2x chamadas. Benefício: filtra ~5-15% de noise.

Calibração com humano

Inegociável antes de confiar:

  1. Sample de 30-50 itens
  2. Humano (calibrado pela rubrica) atribui score
  3. Judge atribui score nos mesmos itens
  4. Correlação Pearson ou Spearman entre os dois
  5. Se >0.7: judge calibrado, pode escalar
  6. Se 0.5-0.7: judge usável mas com cautela
  7. Se <0.5: judge não calibrado, refina prompt ou troca modelo

Calibração deve ser refeita:

  • Ao trocar modelo do judge
  • Ao mudar rubrica
  • A cada 3-6 meses (drift de modelo, drift de tarefa)

LMSYS Chatbot Arena — o caso de produção

Chatbot Arena é o exemplo mais conhecido de eval pairwise em escala:

  • Usuários blind comparam respostas de 2 modelos
  • Voto: A melhor, B melhor, empate, ambas ruins
  • Modelos rankeados por Elo, como xadrez

Por que funciona em escala:

  • Pairwise > absoluto (humanos calibram comparando)
  • Position bias mitigado por randomização de ordem
  • Self-preference mitigado por blind (usuário não sabe qual modelo é qual)
  • Volume → Elo converge (50k+ votos por modelo top)

A metodologia do Arena é a base de quase todo eval pairwise sério em 2026 — vale ler o paper “Chatbot Arena: An Open Platform for Evaluating LLMs by Human Preference” (Chiang et al., 2024).

Custo realista

Judge geralmente é modelo forte (Opus 4, GPT-5, Gemini 2.5 Pro):

1 eval com Opus 4.6 como judge:
  ~500 tokens input + ~400 tokens output = ~$0.012 por item

Golden set de 100 itens, 4 critérios cada:
  100 × 4 × $0.012 = ~$5 por rodada completa

Com CoT judging (mais tokens output):
  ~$8-12 por rodada

Em PR: rodar subset (top-20 críticos) = ~10.

Comparação com humano:

Anotador humano treinado: ~30s-2min por item
Custo equivalente: $5-15/h × 1-3min = $0.10-0.75/item
Custo de eval 100 itens: $10-75 + 50min-3h de wall-clock

Judge é ~10x mais barato e 50x mais rápido. Por isso vale escalar — depois de calibrado.

Anti-patterns

  • Judge não-calibrado em produção — número sem âncora, só ruído com aparência de rigor
  • Judge = avaliado — auto-aprovação garantida
  • Sem CoT no prompt do judge — chute disfarçado de score
  • Sem randomização em pairwise — position bias inflando 7-10%
  • Eval só absoluto, nunca pairwise — perde sinal em comparação A/B de prompts
  • Ignora outliers do judge — quando judge diverge muito do humano, item ambíguo é informação
  • Re-roll até score subir — circular, viola toda a noção de eval

Veja também

Fontes