# RUNBOOK — como executar o benchmark ainda hoje Tempo estimado: **5 minutos** para validar e ensaiar; **1 a 2 dias** para uma rodada ao viva completa (a maior parte do tempo é espera de API e da auditoria humana). --- ## Fase 0 — Verificação local (hoje, sem chaves, sem custo) ```bash cd /home/matheus/benchmark-cego # 1. Banco íntegro? (700 itens, schema, duplicatas, balanceamento) make validate # 2. Testes do pipeline (banco, cegueira, estatística) make test # 3. Rodada completa simulada, ponta a ponta make demo # 4. Inspecionar cat resultados/demo/leaderboard.md head -3 resultados/demo/resultados.csv ``` `make validate` imprime as contagens e a lista de erros. **Saída esperada:** `erros: []`, `total: 700`, `pt 238 / en 231 / zh 231`, `mcq 420 / aberto 175 / cálculo 105`. `make demo` aplica 637 itens (90% do banco) a 15 sistemas simulados, com júri de 3 juízes, adjudicação e relatório. Duração típica: **< 2 segundos**. --- ## Fase 1 — Calibração (metade do dia) Objetivo: fixar ancoragem da rubrica, medir concordância entre juízes e descartar itens defeituosos **antes** de gastar com a rodada cheia. ```bash # aplica os 63 itens de calibração em todos os participantes, em modo mock make calib # ou, ao vivo, apenas um domínio e poucos itens por participante: python3 harness/run.py --live --only-domain juridica --limit 5 --out resultados/calibracao ``` Checklist da calibração: - [ ] taxa de acerto por item entre 20% e 95% (art. 16); - [ ] concordância interjuiz aceitável; calibrar `juizes.perfis` se a divergência for sistêmica; - [ ] paridade de dificuldade entre pt/en/zh — diferença de nota média por idioma < 5 pontos; - [ ] revisar manualmente os 10 itens com pior desempenho (`itens mais difíceis` no relatório). ## Fase 2 — Rodada ao vivo ### 2.1 Configurar chaves Edite `harness/config.json` apenas para confirmar `model` e `base_url` de cada participante. As chaves **não** vão no arquivo: defina-as no ambiente. ```bash export OPENAI_API_KEY="..." export ANTHROPIC_API_KEY="..." export GOOGLE_API_KEY="..." export LLAMA_API_KEY="..." export XAI_API_KEY="..." export MSAI_API_KEY="..." export AWS_BEARER_TOKEN_BEDROCK="..." export COHERE_API_KEY="..." export MISTRAL_API_KEY="..." export AI21_API_KEY="..." export DEEPSEEK_API_KEY="..." export DASHSCOPE_API_KEY="..." export MOONSHOT_API_KEY="..." export ZHIPU_API_KEY="..." export ARK_API_KEY="..." ``` Sem uma chave, o runner avisa e **cai em modo mock** para não travar o ensaio — confira a linha `[ok] modo=...` antes de confiar no resultado. ### 2.2 Escalonar (recomendado) Uma rodada completa são 15 × 637 = **9.555 chamadas** de modelo, mais 3 juízes por item aberto (2625 chamadas de júri, na prova). Rode em fatias para controlar custo: ```bash # por domínio, um de cada vez for d in juridica medica proptech compliance bank energia negocios; do python3 harness/run.py --live --only-domain $d --out resultados/live-$d done # ou amostra de controle antes da rodada cheia python3 harness/run.py --live --limit 40 --out resultados/live-amostra ``` Consolidação manual: some os `pontos` por participante a partir dos `itens.csv` de cada fatia (o `resumo.json` de cada execução já traz o recorte aplicado). ### 2.3 Rodada completa ```bash python3 harness/run.py --live --out resultados/live-2026Q4 ``` Ou, se todas as chaves estiverem definidas: ```bash make live ``` ### 2.4 Reprodutibilidade ```bash python3 harness/run.py --live --seed 20261111 --out resultados/live-2026Q4 ``` A semente fixa a ordem dos itens e os rótulos `SISTEMA-XX`. O `resumo.json` registra `banco_hash`, semente, modelos exatos, temperatura e `max_tokens`. ## Fase 3 — Auditoria humana e consolidação (1 dia) 1. **Amostra:** extraia 10% dos itens abertos (mínimo 3 por domínio e idioma): ```bash python3 - <<'PY' import csv, random rows = [r for r in csv.DictReader(open('resultados/live-2026Q4/itens.csv', encoding='utf-8')) if r['type'] == 'open'] random.seed(20261111) amostra = random.sample(rows, max(30, len(rows)//10)) with open('resultados/live-2026Q4/auditoria_humana.csv','w',newline='',encoding='utf-8') as fh: w = csv.DictWriter(fh, fieldnames=list(rows[0].keys()) + ['nota_humana','revisor']) w.writeheader() for r in amostra: r['nota_humana'], r['revisor'] = '', '' w.writerow(r) print('amostra:', len(amostra)) PY ``` 2. Dois revisores pontuam às cegas contra a rubrica do item (`q` + `rubric` no `banco/.jsonl`). 3. Itens com desvio humano–média > 1,0 ponto são **anulados** na rodada (art. 26). 4. Recalcule as notas com os itens anulados fora e publique. ## Fase 4 — Publicação Entregáveis (art. 41): - `leaderboard.md` — classificação, IC 95%, recortes por domínio e idioma, Elo, latência, recusa; - `resultados.csv` — tabela completa; - `itens.csv` — nota de cada item por sistema (evidência); - `resumo.json` — metadados da rodada e hash do banco; - nota de rodapé com elenco e versões (`participantes/ias.csv`). Divulgação dos itens da prova: **90 dias** após a rodada (art. 42). --- ## Solução de problemas | Sintoma | Causa provável | Ação | |---|---|---| | `BANCO INVÁLIDO` | JSONL corrompido ou contagem fora do padrão | `python3 harness/bank.py banco` lista os erros por item | | `sem chave de API para: ...` | variável de ambiente ausente | exportar a chave; sem ela o runner cai em mock | | `falha após 3 tentativas` | rate limit ou endpoint incorreto | reduzir `--limit`, conferir `base_url` e `model` | | Nota de `calc` sempre 0 | unidade/tolerância incompatível | conferir `tol` e `unit` no item; a resposta deve trazer o número | | Muitas adjudicações | juízes com perfis muito distantes | calibrar `juizes.perfis` na Fase 1 | | Resultado não reproduz | semente diferente ou banco alterado | usar a mesma `--seed` e o mesmo `banco_hash` | ## Comandos de referência | Comando | O que faz | |---|---| | `make validate` | valida o banco de 700 itens | | `make test` | 19 testes unitários | | `make demo` | rodada completa em modo mock | | `make calib` | aplica os 63 itens de calibração (mock) | | `make live` | rodada ao vivo | | `python3 harness/run.py --help` | todas as opções (`--limit`, `--only-domain`, `--seed`, `--out`, `--sem-calibracao`) |