davide 295fb3faa6 refactor: separa config embedding in ingestion/config.py
- ingestion/config.py (nuovo): EMBED_MODEL, EMBED_MAX_CHARS, OLLAMA_URL
- config.py radice: rimossi EMBED_MODEL e EMBED_MAX_CHARS — resta solo la config RAG
- ingest.py: importa da ingestion.config
- rag.py, retrieve.py: importano EMBED_MODEL da ingestion.config

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

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

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

pip install "mineru[all]"

Al primo avvio scarica automaticamente i modelli (~15 GB).

Uso — CLI

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, poi installa i modelli:

ollama pull qwen3-embedding:0.6b    # embedding (obbligatorio)
ollama pull qwen3.5:4b              # generazione LLM (o altro modello)

Setup

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

mineru -p documento.pdf -o sources/<stem>_output/ -b pipeline

Passo 2 — Chunking

# 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)

.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

# 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

# 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 qwen3-embedding:0.6b 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
S
Description
No description provided
Readme 358 KiB
Languages
Python 81.3%
Jupyter Notebook 11.7%
HTML 7%