feat: stemming português no BM25 e índice lexical sobre o versículo
Dois defeitos medidos no índice real (31.098 versículos), ambos na metade
lexical da busca híbrida:
1. Sem normalização morfológica, 'amar' da pergunta nunca casava com 'amai' ou
'amarás' do versículo. Para 'o que Jesus disse sobre amar os inimigos?',
Mateus 5:44 ficava em 434º no BM25 enquanto Marcos 12:34 liderava por casar
apenas 'jesus'+'disse'. keyword.py ganha um stemmer de sufixos em etapas
(estilo RSLP, sem dependência externa) com guarda de comprimento mínimo do
radical — sem ela 'deus' viraria 'd' e 'mar' viraria 'm'. Rank de Mt 5:44: 12º.
2. O BM25 indexava a janela de contexto. Os dois lados querem granularidades
opostas: a janela dá tema ao embedding, mas multiplica os termos incidentais
que o BM25 pontua. Indexando o versículo isolado, Mt 5:44 vai a 1º e os
achados só-lexicais deixam de ser aleatórios ('ansioso e não consigo dormir'
-> Jó 3:13 'teria dormido'; 'não sei que decisão tomar' -> Joel 3:14 'vale da
decisão').
Colisão conhecida do stemming: 'luto' e 'lutavam' reduzem ao mesmo radical.
This commit is contained in:
1 parent
957c73b09e
commit
8f5e098d8f
5 files changed
+226
-15
No files matched your search
@@ -3,6 +3,42 @@
|
||||
**Data:** 2026-11-01
|
||||
**Status:** Proposed
|
||||
|
||||
> ## Atualização (2026-11-02): ingestão por corpus estruturado
|
||||
>
|
||||
> As seções que descrevem **PDF → OCR → parser de índice → reconstrução de
|
||||
> capítulo/versículo** foram substituídas. O resto do desenho (FastAPI, ChromaDB,
|
||||
> validação de citações, SSE, Docker Compose, provedores de LLM) segue válido.
|
||||
>
|
||||
> **O que mudou:** a entrada passou a ser XML [USFX](https://ebible.org/usfx/) em
|
||||
> domínio público (`corpus/por-almeida.usfx.xml`, Almeida, 66 livros, 31.098
|
||||
> versículos), versionado no repositório.
|
||||
>
|
||||
> **Por quê:** o PDF exigia OCR das 3.364 páginas e a camada textual é corrompida,
|
||||
> então cada referência era *reconstruída* a partir de texto ruidoso. Com o corpus
|
||||
> estruturado a referência é a coordenada de onde o texto foi lido. Medido:
|
||||
> indexação de 31.098 versículos em ~30 min contra 17–67 min de OCR, sem Tesseract,
|
||||
> sem PyMuPDF e sem cache de páginas.
|
||||
>
|
||||
> **Duas falhas encontradas no caminho**, ambas silenciadas por projeto anterior:
|
||||
> 1. `create_app` criava o `VectorStore` antes do embedder; como o store default
|
||||
> para `HashEmbedder`, o modelo configurado **nunca** era carregado em produção
|
||||
> e a busca rodava sem semântica nenhuma.
|
||||
> 2. `transformers` não estava pinado: a versão 5.x exige `torch>=2.6`, e o
|
||||
> Dockerfile pinava 2.5.1 — o `sentence-transformers` desativava o PyTorch e o
|
||||
> fallback silencioso caía no mesmo `HashEmbedder`.
|
||||
>
|
||||
> `/api/status` agora reporta o embedder **em uso** (não o do `.env`) e qualquer
|
||||
> fallback aparece em `errors`.
|
||||
>
|
||||
> **Busca:** passou a híbrida (vetorial + BM25, fusão por RRF) e cada chunk indexa o
|
||||
> versículo com uma janela de vizinhos. Medido em 5.703 versículos reais: a busca
|
||||
> puramente vetorial não liga "estou com medo do futuro" a "não temas, porque eu sou
|
||||
> contigo" (similaridade 0,19, no nível de um par sem relação), enquanto acerta
|
||||
> "amar os inimigos" → Mateus 5:44 (0,683). Os dois lados erram de modos diferentes.
|
||||
> `intfloat/multilingual-e5-small` foi descartado apesar de treinado para
|
||||
> recuperação: a faixa de similaridade dele tem 0,02 de largura (0,853–0,873), o que
|
||||
> inutilizaria o piso de evidência do qual a garantia de fidelidade depende.
|
||||
|
||||
## 1. Intenção
|
||||
|
||||
O Pastor Online é uma aplicação web local, containerizada, que lê PDFs da Bíblia,
|
||||
|
||||
Reference in new issue
Block a user