Files
rag-from-scratch/README.md
T
davide 98a8eaa9fb docs/fix: aggiorna README e fix ingest per embedding robusto
README riscritto per rispecchiare la pipeline attuale:
- rimossi riferimenti a Stage 1, md_optimizer, fix_chunks
- pipeline semplificata: MinerU .md → chunker → ingest → rag
- tabelle parametri aggiornate (SKIP_HEADINGS, SKIP_PRE_HEADING,
  MERGE_SHORT_PARAGRAPHS, EMBED_MAX_CHARS al posto dei vecchi)
- struttura repo corretta

ingest.py: strip tag HTML ed entità prima dell'embedding per evitare
HTTP 500 da Ollama su chunk con tabelle HTML grezze; aggiunto
EMBED_MAX_CHARS (default 6000) in config.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 14:29:06 +02:00

264 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RAG su documenti accademici
Pipeline completa per trasformare PDF accademici in un sistema RAG interrogabile in linguaggio naturale.
**Stack:** Python · MinerU · ChromaDB · Ollama
**Chunking:** rule-based, deterministico, senza LLM
**Embedding + Generazione:** Ollama (locale)
---
## Prerequisiti
### 1. MinerU — conversione PDF → Markdown
MinerU è il tool esterno che converte i PDF in Markdown strutturato.
Repository: [https://github.com/opendatalab/MinerU](https://github.com/opendatalab/MinerU)
#### Requisiti di sistema
| Risorsa | Minimo | Raccomandato |
|---------|--------|--------------|
| Python | 3.103.13 | 3.11 |
| RAM | 16 GB | 32 GB+ |
| Disco | 20 GB (modelli inclusi) | 40 GB+ |
| GPU | opzionale | 48 GB VRAM (CUDA) |
| OS | Linux, macOS, Windows | Linux / WSL2 |
#### Installazione
```bash
pip install "mineru[all]"
```
Al primo avvio scarica automaticamente i modelli (~15 GB).
#### Uso — CLI
```bash
mineru -p <documento.pdf> -o <output_dir> -b pipeline
```
| Flag | Descrizione |
|------|-------------|
| `-p` | Percorso PDF o cartella |
| `-o` | Cartella di output |
| `-b` | Backend: `pipeline` (CPU), `hybrid-auto-engine` (GPU raccomandato) |
| `-m` | Metodo: `auto`, `txt`, `ocr` |
#### Output di MinerU
```
<stem>_output/
└── auto/
├── <stem>.md ← Markdown (input della pipeline)
├── <stem>_content_list_v2.json
├── <stem>_model.json
└── images/
```
Il file usato dalla pipeline è **`<stem>.md`** nella cartella `auto/`.
### 2. Ollama — embedding e generazione
Scarica e avvia [Ollama](https://ollama.com), poi installa i modelli:
```bash
ollama pull nomic-embed-text # embedding (obbligatorio)
ollama pull qwen3.5:4b # generazione LLM (o altro modello)
```
---
## Setup
```bash
git clone <questo-repo>
cd rag
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```
---
## Flusso completo
```
PDF
▼ MinerU (esterno — vedi sotto)
sources/<stem>_output/auto/<stem>.md
▼ python chunks/chunker.py --stem <stem>
chunks/<stem>/chunks.json
▼ python chunks/verify_chunks.py --stem <stem>
(verifica qualità — opzionale ma consigliato)
▼ python ingestion/ingest.py --stem <stem>
chroma_db/<stem>/
▼ python rag.py --stem <stem>
Interrogazione in linguaggio naturale
```
---
## Passo 1 — Converti il PDF con MinerU
**Opzione A — Google Colab (nessuna installazione locale)**
Usa il notebook incluso:
```
mineru.ipynb
```
Aprilo su Google Colab, carica il PDF e segui le celle. Al termine scarica automaticamente lo ZIP con l'output. Decomprimi la cartella in `sources/`:
```
sources/
└── <stem>_output/
└── auto/
├── <stem>.md ← usato dalla pipeline
├── <stem>_content_list_v2.json
├── <stem>_model.json
└── images/
```
**Opzione B — Installazione locale**
```bash
mineru -p documento.pdf -o sources/<stem>_output/ -b pipeline
```
---
## Passo 2 — Chunking
```bash
# Singolo documento
.venv/bin/python chunks/chunker.py --stem <stem>
# Tutti i documenti in sources/
.venv/bin/python chunks/chunker.py
# Rigenera anche se chunks.json esiste già
.venv/bin/python chunks/chunker.py --stem <stem> --force
```
Il chunker legge `sources/<stem>_output/auto/<stem>.md` e produce `chunks/<stem>/chunks.json`.
**Regole applicate:**
- 1 paragrafo = 1 chunk; paragrafi di sezioni diverse non si mescolano
- Split a confine di frase se il paragrafo supera `MAX_CHARS` (mai a metà frase)
- Frasi spezzate tra paragrafi consecutivi vengono ri-fuse automaticamente
- Paragrafi brevi (< `MIN_CHARS`) vengono accorpati al successivo (stesso contesto)
- Sezioni configurabili vengono saltate (indice, sommario, frontespizio)
- Tabelle, liste e code block sono blocchi atomici (non si spezzano)
Output in `chunks/<stem>/`:
| File | Contenuto |
|------|-----------|
| `chunks.json` | Chunk con testo, sezione, titolo, n_chars |
| `meta.json` | Parametri usati |
| `report.json` | Statistiche e anomalie (generato da verify) |
---
## Passo 3 — Verifica i chunk (opzionale)
```bash
.venv/bin/python chunks/verify_chunks.py --stem <stem>
```
| Verdict | Significato |
|---------|-------------|
| `ok` | Nessun problema — procedi |
| `warnings_only` | Solo avvisi minori — puoi procedere |
| `blocked` | Problemi strutturali — rivedi il sorgente `.md` |
---
## Passo 4 — Vettorizzazione
```bash
# Singolo documento → collection omonima
.venv/bin/python ingestion/ingest.py --stem <stem>
# Più documenti → collection condivisa (RAG cross-documento)
.venv/bin/python ingestion/ingest.py --collection <nome> --stems doc1 doc2 doc3
# Rigenera dopo aver aggiornato i chunk o cambiato modello embedding
.venv/bin/python ingestion/ingest.py --stem <stem> --force
```
> Se cambi `EMBED_MODEL` in `config.py` devi rieseguire l'ingestion con `--force`.
---
## Passo 5 — Interrogazione
```bash
# RAG interattivo (retrieval + generazione LLM)
.venv/bin/python rag.py --stem <stem>
.venv/bin/python rag.py --collection <nome>
# Retrieval puro (debug, senza LLM)
.venv/bin/python retrieve.py --stem <stem>
.venv/bin/python retrieve.py --stem <stem> --top-k 10
```
---
## Configurazione
### Chunking — `chunks/config.py`
| Parametro | Default | Descrizione |
|-----------|---------|-------------|
| `MAX_CHARS` | 1200 | Lunghezza massima chunk (caratteri) |
| `MIN_CHARS` | 80 | Soglia minima (warning sotto questa soglia) |
| `CONTEXT_DEPTH` | 3 | Livelli heading inclusi nel prefisso chunk (13) |
| `SKIP_HEADINGS` | set italiano | Sezioni saltate completamente (indice, sommario…) |
| `SKIP_PRE_HEADING` | `True` | Salta contenuto prima del primo heading (frontespizio) |
| `MERGE_SHORT_PARAGRAPHS` | `True` | Accorpa paragrafi brevi fino a `MIN_CHARS` |
| `SENTENCE_SPLIT_RE` | regex | Confine di fine frase per lo split |
| `ATOMIC_TYPES` | `table, code, list` | Blocchi mai spezzati |
### RAG — `config.py`
| Parametro | Default | Descrizione |
|-----------|---------|-------------|
| `OLLAMA_MODEL` | `qwen3.5:4b` | Modello LLM per la generazione |
| `EMBED_MODEL` | `nomic-embed-text` | Modello embedding |
| `EMBED_MAX_CHARS` | 6000 | Caratteri massimi inviati al modello embedding |
| `TOP_K` | 6 | Chunk recuperati per domanda |
| `TEMPERATURE` | 0.2 | Creatività del modello (0 = deterministico) |
| `OLLAMA_URL` | `localhost:11434` | URL server Ollama |
---
## Struttura del repository
```
rag/
├── sources/ ← output MinerU (una cartella per documento)
│ └── <stem>_output/auto/
├── chunks/
│ ├── chunker.py ← chunking da MD pulito
│ ├── config.py ← parametri di chunking
│ └── verify_chunks.py ← verifica qualità chunk
├── ingestion/
│ └── ingest.py ← embedding → ChromaDB
├── chroma_db/ ← database vettoriale (ignorato da git)
├── config.py ← parametri RAG (modelli, TOP_K, prompt)
├── rag.py ← loop RAG interattivo
├── retrieve.py ← retrieval puro (debug)
└── mineru.ipynb ← notebook Colab per conversione PDF
```