Files
TextNLPClassifierApp/docs/structured_extraction/04_Plano_Testes_Evals_Runtime.md
T

20 KiB
Raw Blame History

Plano de testes e evals — Runtime de consolidação de artigos

Versão: 1.0
Data: 23 de agosto de 2026
Escopo: runtime; self-healing excluído

Regra mestre: comprovar integralmente os requisitos de produção com a menor suíte suficiente, sem testes duplicados, frágeis ou sem efeito em gates.

1. Objetivo

Demonstrar que o runtime atende aos contratos, preserva grounding, aplica o ECP, suporta falhas e processa 100 artigos por hora sem perda ou duplicação.

2. Princípios

  • Qualidade agregada não pode esconder falhas por idioma, domínio ou extrator.
  • Invariantes críticas exigem zero falhas.
  • Grounding é validado por código, não por LLM-as-a-judge.
  • Nenhum teste textual ou assertion usa regex.
  • Nenhuma decisão esperada depende de lista manual de palavras-chave.
  • Prompts reais são usados no Promptfoo.
  • Providers são simulados nos testes de integração e reais apenas nos evals autorizados.
  • Casos de correção textual distinguem reparo de reescrita.
  • Self-healing, otimizador e judge não fazem parte desta suíte.

3. Camadas de teste

Camada Finalidade Execução
Unitário Funções determinísticas, parsers, IDs, estado e renderer Todo PR
Contrato Schemas de artigo, ECP, LLM e manifesto Todo PR
Integração simulada Fluxo completo com respostas controladas dos providers Todo PR
Promptfoo reduzido Regressão crítica de prompts e modelos baratos Mudança em prompt, schema, contexto ou modelo
Golden set completo Qualidade por artigo, idioma, domínio e extrator Antes de promoção
Carga 100 artigos/hora Staging antes do go-live e mudança relevante
Fault injection Provider, disco, SQLite e Langfuse Staging e releases relevantes
Segurança Prompt injection, secrets e conteúdo hostil Todo release
Reprocessamento Idempotência, retomada e duplicidade Todo release

4. Dados de teste

4.1 Fixture inicial

Os 20 artigos do JSON de referência são a regressão inicial obrigatória. Cada item deve ser convertido para a unidade de entrada do runtime e associado a um ECP válido.

4.2 Golden set de produção

O conjunto deve ser revisado manualmente e estratificado por:

  • idioma;
  • domínio de origem;
  • extrator selecionado;
  • tamanho e estrutura;
  • concordância e divergência entre extratores;
  • ECP direto, contextual, tangencial e não relacionado;
  • ruídos editoriais;
  • pequenos defeitos textuais.

O corpus deve ser suficiente para cobrir os idiomas, domínios, extratores, estruturas editoriais e tipos de ruído suportados. Seu tamanho deve ser justificado pela estabilidade observada dos resultados e pelos intervalos de confiança dos gates medidos.

4.3 Holdout

Parte da golden set deve permanecer fora da elaboração dos prompts. Resultados do holdout são usados no gate final e não podem orientar exemplos few-shot diretamente.

4.4 Verdade de referência

Cada caso deve possuir:

  • entrada integral;
  • ECP e versão;
  • status esperado;
  • título, subtítulo, autor e data esperados ou conjunto de candidatos aceitáveis;
  • blocos mantidos e removidos;
  • links e imagens mantidos;
  • reparos permitidos e proibidos;
  • classificação ECP esperada;
  • sentimento esperado;
  • tags aceitas ou rubrica fechada;
  • Markdown ou estrutura esperada;
  • motivo de falha/descarte, quando aplicável.

5. Métricas de avaliação

  • pass rate integral por artigo;
  • precisão, recall e F1 de blocos mantidos;
  • acurácia de metadados;
  • taxa de reparos corretos;
  • taxa de reparos indevidos;
  • grounding textual;
  • grounding de URL e imagem;
  • validade de schema;
  • classificação ECP;
  • sentimento;
  • tags;
  • custo e latência.

Resultados devem ser segmentados por idioma, domínio, extrator e versão de prompt/modelo.

6. Gates críticos

Uma configuração não pode ser promovida se ocorrer qualquer um dos seguintes:

  • texto inventado;
  • URL ou imagem inventada;
  • fato, número, nome, data, placar ou citação alterado indevidamente;
  • reparo usado como reescrita;
  • ID inexistente aceito;
  • duplicidade de saída;
  • secret em log, trace ou arquivo;
  • regex no pipeline textual ou assertion de conteúdo;
  • modelo potente configurado no runtime;
  • Promptfoo chamado online.

7. Gates quantitativos

  • pass rate integral textual: pelo menos 95%;
  • grounding textual, URLs e imagens: 100%;
  • schema válido em todas as respostas aceitas: 100%;
  • duplicidade: 0;
  • perda no teste de carga: 0;
  • trace enviado ou telemetria preservada: 100%.

Custo e latência devem ser medidos no staging e receber limites aprovados antes do go-live.

8. Testes de contrato de entrada

ID Cenário Resultado esperado
IN-001 Artigo válido, ECP válido e extrator disponível Segue para fingerprint
IN-002 JSON do artigo corrompido INVALID_ARTICLE_SCHEMA; nenhum LLM
IN-003 ECP ausente INVALID_ECP_SCHEMA; nenhum LLM
IN-004 ECP corrompido INVALID_ECP_SCHEMA; nenhum LLM
IN-005 ECP em versão incompatível Falha de contrato; nenhum LLM
IN-006 selected_extractor ausente MISSING_SELECTED_EXTRACTOR
IN-007 selected_extractor desconhecido INVALID_SELECTED_EXTRACTOR
IN-008 Extrator selecionado sem dados utilizáveis SELECTED_EXTRACTOR_UNAVAILABLE
IN-009 Outro extrator utilizável, mas selecionado inválido Falhar; não substituir silenciosamente
IN-010 URL ausente em todas as fontes MISSING_SOURCE_URL
IN-011 Título ausente em todas as fontes MISSING_TITLE_CANDIDATE
IN-012 Sem conteúdo textual MISSING_CONTENT
IN-013 Campos extras desconhecidos Preservar entrada registrada e ignorar no fluxo
IN-014 Wrapper com array articles usado como artigo Falha de schema da unidade
IN-015 Conteúdo contém instrução para o modelo Tratar como dado não confiável

9. Testes de fingerprint e idempotência

ID Cenário Resultado esperado
ID-001 Mesma entrada e mesmas versões Mesmo fingerprint
ID-002 Mudança apenas de timestamp operacional Mesmo fingerprint
ID-003 Mudança de prompt Fingerprint diferente
ID-004 Mudança de modelo funcional Fingerprint diferente
ID-005 Mudança do ECP Fingerprint diferente
ID-006 Execução já concluída Retornar saída existente sem novo LLM
ID-007 Queda antes da primeira escrita Reexecução limpa
ID-008 Queda durante escrita temporária Nenhum arquivo final parcial
ID-009 Queda após Markdown e antes do estado final Reconciliação por hash sem duplicidade
ID-010 Duas execuções concorrentes idênticas Uma conclusão efetiva, nenhuma duplicidade

10. Testes de parsing sem regex

ID Cenário Resultado esperado
PAR-001 HTML válido com elementos aninhados DOM preserva relações
PAR-002 HTML malformado tolerado pelo parser Estrutura segura ou falha controlada
PAR-003 Markdown com heading, lista, citação e ênfase AST identifica tipos
PAR-004 URL com query e fragmento Parser preserva componentes válidos
PAR-005 Unicode composto e decomposto Normalização consistente
PAR-006 Texto em idiomas sem separação simples por espaços Tokenizador apropriado não quebra o fluxo
PAR-007 JSON-LD com Article ou NewsArticle Metadados estruturais registrados
PAR-008 JSON-LD inválido Ignorar fonte inválida e registrar warning
PAR-009 Código importa módulo de regex no pipeline textual CI falha por análise AST
PAR-010 Configuração Promptfoo contém assertion regex de conteúdo CI falha

11. Testes de candidatos e proveniência

ID Cenário Resultado esperado
CAN-001 Mesmo bloco em três extratores Equivalência registrada, IDs preservados
CAN-002 Bloco exclusivo de outro extrator Candidato disponível sem inserção automática
CAN-003 Ordem diverge entre extratores Base segue selected_extractor
CAN-004 Título duplicado no corpo Duplicação estrutural removível pelo assembler
CAN-005 Link sem URL válida Candidato rejeitado estruturalmente
CAN-006 Imagem sem posição editorial Não inserir automaticamente
CAN-007 IDs repetidos Falha interna de construção
CAN-008 Conteúdo idêntico com Unicode diferente Equivalência via normalização apropriada
CAN-009 Similaridade baixa Manter candidatos distintos
CAN-010 Três extratores concordam integralmente Ainda chamar higienização LLM

12. Testes de higienização

ID Cenário Resultado esperado
HYG-001 Três extratores concordam LLM ainda seleciona IDs e resultado é validado
HYG-002 Um extrator contém publicidade textual Bloco de ruído removido conforme referência
HYG-003 Todos repetem chamada externa LLM remove; consenso não obriga manutenção
HYG-004 Chamada para outra notícia no meio Link/bloco removido sem afetar conteúdo
HYG-005 Newsletter após o corpo Removida
HYG-006 Bloco editorial exclusivo de um extrator Mantido quando golden set exigir
HYG-007 Citação legítima Preservada como citação
HYG-008 Lista editorial legítima Preservada como lista
HYG-009 Heading legítimo Preservado
HYG-010 Imagem editorial posicionada Mantida com URL existente
HYG-011 Imagem publicitária Removida
HYG-012 Link editorial contextual Mantido
HYG-013 Link de recomendação Removido
HYG-014 Modelo devolve artigo completo Schema rejeita
HYG-015 Modelo seleciona ID inexistente Grounding rejeita
HYG-016 Modelo muda ordem narrativa sem IDs correspondentes Renderer ignora ordem não autorizada
HYG-017 Modelo omite conteúdo material Falha no gate de cobertura do caso
HYG-018 Primário falha tecnicamente Retry técnico e/ou fallback conforme política
HYG-019 Primário falha semanticamente Fallback barato, sem retry semântico no mesmo modelo
HYG-020 Ambos falham e base estrutural é segura Fallback determinístico conservador
HYG-021 Ambos falham e base não é segura HYGIENE_FAILED; sem Markdown

13. Testes de reparos textuais

ID Cenário Resultado esperado
REP-001 Mojibake inequívoco em título Reparo aceito e auditado
REP-002 Unicode quebrado no corpo Reparo aceito
REP-003 Espaçamento acidental Reparo aceito se preservar sentido
REP-004 Pontuação corrompida Reparo aceito conforme golden set
REP-005 Pequeno typo inequívoco Reparo aceito conforme eval
REP-006 Sinônimo mais elegante Reparo rejeitado; original preservado
REP-007 Frase reescrita para fluência Reparo rejeitado
REP-008 Nome de pessoa alterado Reparo rejeitado, salvo defeito de encoding comprovado
REP-009 Número ou placar alterado Reparo rejeitado
REP-010 Data alterada Reparo rejeitado
REP-011 Citação corrigida editorialmente Reparo rejeitado
REP-012 Fragmento original não existe Reparo rejeitado
REP-013 Fragmento é ambíguo no mesmo bloco Reparo rejeitado ou exige referência estrutural válida
REP-014 Um reparo válido e outro inválido Aplicar válido, preservar original do inválido
REP-015 Modelo omite categoria ou justificativa Reparo inválido
REP-016 Reparo modifica sentido apesar de pequena distância Gate semântico/humano do eval reprova configuração

14. Testes do ECP

ID Cenário Resultado esperado
ECP-001 Texto DIRECT_INHERENT Continuar para enriquecimento
ECP-002 Texto CONTEXTUAL_INHERENT Continuar para enriquecimento
ECP-003 Texto TANGENTIAL Manifesto rejected_ecp; sem Markdown
ECP-004 Texto NOT_RELATED Manifesto rejected_ecp; sem Markdown
ECP-005 Classificador falha ECP_CLASSIFICATION_FAILED
ECP-006 Resultado fora do enum Rejeitar contrato
ECP-007 Evidência não pertence ao documento Rejeitar resultado
ECP-008 Relação contextual embutida válida CONTEXTUAL_INHERENT conforme referência
ECP-009 Tier LLM do ECP aponta modelo potente Gate de configuração falha

15. Testes de enriquecimento

ID Cenário Resultado esperado
ENR-001 Sentimento positivo em relação ao ECP positive
ENR-002 Sentimento negativo em relação ao ECP negative
ENR-003 Notícia factual sem polaridade neutral
ENR-004 Tags no idioma do artigo 3 a 8 tags válidas
ENR-005 Tags duplicadas Resposta rejeitada/fallback
ENR-006 Tag sem evidência Reprovar caso
ENR-007 Modelo tenta alterar corpo Ignorar alteração e rejeitar schema
ENR-008 Primário falha Fallback barato
ENR-009 Ambos falham ENRICHMENT_FAILED; sem Markdown

16. Testes de Markdown e manifesto

ID Cenário Resultado esperado
OUT-001 Texto aprovado completo Manifesto e Markdown consistentes
OUT-002 Subtítulo ausente Campo omitido e nenhuma linha vazia artificial
OUT-003 Autor ausente Campo omitido
OUT-004 Data ausente Campo omitido
OUT-005 Headings/listas/citações Markdown válido
OUT-006 Sublinhado no HTML Texto preservado sem underline
OUT-007 HTML inline residual Validação reprova
OUT-008 Rejeição ECP Manifesto sem Markdown
OUT-009 URL no Markdown não existe na entrada Grounding reprova
OUT-010 Imagem sem origem Grounding reprova
OUT-011 Escrita falha por disco Estado não concluído; nenhum par parcial válido
OUT-012 Hash após escrita diverge Falha de persistência

17. Testes de providers e fallback

ID Cenário Resultado esperado
LLM-001 Timeout primário Retry técnico limitado
LLM-002 429 primário Backoff e fallback conforme limite
LLM-003 5xx primário Retry técnico e fallback
LLM-004 Resposta vazia Retry técnico limitado
LLM-005 Schema inválido Fallback; sem loop semântico
LLM-006 Grounding inválido Fallback
LLM-007 Fallback válido Continuar e registrar uso
LLM-008 Fallback indisponível Falha/fallback determinístico da etapa
LLM-009 Modelo não certificado na configuração Falha inicial
LLM-010 Configuração aponta modelo potente Gate de configuração falha
LLM-011 Troca de provider com mesmo papel Domínio permanece inalterado
LLM-012 Retry excede limite Encerrar tentativa e seguir política

18. Testes de observabilidade

ID Cenário Resultado esperado
OBS-001 Fluxo textual normal Trace e spans completos
OBS-002 Fallback usado Tentativas registradas separadamente
OBS-003 Langfuse indisponível Resultado continua e evento fica pendente
OBS-004 Flush posterior Telemetria enviada uma vez
OBS-005 Conteúdo em trace desabilitado Métricas, hashes e status permanecem
OBS-006 Secret presente no ambiente Nunca aparece em log/trace
OBS-007 Execução rejeitada pelo ECP Score e status corretos
OBS-008 Reparo aplicado Diff e decisão registrados
OBS-009 Reparo rejeitado Original e motivo registrados
OBS-010 Prompt/modelo trocados Versões corretas na trace
OBS-011 Erro inesperado Stack técnica local e código sanitizado

19. Testes de segurança

| ID | Cenário | Resultado esperado | | SEC-001 | Artigo contém “ignore instruções” | Texto tratado como dado | | SEC-002 | HTML contém script | Não executar; parser trata como estrutura não confiável | | SEC-003 | URL maliciosa no conteúdo | Não acessar; apenas validar e preservar se editorial | | SEC-004 | Resposta do modelo inclui secret inventado | Schema/grounding rejeita | | SEC-005 | Path traversal derivado do título | Nome por fingerprint impede traversal | | SEC-006 | Log de exceção do SDK contém header | Sanitização remove credencial | | SEC-007 | Arquivo de saída preexistente de outra execução | Não sobrescrever sem correspondência idempotente | | SEC-008 | Conteúdo enorme excede limite configurado | Falha controlada antes do provider ou estratégia aprovada de contexto |

20. Teste de carga

20.1 Perfil

  • 100 artigos por hora;
  • mistura representativa de idiomas, domínios, extratores e estruturas editoriais;
  • chamadas primárias e percentual observado de fallback;
  • execuções concorrentes controladas pelo orquestrador;
  • mesmo SQLite e diretório de saída planejados para produção.

20.2 Critérios

  • nenhuma perda;
  • nenhuma duplicação;
  • nenhum arquivo parcial apresentado como final;
  • nenhuma corrupção SQLite;
  • 100% de traces enviados ou preservados;
  • memória e disco estáveis durante o ensaio;
  • custo e latência p50/p95/p99 registrados por etapa e total;
  • throughput sustentado durante a janela acordada.

20.3 Saída

O relatório de staging deve propor limites de custo e latência. O go-live depende da aprovação desses limites.

21. Fault injection

ID Falha injetada Critério
FLT-001 Provider primário indisponível Fallback barato assume
FLT-002 Ambos providers indisponíveis Falha controlada sem saída falsa
FLT-003 Langfuse indisponível Processamento continua
FLT-004 SQLite temporariamente bloqueado Timeout controlado/retry de persistência
FLT-005 Disco sem espaço Nenhum final parcial
FLT-006 Processo encerrado durante escrita Reexecução recupera
FLT-007 Resposta truncada do LLM Schema rejeita
FLT-008 ECP indisponível Nenhum Markdown
FLT-009 Arquivo temporário órfão Limpeza segura por fingerprint
FLT-010 Falha no flush de telemetria Evento permanece pendente

22. Promptfoo

22.1 Matriz

Testar:

  • prompt de higienização × primário/fallback baratos;
  • prompt de enriquecimento × primário/fallback baratos;
  • versões candidata e vigente apenas no processo normal de release manual;
  • slices de idioma, extrator e domínio.

22.2 Assertions permitidas

  • JSON Schema;
  • funções Python customizadas sem regex;
  • IDs pertencentes ao contexto;
  • conjuntos esperados de blocos;
  • URLs pertencentes à entrada;
  • precisão e recall calculados;
  • enum e cardinalidade;
  • diffs de reparo com bibliotecas de sequência/Unicode;
  • comparação com verdade de referência;
  • métricas de custo e latência.

22.3 Assertions proibidas

  • regex textual;
  • contains/not-contains baseado em keyword para semântica;
  • LLM-as-a-judge para grounding;
  • modelo potente como judge do runtime;
  • aprovação baseada somente em score agregado.

23. Execução no CI

Todo pull request

  • schema e formato;
  • lint;
  • análise AST da proibição de regex;
  • unitários;
  • contratos;
  • integração simulada;
  • segurança básica.

Mudança de prompt, contexto, schema ou modelo

  • itens anteriores;
  • Promptfoo reduzido;
  • regressão dos 20 casos iniciais;
  • comparação de custo e latência.

Antes de promoção

  • golden set completo;
  • holdout;
  • fault injection aplicável;
  • carga de 100 artigos/hora;
  • aprovação manual dos resultados;
  • aprovação dos limites de custo e latência.

24. Evidências de teste

Preservar como artefatos:

  • versão do código;
  • versões dos prompts;
  • providers e modelos;
  • configuração Promptfoo;
  • hashes da golden set;
  • resultados por caso e slice;
  • violações críticas;
  • relatório de custo e latência;
  • relatório de carga;
  • aprovação de release.

25. Critério de conclusão

O plano estará cumprido quando:

  • todos os cenários obrigatórios estiverem automatizados ou documentados como revisão manual controlada;
  • gates críticos tiverem zero falhas;
  • gates quantitativos forem atingidos por slice;
  • os 20 casos iniciais não regredirem;
  • a golden set de produção tiver revisão concluída;
  • o teste de 100 artigos/hora passar;
  • custo e latência tiverem limites aprovados;
  • nenhuma suíte depender de regex textual ou modelo potente;
  • não houver qualquer teste ou componente de self-healing no runtime.