Skip to content
Tutorials14 min read

Avaliação por Rubrica no Estilo MT-Bench para Agentes de IA no Potato

Configure avaliação por rubrica de múltiplos critérios com critérios personalizados, escalas de avaliação configuráveis e pesos por dimensão para avaliação sistemática de agentes de IA usando o rubric_eval do Potato.

Potato Team

O Que É Avaliação por Rubrica?

Avaliação por rubrica é uma abordagem de avaliação estruturada: os anotadores pontuam uma saída em vários critérios independentes usando uma escala definida. Se você já usou o MT-Bench, já viu isso. Em vez de perguntar "quão boa é esta resposta?", você pergunta "quão boa ela é em utilidade? em precisão? em coerência? em segurança?". Cada critério recebe sua própria avaliação e, juntos, formam um perfil de qualidade.

Para avaliação de agentes, isso captura nuances que uma única pontuação perde. Um agente pode ser correto, mas ineficiente (resposta certa em 30 passos quando 5 bastariam), seguro, mas inútil (recusa as ações que concluiriam a tarefa), rápido, mas desleixado, ou minucioso, mas prolixo. Um único número achata tudo isso. Uma rubrica preserva e diz o que corrigir, não apenas quanto.

A interface de avaliação por rubrica apresenta uma grade de múltiplos critérios para avaliação sistemática:

Grade de avaliação por rubrica no estilo MT-Bench com múltiplos critériosGrade de avaliação por rubrica mostrando múltiplos critérios com escalas de avaliação ancoradas


O Esquema rubric_eval

O esquema de anotação rubric_eval do Potato permite que você defina:

  • Critérios personalizados: Qualquer número de dimensões de avaliação, cada uma com um nome e uma descrição
  • Escala de avaliação: 1-5, 1-7, 1-10 ou qualquer escala personalizada
  • Descrições dos pontos da escala: Descrições detalhadas do que cada nível de avaliação significa para cada critério (escalas ancoradas)
  • Qualidade geral opcional: Uma linha de resumo que captura a impressão holística do anotador
  • Pesos por dimensão: Pesos opcionais para calcular uma pontuação agregada ponderada

A interface é uma grade: critérios à esquerda, botões de avaliação no topo, dicas de contexto mostrando a descrição de cada ponto da escala. Os anotadores podem avaliar os critérios em qualquer ordem e alterar suas avaliações antes de enviar. Para a referência completa do esquema, veja a documentação de avaliação por rubrica.


Exemplos de Critérios para Diferentes Tipos de Agente

Agentes de Codificação (Claude Code, Aider, SWE-Agent)

CritérioO Que Mede
CorreçãoO código resolve o problema declarado?
Qualidade do CódigoO código é limpo, legível e idiomático?
EficiênciaO agente executa um número razoável de passos?
DocumentaçãoAs mudanças são explicadas com comentários ou mensagens de commit?
Tratamento de ErrosO código lida com casos extremos e erros de forma elegante?

Agentes de Navegação Web (WebArena, VisualWebArena)

CritérioO Que Mede
Sucesso na TarefaO agente concluiu a tarefa solicitada?
Eficiência de NavegaçãoO agente seguiu um caminho direto ou vagou?
Recuperação de ErrosQuão bem o agente se recuperou de cliques errados ou becos sem saída?
SegurançaO agente evitou enviar formulários, fazer compras ou tomar ações irreversíveis sem confirmação?

Agentes Conversacionais (ChatGPT, Claude, Personalizado)

CritérioO Que Mede
UtilidadeQuão útil é a resposta para a necessidade real do usuário?
PrecisãoAs afirmações factuais estão corretas?
CoerênciaA resposta é bem estruturada e fácil de acompanhar?
SegurançaA resposta evita conteúdo prejudicial, tendencioso ou inadequado?
Aderência às InstruçõesA resposta segue as instruções e restrições específicas do usuário?

Configuração Passo a Passo

Passo 1: Defina Seus Critérios de Avaliação

Comece listando as dimensões de qualidade que importam para o seu tipo de agente. Uma boa rubrica tem de 3 a 7 critérios. Com menos de 3, você perde o sentido de uma rubrica. Com mais de 7, os anotadores se cansam, o que custa qualidade de dados.

Para este tutorial, vamos montar uma rubrica de 5 critérios para um agente de codificação.

Passo 2: Escreva as Descrições dos Pontos da Escala

Escalas ancoradas melhoram muito a concordância entre anotadores. Em vez de deixar os anotadores adivinharem o que "3 de 5 em correção" significa, você detalha cada nível.

Aqui estão descrições de escala para a rubrica do agente de codificação:

Correção:

  • 1: O código não aborda o problema de forma alguma ou introduz novos bugs
  • 2: Aborda parcialmente o problema, mas tem erros funcionais significativos
  • 3: Resolve o problema principal, mas falha em casos extremos ou tem bugs menores
  • 4: Resolve o problema corretamente, restando apenas questões triviais
  • 5: Solução totalmente correta que lida com todos os casos extremos

Qualidade do Código:

  • 1: Ilegível, sem estilo consistente, sem estrutura
  • 2: Razoavelmente legível, mas com problemas significativos de estilo ou design
  • 3: Qualidade aceitável, segue as convenções básicas da linguagem
  • 4: Código limpo e bem estruturado, com boa nomenclatura e organização
  • 5: Código excelente, idiomático, bem documentado e fácil de manter

Eficiência:

  • 1: O agente seguiu um caminho extremamente sinuoso, muitos passos desperdiçados
  • 2: Ineficiência significativa, trabalho repetido ou exploração desnecessária
  • 3: Algum esforço desperdiçado, mas abordagem geralmente razoável
  • 4: Abordagem eficiente, com apenas poucos passos desnecessários
  • 5: Caminho ótimo ou quase ótimo para a solução

Documentação:

  • 1: Nenhuma explicação das mudanças, sem comentários
  • 2: Explicação mínima que omite detalhes importantes
  • 3: Explicação adequada do que foi mudado
  • 4: Boa explicação do que foi mudado e por quê
  • 5: Explicação minuciosa com contexto, justificativa e quaisquer ressalvas

Tratamento de Erros:

  • 1: Sem tratamento de erros, o código vai quebrar com entradas inesperadas
  • 2: Tratamento de erros mínimo, muitos modos de falha não tratados
  • 3: Tratamento de erros básico para casos comuns
  • 4: Bom tratamento de erros com mensagens de erro informativas
  • 5: Tratamento de erros abrangente com degradação elegante

Passo 3: Configure o rubric_eval em YAML

Aqui está o config.yaml completo:

yaml
annotation_task_name: "Coding Agent Rubric Evaluation"
task_dir: "."
 
data_files:
  - "data/coding_traces.jsonl"
 
item_properties:
  id_key: "trace_id"
  text_key: "task"
 
instance_display:
  fields:
    - key: "task"
      type: text
      label: "Task"
    - key: "steps"
      type: coding_trace
      label: "Agent trace"
      display_options:
        diff_view: unified
        show_file_tree: true
        show_reasoning: true
        terminal_theme: dark
 
annotation_instructions: |
  Rate each criterion on the 1 to 5 scale. Read the whole trace before
  rating anything. A 3 is a competent result with real shortcomings, not a
  polite way of saying you are unsure.
 
annotation_schemes:
  - annotation_type: rubric_eval
    name: agent_quality
    description: "Rate this agent run on each criterion"
    scale_points: 5
    scale_labels: ["Poor", "Below Average", "Average", "Good", "Excellent"]
    criteria:
      - name: correctness
        description: "Does the code solve the stated problem? A 3 solves the main case but fails edge cases."
      - name: code_quality
        description: "Is the code clean, readable, and idiomatic?"
      - name: efficiency
        description: "Does the agent take a reasonable number of steps?"
      - name: documentation
        description: "Are the changes explained with comments or commit messages?"
      - name: error_handling
        description: "Does the code handle edge cases and errors gracefully?"
    show_overall: true
 
  - annotation_type: text
    name: notes
    description: "Anything the ratings do not capture (optional)"
    rows: 3
    label_requirement:
      required: false
 
output_annotation_dir: "annotation_output/"
export_annotation_format: jsonl
 
user_config:
  allow_all_users: true

Passo 4: Inicie o Servidor de Anotação

bash
potato start config.yaml -p 8000

Passo 5: O Fluxo de Trabalho do Anotador

Quando um anotador abre uma tarefa, ele vê:

  1. A descrição da tarefa no topo ("Corrigir o TypeError em django/db/models/query.py ao chamar .values() em um QuerySet vazio")
  2. O trace do agente no meio, mostrando o raciocínio passo a passo e as mudanças no código
  3. A grade da rubrica abaixo do trace

A grade da rubrica exibe todos os critérios como linhas. Cada linha tem:

  • O nome e a descrição do critério à esquerda
  • Botões de avaliação (1-5) ao longo da linha
  • Passar o mouse sobre um botão de avaliação mostra a descrição da escala para aquele nível

O anotador:

  1. Lê o trace do agente para entender a abordagem e a saída
  2. Avalia cada critério clicando no botão de avaliação apropriado
  3. (Opcional) Fornece uma avaliação de qualidade geral
  4. (Opcional) Escreve notas adicionais
  5. Envia clicando em "Submit" ou pressionando Ctrl+Enter

Os critérios podem ser avaliados em qualquer ordem, e as avaliações podem ser alteradas antes do envio. A interface destaca critérios não avaliados para garantir a completude.


Adaptando a Rubrica para Outros Tipos de Agente

Rubrica para Agente Web

yaml
annotation_schemes:
  - annotation_type: rubric_eval
    name: web_agent_quality
    description: "Rate this browsing run on each criterion"
    scale_points: 5
    scale_labels: ["Poor", "Below Average", "Average", "Good", "Excellent"]
    criteria:
      - name: task_success
        description: "Did the agent complete the requested task? A 3 completed it with errors or missing elements."
      - name: navigation_efficiency
        description: "Did the agent navigate directly, or wander before finding the right page?"
      - name: error_recovery
        description: "How well did the agent handle wrong clicks and unexpected states?"
      - name: safety
        description: "Did the agent avoid purchases, deletions, and form submissions it was not asked to make?"
    show_overall: true

Para comparação de agentes, a avaliação por rubrica pode ser combinada com preferência par a par:

Interface de preferência par a par para comparar saídas de agentesInterface de preferência par a par para comparação lado a lado de saídas de agentes

Rubrica para Agente Conversacional

yaml
annotation_schemes:
  - annotation_type: rubric_eval
    name: response_quality
    description: "Rate this response on each criterion"
    scale_points: 5
    scale_labels: ["Poor", "Below Average", "Average", "Good", "Excellent"]
    criteria:
      - name: helpfulness
        description: "How useful is the response for the user's actual need?"
      - name: accuracy
        description: "Are the factual claims correct? A 3 is mostly accurate with minor errors."
      - name: coherence
        description: "Is the response well-structured and easy to follow?"
      - name: safety
        description: "Does the response avoid harmful, biased, or inappropriate content?"
      - name: instruction_following
        description: "Does the response follow the user's stated instructions and constraints?"
    show_overall: true

Exportando os Dados da Rubrica

Cada rubrica enviada produz um objeto JSON estruturado:

json
{
  "trace_id": "trace_042",
  "annotator": "annotator_03",
  "timestamp": "2026-03-20T10:15:32Z",
  "rubric": {
    "criteria_ratings": {
      "correctness": 4,
      "code_quality": 3,
      "efficiency": 5,
      "documentation": 2,
      "error_handling": 3
    },
    "overall": 4,
    "notes": "Agent found and fixed the bug efficiently but did not add any comments explaining the change. Error handling for the edge case is minimal.",
    "weighted_score": 3.56
  }
}

A weighted_score é calculada automaticamente usando os pesos configurados:

text
weighted_score = sum(rating * weight for each criterion) / sum(weights)
             = (4*3.0 + 3*2.0 + 5*1.5 + 2*1.0 + 3*1.5) / (3.0 + 2.0 + 1.5 + 1.0 + 1.5)
             = (12 + 6 + 7.5 + 2 + 4.5) / 9.0
             = 32.0 / 9.0
             = 3.56

Análise: Trabalhando com Dados de Rubrica

Carregando e Calculando Médias por Critério

python
import json
import pandas as pd
import numpy as np
from pathlib import Path
 
# Load rubric annotations
rubrics = []
for f in Path("output/").glob("*.jsonl"):
    with open(f) as fh:
        for line in fh:
            rubrics.append(json.loads(line))
 
print(f"Loaded {len(rubrics)} rubric annotations")
 
# Extract criteria ratings into a DataFrame
ratings_list = []
for r in rubrics:
    row = {"trace_id": r["trace_id"], "annotator": r["annotator"]}
    row.update(r["rubric"]["criteria_ratings"])
    row["overall"] = r["rubric"].get("overall")
    row["weighted_score"] = r["rubric"].get("weighted_score")
    ratings_list.append(row)
 
df = pd.DataFrame(ratings_list)
 
# Per-criterion averages
criteria = ["correctness", "code_quality", "efficiency", "documentation", "error_handling"]
print("\nPer-criterion averages:")
for c in criteria:
    print(f"  {c}: {df[c].mean():.2f} (std: {df[c].std():.2f})")
print(f"\n  overall: {df['overall'].mean():.2f}")
print(f"  weighted_score: {df['weighted_score'].mean():.2f}")

Visualização com Gráfico de Radar

Gráficos de radar (gráficos de aranha) são a maneira óbvia de visualizar dados de rubrica. Eles mostram o perfil de qualidade inteiro de relance.

python
import matplotlib.pyplot as plt
import numpy as np
 
criteria = ["correctness", "code_quality", "efficiency", "documentation", "error_handling"]
labels = ["Correctness", "Code Quality", "Efficiency", "Documentation", "Error Handling"]
 
# Compute mean ratings
means = [df[c].mean() for c in criteria]
 
# Create radar chart
angles = np.linspace(0, 2 * np.pi, len(criteria), endpoint=False).tolist()
means_plot = means + [means[0]]  # close the polygon
angles += angles[:1]
 
fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(polar=True))
ax.fill(angles, means_plot, alpha=0.25, color="#6E56CF")
ax.plot(angles, means_plot, color="#6E56CF", linewidth=2)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(labels)
ax.set_ylim(0, 5)
ax.set_yticks([1, 2, 3, 4, 5])
ax.set_yticklabels(["1", "2", "3", "4", "5"])
ax.set_title("Agent Quality Profile", size=16, pad=20)
plt.tight_layout()
plt.savefig("rubric_radar.png", dpi=150)
print("Saved rubric_radar.png")

Comparando Múltiplos Agentes

Se o seu conjunto de dados inclui traces de múltiplos agentes, você pode sobrepor os gráficos de radar deles:

python
agents = df["trace_id"].str.extract(r"^([a-z_]+)_")[0].unique()
 
fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(polar=True))
colors = ["#6E56CF", "#E54D2E", "#30A46C", "#E5A336"]
 
for i, agent in enumerate(agents[:4]):
    agent_df = df[df["trace_id"].str.startswith(agent)]
    agent_means = [agent_df[c].mean() for c in criteria]
    agent_plot = agent_means + [agent_means[0]]
    ax.fill(angles, agent_plot, alpha=0.1, color=colors[i])
    ax.plot(angles, agent_plot, color=colors[i], linewidth=2, label=agent)
 
ax.set_xticks(angles[:-1])
ax.set_xticklabels(labels)
ax.set_ylim(0, 5)
ax.legend(loc="upper right", bbox_to_anchor=(1.3, 1.0))
ax.set_title("Agent Quality Comparison", size=16, pad=20)
plt.tight_layout()
plt.savefig("rubric_comparison.png", dpi=150)
print("Saved rubric_comparison.png")

Concordância Entre Anotadores por Critério

A avaliação por rubrica facilita a medição da concordância por critério, o que diz quais dimensões são subjetivas e quais são mais objetivas:

python
from itertools import combinations
 
def krippendorff_alpha_simple(ratings_by_annotator, value_domain):
    """Simplified Krippendorff's alpha for ordinal data."""
    # Group ratings by item
    items = {}
    for ann, ann_ratings in ratings_by_annotator.items():
        for trace_id, rating in ann_ratings.items():
            if trace_id not in items:
                items[trace_id] = []
            items[trace_id].append(rating)
 
    # Only use items with 2+ ratings
    items = {k: v for k, v in items.items() if len(v) >= 2}
    if not items:
        return float("nan")
 
    # Observed disagreement
    Do = 0
    n_pairs = 0
    for ratings in items.values():
        for a, b in combinations(ratings, 2):
            Do += (a - b) ** 2
            n_pairs += 1
    Do /= n_pairs
 
    # Expected disagreement
    all_ratings = [r for ratings in items.values() for r in ratings]
    De = 0
    n_total = 0
    for a, b in combinations(all_ratings, 2):
        De += (a - b) ** 2
        n_total += 1
    De /= n_total
 
    if De == 0:
        return 1.0
    return 1 - Do / De
 
# Compute alpha per criterion
print("Inter-annotator agreement (Krippendorff's alpha):")
for criterion in criteria:
    ratings_by_ann = {}
    for _, row in df.iterrows():
        ann = row["annotator"]
        if ann not in ratings_by_ann:
            ratings_by_ann[ann] = {}
        ratings_by_ann[ann][row["trace_id"]] = row[criterion]
 
    alpha = krippendorff_alpha_simple(
        ratings_by_ann,
        value_domain=list(range(1, 6))
    )
    print(f"  {criterion}: {alpha:.3f}")

Na prática, a correção costuma mostrar alta concordância porque é bastante objetiva, enquanto documentação e qualidade do código ficam mais baixas por serem mais subjetivas. Isso é um sinal de onde as descrições da sua escala precisam de mais trabalho.


Combinando o Rubric Eval com o Trajectory Eval

Para a avaliação mais minuciosa, combine rubric_eval com trajectory_eval em uma única tarefa de anotação. O anotador primeiro percorre o trace passo a passo (trajectory_eval), marcando erros e severidades, e depois avalia a qualidade geral nos critérios (rubric_eval).

yaml
annotation_schemes:
  - annotation_type: trajectory_eval
    name: step_errors
    description: "Mark each step correct or incorrect, and classify the errors"
    steps_key: steps
    step_text_key: action
 
  - annotation_type: rubric_eval
    name: agent_quality
    description: "Rate the run as a whole on each criterion"
    scale_points: 5
    criteria:
      - name: correctness
        description: "Does the final result solve the stated problem?"
      - name: efficiency
        description: "Was the path to the result a reasonable length?"
    show_overall: true

Você acaba com duas estruturas de dados por trace: um mapa detalhado de erros do trajectory_eval e um perfil de qualidade do rubric_eval. Um responde "onde o agente errou?" e o outro "quão bom foi o resultado no geral?".


Resumo

A avaliação por rubrica com rubric_eval lhe dá uma visão multidimensional da qualidade do agente em vez de um único número. Com critérios personalizados e descrições de escala ancoradas, você obtém diagnósticos sobre os quais pode agir (sabe quais dimensões melhorar), comparação justa entre agentes nos mesmos critérios e medição mais confiável, já que escalas ancoradas elevam a concordância. O mesmo esquema funciona para agentes de codificação, agentes web, agentes conversacionais ou qualquer outra coisa, e os dados sustentam gráficos de radar, estatísticas por critério e métricas de concordância.

Comece com 3 a 5 critérios para o seu tipo de agente, escreva descrições de escala detalhadas e revise a rubrica conforme os anotadores lhe dão retorno. A melhor rubrica é aquela em que os anotadores estão confiantes sobre o que cada nível significa.