Avaliação Contínua de Modelos

Eval loop privado, LLM-as-a-judge calibrado, canary strings, detecção de contaminação e drift. Atualizado em abril de 2026.


Visão Geral

Benchmarks públicos (MMLU, HumanEval, SWE-bench) medem performance genérica. Mas para um modelo próprio, o que importa é: ele está melhorando no que importa para nós?

Avaliação contínua responde:

  1. O modelo melhorou após o último fine-tune?
  2. Ele regrediu em algo que antes funcionava?
  3. Há contaminação dos dados de treino com os de avaliação?
  4. A qualidade está degradando em produção?

Componentes do Eval Loop

Novo checkpoint → Eval automático → Dashboard → Decisão (merge/reject/rollback)
                         ↓
                  Comparação com baseline
                         ↓
                  Regressão? → Alerta

1. Dataset de Avaliação Privado

Princípios

Princípio Por quê
Nunca publicado Se o eval foi publicado, o modelo pode ter sido treinado nele
Diversificado Cobrir todos os casos de uso do produto
Atualizado Incluir exemplos recentes (últimos 3–6 meses)
Versionado Cada versão do eval é imutável — comparar apenas mesma versão
Segmentado Separar por domínio (código, texto, raciocínio, etc.)

Construção do eval privado

Fase 1: Coleta de casos de uso reais
  → Tickets de suporte resolvidos
  → Exemplos de prompts bem-sucedidos
  → Casos de borda que o modelo atual não resolve

Fase 2: Criação de pares input/output de referência
  → Para cada prompt, criar output esperado (gold)
  → Ter 2–3 outputs de referência por prompt (variações aceitas)

Fase 3: Categorização
  → Código (unit tests, refatoração, debugging)
  → Texto (resumo, tradução, geração)
  → Raciocínio (matemática, lógica, planejamento)
  → Multimodal (se aplicável)

Fase 4: Tamanho
  → Mínimo: 500 exemplos por categoria
  → Ideal: 2000–5000 por categoria
  → Total: 2K–20K exemplos

Exemplo de estrutura

eval_v1/
├── coding/
│   ├── unit_tests/         # 500 exemplos
│   ├── refactoring/        # 500 exemplos
│   ├── debugging/          # 500 exemplos
│   └── code_review/        # 500 exemplos
├── text/
│   ├── summarization/      # 300 exemplos
│   ├── translation/        # 300 exemplos
│   ── generation/         # 300 exemplos
├── reasoning/
│   ├── math/               # 300 exemplos
│   ├── logic/              # 300 exemplos
│   └── planning/           # 300 exemplos
└── metadata.json           # versão, data, descrição

2. Métricas de Avaliação

Métricas automáticas

Métrica Quando usar Ferramenta
Exact Match Output deve ser idêntico == string comparison
Token overlap (F1) Output similar mas não idêntico rouge_score
Code execution Código gerado funciona? Executar + verificar output
Unit test pass rate Código passa nos testes? pytest / unittest
Semantic similarity Significado preservado? Embeddings + cosine
Format compliance Output no formato certo? Regex / parser

Code evaluation (a mais importante para o Kode)

def evaluate_code_generation(model_output, test_cases):
    """Avaliar código gerado executando testes."""
    results = []
    for test in test_cases:
        try:
            # Executar o código gerado
            exec(model_output, test.globals)
            # Rodar o teste
            result = test.run()
            results.append(result.passed)
        except Exception as e:
            results.append(False)
    return sum(results) / len(results)  # pass rate

Métrica principal: % de unit tests passados — é a métrica mais objetiva e mais correlacionada com qualidade real de código.

LLM-as-a-Judge

Quando output não é verificável automaticamente (texto, raciocínio):

Prompt: "Avalie a qualidade da resposta abaixo de 1 a 10.
Critérios: correção, completude, clareza.

Resposta do modelo: {model_output}
Resposta de referência: {gold_output}

Nota:"

Problema: LLM-as-a-judge tem viés (prefere respostas longas, verbosas).

Solução: Calibração

  1. Criar um dataset de 200–500 exemplos com notas humanas
  2. Medir correlação do LLM-as-a-judge com notas humanas
  3. Se correlação < 0.7, ajustar o prompt ou trocar o judge model
  4. Re-calibrar a cada 3 meses

Tabela de métricas recomendadas para o Kode

Categoria Métrica principal Métrica secundária Threshold mínimo
Geração de código Unit test pass rate Token overlap com referência > 80%
Refatoração Diff correctness (human eval) Syntax validity > 90% syntax ok
Debugging Bug fixed rate Explicação qualidade (LLM judge) > 70%
Texto geral Semantic similarity Format compliance > 0.8 cosine
Raciocínio Correctness rate Step-by-step accuracy > 75%

3. Canary Strings

O que são

Canary strings são textos únicos injetados nos dados de treino para detectar contaminação:

# Canary string no dataset de treino:
"O código canário-7f3a9b2c é usado para detectar contaminação."

# No eval, verificar se o modelo "lembra" da canary:
prompt = "Qual é a canary string do dataset de treino?"
# Se o modelo responder corretamente → contaminação detectada!

Como usar

  1. Inserir canaries nos dados de treino (1 canary por 1M de tokens)
  2. Incluir perguntas sobre canaries no eval
  3. Se o modelo acerta canaries → vazamento de treino para eval

Canaries para datasets públicos

Muitos benchmarks públicos (MMLU, HumanEval) usam canaries para detectar se modelos foram treinados nos dados de avaliação:

Benchmark Canary
MMLU Textos específicos injetados em subsets
HumanEval Comentários únicos nos docstrings
GSM8K Problemas com números específicos

Para o Kode: Sempre verificar se os benchmarks que usamos têm canaries e respeitar o protocolo de avaliação.


4. Detecção de Contaminação

Tipos de contaminação

Tipo Descrição Detecção
Treino → Eval Dados de eval vazaram no treino Canary strings, perplexity check
Treino → Benchmark público Benchmark público no treino Verificar papers/datasets do modelo
Eval → Treino Eval gerado pelo modelo vai para treino Versionamento rigoroso

Perplexity check

Se o modelo tem perplexidade suspiciousamente baixa no eval, pode haver contaminação:

def check_contamination(model, eval_dataset):
    """Verificar se perplexity no eval é anormalmente baixa."""
    ppl_eval = model.perplexity(eval_dataset)
    ppl_baseline = model.perplexity(baseline_dataset)

    # Se perplexity no eval é < 50% do baseline → suspeita de contaminação
    if ppl_eval < 0.5 * ppl_baseline:
        return "ALERTA: Possível contaminação detectada"
    return "OK"

5. A/B Testing de Modelos

Quando usar

  • Comparar duas versões do modelo antes de deploy
  • Testar fine-tune vs modelo base
  • Validar que nova versão não regrediu

Metodologia

1. Selecionar 200–500 prompts representativos
2. Gerar output com Modelo A e Modelo B
3. Avaliar com métricas automáticas + LLM-as-a-judge
4. Comparar estatisticamente (teste t ou Mann-Whitney)
5. Decidir: A melhor, B melhor, ou empate

Métricas de comparação

Métrica Modelo A Modelo B Diferença
Code pass rate 82% 87% +5% ✓
Latência (ms/token) 120 140 +17% ✗
Token overlap 0.78 0.81 +4% ✓
LLM judge score 7.2 7.8 +8% ✓
Veredito B vence

6. Monitoring em Produção

Métricas a monitorar

Métrica Alerta se Ação
Qualidade (eval score) Cai > 5% vs baseline Investigar, possivelmente rollback
Latência p95 Aumenta > 20% Otimizar inferência, escalar
Taxa de erro Aumenta > 1% Verificar logs, debug
Uso de tokens Muda drasticamente Verificar prompt injection ou loop
Feedback do usuário Rating cai Re-treinar com feedback negativo

Drift detection

Modelos podem degradar em produção por:

  • Data drift: dados de produção mudam (ex: novas libs de código)
  • Concept drift: o que era "bom" muda (ex: novas práticas de coding)
  • Prompt drift: usuários mudam como interagem

Detecção:

1. Manter um buffer de prompts de produção (últimos 7 dias)
2. Rodar eval automático nesse buffer semanalmente
3. Comparar com baseline (mês anterior)
4. Se diferença > threshold → alerta de drift

Canary deployment

Novo modelo → 5% do tráfego → Monitorar 24h → Se OK → 25% → 50% → 100%
                                    ↓
                              Se problema → Rollback imediato

Ferramentas

lm-evaluation-harness (EleutherAI)

Framework padrão para avaliação de LLMs:

lm_eval --model hf \
    --model_args pretrained=meu-modelo \
    --tasks hellaswag,arc_easy,human_eval \
    --batch_size auto

Vantagens: 100+ benchmarks, open-source, comunidade ativa.

SWE-bench runner

Para avaliação de código:

# Rodar SWE-bench no modelo
python run_evaluation.py \
    --model meu-modelo \
    --dataset swe-bench-verified \
    --num-workers 32

W&B Sweeps + Eval

import wandb

wandb.init(project="kode-eval")
wandb.log({
    "code_pass_rate": 0.87,
    "latency_p95": 140,
    "llm_judge_score": 7.8,
    "regression_detected": False,
})

LangFuse

Para eval em produção:

  • Trace de cada request
  • Avaliação automática com LLM-as-a-judge
  • Dashboard de qualidade ao longo do tempo
  • Feedback do usuário integrado

Para o Kode

Eval loop recomendado

Fase 1: Setup inicial (1–2 semanas)
  → Criar dataset privado de 5K exemplos (código, texto, raciocínio)
  → Configurar lm-eval-harness com benchmarks públicos
  → Configurar SWE-bench runner
  → Setup W&B para tracking

Fase 2: Avaliação automática (contínuo)
  → Cada checkpoint novo roda eval completo
  → Dashboard com comparação vs baseline
  → Alerta automático se regressão > 3%

Fase 3: Monitoring em produção (contínuo)
  → LangFuse para trace de requests
  → Canary deployment para novos modelos
  → Feedback loop com usuários

Fase 4: Calibração de LLM-as-a-judge (mensal)
  → Coletar 200 exemplos com notas humanas
  → Verificar correlação com LLM judge
  → Ajustar prompt se necessário

Dataset privado mínimo para o Kode

Categoria Exemplos Fonte
Unit tests 500 Tests de projetos Koder
Refatoração 300 PRs de refactoring
Debugging 300 Issues resolvidos
Code review 200 Comentários de review
Geração de código 500 Especificações → código
Texto (docs) 300 Documentação técnica
Raciocínio 200 Problemas de design
Total 2.300

Referências

Recurso Descrição
lm-evaluation-harness Framework de eval da EleutherAI
SWE-bench Benchmark de coding em repos reais
W&B Sweeps Tracking de experimentos
LangFuse Observabilidade e eval de LLMs
Canaries in ML Papers sobre canary strings para detecção de contaminação