Evals: como saber se está bom (e como trocar de modelo sem medo)
- ⬜♟️ Padrões agênticos e context engineering(AWS Bedrock — GenAI em Produção)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Existe uma pergunta que trava mais projetos de IA do que qualquer limitação técnica: "como a gente sabe se ficou bom?" Sem resposta para ela, o time não consegue aprovar um deploy, não consegue justificar trocar de modelo e — o que dói mais na conta — não consegue descer para um modelo mais barato, porque ninguém quer assinar embaixo. Eval não é burocracia de qualidade: é a capacidade que destrava a maior alavanca de custo que existe. Este módulo mostra como montar uma que funcione sem virar projeto paralelo.
Por que a eval é pré-requisito de FinOps
Praticamente toda alavanca séria de redução de custo é uma troca controlada de qualidade por preço. Sem medição, todas elas são apostas — e times racionais não apostam em produção. É por isso que a ausência de eval congela a conta no patamar mais caro.
| Alavanca de custo | O que ela exige saber | Sem eval |
|---|---|---|
| Descer de tier de modelo | A qualidade caiu? Em quais casos exatamente? | Ninguém aprova — a conta fica no tier caro para sempre |
| Cortar top-k do RAG | O recall se manteve nos casos que importam? | O time mantém 10 trechos "por segurança" e paga por isso em todo request |
| Encurtar o prompt | A instrução removida era load-bearing? | Ninguém mexe no prompt que funciona, mesmo sabendo que está inchado |
| Distillation | O modelo aluno chegou perto o suficiente? | Não dá para afirmar o "perto o suficiente", então não se faz |
| Reduzir max_tokens | As respostas estão sendo cortadas? | Deixa alto por precaução e paga a verbosidade |
| Trocar por modelo novo mais barato | Regrediu em algum caso conhecido? | Fica no modelo antigo por inércia, mesmo mais caro |
O retorno mais direto de montar eval
Uma eval de 150 casos costuma levar duas semanas para montar e, na primeira aplicação, autoriza uma redução de tier em parte do volume que se paga em semanas. Apresente o projeto de eval como investimento de FinOps, não como iniciativa de qualidade — a aprovação sai mais rápido e a descrição é mais honesta.
As quatro camadas de avaliação
Formato válido, campos obrigatórios, valores no domínio, regra de negócio satisfeita, citação existe no contexto.Recall@k, precision@k, MRR contra o conjunto anotado — só faz sentido em sistema com RAG.Um modelo avalia a resposta contra uma rubrica explícita, com saída estruturada.Amostra revisada por quem entende do domínio, com o mesmo critério do juiz.Comece pela camada 1, não pela 3
Times empolgam com LLM-as-judge e pulam a verificação determinística — que é gratuita, roda em 100% do tráfego e pega uma fatia enorme dos problemas reais: JSON inválido, campo obrigatório ausente, citação que não existe no contexto recuperado, valor fora do domínio permitido. Essa camada não julga qualidade, mas elimina a categoria de erro mais barata de detectar e a mais constrangedora de deixar passar.
O golden set: como montar o que realmente importa
O conjunto de referência é o ativo mais duradouro do projeto — ele sobrevive a todas as versões de prompt, modelo e arquitetura. Não precisa ser grande: 100 a 300 casos bem escolhidos valem mais que mil casos genéricos gerados sinteticamente.
| Fatia sugerida | De onde vêm | O que protegem | |
|---|---|---|---|
| Casos frequentes | ~40% | Log de produção, as perguntas mais comuns | A experiência da maioria — regressão aqui é visível no dia seguinte |
| Casos difíceis | ~25% | Casos que o time sabe que o sistema erra | O progresso real; é onde a melhoria aparece |
| Casos de borda | ~15% | Entrada malformada, pergunta ambígua, contexto vazio | Comportamento sob condição ruim, que produção sempre traz |
| Casos adversariais | ~10% | Tentativas de injeção, pedido fora de escopo, dado de terceiros | Segurança e limites — precisam entrar na régua, não só no pentest |
| Casos de recusa | ~10% | Perguntas sem resposta na base | A honestidade do sistema: dizer que não sabe é o comportamento correto |
- Cada caso tem entrada, saída esperada (ou critério de aceitação) e o motivo de estar no conjunto.
- Os casos vêm de produção sempre que possível. Caso inventado testa o que você imaginou, não o que os usuários fazem.
- Versione o conjunto junto com o código: mudança na régua precisa aparecer no diff, ou você compara resultados incomparáveis.
- Guarde o resultado de cada rodada com data, modelo e versão de prompt. O histórico é o que permite afirmar que algo melhorou.
- Nunca ajuste o conjunto para o sistema passar. Se um caso está errado, corrija com justificativa registrada.
- Reavalie trimestralmente: mix de perguntas muda, e conjunto congelado deixa de representar produção.
O jeito mais rápido de começar
Pegue as 200 interações mais recentes de produção, faça duas pessoas do domínio classificarem cada resposta como aceitável ou não, e escrevam uma linha de motivo nas rejeitadas. Em dois dias você tem um conjunto real e uma primeira medida de qualidade — e os motivos escritos viram, quase sem trabalho extra, a rubrica do juiz automático.
LLM-as-judge: como fazer certo
Usar um modelo para avaliar respostas é o que torna a eval escalável. Mas o juiz é um modelo — ele tem vieses conhecidos, e ignorá-los produz uma métrica que sobe enquanto a qualidade real não muda. Os quatro vieses abaixo são reproduzíveis e todos têm mitigação simples.
| Viés do juiz | Como se manifesta | Mitigação |
|---|---|---|
| Posição | Em comparações A/B, tende a preferir uma das posições | Rode nas duas ordens e considere empate quando o veredito inverter |
| Verbosidade | Confunde resposta longa com resposta melhor | Rubrica com critério de concisão explícito; penalize o que não agrega |
| Autopreferência | Favorece texto gerado por modelo parecido com ele | Prefira um juiz de família diferente da do gerador quando puder |
| Complacência | Aprova quase tudo quando o critério é vago | Critérios binários e verificáveis; peça a evidência junto do veredito |
import json, boto3
br = boto3.client("bedrock-runtime")
# Rubrica BINARIA e VERIFICAVEL. "A resposta e boa?" nao e criterio:
# produz aprovacao vaga e metrica que nao mede nada.
RUBRICA = """Avalie a RESPOSTA contra o CONTEXTO e a PERGUNTA.
Para cada criterio responda true/false e cite o trecho que justifica:
C1 ancorada: toda afirmacao factual da resposta aparece no CONTEXTO.
C2 completa: responde o que foi perguntado, sem deixar parte de fora.
C3 honesta: se o CONTEXTO nao contem a resposta, ela admite isso
explicitamente em vez de preencher a lacuna.
C4 citada: cita a fonte quando afirma algo factual.
C5 concisa: sem repeticao, preambulo ou texto que nao agrega.
Nao premie tamanho. Resposta curta e correta e MELHOR que longa e correta."""
ESQUEMA = {
"type": "object",
"properties": {
"criterios": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "string", "enum": ["C1", "C2", "C3", "C4", "C5"]},
"passou": {"type": "boolean"},
"evidencia": {"type": "string"},
},
"required": ["id", "passou", "evidencia"],
},
},
"aprovado": {"type": "boolean", "description": "true so se C1..C4 passaram"},
},
"required": ["criterios", "aprovado"],
}
def julgar(pergunta, contexto, resposta, model_id):
r = br.converse(
modelId=model_id,
system=[
{"text": RUBRICA},
{"cachePoint": {"type": "default"}}, # a rubrica e identica em todo caso
],
messages=[{"role": "user", "content": [{"text":
f"<pergunta>{pergunta}</pergunta>\n"
f"<contexto>{contexto}</contexto>\n"
f"<resposta>{resposta}</resposta>"}]}],
toolConfig={
"tools": [{"toolSpec": {
"name": "registrar_veredito",
"description": "Registra a avaliacao criterio a criterio.",
"inputSchema": {"json": ESQUEMA},
}}],
"toolChoice": {"tool": {"name": "registrar_veredito"}},
},
inferenceConfig={"maxTokens": 1500},
)
for bloco in r["output"]["message"]["content"]:
if "toolUse" in bloco:
return bloco["toolUse"]["input"]
raise ValueError("juiz nao retornou veredito estruturado")
def calibrar(casos_rotulados_por_humano, model_id):
"""Antes de confiar no juiz, meça a concordância dele com o humano.
Abaixo de ~80% de concordancia, conserte a rubrica — nao o sistema."""
acordos = sum(
1 for c in casos_rotulados_por_humano
if julgar(c["pergunta"], c["contexto"], c["resposta"], model_id)["aprovado"]
== c["humano_aprovou"]
)
return acordos / len(casos_rotulados_por_humano)
Juiz não calibrado é pior que não ter eval
Uma métrica que ninguém verificou dá falsa segurança: o time aprova deploys com base num número que não corresponde ao julgamento humano. Antes de usar o juiz para decidir qualquer coisa, meça a concordância dele com rótulos humanos num subconjunto. Abaixo de mais ou menos 80%, o problema é a rubrica — critério vago, ambíguo ou não verificável — e é a rubrica que você conserta, não o sistema avaliado.
Comparação par a par é mais confiável que nota
Pedir uma nota de 0 a 10 produz números instáveis: o mesmo modelo dá 7 hoje e 8 amanhã para a mesma resposta. Perguntar "qual destas duas é melhor segundo o critério X?" é bem mais estável — e é o formato ideal para decidir troca de modelo ou de prompt, que é sempre uma comparação entre duas versões. Só lembre de rodar nas duas ordens por causa do viés de posição.
Eval no ciclo de vida: gate, canário e produção
| Estágio | O que roda | Critério de bloqueio |
|---|---|---|
| Local / PR rápido | 20 a 30 casos, verificação determinística + juiz | Qualquer falha determinística bloqueia |
| Gate de merge | Conjunto completo (100 a 300 casos) | Zero regressão em caso crítico; queda acima do limiar acordado nos demais |
| Canário | Tráfego real em fatia pequena, 24 a 72 horas | Métrica de negócio estável e sem pico de reclamação ou escalonamento |
| Produção | Determinística em 100%, juiz em amostra diária | Alerta quando a taxa cai além da faixa histórica |
| Troca de modelo | Conjunto completo, comparação par a par nas duas ordens | Empate ou vitória do candidato nos casos críticos |
Eval que demora meia hora não é usada
Se rodar a régua completa leva muito tempo, o time para de rodar antes de mudar o prompt — e a eval vira ritual de release em vez de ferramenta de desenvolvimento. Mantenha duas: uma rápida de algumas dezenas de casos para o dia a dia e a completa no gate. Rode a completa em batch quando ela não for bloqueante, e mantenha a rubrica no prefixo cacheado; as duas medidas juntas derrubam bastante o custo de avaliar.
- → feedback em minutos, ou o time para de rodar
- → conjunto completo no gate, em modo assíncrono
- → concordância abaixo de ~80% é problema de rubrica
- → formato, campo obrigatório, citação existente
- → o dado que autoriza rebaixar de tier
- Fora da AWS
- IA e machine learning
- Gestão e governança
- Armazenamento
- Compute
- Integração de apps
- Rede e entrega
A camada determinística é a única que roda em 100% do tráfego, porque custa quase zero. O juiz automático roda em amostra — e precisa ter sido calibrado contra rótulo humano antes de decidir qualquer coisa.
- Conjunto rápido no dia a dia. 20 a 30 casos a cada mudança de prompt. Se rodar demora, o time para de rodar antes de mexer — e a eval vira ritual de release.
- Gate completo antes do merge. Conjunto inteiro em modo assíncrono, com a rubrica no prefixo cacheado. Regressão em caso crítico bloqueia; queda pequena em caso comum vira aviso.
- Calibrar o juiz antes de confiar nele. Compare o veredito com rótulo humano numa amostra. Abaixo de ~80% de concordância, conserte a rubrica — não o sistema avaliado.
- Canário com tráfego real. Fatia pequena por 24 a 72 horas, olhando métrica de negócio e não só a eval. É onde aparece o que o conjunto não representa.
- Determinística em 100%, juiz em amostra. Formato inválido, campo obrigatório ausente e citação inexistente custam quase nada para detectar — então rodam em tudo. O juiz roda em amostra diária.
- O que a eval autoriza. Com a régua no lugar, rebaixar de tier por segmento deixa de ser aposta — e passa a ser mudança de configuração, sem deploy.
Sua eval com LLM-as-judge mostra 94% de aprovação, mas o time de atendimento continua reclamando da qualidade das respostas. Qual é a primeira verificação?
O experimento que autoriza descer de tier
Este é o procedimento que transforma a eval em economia. Ele é simples, dura poucos dias e produz um resultado que dá para levar para o comitê: "em X% do volume, o tier barato é indistinguível do caro; nos outros, escalamos".
O resultado quase sempre é segmentado
É raro que o modelo barato empate no geral, e é comum que ele empate em metade das categorias — classificação, extração de campo, reescrita, roteamento e resumo curto costumam ser indistinguíveis. Como essas categorias frequentemente concentram a maior parte do volume, o efeito na conta é grande mesmo quando o tier caro continua obrigatório nas tarefas difíceis. Por isso o passo 4 é o mais importante do protocolo: a média esconde a oportunidade.
O que medir em cada tipo de sistema
| Sistema | Métrica primária | Contrapeso obrigatório |
|---|---|---|
| RAG / perguntas e respostas | Fidelidade ao contexto (nada afirmado fora dele) | Recall@k — sem o trecho certo, fidelidade alta só significa recusa |
| Extração estruturada | Acurácia por campo crítico | Taxa de campos marcados como incertos — precisão sem cobertura não serve |
| Classificação e roteamento | Acurácia e matriz de confusão | Custo do erro por classe: nem todo engano custa igual |
| Agent com ferramentas | Tarefas concluídas sem intervenção | Tokens por tarefa concluída e taxa de ação errada |
| Geração de texto | Aderência à rubrica de estilo e conteúdo | Concisão — sem ela, o juiz premia texto longo |
| Copiloto interno | Taxa de resposta marcada como útil | Adoção semanal; utilidade alta com adoção baixa é piloto bonito |
Toda métrica precisa de um contrapeso
Métrica solitária é otimizada até virar mentira: fidelidade sobe se o sistema recusar tudo; acurácia de extração sobe se ele marcar tudo como incerto; deflexão sobe se contar abandono. O par existe para tornar visível o efeito colateral da otimização — e é a diferença entre um painel que informa e um painel que tranquiliza.
Quanto custa avaliar (e como manter barato)
| Medida | Efeito no custo da eval | Perda |
|---|---|---|
| Rodar o conjunto completo em batch | Aproximadamente metade do preço | Nenhuma — avaliação é assíncrona por natureza |
| Rubrica no prefixo cacheado | Corta o custo do prefixo repetido em todos os casos | Nenhuma — a rubrica é idêntica caso a caso |
| Juiz em tier médio, não no topo | Redução relevante por avaliação | Verifique a concordância antes; se cair, volte |
| Conjunto rápido no dia a dia, completo no gate | Ordem de grandeza a menos de execuções | Nenhuma, se o conjunto rápido for representativo |
| Amostra em produção em vez de 100% | Proporcional à taxa de amostragem | Detecção mais lenta — compense com determinística em 100% |
| Verificação determinística onde couber | Praticamente zero | Nenhuma — só não cobre julgamento subjetivo |
A eval se paga na primeira decisão
Um conjunto de 200 casos avaliado em batch com rubrica cacheada e juiz de tier médio custa pouco por execução completa. Compare com o que ela autoriza: rebaixar de tier a parcela do volume em que os modelos empatam. A eval é, com folga, o investimento de melhor retorno em qualquer plataforma de IA — e o único que melhora simultaneamente qualidade, velocidade de entrega e custo.
Anti-padrões de avaliação
- Avaliar com o mesmo prompt do sistema: o juiz herda os mesmos vieses e aprova o mesmo erro.
- Rubrica vaga: "a resposta é boa e útil?" produz aprovação em quase tudo e uma métrica que não se move.
- Nota de 0 a 10 em vez de critérios binários: instável entre execuções e impossível de auditar.
- Juiz sem calibração humana: um número que ninguém verificou virando critério de deploy.
- Conjunto ajustado para passar: quando um caso incomoda, ele é removido — e a régua encolhe até não medir nada.
- Só casos fáceis: 98% de aprovação num conjunto que não representa o que produção manda.
- Eval sem histórico: sem guardar resultado por data e versão, você não consegue provar melhoria nem detectar regressão.
- Métrica sem contrapeso: fidelidade que sobe porque o sistema passou a recusar mais.
- Rodar só antes do release: a régua vira ritual e para de guiar o desenvolvimento.
Você quer trocar o tier de raciocínio pelo tier de volume para economizar. A comparação par a par no conjunto completo mostra que o modelo barato perde em 22% dos casos. Qual é a conclusão correta?
Qual destas camadas de avaliação deve rodar em 100% do tráfego de produção, e por quê?
Próximo passo
Com eval no lugar, você ganhou permissão para otimizar sem medo — e é exatamente isso que o próximo módulo faz. O playbook de redução de custo traz 14 alavancas com economia típica, esforço, risco e a ordem certa de aplicar, das que não custam nada às que exigem projeto.
Perguntas frequentes
❓ Como trocar de modelo sem medo?
❓ Como montar uma rubrica de avaliação?
❓ Modelo como juiz é confiável?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…