5.4 KiB
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 campoerroré nulo/vazio.DEGRADED: Campo de texto contém string não-vazia após normalização, porém campoerrornã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"