omp 621679cee5 fix: corrige bugs críticos de índice de páginas e cache de OCR
- C-1: corrige índice de páginas OCR'd (retorna page_number em vez de position)
- C-2: adiciona tratamento para falhas de OCR no cache (não distingue erro de não processado)
- Integra paralelização do OCR via subprocessos (parallel.py)
- Indexador usa extração paralela quando disponível
- Melhora relatório de progresso com contagem de páginas processadas
2026-11-01 20:01:28 -03:00
2026-11-01 19:12:42 -03:00

Pastor Online

Sistema web RAG para consulta bíblica. Lê PDFs da Bíblia, indexa o conteúdo em um banco vetorial e responde em chat com um agente pastoral ancorado exclusivamente nos versículos recuperados — com as referências sempre à vista.

Containerizado com Docker Compose: frontend React, backend FastAPI, ChromaDB e (opcionalmente) Ollama local.


Como funciona

./PDF/*.pdf  ──▶  PyMuPDF + OCR (Tesseract)  ──▶  parser bíblico  ──▶  embeddings
                                                                            │
                          navegador  ◀── SSE ──  FastAPI  ◀── busca + validação
                                                                            │
                                                                     ChromaDB

Fidelidade ao texto. A resposta só é gerada quando há evidência recuperada do corpus. As citações são conferidas no servidor contra as fontes consultadas: uma referência que o modelo inventou é removida antes de chegar à tela. Sem evidência, o sistema responde com uma mensagem fixa e não chama o LLM.

Extração. Se a camada textual do PDF é utilizável, ela é usada (rápido). Se o PDF usa fontes sem mapeamento Unicode — caso comum em PDFs de Bíblia digitalizados — o sistema detecta a corrupção e aplica OCR na página. O resultado do OCR é cacheado por página: reindexações não repetem o trabalho.


Requisitos

  • Docker com Compose v2 (ou Podman com podman-compose)
  • ~2 GB de RAM livres para o backend
  • ~1,5 GB de disco para o modelo de embeddings e o banco vetorial

Início rápido

1. Coloque os PDFs

Copie seus PDFs da Bíblia para a pasta ./PDF. O diretório já contém o biblia.pdf desta edição da Almeida Revista e Corrigida.

A pasta ./pdfs (minúscula) também funciona: basta apontar PDF_DIR para ela no docker-compose.yml. O Compose monta ./PDF como somente-leitura em /data/pdfs.

2. Configure o provedor de LLM

cp .env.example .env

Edite o .env. Três caminhos possíveis:

Provedor Configuração Observação
Ollama (local) LLM_PROVIDER=ollama Subir com --profile local; o modelo é baixado na primeira execução
OpenAI LLM_PROVIDER=openai + OPENAI_API_KEY
Groq LLM_PROVIDER=groq + GROQ_API_KEY
Anthropic LLM_PROVIDER=anthropic + ANTHROPIC_API_KEY

3. Suba o sistema

# Com Ollama local:
docker compose --profile local up --build -d

# Sem Ollama (usando OpenAI, Groq ou Anthropic):
docker compose up --build -d

Acesse http://localhost:8080.

4. Acompanhe a indexação

A primeira indexação faz OCR de todas as páginas do PDF — são ~3.400 páginas, e o tempo típico fica entre 15 e 30 minutos em CPU. O painel lateral mostra o progresso (PDFs lidos e vetores indexados) e o chat já responde durante a indexação.

Para acompanhar os logs:

docker compose logs -f backend

Comandos úteis

# Reiniciar só o frontend (após mudanças no React)
docker compose up -d --build frontend

# Forçar a reindexação dos PDFs
curl -X POST http://localhost:8080/api/reindex

# Ver o estado da indexação
curl http://localhost:8080/api/status

# Rodar os testes do backend
docker compose exec backend pytest tests/ -v

# Rodar os testes do frontend
docker compose exec frontend npm test

API

Rota Método Descrição
/api/health GET Saúde do serviço
/api/status GET PDFs lidos, vetores indexados, erros
/api/reindex POST Força a reindexação (202). 409 se já em andamento
/api/chat POST Chat em streaming (SSE)
/api/sources GET Trechos consultados na última resposta

O chat responde em Server-Sent Events:

event: sources
data: {"sources":[{"reference":"Gênesis 1:1","text":"...","page":6}]}

event: token
data: {"text":"No princípio criou Deus os céus e a terra..."}

event: done
data: {"citations":["Gênesis 1:1"]}

O frontend consome o stream com fetch + ReadableStream, porque EventSource não aceita POST.


Configuração

Todas as variáveis ficam no .env. As principais:

Variável Padrão Efeito
LLM_PROVIDER ollama ollama, openai, groq ou anthropic
EMBEDDING_MODEL paraphrase-multilingual-MiniLM-L12-v2 all-MiniLM-L6-v2 é menor e mais rápido
TOP_K 6 Quantos trechos são recuperados por pergunta
MIN_SIMILARITY 0.35 Corte de relevância; acima disso, o sistema responde que o texto não aborda o assunto
OCR_DPI 200 Resolução do OCR
OCR_LANGUAGE por+eng Idiomas do Tesseract
REINDEX_TOKEN vazio Se preenchido, /api/reindex exige o header X-Reindex-Token
CORS_ORIGINS http://localhost:8080 Origens permitidas
AUTO_INDEX true Indexa automaticamente na inicialização

Solução de problemas

A indexação não termina / fica em "Indexando". O OCR é o gargalo. Verifique docker compose logs backend. Se o OCR estiver lento, aumente OCR_DPI não ajuda — reduza para 150 para acelerar, com perda de acurácia. Para retomar após uma interrupção, basta reiniciar o container: o cache de OCR é preservado no volume e só as páginas faltantes são reprocessadas.

O chat responde que o texto "não aborda diretamente o assunto". O índice pode estar vazio (/api/status) ou a pergunta pode estar longe do corpus. Reduza MIN_SIMILARITY para 0.25, ou increase TOP_K para 10. Verifique também se a pergunta cita uma referência explícita — nesse caso a busca é determinística e não depende do limiar.

"Nenhum versículo pôde ser extraído". O PDF pode não ser de uma Bíblia com capítulos e versículos numerados, ou o OCR pode ter falhado. Inspecione o cache de OCR em /data/vector_db/ocr_cache/ para ver o texto que foi extraído de cada página.

Ollama não sobe. docker compose --profile local up -d. O serviço ollama-pull baixa o modelo indicado em OLLAMA_MODEL na primeira execução. Para outro modelo: OLLAMA_MODEL=llama3.2:3b docker compose --profile local up -d.

Porta 8080 já em uso. FRONTEND_PORT=8090 docker compose up -d. Atualize também CORS_ORIGINS.


Estrutura do projeto

.
├── docker-compose.yml
├── .env.example
├── PDF/                     # PDFs da Bíblia (entrada, somente-leitura)
├── backend/
│   ├── Dockerfile
│   ├── requirements.txt
│   ├── app/
│   │   ├── config.py        # settings via pydantic-settings
│   │   ├── models.py        # schemas da API
│   │   ├── extraction.py    # PDF → texto (PyMuPDF + OCR + cache)
│   │   ├── bible_parser.py  # livro / capítulo / versículo
│   │   ├── embedding.py     # sentence-transformers
│   │   ├── vector_store.py  # ChromaDB
│   │   ├── indexer.py       # manifesto incremental
│   │   ├── llm.py           # adaptadores Ollama/OpenAI/Groq/Anthropic
│   │   ├── chat.py          # contexto, validação de citações
│   │   └── main.py          # rotas FastAPI
│   └── tests/
├── frontend/
│   ├── Dockerfile
│   ├── nginx.conf
│   └── src/
│       ├── App.tsx
│       ├── api.ts
│       ├── lib/sse.ts
│       └── components/
└── docs/superpowers/        # design e plano de implementação

Segurança

  • As chaves de API vivem apenas no backend, via variáveis de ambiente. Nunca chegam ao bundle do navegador.
  • Os PDFs são montados somente-leitura; a escrita fica restrita ao volume /data.
  • O conteúdo indexado é entregue ao modelo como dado delimitado, nunca como instrução — o que neutraliza tentativas de prompt injection via corpus.
  • Mensagens acima de 4.000 caracteres são recusadas; o histórico é limitado às últimas 10 trocas.
  • O endpoint de reindexação rejeita chamadas concorrentes (409) e aceita um token opcional (REINDEX_TOKEN).

A aplicação é local, sem autenticação. Não a exponha à internet sem colocar um proxy com autenticação à frente.

S
Description
Sistema web RAG para consulta bíblica: corpus USFX em domínio público, busca híbrida (vetorial + BM25) e agente pastoral ancorado exclusivamente nos versículos recuperados. FastAPI + ChromaDB + React, containerizado.
Readme
1.5 MiB
0 Stars 1 Watchers 0 Forks
Languages
Python 83.7%
TypeScript 10.1%
CSS 5.2%
Dockerfile 0.8%
HTML 0.2%