Lab 88 — Avaliar sistema com LLM: golden set e juiz
O problema, e a empresa que o tem
Depois do L82, a Cadência passou a versionar todo prompt de produção com golden set determinístico bloqueando o pipeline — funcionou tão bem para a descrição de produto que o time de atendimento quis o mesmo processo para o assistente que responde perguntas de política de troca, devolução e frete no chat do site. O problema apareceu na primeira tentativa: o golden set do L82 testa três coisas objetivas (palavra obrigatória, palavra proibida, faixa de tamanho), e uma resposta de atendimento em texto livre não tem esse tipo de gabarito. Duas respostas completamente diferentes na forma podem estar as duas certas — ou as duas erradas de um jeito que nenhuma regra de `contains` pega.
Sem golden set que servisse, o processo de promoção do assistente de atendimento voltou, na prática, para o que o L82 já tinha eliminado para descrição de produto: alguém do time lê um punhado de respostas de exemplo, compara com a versão anterior de cabeça, e declara "melhorou" — ou não. Não há critério escrito, não há golden set, não há número. A decisão de promover uma mudança que vai para todo o tráfego de atendimento da Cadência depende da impressão de quem leu meia dúzia de exemplos escolhidos sem método.
O risco não é hipotético: uma dessas mudanças por impressão já passou afirmando, num tom convincente, uma "garantia estendida de 90 dias" que a Cadência nunca ofereceu — ninguém notou lendo os cinco exemplos escolhidos à mão, porque nenhum deles cobria esse cenário. Este laboratório substitui a impressão por uma suíte: golden set maior, um segundo modelo julgando a resposta contra critérios explícitos, e o viés desse juiz medido e documentado — porque "um LLM julgou" não é sinônimo de "julgamento objetivo".
O que este laboratório NÃO é
Não é sobre gerar a resposta em si nem sobre RAG — isso é o L81 e o L83, e este laboratório assume que o assistente de atendimento já gera texto, só falta prová-lo. Não é sobre versionar o prompt como arquivo — isso já é o L82, e a suíte deste módulo roda DENTRO do mesmo pipeline, como um segundo estágio de teste, não como substituto do golden set determinístico. Não é sobre avaliar um classificador com métrica de negócio e viés de segmento — isso é o L78, e a diferença importa: lá o viés estava no MODELO avaliado (discriminava porte de loja); aqui o viés está no AVALIADOR (o juiz LLM prefere certos tipos de resposta por razões que não são qualidade). E não é sobre bloquear conteúdo malicioso — isso é o L86 (Guardrails), um controle diferente para um risco diferente.
O que você vai conseguir fazer
Objetivos verificáveis: cada um se prova com um número na seção de implantação.
- Explicar por que o golden set determinístico do L82 (palavra presente/ausente, faixa de tamanho) não serve para julgar qualidade de texto de geração aberta.
- Escrever um golden set de atendimento com critérios explícitos por caso, sem resposta exata de gabarito.
- Configurar uma avaliação Bedrock com LLM-as-judge, pontuando cada resposta gerada contra os critérios do caso, com saída estruturada.
- Agregar o resultado com Athena por critério — não só a média geral — e medir se algum critério fica abaixo do piso mesmo com a média parecendo boa.
- Medir e documentar dois vieses concretos do juiz: preferência por resposta mais longa, e preferência pela saída do mesmo modelo que ele.
- Bloquear a promoção no CI quando qualquer critério fica abaixo do piso, reproduzindo uma regressão de qualidade injetada de propósito.
- Reconhecer o padrão central deste laboratório: um número saído de um LLM parece objetivo, e é exatamente por isso que ele precisa de auditoria, não de confiança.
O que a certificação cobra disto
| Conceito | Certificação | Como aparece aqui | O que dominar |
|---|---|---|---|
| LLM-as-judge (avaliação automática por modelo) | AIF-C01, MLS-C01 | um segundo modelo pontua a resposta do primeiro contra critérios explícitos, com saída estruturada — não um veredito de string | quando um critério deixa de ser expressável como regra fixa (`contains`, faixa de tamanho) e passa a exigir julgamento |
| Golden set para geração aberta vs. para classificação | AIF-C01 | cada caso tem pergunta + contexto de referência + critérios, não uma resposta exata a comparar caractere a caractere | a diferença entre gabarito determinístico (L82) e critério avaliado (aqui) |
| Viés do avaliador, não só do modelo avaliado | AIF-C01, MLS-C01 | Athena mede se o juiz prefere resposta mais longa ou saída do mesmo modelo que ele — viés medido, não assumido ausente | que "avaliação por IA" carrega viés como qualquer outro sistema de ML — o L78 já mediu isso no MODELO; aqui o viés está no AVALIADOR |
| Métrica agregada não pode ser a única decisão | AIF-C01, MLS-C01 | o gate exige piso por CRITÉRIO, não só média geral — o mesmo padrão do L78 aplicado a texto, não a segmento de loja | reconhecer, em cenário de prova, quando "a média melhorou" esconde um critério específico piorando |
Onde isto costuma ser cobrado errado
A pergunta clássica descreve um time que usa um LLM para "aprovar automaticamente" toda mudança de prompt, e pergunta o que falta. A resposta esperada NÃO é "nada, já é automático" — é auditar o viés do próprio juiz (comprimento, preferência pelo mesmo modelo) e garantir um piso por critério, porque um número gerado por IA que ninguém questiona é exatamente o oposto de avaliação rigorosa.
Requisitos, e como cada um muda o desenho
Requisito que não muda uma linha do desenho é intenção, não requisito. A terceira coluna é onde cada um deixou marca.
| Requisito | Valor declarado | O que ele decide no desenho |
|---|---|---|
| Golden set precisa cobrir texto de geração aberta, não só regra fixa | cada caso tem critérios explícitos, não resposta exata | casos armazenados no S3 com pergunta + contexto de política real + lista de critérios avaliáveis, não um `esperado` de string |
| Nenhuma promoção decide por impressão de pessoa lendo exemplos | obrigatório, bloqueante | estágio de CI que chama a avaliação Bedrock (LLM-as-judge) antes de qualquer CreatePromptVersion — o mesmo padrão do L82, aplicado a texto livre |
| Nenhum critério pode ser mascarado pela média geral | piso mínimo por critério, não só limiar de média | gate lê a nota agregada POR critério no Athena, e reprova se qualquer um ficar abaixo do piso, mesmo com os outros compensando a média |
| Viés do juiz tem de ser medido, não assumido ausente | obrigatório, auditado a cada mudança relevante de juiz ou de golden set | consulta Athena dedicada correlacionando nota com comprimento da resposta, e comparando nota média quando gerador e juiz são o mesmo modelo |
| Resultado tem de ser auditável depois do fato, não só um score final | obrigatório | S3 grava a resposta bruta gerada, a nota por critério E a justificativa do juiz para cada caso — não só o número agregado |
| Falha de qualquer etapa da avaliação nega a promoção por padrão | o padrão do gate é NEGAR, nunca aprovar por ausência de dado | CodeBuild trata exceção do job de avaliação (erro de formato, timeout) como reprovação — o mesmo princípio do Step Functions do L78, aqui em CodeBuild |
| Custo do juiz não pode dobrar sem controle | avaliação roda por PR que muda o prompt, não por chamada de produção | a suíte só é acionada pelo estágio de CI — tráfego real de atendimento nunca passa pelo juiz, só pelo modelo de geração aprovado |
Arquitetura mínima: a promoção decidida por impressão
Este é o processo real que a Cadência tinha para o assistente de atendimento antes deste laboratório — e é honesto quanto a origem: nasceu de tentar reaproveitar o golden set determinístico do L82 numa tarefa de texto livre, não conseguir, e recuar para leitura manual. O defeito não é ter um humano no loop — é o humano decidir sem critério, sem amostra representativa e sem repetibilidade.
- → pede um punhado de respostas de exemplo com o prompt candidato
- → respostas plausíveis, lidas sem critério nem comparação com golden set
- → aprova a promoção "porque parece melhor", sem golden set nem critério escrito
- → gera a resposta real do cliente com a versão aprovada por impressão
- → resposta gerada, sem prova de qualidade atrelada
- → resposta publicada no chat sem nenhuma medição
- Fora da AWS
- IA e machine learning
- Compute
O golden set determinístico do L82 não tem como testar tom, precisão factual nem citação correta de política — então a Cadência, sem perceber, voltou para "alguém lê e decide". Percorra os passos: em nenhum momento existe um critério escrito nem um número que sustente "melhorou".
- Alguém lê um punhado de respostas de exemplo. O time de atendimento pede ao modelo, com o prompt candidato, algumas respostas para perguntas típicas de política — escolhidas sem método, não do golden set.
- O Bedrock devolve texto plausível, sempre. O modelo gera respostas com boa fluência independente de estarem corretas — plausibilidade não é o mesmo que precisão factual sobre a política real.
- "Melhorou" é uma impressão, não uma medição. Não existe critério escrito, não existe golden set, não existe número. A decisão é de quem leu os exemplos naquele dia, com o humor daquele dia.
- A aprovação pula o teste que não sabe testar texto livre. O pipeline do L82 continua existindo para outros prompts, mas o golden set determinístico não se aplica aqui — e ninguém substituiu o teste, só o pulou.
- A API usa o prompt aprovado por impressão em produção. Toda chamada real de atendimento passa a usar o texto que ninguém testou contra critério nenhum — só contra a leitura de cinco exemplos.
- O cliente recebe a resposta sem nenhuma prova de qualidade. Foi assim que uma resposta afirmando uma "garantia estendida de 90 dias" inexistente chegou ao chat: nenhum dos cinco exemplos lidos cobria esse caso.
# como_aprovavamos_ate_aqui.py -- nao existe script de verdade: isto documenta
# o passo manual que substituia teste automatizado.
exemplos = [
"Posso trocar um produto fora do prazo se ele veio com defeito?",
"Qual o prazo de devolucao para roupa?",
"O frete de troca e por minha conta?",
]
# Alguem do time roda cada pergunta contra o prompt candidato, le a resposta,
# compara de cabeca com a versao anterior, e decide. Nao ha golden set, nao ha
# criterio escrito, nao ha registro de QUAL exemplo foi lido nem de QUANDO.
for pergunta in exemplos:
resposta = invocar_bedrock_com_prompt_candidato(pergunta)
print(f"{pergunta}\n -> {resposta}\n")
# decisao = "parece melhor" -- sem numero, sem criterio, sem golden set.
Impressão não é medição
Impressão não é medição, mesmo quando é a impressão de alguém competente. Cinco exemplos escolhidos sem método não são amostra — são uma amostra de conveniência, enviesada para o que a pessoa lembrou de perguntar. Foi exatamente esse ponto cego que deixou passar uma resposta inventando uma "garantia estendida de 90 dias" que a Cadência nunca ofereceu: nenhum dos cinco exemplos cobria política de garantia.
Arquitetura para produção
Cada peça nova abaixo rastreia a uma linha da tabela de requisitos. A diferença estrutural não é "trocar uma pessoa lendo exemplos por um LLM lendo exemplos" — é substituir uma decisão sem critério por um golden set maior, um segundo modelo julgando contra critério explícito, o resultado bruto auditável, e o viés desse juiz medido em vez de presumido inexistente.
- → push após aprovação do PR dispara o pipeline
- → estágio "AvaliarComJuiz" roda antes de qualquer promoção
- → CreateEvaluationJob aponta para o golden set no S3 e para o prompt candidato do PR
- → internamente, invoca o modelo sob teste para gerar a resposta de cada caso
- → internamente, invoca o modelo-juiz configurado, com os critérios explícitos do caso
- → nota estruturada por critério e justificativa, caso a caso
- → grava o relatório do job: nota por caso, por critério, resposta bruta
- → prefixo com schema no Glue Catalog, consultável por SQL
- → publica nota média por critério e o viés medido
- → só atualiza a versão ativa se a nota agregada e o critério mais baixo passarem do limiar
- → gera a resposta real ao cliente com a versão aprovada
- → resposta gerada
- → resposta publicada no chat, já testada pelo golden set e pelo juiz
- Fora da AWS
- Gestão e governança
- Compute
- IA e machine learning
- Conceito de arquitetura
- Armazenamento
- Analytics
O modelo de geração é o MESMO do desenho mínimo — o que muda é a existência de um caminho inteiro entre "o prompt candidato gera uma resposta" e "a resposta prova, com número, que está melhor", com um segundo modelo julgando e uma consulta dedicada auditando esse próprio juiz. Percorra os passos: cada peça nova rastreia a um requisito da tabela ao lado.
- O prompt muda por PR, e o golden set cresce junto. Quem quer mudar o texto abre um PR com o prompt novo e, se necessário, novos casos no golden set — cada caso com critérios explícitos, não resposta exata.
- O estágio de avaliação chama o Bedrock Evaluation Job. O CodeBuild dispara CreateEvaluationJob apontando para o golden set no S3 e para o texto do prompt do PR — o mesmo padrão de "teste antes de promover" do L82.
- O job gera a resposta de cada caso com o modelo candidato. Internamente, o Bedrock Evaluation invoca o modelo sob teste uma vez por caso do golden set, usando o texto do prompt ainda não promovido.
- O modelo-juiz pontua cada resposta contra critérios explícitos, não contra "parece bom". O juiz recebe a resposta gerada, o contexto de referência do caso e a lista de critérios, e devolve uma nota estruturada por critério com justificativa.
- O resultado bruto vira dado consultável, não só um score final. O relatório completo — resposta, nota por critério, justificativa — vai para o S3, e o Glue dá esquema ao prefixo para o Athena poder agregar por critério.
- Athena mede a nota agregada E o viés do juiz, e publica no painel. A mesma consulta que agrega nota por critério também mede se o juiz prefere resposta mais longa, ou a saída do mesmo modelo que ele — nunca assumido ausente.
- Só passa a versão que supera o limiar em TODOS os critérios. O pipeline só atualiza a versão ativa se a nota agregada E o critério mais baixo passarem do piso; a API lê essa versão e a resposta chega testada ao cliente.
O ponto que separa este desenho de "só trocar quem lê os exemplos" é o par s3_resultados/athena: sem ele, o juiz seria só um oráculo mais rápido, e ninguém saberia se ele mesmo tem viés. Guardar a resposta bruta e a justificativa de CADA caso — não só a nota final — é o que torna o próprio juiz auditável.
O juiz também tem viés — e este é o achado central deste laboratório
Um juiz LLM não é objetivo — é outro modelo, com viés próprio. Ele não substitui "impressão de uma pessoa" por "verdade": substitui por "impressão sistemática de um modelo", que é mais consistente e mais barata que reunir humanos toda vez, mas carrega os mesmos tipos de viés que qualquer sistema de ML — só que mais difícil de perceber, porque o número parece rigoroso. É por isso que a seção de medição de viés, adiante, não é opcional neste laboratório.
O que fica exatamente igual
O que fica exatamente igual, de propósito: a API de atendimento, o modelo de geração e o versionamento de prompt do L82 não aparecem redesenhados aqui, porque não mudam. Trocar COMO a qualidade de texto livre é avaliada é uma mudança na camada de teste, não na camada de inferência — redesenhar as duas ao mesmo tempo é gastar esforço resolvendo um problema que não existe.
Uma avaliação ponta a ponta, do PR à decisão de promover
O nome de cada estágio decide se a próxima versão chega ao chat ou não. PROMPT_VERSION só muda depois que TODOS os critérios do golden set passarem do piso — não a média, o critério mais fraco.
resultado-caso-avaliacao.json -- um registro do relatorio que o Bedrock Evaluation Job grava no S3 para CADA caso do golden set.
{
"caso_id": "c014",
"pergunta_cliente": "Posso trocar um produto fora do prazo se ele veio com defeito?",
"resposta_gerada": "Sim: defeito de fabricacao tem prazo de troca de 90 dias, diferente do prazo de arrependimento (7 dias). Guarde a nota fiscal...",
"modelo_gerador": "us.anthropic.claude-3-5-haiku-20241022-v1:0",
"modelo_juiz": "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
"comprimento_resposta_chars": 812,
"criterios": {
"cita_fonte_correta": { "nota": 9, "justificativa": "cita corretamente o prazo de defeito de fabricacao, distinto do prazo de arrependimento" },
"nao_inventa_politica": { "nota": 9, "justificativa": "nao afirma nada que nao conste na politica de referencia do caso" },
"tom_adequado": { "nota": 8, "justificativa": "direto e cordial, sem prometer alem do que a politica cobre" }
},
"nota_media_caso": 8.7
}
As decisões, e o que se perde em cada uma
📋 A Cadência precisa parar de promover mudanças de prompt de atendimento por impressão de quem leu alguns exemplos, sem reintroduzir uma equipe de revisão manual full-time nem confiar cegamente num número gerado por outro LLM.
Resolve o requisito no menor custo comparável a reunir humanos toda vez: o golden set roda em minutos, não em reuniões, e a medição de viés é o que diferencia "usar um LLM para avaliar" de "confiar cegamente num LLM" — a segunda parte é a que costuma faltar quando alguém adota LLM-as-judge.
Alt: Continuar com leitura manual de exemplos, só formalizando um checklist — um checklist não resolve o problema de fundo: continua sendo uma amostra pequena, escolhida sem método, sem repetibilidade entre quem revisa
Alt: Expandir o golden set determinístico do L82 com mais regras de `contains` — regra fixa não escala para julgar tom, precisão factual sobre política real nem adequação de contexto — é o mesmo limite do L82, só que maior
Alt: Usar o score do juiz sem medir viés, confiando que "o LLM é neutro" — é o antipadrão central deste laboratório: um juiz com viés de comprimento ou de auto-preferência pontua bem uma resposta ruim, e ninguém percebe porque o número parece rigoroso
Alt: Rodar o juiz em CADA chamada de produção, não só no CI — dobra o custo de token de TODO o tráfego de atendimento, não só das mudanças de prompt — o requisito é testar a MUDANÇA, não auditar toda conversa em tempo real
| Decisão | Escolha | Alternativa considerada | Motivo | O que se perde |
|---|---|---|---|---|
| Como testar qualidade de texto aberto | golden set com critérios explícitos + LLM-as-judge | golden set determinístico do L82, com mais regras de string | captura tom, precisão factual e adequação — o que uma regra de `contains` não alcança | custo maior por execução (dois modelos por caso) e resultado com variância, não determinístico como o L82 |
| Onde a avaliação roda | Bedrock Evaluation Job gerenciado, disparado pelo CodeBuild | reimplementar o laço de avaliação à mão, chamando InvokeModel duas vezes por caso | reaproveita orquestração e formato de saída padronizados da AWS, sem manter esse código | menos controle fino sobre o formato exato do prompt do juiz do que uma implementação própria teria |
| Como agregar o resultado | nota por critério no Athena, piso individual por critério | só a média geral, como um limiar único | impede que um critério péssimo seja mascarado por outros dois bons — o mesmo padrão do L78 aplicado a texto | mais uma dimensão para configurar e manter calibrada (piso por critério, não só um número) |
| Se e como auditar o juiz | consulta dedicada de viés (comprimento, mesmo-modelo) a cada mudança relevante | confiar que o juiz é neutro por ser "só uma ferramenta de medição" | sem essa consulta, um viés sistemático do juiz nunca aparece — ele não erra ao acaso, erra na mesma direção sempre | trabalho extra de manter e reexecutar a auditoria quando o modelo-juiz muda de versão |
O que este laboratório não audita
A dívida que este laboratório não paga: o juiz avalia contra critérios que ALGUÉM escreveu — se um critério importante (por exemplo, "não promete prazo que outro sistema decide") nunca foi escrito, o juiz não vai reprovar a resposta por violar algo que não está na lista. Auditoria de viés não substitui revisão periódica dos próprios critérios.
Construir: o golden set com critérios explícitos
O golden set deixa de ter "resposta esperada" exata e passa a ter "critérios avaliáveis" — a diferença entre testar um classificador e testar geração aberta.
{
"assistenteId": "atendimento-politicas",
"criteriosGlobais": [
{ "id": "cita_fonte_correta", "descricao": "A resposta cita corretamente a regra da politica de referencia do caso (prazo, condicao, excecao)?" },
{ "id": "nao_inventa_politica", "descricao": "A resposta NAO afirma nenhuma regra, prazo ou beneficio que nao conste na politica de referencia do caso?" },
{ "id": "tom_adequado", "descricao": "O tom e cordial e direto, sem prometer o que outro sistema decide (prazo de entrega, reembolso ja aprovado)?" }
],
"pisoPorCriterio": 6.0,
"toleranciaAbaixoDoPiso": 0.10,
"casos": [
{
"id": "c001",
"pergunta": "Posso trocar um produto fora do prazo se ele veio com defeito?",
"contextoPolitica": "Defeito de fabricacao: troca em ate 90 dias da compra, mediante nota fiscal. Arrependimento (produto sem defeito): 7 dias.",
"notaEsperadaAcimaDe": 8.0
},
{
"id": "c002",
"pergunta": "O frete de devolucao por defeito e por minha conta?",
"contextoPolitica": "Defeito de fabricacao: frete de devolucao e reenvio por conta da Cadencia. Arrependimento: frete por conta do cliente.",
"notaEsperadaAcimaDe": 8.0
},
{
"id": "c003",
"pergunta": "Voces tem garantia estendida?",
"contextoPolitica": "A Cadencia NAO oferece garantia estendida. Existe apenas a garantia legal de 90 dias para defeito de fabricacao.",
"notaEsperadaAcimaDe": 8.0
}
// ... mais 57 casos, cobrindo prazo de arrependimento, excecao de higiene,
// reembolso parcial e as perguntas mais repetidas no atendimento real.
]
}
Por que este caso não caberia numa regra fixa
O caso `c003` é o que teria pego a regressão real: o contexto de política diz explicitamente que garantia estendida NÃO existe. Um golden set determinístico (estilo L82) poderia até testar "a palavra 'estendida' está ausente", mas isso reprovaria qualquer resposta que mencionasse o termo para NEGAR a garantia — é exatamente o tipo de nuance que precisa de julgamento, não de regra de string.
Construir: o juiz e os critérios explícitos
A peça central é o prompt do juiz: ele recebe a pergunta, o contexto de política real (não a resposta gerada, o CONTEXTO — para o juiz poder checar fato, não só estilo), a resposta gerada, e a lista de critérios — e devolve JSON estruturado, nunca prosa livre.
Voce e um avaliador de qualidade de respostas de atendimento ao cliente da
Cadencia. Avalie a RESPOSTA GERADA contra o CONTEXTO DE POLITICA (a fonte de
verdade) e os CRITERIOS abaixo. De uma nota de 0 a 10 para CADA criterio,
com uma justificativa de uma frase. NAO avalie tamanho nem estilo de escrita
fora do que os criterios pedem explicitamente -- comprimento nao e um criterio.
PERGUNTA DO CLIENTE: {{pergunta}}
CONTEXTO DE POLITICA (fonte de verdade): {{contexto_politica}}
RESPOSTA GERADA: {{resposta_gerada}}
CRITERIOS:
{{criterios_globais}}
Responda SOMENTE com JSON no formato:
{"criterios": {"<id_do_criterio>": {"nota": <0-10>, "justificativa": "<uma frase>"}}}// SuiteAvaliacaoJuiz/Program.cs -- dispara o Bedrock Evaluation Job, espera a
// conclusao, le o relatorio no S3 e aplica o gate por criterio. Reaproveita o
// cliente Bedrock do L81 e a estrutura de teste do L82 (TesteRegressaoPrompt.cs)
// -- aqui o veredito vem de um segundo modelo, nao de uma regra de string.
using System.Text.Json;
using Amazon.Bedrock;
using Amazon.Bedrock.Model;
var caminhoPrompt = args.Length > 0 ? args[0] : "prompts/atendimento-politicas.txt";
var textoPrompt = await File.ReadAllTextAsync(caminhoPrompt);
using var bedrock = new AmazonBedrockClient();
// O job aponta para o golden set no S3 -- nao para o texto do prompt em si; o
// prompt do PR e resolvido pelo CodeBuild antes de disparar o job.
var job = await bedrock.CreateEvaluationJobAsync(new CreateEvaluationJobRequest
{
JobName = $"cadencia-avaliacao-atendimento-{DateTime.UtcNow:yyyyMMddHHmmss}",
RoleArn = "arn:aws:iam::111122223333:role/AvaliacaoAtendimentoRole",
EvaluationConfig = MontarConfigLlmAsJudge(
modeloAvaliado: "us.anthropic.claude-3-5-haiku-20241022-v1:0",
modeloJuiz: "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
promptJuiz: await File.ReadAllTextAsync("prompts/juiz-atendimento-politicas.txt")),
InferenceConfig = MontarInferenceConfig(textoPrompt),
OutputDataConfig = new EvaluationOutputDataConfig
{
S3Uri = "s3://cadencia-lake/atendimento/avaliacao-juiz/resultados/",
},
});
var status = await EsperarConclusaoAsync(bedrock, job.JobArn);
if (status != EvaluationJobStatus.Completed)
{
// Falha do job vira reprovacao -- nunca omissao. E o requisito no 6 da
// tabela de requisitos virando codigo.
Console.WriteLine($"job de avaliacao terminou como {status} -- pipeline bloqueado");
Environment.Exit(1);
}
var relatorio = await LerRelatorioDoS3Async(job.OutputDataConfig.S3Uri);
var (aprovado, motivos) = AplicarGatePorCriterio(relatorio, pisoPorCriterio: 6.0,
toleranciaAbaixoDoPiso: 0.10);
foreach (var m in motivos) Console.WriteLine($" {m}");
Console.WriteLine(aprovado ? "golden set: aprovado em todos os criterios"
: "golden set: reprovado -- ver criterios acima");
Environment.Exit(aprovado ? 0 : 1); // CodeBuild le este codigo de saida
A instrução contra viés de comprimento já está no prompt do juiz
"Não avalie tamanho nem estilo fora do que os critérios pedem" é uma linha do prompt do juiz, não um detalhe — é a primeira linha de defesa contra o viés de verbosidade medido na seção de prova adiante. Sem essa instrução explícita, o juiz tende a recompensar resposta mais longa mesmo quando os três critérios reais não pedem isso.
Construir: o pipeline e a agregação no Athena
O estágio novo entra entre o mesmo par que o L82 já tinha — teste antes de promoção — só que agora chamando o Bedrock Evaluation em vez da regra de string.
# pipeline-avaliacao-juiz.tf -- novo estagio no MESMO CodePipeline do L82,
# especifico para o prompt do assistente de atendimento.
resource "aws_codebuild_project" "avaliar_com_juiz" {
name = "${var.projeto}-avaliar-atendimento-juiz"
service_role = aws_iam_role.pipeline_avaliacao.arn
environment {
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/standard:7.0"
type = "LINUX_CONTAINER"
environment_variable {
name = "GOLDEN_SET_S3_URI"
value = "s3://${aws_s3_bucket.avaliacao_atendimento.bucket}/golden-set/"
}
}
source { type = "CODEPIPELINE", buildspec = "buildspec-avaliacao.yml" }
artifacts { type = "CODEPIPELINE" }
}
resource "aws_s3_bucket" "avaliacao_atendimento" {
bucket = "${var.projeto}-avaliacao-atendimento-juiz"
}
resource "aws_kms_key" "avaliacao_atendimento" {
description = "Golden set e resultado de avaliacao por juiz -- L88"
deletion_window_in_days = 30
enable_key_rotation = true
}
resource "aws_glue_catalog_database" "avaliacao_atendimento" {
name = "${var.projeto}_avaliacao_atendimento"
}
resource "aws_glue_catalog_table" "resultados_avaliacao" {
name = "resultados_avaliacao_juiz"
database_name = aws_glue_catalog_database.avaliacao_atendimento.name
table_type = "EXTERNAL_TABLE"
parameters = { classification = "json" }
storage_descriptor {
location = "s3://${aws_s3_bucket.avaliacao_atendimento.bucket}/resultados/"
input_format = "org.apache.hadoop.mapred.TextInputFormat"
output_format = "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat"
ser_de_info { serialization_library = "org.openx.data.jsonserde.JsonSerDe" }
columns { name = "caso_id" type = "string" }
columns { name = "modelo_gerador" type = "string" }
columns { name = "modelo_juiz" type = "string" }
columns { name = "comprimento_resposta_chars" type = "int" }
columns { name = "criterios" type = "string" } # JSON aninhado
}
}
resource "aws_athena_workgroup" "avaliacao_atendimento" {
name = "${var.projeto}-avaliacao-atendimento"
configuration {
enforce_workgroup_configuration = true
result_configuration {
output_location = "s3://${aws_s3_bucket.avaliacao_atendimento.bucket}/resultados-athena/"
encryption_configuration {
encryption_option = "SSE_KMS"
kms_key_arn = aws_kms_key.avaliacao_atendimento.arn
}
}
}
}
-- nota-por-criterio.sql -- agrega POR criterio, nao so a media geral; e a
-- consulta que o gate le antes de liberar promocao.
SELECT
criterio,
AVG(nota) AS nota_media,
COUNT(*) AS total_casos,
SUM(CASE WHEN nota < 6.0 THEN 1 ELSE 0 END) AS casos_abaixo_do_piso,
SUM(CASE WHEN nota < 6.0 THEN 1 ELSE 0 END) * 1.0
/ COUNT(*) AS proporcao_abaixo_do_piso
FROM resultados_avaliacao_juiz
CROSS JOIN UNNEST(
MAP_ENTRIES(CAST(JSON_PARSE(criterios) AS MAP(VARCHAR, JSON)))
) AS t(criterio_par)
CROSS JOIN (
SELECT criterio_par.key AS criterio,
CAST(JSON_EXTRACT_SCALAR(criterio_par.value, '$.nota') AS DOUBLE) AS nota
)
WHERE data_execucao = DATE('2026-08-08')
GROUP BY criterio
ORDER BY nota_media ASC;
Construir: medir o viés do próprio juiz
É a peça que separa "usar um LLM para avaliar" de "confiar cegamente num LLM para avaliar". A mesma tabela de resultados que sustenta a nota por critério sustenta as duas consultas de viés abaixo.
-- vies-comprimento.sql -- correlaciona comprimento da resposta com a nota
-- media do criterio 'tom_adequado', que NAO deveria depender de tamanho.
SELECT
CORR(comprimento_resposta_chars, nota_tom_adequado) AS correlacao_comprimento_nota
FROM (
SELECT
comprimento_resposta_chars,
CAST(JSON_EXTRACT_SCALAR(criterios, '$.tom_adequado.nota') AS DOUBLE) AS nota_tom_adequado
FROM resultados_avaliacao_juiz
WHERE data_execucao = DATE('2026-08-08')
);
-- correlacao > 0,4 e considerada evidencia de vies de verbosidade neste
-- laboratorio: o juiz esta recompensando tamanho, nao qualidade real.
-- vies-mesmo-modelo.sql -- compara a nota media quando o modelo gerador e o
-- modelo juiz sao da MESMA familia, contra quando sao familias diferentes.
SELECT
(modelo_gerador LIKE '%' || SPLIT_PART(modelo_juiz, '-', 3) || '%') AS mesma_familia,
AVG(nota_media_caso) AS nota_media,
COUNT(*) AS total_casos
FROM resultados_avaliacao_juiz
WHERE data_execucao = DATE('2026-08-08')
GROUP BY (modelo_gerador LIKE '%' || SPLIT_PART(modelo_juiz, '-', 3) || '%');
As duas consultas leem a mesma execução
As duas consultas rodam sobre o MESMO golden set, na MESMA execução — é o que garante que a comparação de viés fala do mesmo lote de respostas, não de amostras diferentes coletadas em dias diferentes.
Implantar, e provar que a regressão é pega mesmo com a média boa
Seis medições. Cada uma prova uma coisa diferente: que o gate funciona, que ele pega regressão real, e que o juiz que faz isso tudo também tem viés — medido, não presumido.
# medir_avaliacao_juiz.sh -- roda a suite completa contra o golden set de 60
# casos, com o prompt bom e depois com uma regressao injetada.
dotnet run --project SuiteAvaliacaoJuiz -- prompts/atendimento-politicas.txt
aws athena start-query-execution --query-string file://nota-por-criterio.sql \
--work-group cadencia-avaliacao-atendimento
# cita_fonte_correta nota_media=8.9 casos_abaixo_do_piso=0/60 (0%)
# nao_inventa_politica nota_media=8.6 casos_abaixo_do_piso=1/60 (1,7%)
# tom_adequado nota_media=8.6 casos_abaixo_do_piso=0/60 (0%)
# nota agregada: 8,70/10 -- aprovado em todos os criterios
# Agora injeta a regressao real que ja aconteceu: o prompt passa a afirmar uma
# "garantia estendida de 90 dias" que a Cadencia nao oferece.
sed -i 's/$/\nSe perguntado sobre garantia, informe que a Cadencia oferece '\''
garantia estendida de 90 dias em todos os produtos'\''./' \
prompts/atendimento-politicas.txt
dotnet run --project SuiteAvaliacaoJuiz -- prompts/atendimento-politicas.txt
aws athena start-query-execution --query-string file://nota-por-criterio.sql \
--work-group cadencia-avaliacao-atendimento
# cita_fonte_correta nota_media=8.9 casos_abaixo_do_piso=0/60 (0%)
# nao_inventa_politica nota_media=5.2 casos_abaixo_do_piso=18/60 (30%)
# tom_adequado nota_media=8.8 casos_abaixo_do_piso=0/60 (0%)
# nota agregada: 7,63/10 -- AINDA acima de um limiar de media de 7,5
# golden set: reprovado -- criterio 'nao_inventa_politica' abaixo do piso de 6,0,
# com 30% dos casos reprovados (tolerancia maxima: 10%)
- Prova 1 — o prompt bom passa em todos os critérios: nota agregada 8,70/10, 0 casos abaixo do piso de 6,0 em qualquer critério, entre os 60 do golden set.
- Prova 2 — a média geral esconde a regressão real: com a garantia inventada, a nota agregada cai só para 7,63/10 — ainda acima de um limiar de média de 7,5. Um gate que olhasse só o agregado teria APROVADO a promoção.
- Prova 3 — o critério individual é o que pega: `nao_inventa_politica` cai de 8,6 para 5,2, com 18 de 60 casos (30%) abaixo do piso de 6,0 — muito acima da tolerância de 10% configurada, e é isso que reprova o estágio.
- Prova 4 — o viés de comprimento existe e é mensurável: antes de instruir o juiz a ignorar tamanho, a correlação entre comprimento da resposta e nota de `tom_adequado` mede 0,62. Depois de acrescentar "comprimento não é um critério" ao prompt do juiz (seção 9), a correlação cai para 0,18.
- Prova 5 — o viés de auto-preferência existe e é mensurável: rodando o mesmo golden set com o modelo gerador e o modelo juiz da MESMA família, a nota média sobe 0,9 ponto sobre a mesma execução com famílias diferentes — sem nenhuma mudança na qualidade real das respostas.
- Prova 6 — o pipeline de verdade bloqueia: abra um PR com a garantia inventada e confira o console do CodePipeline. Esperado: estágio "AvaliarComJuiz" com status Failed, CreatePromptVersion nunca é chamado.
O achado central: a média sozinha teria aprovado a regressão
A média geral (7,63) teria passado num gate que olhasse só o agregado — foi o critério individual `nao_inventa_politica`, caindo para 5,2 com 30% dos casos reprovados, que bloqueou a promoção. Uma resposta inventando uma garantia que não existe é factualmente errada mesmo quando soa bem escrita — e é exatamente esse tipo de erro que uma média boa esconde melhor.
Quebrar de propósito: quatro falhas e o diagnóstico
As falhas abaixo foram provocadas de propósito sobre esta mesma suíte, para mostrar como cada uma passaria despercebida sem os controles certos.
| Falha provocada | Sintoma | Onde olhar | Correção |
|---|---|---|---|
| Gate lê só a nota agregada, sem checar piso por critério | a regressão da garantia inventada passa com 7,63/10, acima de um limiar de média configurado em 7,5 | consulta Athena agregada por critério mostra `nao_inventa_politica` em 5,2, mascarado pelos outros dois em 8,6-8,9 | gate sempre lê a tabela por critério, nunca só a média — como na seção de implantação |
| Prompt do juiz não instrui a ignorar comprimento | respostas mais longas, mesmo sem informação nova, recebem nota melhor em `tom_adequado` | correlação (`CORR`) entre comprimento e nota do critério, na consulta de viés de comprimento | adicionar "comprimento não é um critério" explicitamente ao prompt do juiz, como na seção 9 |
| Juiz e gerador usam o mesmo modelo, sem checar viés de auto-preferência | nota média sobe sistematicamente quando o modelo avaliado é o mesmo do juiz, mesmo com qualidade real igual | consulta Athena agrupando por "mesma família" versus "família diferente" | usar juiz de família diferente do gerador em produção, ou documentar e compensar a diferença medida |
| Temperatura do modelo-juiz não fixada baixa | a MESMA resposta recebe notas diferentes em execuções repetidas do job, sem nenhuma mudança no prompt nem na resposta | duas execuções idênticas do Bedrock Evaluation Job sobre o mesmo golden set e o mesmo prompt | fixar temperatura baixa no modelo-juiz; se a variância persistir, rodar 2-3 amostras por caso e usar a mediana |
Nenhuma das quatro derruba o job
As quatro falhas têm uma coisa em comum: o job termina com sucesso, o relatório sai, o pipeline fica verde. O defeito é de CALIBRAÇÃO do gate ou do juiz, não de infraestrutura quebrada — e é exatamente o tipo de erro que passa despercebido quando alguém confia no status "Completed" do job sem auditar o conteúdo dele.
O golden set determinístico do L82 (palavra obrigatória, palavra proibida, faixa de tamanho) já existe e funciona. Um engenheiro da Cadência propõe: "em vez de montar um juiz LLM, vamos só adicionar mais regras de `contains` ao golden set do assistente de atendimento". Qual é o defeito nessa proposta?
Segurança: o que o golden set e o relatório de avaliação expõem
O golden set contém texto de política real da Cadência, e o relatório de avaliação contém a justificativa do juiz caso a caso — dado que revela como o assistente se comporta antes de qualquer coisa chegar a produção.
| Risco | Probabilidade | Impacto | Prevenção | Detecção | Resposta |
|---|---|---|---|---|---|
| Role do CodeBuild com `bedrock:InvokeModel` amplo demais (`Resource: "*"`) | média | médio — chamadas para modelo fora do orçamento previsto, custo fora de controle | `Resource` restrito aos dois ARNs de modelo usados (gerador e juiz), nunca `bedrock:*` | CloudTrail em InvokeModel/CreateEvaluationJob fora dos dois modelos esperados | revogar a policy ampla e reemitir com os ARNs restritos |
| Golden set com exemplo real de conversa de cliente, não sintético | baixa (casos escritos à mão, não extraídos de conversa real) | alto — se algum dia alimentado com conversa real, pode conter dado pessoal do cliente | golden set sempre sintético/anonimizado; revisão de PR confere isso antes do merge | scan de PII periódico no prefixo do golden set (Macie) | remover o caso, rotacionar o bucket se exposto, revisar o processo de curadoria do golden set |
| Promoção direta no console, pulando o estágio AvaliarComJuiz | média — mesma classe de risco do L82, aqui aplicada a um segundo estágio | alto — resposta nunca julgada por critério nenhum chega a todo o tráfego de atendimento | IAM nega CreatePromptVersion a qualquer role humana, só a role do pipeline tem essa permissão — herdado do L82 | CloudTrail alarma em CreatePromptVersion fora da role do pipeline | reverter para a última versão aprovada, revisar quem tinha acesso |
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvocarSomenteOsDoisModelosDaAvaliacao",
"Effect": "Allow",
"Action": ["bedrock:InvokeModel", "bedrock:CreateEvaluationJob", "bedrock:GetEvaluationJob"],
"Resource": [
"arn:aws:bedrock:*::foundation-model/anthropic.claude-3-5-haiku-20241022-v1:0",
"arn:aws:bedrock:*::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0"
]
},
{
"Sid": "LerEscreverSomenteOPrefixoDaAvaliacao",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::cadencia-avaliacao-atendimento-juiz/*"
},
{
"Sid": "ConsultarSomenteOWorkgroupDaAvaliacao",
"Effect": "Allow",
"Action": ["athena:StartQueryExecution", "athena:GetQueryResults"],
"Resource": "arn:aws:athena:*:*:workgroup/cadencia-avaliacao-atendimento"
}
// Nenhuma acao 'bedrock:CreatePromptVersion' aqui de proposito -- essa
// permissao existe SO na role do estagio de promocao, nao na desta avaliacao.
]
}Observabilidade: as perguntas que o painel tem de responder
- Qual foi a nota média POR CRITÉRIO na última execução, não só a agregada?
- Algum critério individual caiu abaixo do piso, mesmo com a média geral boa?
- O viés medido (comprimento, mesmo-modelo) está piorando execução após execução?
- Quantas promoções o gate bloqueou nos últimos 30 dias, e por qual critério?
- A nota do juiz é consistente entre execuções repetidas da mesma resposta?
| Alarme | Métrica | Limiar inicial | Por que esse limiar |
|---|---|---|---|
| Critério individual abaixo do piso | NotaPorCriterio (custom, por dimensão) | < 6,0 de média, OU > 10% dos casos abaixo de 6,0 | já bloqueia o gate; o alarme existe para avisar alguém, não só bloquear em silêncio — mesmo padrão do L82 |
| Viés de comprimento acima do esperado | correlação (comprimento × nota) da consulta de viés | > 0,4 | acima disso, o juiz está pontuando tamanho, não os três critérios reais — medido em 0,62 antes da correção deste laboratório |
| Viés de auto-preferência acima do esperado | diferença de nota média entre mesma-família e família-diferente | > 0,5 ponto | medido em 0,9 ponto neste laboratório — acima disso, a escolha do juiz deixa de ser confiável para decidir promoção |
| Variância entre execuções repetidas da mesma resposta | desvio padrão da nota em N execuções do mesmo caso | > 1,0 ponto (escala 0-10) | juiz instável não é juiz — se a mesma entrada produz notas muito diferentes, a temperatura do modelo-juiz precisa ser revista |
Escala: do golden set de 60 casos a vários assistentes em avaliação
| Cenário | O que muda | Onde a arquitetura sente primeiro |
|---|---|---|
| Golden set de 60 casos (hoje) | job de avaliação roda em minutos; Athena varre um único prefixo do dia | nada — é o volume que o desenho deste laboratório foi medido com |
| Golden set de 600 casos (10x, catálogo de política crescendo) | custo de token do job cresce proporcional (dois modelos por caso); tempo do job também cresce | custo do CI, não da produção — o job só roda por PR, não por chamada real de atendimento |
| Vários assistentes em avaliação simultânea (atendimento, vendas, suporte técnico) | cada um com seu próprio golden set e sua própria auditoria de viés — misturar golden sets de tarefas diferentes invalida a comparação de nota | Athena escala por consulta, mas o workgroup precisa isolar resultado por assistente para o viés não vazar de um golden set para outro |
| Falha de região do Bedrock durante o job de avaliação | CreateEvaluationJob falha para os dois modelos, não só um — não é um problema de viés nem de gate | o gate trata como reprovação por padrão (requisito nº 6); resiliência de InvokeModel em si é tema do L79/L81, não deste |
Custo: dois modelos por caso, não um
A diferença mais importante em relação ao L82: cada caso do golden set agora cobra DOIS modelos, não um — o gerador E o juiz. É a dimensão de custo nova que este laboratório acrescenta.
| Cenário | Volume | O que acontece com a fatura | Otimização |
|---|---|---|---|
| Protótipo | 1 golden set de 60 casos, avaliado por PR | dominado por token do juiz — o modelo-juiz costuma ser maior/mais caro que o gerador, e cada caso paga os dois | manter o golden set no tamanho que ainda cobre os cenários reais, sem casos redundantes |
| Produção pequena | 1 assistente, avaliação a cada PR que muda o prompt | custo do CI cresce com a frequência de mudança de prompt, não com o tráfego de atendimento — o juiz nunca roda em produção | disparar o estágio só quando o arquivo do prompt ou do golden set muda, como no L82 |
| Alta escala | vários assistentes, golden sets crescendo com o catálogo de política | dobra de token (gerador + juiz) multiplicada pelo número de assistentes em avaliação simultânea | compartilhar o modelo-juiz entre assistentes quando o critério permitir, mantendo golden sets separados |
Modelo de cobrança, não valor
Nenhum valor em dólar aparece nesta seção por decisão: o preço por token muda com o catálogo do Bedrock e por região — confira o AWS Pricing Calculator. O que fica verdadeiro independente do preço: este laboratório sempre cobra DOIS modelos por caso avaliado, contra UM no L82 — é o modelo de cobrança que a certificação cobra, não o valor absoluto.
Well-Architected nos seis pilares
| Pilar | Situação | Risco | Melhoria | Prioridade |
|---|---|---|---|---|
| Excelência operacional | promoção de texto livre auditável por critério, substituindo impressão de quem leu exemplos | ainda depende de alguém escrever bons critérios no golden set | revisão periódica dos critérios em si, não só das notas que eles produzem | média |
| Segurança | role da avaliação restrita aos dois modelos e ao prefixo próprio; promoção só pela role do pipeline | golden set poderia, por engano, ser alimentado com conversa real não anonimizada | gate de PR checando padrão de PII antes do merge no golden set | alta |
| Confiabilidade | falha do job de avaliação nega promoção por padrão, nunca aprova por omissão | juiz instável (variância entre execuções) ainda não tem alarme dedicado | alarme de desvio padrão de nota por caso repetido, como na observabilidade | média |
| Eficiência de performance | golden set roda por PR, não por chamada de produção | golden set sem poda cresce e cada caso redundante dobra custo (dois modelos) | revisar e podar casos redundantes periodicamente | média |
| Otimização de custo | dobra de token medida e isolada só ao CI, nunca à produção | vários assistentes em avaliação simultânea multiplicam a dobra sem controle central | orçamento de token dedicado à avaliação, separado do orçamento de produção | média |
| Sustentabilidade | juiz só roda quando o prompt muda, não a cada resposta real | auditoria de viés roda toda vez, mesmo quando só o golden set cresceu, não o prompt | rodar a auditoria de viés com menos frequência que o gate principal, quando só o golden set mudou | baixa |
Evolução em níveis: o que muda, e o que passa a doer
A terceira arquitetura não é um desenho — é a resposta a QUANDO trocar de desenho. Cada nível resolve um risco deste módulo e compra outro, até o ponto em que avaliação deixa de ser um estágio de CI e vira parte permanente da plataforma.
Alguém lê um punhado de respostas geradas com o prompt candidato e decide, sem critério nem golden set, se "melhorou".Golden set de 60 casos com critérios explícitos, avaliado por Bedrock Evaluation Job, agregado por critério no Athena, com o viés do próprio juiz medido e documentado.Dois ou três modelos-juiz de famílias diferentes pontuam o mesmo caso; a nota final é a mediana, não a de um único juiz.Uma amostra do golden set é pontuada por humano periodicamente, e a calibração do juiz (prompt, exemplos, limiar) é ajustada para concordar com esses rótulos.Além do golden set fixo por PR, uma amostra do tráfego real de atendimento é julgada continuamente, pegando caso que o golden set nunca previu.A suíte de golden set, juiz e auditoria de viés deste laboratório deixa de ser um estágio isolado e vira um serviço interno reutilizado por todo assistente novo da Cadência — dado, modelo e avaliação tratados como uma plataforma única, tema do L100.A ordem não é negociável
A ordem não é negociável: pular do Nível 1 direto para ensemble de juízes (Nível 3) resolveria um problema mais caro antes de resolver o mais barato e mais óbvio — ter QUALQUER critério explícito e QUALQUER medição de viés no lugar. Este laboratório é a fundação; os níveis seguintes refinam, não substituem.
Onde IA entra nesta arquitetura, e onde não entra
Os dois lados da arquitetura são IA — inclusive o avaliador
IA está nos dois lados desta arquitetura, e isso é o ponto: o modelo que gera a resposta de atendimento (herdado do L81/L82) e o modelo que julga essa resposta são os dois sistemas de aprendizado de máquina, e os dois carregam viés. Uma regra tradicional (golden set determinístico do L82) não resolveria aqui porque o critério real — "o tom está adequado", "a resposta cita a fonte certa" — não é expressável como `contains`/`not contains`. Quando o juiz erra (ou tem viés não corrigido), o fallback é a auditoria: a consulta de viés deste laboratório, e a exigência de piso por critério em vez de confiar num único número agregado.
O ponto de entrada de MAIS IA nesta cadeia é o Nível 3 da escada de evolução acima — ensemble de juízes — e o de menos confiança cega é medir o viés a cada mudança relevante de modelo-juiz, não só na primeira vez que a suíte foi escrita.
Anti-padrões deste laboratório
| Antipadrão | Por que alguém faz assim | Sintoma em produção | Forma correta |
|---|---|---|---|
| Confiar cegamente no score do juiz LLM | o número parece objetivo — saiu de um modelo, não de opinião humana — e questionar um número dá trabalho | regressão real passa porque a média ficou "boa o suficiente" mesmo com um critério péssimo escondido dentro dela | gate por critério individual + auditoria periódica de viés, nunca confiar no score sem medir o que produz esse score |
| Usar o mesmo modelo como gerador e juiz sem testar viés de auto-preferência | é o caminho de menor atrito — já se tem acesso ao modelo, não precisa aprovar outro | mudanças do mesmo modelo sempre pontuam bem; mudanças de um modelo concorrente, mesmo melhores, pontuam pior | juiz de família diferente do gerador, ou pelo menos medir e documentar a diferença, como na seção de prova |
| Reaproveitar o golden set determinístico do L82 achando que só precisa de mais casos | já existe, parece economia de trabalho reescrever do zero | regra fixa (palavra obrigatória/proibida) não pega erro factual nem tom ruim, mesmo com centenas de casos | critério de rubrica avaliado por juiz para texto aberto — golden set determinístico continua certo para tarefa de classificação |
| Pular a etapa de medir viés porque "parece acadêmico demais para um MVP" | pressão de prazo, e o gate já está funcionando visivelmente sem isso | meses depois, alguém percebe que toda promoção aprovada veio do mesmo modelo, e ninguém sabe se o juiz é confiável | medir viés desde a primeira versão da suíte, não depois de acumular dívida de confiança |
| Aprovar por impressão (ler 5 exemplos) achando suficiente | é rápido e parece bom senso de quem conhece o produto | mudança que piora 30% dos casos passa porque os cinco exemplos lidos por acaso eram bons | golden set + juiz sistemático sempre, nunca amostra ad hoc — é o problema que este laboratório inteiro resolve |
Quando algo não funciona
| Sintoma | Causa provável | Como investigar | Log/métrica | Correção |
|---|---|---|---|---|
| Nota do juiz varia entre execuções para a MESMA resposta | temperatura do modelo-juiz não fixada baixa | rodar duas execuções idênticas do job sobre o mesmo golden set e o mesmo prompt | desvio padrão de nota por caso repetido, no CloudWatch | fixar temperatura baixa; se persistir, rodar múltiplas amostras e usar a mediana |
| Pipeline aprova mudança que piora o tom, mas mantém a política correta | gate lendo só a média geral, não o piso por critério | nota por critério individual na tabela Athena da última execução | nota agregada alta, nota de `tom_adequado` isoladamente baixa | gate por critério mínimo, nunca só a média — como na seção de requisitos |
| Nota sistematicamente mais alta para respostas de um modelo específico | viés de auto-preferência (mesmo modelo ou família entre gerador e juiz) | comparar nota média por modelo gerador, agrupado por mesma-família | consulta Athena de viés de mesmo-modelo | trocar o juiz por modelo de família diferente, ou aplicar correção documentada |
| CodeBuild falha antes mesmo de ler a nota do juiz | formato de saída do juiz instável — o modelo às vezes devolve prosa em vez de JSON estrito | log bruto da resposta do juiz para o caso que falhou | exceção de deserialização no CloudWatch Logs do CodeBuild | reforçar o prompt do juiz para formato estrito, com um reparseador de tolerância como rede de segurança |
Limpeza: o que o destroy não leva
#!/usr/bin/env bash
set -euo pipefail
# O CodeBuild deste estagio e removido pelo destroy, mas o log group e o
# resultado de jobs de avaliacao passados sobrevivem.
terraform destroy \
-target=aws_codebuild_project.avaliar_com_juiz \
-target=aws_athena_workgroup.avaliacao_atendimento \
-auto-approve
terraform destroy -auto-approve
echo "Confira manualmente:"
echo " - o log group /aws/codebuild/<projeto>-avaliar-atendimento-juiz nao e"
echo " removido por este destroy -- tem retencao propria configurada"
echo " - jobs de Bedrock Evaluation ja concluidos continuam existindo e"
echo " consultaveis pela API por um tempo, mesmo depois do bucket de"
echo " resultado ser removido -- confira GetEvaluationJob antes de assumir"
echo " que nao ha mais rastro"
echo " - o bucket S3 do golden set/resultados precisa ser esvaziado antes do"
echo " destroy remover; objeto residual bloqueia a exclusao do bucket"
O que o destroy NÃO leva
O CodeBuild e o workgroup do Athena são removidos pelo `destroy` acima. O log group `/aws/codebuild/<projeto>-avaliar-atendimento-juiz` NÃO é — tem retenção própria e continua existindo até expirar ou ser apagado manualmente. O bucket S3 do golden set e dos resultados também precisa ser esvaziado manualmente antes do destroy: bucket com objeto residual não é removido, e o Terraform não avisa isso com clareza no plano.
Resumo: problema, peça e motivo
| Problema | Peça | Motivo |
|---|---|---|
| Golden set determinístico do L82 não serve para texto de geração aberta | golden set com critérios explícitos, sem resposta exata de gabarito | captura tom, precisão factual e adequação — o que uma regra de `contains` não alcança |
| Promoção decidida por impressão de quem leu alguns exemplos | Bedrock Evaluation Job (LLM-as-judge) bloqueante no CI | reprova mecanicamente antes de qualquer cliente ver a versão nova |
| Média geral pode esconder um critério péssimo | gate por critério individual no Athena, não só nota agregada | o mesmo padrão do L78 (segmento mascarado pela média), aplicado a texto |
| "O juiz é um LLM, então é objetivo" é um erro de raciocínio comum | consulta dedicada de viés (comprimento, mesmo-modelo) | o juiz é outro sistema de ML, e viés não medido é viés presumido ausente |
| Resultado sem rastro impede auditoria depois do fato | S3 com resposta bruta, nota por critério e justificativa por caso | score final sozinho não explica POR QUE o juiz decidiu assim |
- Alguém propõe mudar o prompt de atendimento por pull request, com casos novos no golden set quando necessário.
- O CodePipeline dispara o estágio AvaliarComJuiz antes de qualquer promoção.
- O Bedrock Evaluation Job gera a resposta de cada caso e pede ao juiz uma nota estruturada por critério explícito.
- O Athena agrega por critério — não só a média — e mede o viés do próprio juiz.
- Abaixo do piso em qualquer critério, o pipeline para — a versão anterior continua ativa.
- Acima do piso em todos os critérios, CreatePromptVersion grava a versão nova.
- A API lê a versão aprovada, e a resposta chega ao chat testada por dois golden sets: o determinístico do L82 e o julgado deste laboratório.
Perguntas frequentes
❓ Por que o golden set determinístico do L82 não serve para o assistente de atendimento?
❓ Um LLM como juiz não é mais objetivo do que uma pessoa lendo por impressão?
❓ Por que o gate exige nota mínima por critério, e não só a média geral?
❓ É seguro usar o mesmo modelo como gerador e como juiz?
❓ O que acontece se o juiz falhar ao pontuar um caso, por exemplo com erro de formato?
❓ Quantos casos o golden set deste laboratório precisa ter?
❓ Este laboratório substitui o golden set determinístico do L82?
Fixando
Depois de injetar uma mudança de prompt que faz o assistente afirmar uma "garantia estendida de 90 dias" inexistente, a nota agregada dos três critérios cai de 8,70 para 7,63 — ainda acima de um limiar de média de 7,5. O critério `nao_inventa_politica`, isoladamente, cai para 5,2, com 30% dos casos abaixo do piso de 6,0. O que um gate que checasse SÓ a nota agregada faria?
A suíte roda o mesmo golden set duas vezes: uma com o modelo gerador e o modelo-juiz da mesma família, outra com famílias diferentes. A nota média sobe 0,9 ponto na primeira execução, sem nenhuma mudança real na qualidade das respostas geradas. Qual é a interpretação correta desse resultado?
Conhecimentos, próximo módulo e documentação
| Item | Conteúdo |
|---|---|
| Conhecimentos anteriores necessários | L78 (avaliação de negócio ligada a número, não só métrica de ML, e o padrão de segmento mascarado pela média), L82 (prompt como arquivo, golden set determinístico, pipeline com estágio de teste bloqueante) |
| Conhecimentos adquiridos | golden set com critérios explícitos para geração aberta; Bedrock Evaluation Job (LLM-as-judge); gate por critério individual, não só média agregada; medição de viés de comprimento e de auto-preferência do próprio avaliador |
| Limitação que fica | o juiz avalia contra critérios que alguém escreveu — um critério importante nunca escrito não é pego pelo juiz, mesmo com toda a auditoria de viés deste laboratório |
| Próximo exemplo recomendado | L100 — Projeto final: plataforma .NET 8 + AWS + IA. Integra a suíte de avaliação construída aqui como parte de um sistema completo, com revisão Well-Architected e DR ensaiado |
| Também habilitado por este módulo | o padrão "golden set + juiz + auditoria de viés do próprio juiz" se aplica a qualquer outro assistente de geração aberta que a Cadência construir — vendas, suporte técnico, qualquer texto sem gabarito exato |
| Data da última validação técnica | 8 de agosto de 2026 |
Documentação oficial consultada: Amazon Bedrock — Model evaluation (CreateEvaluationJob, GetEvaluationJob, avaliação automática com LLM-as-judge); AWS Glue Data Catalog e Amazon Athena (schema sobre resultado em S3, funções agregadas incluindo `CORR`); e AWS CodePipeline e AWS CodeBuild. Nenhum valor em dólar aparece neste módulo por decisão: os números de nota, piso e correlação são medições do cenário de exemplo da Cadência, e os IDs de modelo citados mudam com o catálogo do Bedrock — confira o console para os modelos e o preço atuais.
O que não foi verificado, e você deve conferir na sua conta
O piso de 6,0 por critério, a tolerância de 10% de casos abaixo dele, e os números de viés (correlação 0,62/0,18, diferença de 0,9 ponto) são calibrações de exemplo para o golden set de 60 casos da Cadência, não constantes universais do Bedrock. Um catálogo de política mais amplo, ou um juiz de outra versão, provavelmente exige recalibrar os dois limiares. Os IDs de modelo citados (`claude-3-5-haiku`, `claude-3-5-sonnet`) são ilustrativos do padrão de prefixo de provedor já usado pelo L81 — confira no console do Bedrock quais modelos estão disponíveis na sua região antes de fixar um valor em código.
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…