Files

5.4 KiB

Data Model: Deterministic Content Selection

Branch: 004-deterministic-content-selection | Date: 2026-08-20 | Spec: spec.md


1. Domain Entities & Value Types

classDiagram
    class ExtractorName {
        <<enumeration>>
        TRAFILATURA = "trafilatura"
        NEWSPAPER4K = "newspaper4k"
        READABILITY = "readability"
    }

    class CandidateStatus {
        <<enumeration>>
        USABLE
        DEGRADED
        UNAVAILABLE
    }

    class ExtractorCandidate {
        +ExtractorName name
        +str raw_text
        +str error
        +CandidateStatus status
        +List~str~ tokens
        +Set~Tuple~ shingles
        +int shingle_count
        +float coverage
        +float support
        +float score
    }

    class ArticleSelectionResult {
        +int article_index
        +ExtractorName selected_extractor
        +str selection_reason
        +int active_candidates_count
        +int consensus_shingles_count
        +Dict~ExtractorName, ExtractorCandidate~ candidates
    }

    class BatchProcessingResult {
        +int total_articles
        +int processed_count
        +Dict~str, int~ selection_distribution
        +str input_file
        +str output_file
    }

    ExtractorCandidate --> ExtractorName
    ExtractorCandidate --> CandidateStatus
    ArticleSelectionResult --> ExtractorName
    ArticleSelectionResult --> ExtractorCandidate
    BatchProcessingResult --> ArticleSelectionResult

2. Entity Descriptions & Fields

ExtractorName (Enum / Literal)

Enumeração estrita com os três motores de extração suportados:

  • "trafilatura"
  • "newspaper4k"
  • "readability"

CandidateStatus (Enum)

Classificação do estado de cada extrator em um dado artigo:

  • USABLE: Campo de texto contém string não-vazia após normalização e campo error é nulo/vazio.
  • DEGRADED: Campo de texto contém string não-vazia após normalização, porém campo error não é nulo.
  • UNAVAILABLE: Campo de texto é ausente, nulo, tipo diferente de string ou vazio após normalização.

ExtractorCandidate (Dataclass)

Representação estruturada de um candidato durante o cálculo:

Campo Tipo Descrição
name ExtractorName Identificador do motor de extração (trafilatura, newspaper4k, readability).
raw_text str | None Texto bruto obtido do campo correspondente no JSON (trafilatura.text, newspaper4k.text, readability.cleaned_text).
error str | None Mensagem de erro do motor, se houver (trafilatura.error, etc.).
status CandidateStatus Estado de viabilidade do candidato (USABLE, DEGRADED, UNAVAILABLE).
tokens list[str] Sequência ordenada de tokens alfanuméricos minúsculos após normalização NFKC.
shingles set[tuple[str, ...]] Conjunto de n-grams consecutivos de 5 tokens (ou 1 n-gram se 1 \le \text{tokens} \le 4).
shingle_count int Quantidade total de shingles gerados (len(shingles)).
coverage float Proporção de shingles do consenso presentes no candidato ([0.0, 1.0]).
support float Proporção de shingles do candidato que pertencem ao consenso ([0.0, 1.0]).
score float Pontuação F_1 baseada em cobertura e suporte ([0.0, 1.0]).

ArticleSelectionResult (Dataclass)

Resultado detalhado da avaliação para um único artigo:

Campo Tipo Descrição
article_index int Posição ordinal do artigo no array articles original (0-indexed).
selected_extractor ExtractorName Vencedor da seleção determinística (trafilatura, newspaper4k, readability).
selection_reason str Justificativa rastreável da escolha (ex: "highest_score", "technical_tie_smallest_shingles", "no_consensus_median_shingles", "single_usable_candidate", "fallback_all_unavailable").
active_candidates_count int Número de candidatos que formaram o conjunto ativo avaliado.
consensus_shingles_count int Quantidade de shingles no conjunto de consenso.
candidates dict[ExtractorName, ExtractorCandidate] Dicionário com o detalhamento de cada um dos 3 motores.

BatchProcessingResult (Dataclass)

Sumário da execução do lote:

Campo Tipo Descrição
total_articles int Total de artigos encontrados no arquivo de entrada.
processed_count int Total de artigos processados e enriquecidos com sucesso.
selection_distribution dict[str, int] Contagem de seleções por motor ({"trafilatura": X, "newspaper4k": Y, "readability": Z}).
input_file str Caminho do arquivo lido.
output_file str Caminho do arquivo gerado de forma atômica.

3. JSON Schema Mapping

Entrada

  • Raiz: Objeto contendo chave articles: list[dict].
  • Cada item em articles:
    • trafilatura (objeto opcional): { "text": str | null, "error": str | null, ... }
    • newspaper4k (objeto opcional): { "text": str | null, "error": str | null, ... }
    • readability (objeto opcional): { "cleaned_text": str | null, "error": str | null, ... }

Saída

  • Mesma estrutura exata da entrada, preservando 100% dos dados anteriores e ordem da lista articles.
  • Em cada item de articles, adição/atualização da chave:
    "selected_extractor": "newspaper4k" | "readability" | "trafilatura"