Pular para o conteúdo

ADR-0003: Harness de avaliação

  • Status: Accepted
  • Data: 2026-03-18
  • Responsáveis pela decisão: Waldemar Szemat

O harness de avaliação é o centro deste projeto. O agente é o veículo; o harness é o artefato. Um leitor tem que sair convencido de que o harness é real: ele carrega datasets golden em JSONL, executa o agente de ponta a ponta, emite traces por turno, pontua esses traces ao longo de um conjunto de dimensões de avaliação determinísticas e apoiadas pelo juiz e produz um veredito que bloqueia PRs mais um relatório de formato mais longo.

Nenhuma das “plataformas de avaliação de agentes” de prateleira cobre todas essas dimensões para um agente multi-turno do domínio de saúde. O DeepEval contribui com uma métrica de alucinação sólida; um LLM-como-juiz da Anthropic Claude Haiku pontua as dimensões baseadas em rubrica (fundamentação, fidelidade, tom e empatia); o Phoenix dá um backend OTel com UI de tracing; o Promptfoo é o runner canônico de red-team / OWASP LLM Top 10. Um núcleo artesanal em pytest que orquestra essas peças é a menor quantidade de cola que entrega cada dimensão enquanto permanece portável.

Como estruturamos o harness de avaliação de modo que (a) ele rode como um job pytest normal em CI, (b) avaliadores determinísticos bloqueiem cada PR de forma barata, (c) o LLM-como-juiz rode todas as noites sem estourar o orçamento do nível gratuito, (d) os cenários de red-team rodem todas as noites fora de banda e (e) cada avaliador possa ser trocado ou atualizado sem reescrever o runner?

  • Cobertura das dimensões de avaliação com as quais o projeto se compromete
  • Teto de custo do gate de PR: apenas avaliadores determinísticos em cada PR; LLM-como-juiz todas as noites
  • Reprodutibilidade: um contribuidor deve ser capaz de rodar a suíte de avaliação localmente e obter o mesmo veredito que o CI dá
  • Fixar o modelo juiz exatamente (provedor + modelo + versão) para que a pontuação seja estável entre execuções
  • Higiene de licenças: toda biblioteca de avaliador deve ter licença permissiva (Apache 2 / MIT / ELv2 aceitáveis para ferramental)
  • Evitar uma “plataforma de avaliação de IA” SaaS caixa-preta; o harness tem que ser portável e auto-hospedado
  • Núcleo artesanal em pytest + DeepEval + um LLM-como-juiz da Anthropic + Promptfoo + Phoenix com um modelo Anthropic Claude Haiku fixado como o juiz (escolhida)
  • Um SaaS de fornecedor (Braintrust / Galileo / LangSmith Eval)
  • DeepEval puro como o harness inteiro, com seus runners embutidos de dataset e relatório
  • OpenAI Evals como o runner

Opção escolhida: núcleo artesanal em pytest orquestrando DeepEval, um LLM-como-juiz da Anthropic, Promptfoo e Phoenix, com um modelo Anthropic Claude Haiku fixado como o juiz LLM (id do modelo atrás de uma flag de ambiente, versão fixada). O harness tem três workflows:

  • Bloqueio de PR: apenas avaliadores determinísticos (cobertura de citação, correção de citação, correspondência de template de recusa, correspondência de lista de escalonamento, recall de recuperação). Não exigem LLM nem chave de API, então o gate é barato e totalmente reproduzível. Os limiares de corpus apoiados pelo juiz são avaliados no workflow noturno do juiz, não no gate de PR.
  • LLM-como-juiz noturno (agendado): o juiz fixado Anthropic Claude Haiku pontua as dimensões baseadas em rubrica (fundamentação, fidelidade e as rubricas de tom / empatia / adequação médica), e o DeepEval contribui com sua métrica de alucinação. Este é o único workflow que gasta tokens do juiz.
  • Red-team (workflow separado): duas camadas. (a) Um gate de CI determinístico e sem chaves — uma avaliação Promptfoo dos 13 casos adversariais feitos à mão; o shim conduz o agente LangGraph real usando um cliente stub offline; a camada de guardrail do agente decide, não o LLM. (b) Uma medição ao vivo separada e com chaves — uma execução de red-team do Promptfoo com Groq llama-3.3-70b-versatile como alvo, OpenAI gpt-4o como gerador de ataque e Groq como avaliador. Não bloqueante; falhas reais são esperadas e documentadas com procedência.

O Phoenix é o sink de observabilidade durante as execuções de avaliação: cada turno emite spans OTel pela fiação OpenInference existente do projeto (ver ADR-0006), o Phoenix os coleta, e o harness anexa as URLs de trace do Phoenix ao relatório de avaliação. O Inspect AI (UK AISI) está reservado como uma tarefa bônus de avaliação de capacidades, opcional para o milestone inicial.

Esta composição dá a cada dimensão de avaliação um lar concreto, mantém o gate de PR barato e nunca depende de uma plataforma de avaliação fechada.

  • A suíte de avaliação roda o subconjunto de bloqueio de PR localmente e em CI; o job de CI falha nas violações de limiar configuradas
  • Todo avaliador é implementado atrás de um pequeno Protocol Scorer; o runner não importa bibliotecas de avaliador diretamente
  • O provedor do juiz é a Anthropic e o id do modelo juiz é lido de uma variável de ambiente JUDGE_MODEL; o juiz ao vivo é construído com essa variável vazia, de modo que um id digitado errado recai no valor padrão fixado Claude Haiku do adaptador (falha fechada) em vez de falhar aberto diante de uma string de modelo inválida
  • Um relatório de red-team noturno é publicado como um artefato

O juiz avalia cinco dimensões de rubrica específicas de features quando um caso golden carrega tags de feature em seus metadados. As features são: voice, i18n (internacionalização), pii (redação de PII), governance (cobertura regulatória) e data_layer (controle de chaves da camada de dados / exibição de custo).

  • Um conjunto de templates de rubrica de feature define as cinco descrições de rubrica de feature, cada uma com seus próprios critérios de pontuação graduados.
  • O avaliador de fundamentação estende condicionalmente sua rubrica com entradas de feature quando um caso carrega metadados de feature. Casos sem metadados de feature produzem pontuação idêntica à baseline.
  • As chaves de pontuação de feature seguem o padrão feature_{name} (por exemplo, feature_voice, feature_i18n).
  • Um gate de CI de cobertura de features verifica que todas as cinco categorias de feature tenham ao menos um caso golden e que nenhuma dimensão de feature retorne uma justificativa malformada em todos os casos (detecção de malformação). Pontuações zero legítimas com justificativas não malformadas não são sinalizadas.

Calibração do juiz (gate de concordância humano-vs-juiz)

Seção intitulada “Calibração do juiz (gate de concordância humano-vs-juiz)”

Um juiz LLM só é confiável na medida em que concorda com um especialista humano. Por isso o arcabouço inclui um gate de calibração: um conjunto reservado de casos rotulados por humanos é pontuado tanto por um especialista de domínio quanto pelo juiz, e a concordância entre eles é medida por dimensão. O gate é consultivo por padrão - reporta a concordância e nunca bloqueia um PR normal - mas no trilho de CI que exige, ele fica armado em fail-closed sobre as duas dimensões de segurança, escalonamento e autolesão, de modo que um juiz que se desvia da concordância com os rótulos humanos em uma dimensão de segurança bloqueia o trilho de lançamento em vez de pontuá-la errado em silêncio. As dimensões restantes (fundamentação, fidelidade, estabilidade de persona) calibram em modo consultivo. O gate é determinístico e sem chaves na CI; o ponto de operação da concordância e o protocolo de rotulagem são calibrados por implantação e entregues como parte do serviço contratado.

Isso fecha a lacuna que a maioria dos arcabouços de LLM-como-juiz deixa aberta: transforma “o juiz pontuou alto” em “o juiz concorda com nosso especialista o suficiente para ser confiável nas dimensões que decidem a segurança.”

  • Cada dimensão de avaliação é produzida por um avaliador nomeado atrás de um único Protocol Scorer, de modo que os avaliadores podem ser trocados ou atualizados de forma independente
  • O gate de PR é barato e determinístico o suficiente para rodar a cada push sem queimar cotas do nível gratuito
  • O LLM-como-juiz permanece noturno e usa um Claude Haiku fixado, o modelo Anthropic de menor custo por token que ainda pontua bem em rubricas de tom / empatia
  • O Phoenix auto-hospedado dá um backend OTel real sem pressão de cota; sua licença ELv2 é aceitável para este caso de uso
  • A suíte OWASP LLM Top 10 do Promptfoo cobre uma superfície de red-team que o DeepEval não cobre, fixada a um catálogo de ataques público
  • O harness é portável: sem lock-in de SaaS, toda dependência é de código aberto
  • O juiz é calibrado contra rótulos humanos: um gate de concordância por dimensão bloqueia o trilho de lançamento se o juiz se desviar da concordância em uma dimensão de segurança (escalonamento ou autolesão)
  • Três bibliotecas de avaliação externas significam três trilhas de atualização; mitigamos fixando versões minor
  • O núcleo artesanal é código real que mantemos; ele justifica seu custo ao nos dar controle total sobre limiares e formato de relatório
  • As chamadas ao juiz Anthropic Haiku são cobradas; a cadência noturna mais um pequeno teto de tokens as mantêm dentro do envelope de $0/mês
  • O harness emite dois artefatos por execução, um relatório JSON legível por máquina e um resumo em Markdown
  • O Inspect AI está reservado como uma tarefa opcional de avaliação de capacidades; o milestone inicial não depende dele
  • O Phoenix e o Promptfoo rodam em perfis Docker, não no arquivo Compose principal, para manter pequena a imagem da demo ao vivo

Núcleo artesanal em pytest + DeepEval + um juiz da Anthropic + Promptfoo + Phoenix

Seção intitulada “Núcleo artesanal em pytest + DeepEval + um juiz da Anthropic + Promptfoo + Phoenix”
  • Boa, porque cada peça é a melhor da categoria em sua fatia (métrica de alucinação / juiz com pontuação por rubrica / backend OTel / red-team)
  • Boa, porque o pytest já é o harness de testes do projeto
  • Boa, porque todo avaliador é trocável atrás de um Protocol
  • Ruim, porque várias partes móveis têm que ser mantidas

Um SaaS de fornecedor (Braintrust / Galileo / LangSmith Eval)

Seção intitulada “Um SaaS de fornecedor (Braintrust / Galileo / LangSmith Eval)”
  • Boa, porque a história do dashboard é excelente de imediato
  • Ruim, porque o projeto precisa rodar com zero contas
  • Ruim, porque as definições de avaliação vivem na UI de outra pessoa
  • Boa, porque a métrica de alucinação do DeepEval é sólida e bem suportada
  • Ruim, porque não cobre por si só as dimensões do juiz com pontuação por rubrica (fundamentação, fidelidade, tom) nem a superfície de red-team do Promptfoo
  • Boa, porque o formato é bem conhecido
  • Ruim, porque o runner é centrado em OpenAI e não mapeia de forma limpa para avaliações de agentes multi-turno