feat: integra pipeline PDF→Markdown a 9 stadi e test suite

Porta da branch marker la riscrittura completa di conversione/_pipeline/
(9 stadi PyMuPDF) e la suite tests/ senza modificare il resto del progetto
RAG (ollama/, step-5/, step-6/, step-8/, rag.py, retrieve.py, config.py).

requirements.txt: aggiunge PyMuPDF>=1.24.0 e pytest>=8.0, mantiene chromadb,
rimuove opendataloader-pdf e pymupdf4llm.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-11 14:44:16 +02:00
parent 5215f53ad0
commit e1b5298b20
38 changed files with 3691 additions and 169 deletions
+31 -122
View File
@@ -1,62 +1,9 @@
# RAG from Scratch
# PDF → Markdown
Sistema RAG (Retrieval-Augmented Generation) costruito da zero, senza framework di alto livello.
Funziona su qualsiasi PDF digitale. Gira interamente in locale, senza GPU, senza cloud.
Converte PDF digitali in Markdown strutturato e pulito.
**Stack:** Python · Ollama · ChromaDB
**Compatibile con:** Linux · macOS · Windows (WSL2) · CPU only · ~8 GB RAM
---
## Pipeline
```
PDF → conversione → chunking → verifica → vettorizzazione → retrieval
```
| Fase | Rischio | Motivo |
|---|---|---|
| Conversione | 🟡 Medio | Automatica, ma il PDF deve essere digitale e non protetto |
| Revisione Markdown | 🔴 Alto | La qualità del MD determina la qualità del RAG |
| Chunking | 🟡 Medio | Adattivo, dipende dalla qualità del MD |
| Vettorizzazione | 🟢 Basso | Meccanica, lenta ma affidabile |
| Retrieval | 🟡 Medio | Dipende dai parametri in `config.py` |
---
## Struttura del progetto
```
rag/
├── sources/ # PDF originali — non modificare
├── conversione/ # PDF → Markdown strutturato
│ ├── pipeline.py
│ ├── validate.py
│ └── <stem>/
│ ├── raw.md # grezzo — non modificare
│ ├── clean.md # copia di lavoro
│ └── report.json
├── step-5/ # Chunking
│ ├── chunker.py
│ └── <stem>/chunks.json
├── step-6/ # Verifica e fix chunk
│ ├── verify_chunks.py
│ ├── fix_chunks.py
│ └── <stem>/
│ ├── chunks.json
│ └── report.json
├── step-8/ # Vettorizzazione
│ └── ingest.py
├── ollama/ # Setup ambiente
│ ├── check_env.py
│ └── test_ollama.py
├── chroma_db/ # Vector store (generato)
├── config.py # Configurazione pipeline ← modifica qui
├── rag.py # Interrogazione RAG interattiva
└── retrieve.py # Retrieval puro (senza LLM)
```
`--stem` = nome del PDF senza estensione = nome della collection ChromaDB.
**Stack:** Python · opendataloader-pdf (XY-Cut++) · Java 11+
**Compatibile con:** Linux · macOS · Windows (WSL2)
---
@@ -68,92 +15,54 @@ source .venv/bin/activate
pip install -r requirements.txt
```
**Java 11+** richiesto per la conversione (`opendataloader-pdf`):
**Java 11+** richiesto:
```bash
sudo apt install default-jdk # Ubuntu/Debian/WSL
java -version # verifica
java -version
```
Vedi [`ollama/README.md`](ollama/README.md) per l'installazione di Ollama e il download dei modelli.
---
## Workflow
### 1. Converti il PDF
## Utilizzo
```bash
# Singolo PDF
python conversione/pipeline.py --stem <nome>
# Tutti i PDF in sources/
python conversione/pipeline.py
# Forza riesecuzione
python conversione/pipeline.py --stem <nome> --force
```
Produce `conversione/<stem>/clean.md`. Vedi [`conversione/README.md`](conversione/README.md).
### 2. Rivedi il Markdown
```
/prepare-md conversione/<stem>/clean.md
```
Passaggio più importante: la qualità del RAG dipende da questo.
### 3. Chunking
```bash
python step-5/chunker.py --stem <nome>
```
### 4. Verifica e fix chunk
```bash
python step-6/verify_chunks.py --stem <nome>
python step-6/fix_chunks.py --stem <nome> # se ci sono 🔴
python step-6/verify_chunks.py --stem <nome> # ri-verifica
```
Non procedere alla vettorizzazione se ci sono 🔴.
### 5. Vettorizza
```bash
python step-8/ingest.py --stem <nome>
```
Vedi [`step-8/README.md`](step-8/README.md). Usa `--force` se hai cambiato `EMBED_MODEL` o i chunk.
### 6. Interroga
```bash
python rag.py --stem <nome> # risposta LLM
python retrieve.py --stem <nome> # retrieval puro (debug)
```
`--stem` = nome file PDF senza estensione.
Esempio: `sources/analisi1.pdf``--stem analisi1`
---
## Configurazione (`config.py`)
## Output
| Parametro | Default | Descrizione |
|---|---|---|
| `EMBED_MODEL` | `"nomic-embed-text"` | Modello embedding — deve corrispondere tra ingest e retrieval |
| `OLLAMA_MODEL` | `"qwen3.5:0.8b"` | Modello LLM |
| `OLLAMA_URL` | `"http://localhost:11434"` | Endpoint Ollama |
| `TOP_K` | `6` | Chunk recuperati per query |
| `TEMPERATURE` | `0.0` | Deterministico a `0.0` |
| `NO_THINK` | `True` | Disabilita chain-of-thought (Qwen3/Qwen3.5) |
| `SYSTEM_PROMPT` | *(vedi file)* | Istruzioni di comportamento per il LLM |
Per ogni stem in `conversione/<stem>/`:
> Se cambi `EMBED_MODEL`, riesegui `step-8/ingest.py --stem <nome> --force`.
| File | Descrizione |
|------|-------------|
| `raw.md` | Markdown grezzo — **non modificare** |
| `clean.md` | Markdown pulito — copia di lavoro |
| `structure_profile.json` | Struttura rilevata e metriche |
| `report.json` | Statistiche complete della conversione |
---
## Principi
## Validazione batch
**Atomico** — ogni fase fa una cosa sola; se si rompe qualcosa sai esattamente dove.
```bash
python conversione/validate.py
```
**Verificabile** — ogni fase ha un criterio di completamento oggettivo prima di procedere.
Stampa una tabella di stato su tutti gli stem convertiti.
**Reversibile** — puoi tornare indietro senza perdere il lavoro delle altre fasi.
---
**Adattivo** — nessuna assunzione sulla struttura del documento; si adatta automaticamente.
**Locale** — nessuna API esterna, nessun dato trasmesso fuori dalla macchina.
Vedi [`conversione/README.md`](conversione/README.md) per dettagli sulla pipeline e i tipi di documento supportati.