Files
rag-from-scratch/README.md
T

6.0 KiB

PDF → Chunk RAG-ready

Converte PDF digitali in chunk semantici pronti per la vettorizzazione RAG, senza LLM né OCR.

Pipeline: PDF → Markdown strutturato → chunk semantici → embedding ChromaDB
Stack: Python · PyMuPDF · pdfplumber
Non supportati: PDF scansionati (solo immagini), PDF protetti da password.


Setup

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Flusso completo

1. Posiziona il PDF

sources/<nome>.pdf

2. Converti il PDF in Markdown

# Singolo documento
.venv/bin/python conversione/ --stem <nome>

# Tutti i PDF in sources/
.venv/bin/python conversione/

# Forza riesecuzione (sovrascrive output esistente)
.venv/bin/python conversione/ --stem <nome> --force

Output in conversione/<nome>/:

File Descrizione
raw.md Markdown grezzo — non modificare
clean.md Markdown pulito — input per il chunker
structure_profile.json Struttura rilevata e strategia di chunking
report.json Metriche di qualità della conversione

3. Verifica la qualità del Markdown (opzionale)

.venv/bin/python conversione/ validate <nome> --detail

Se lo score è ≥ 80 e valid=true, procedi. Altrimenti usa /prepare-md per correzioni manuali (sillabazione residua, header malformati, ecc.).

4. Genera i chunk

.venv/bin/python chunks/chunker.py --stem <nome>

# Forza riesecuzione
.venv/bin/python chunks/chunker.py --stem <nome> --force

La strategia di chunking (h3_aware, h2_paragraph_split, paragraph, sliding_window) viene scelta automaticamente da structure_profile.json.

Output in chunks/<nome>/:

File Descrizione
chunks.json Lista di chunk con testo, sezione, titolo e metadati
report.json Statistiche e anomalie del chunking

5. Verifica i chunk

.venv/bin/python chunks/verify_chunks.py --stem <nome>

Verdict possibili:

Verdict Significato Cosa fare
ok Nessun problema Procedi alla vettorizzazione
warnings_only Solo avvisi minori Puoi procedere o eseguire il fix
blocked Problemi bloccanti (chunk incompleti) Esegui il fix

6. Correggi i problemi (se necessario)

# Anteprima delle correzioni senza applicarle
.venv/bin/python chunks/fix_chunks.py --stem <nome> --dry-run

# Applica le correzioni (ricorsivo, fino a 3 iterazioni)
.venv/bin/python chunks/fix_chunks.py --stem <nome>

Il fix gestisce automaticamente: chunk incompleti (frase spezzata), chunk troppo corti (accorpa al successivo), chunk eccessivamente lunghi (spezza su punteggiatura). Ogni chunk termina sempre su un confine di frase.

7. Esegui l'ingestion

Prima verifica che Ollama e i modelli siano pronti:

.venv/bin/python ollama/check_env.py

Poi genera gli embedding e salva in ChromaDB:

# Singolo documento
.venv/bin/python ingestion/ingest.py --stem <nome>

# Tutti i documenti in chunks/
.venv/bin/python ingestion/ingest.py

# Rigenera dopo aver cambiato modello o aggiornato i chunk
.venv/bin/python ingestion/ingest.py --stem <nome> --force

Output in chroma_db/<nome>/ (ignorata da git).


Configurazione del chunking

Tutti i parametri sono in chunks/config.py:

TARGET_CHARS    = 600   # dimensione target dei chunk
CHUNK_TOLERANCE = 0.25  # ±25% → range accettabile [450, 750]
OVERLAP_SENTENCES = 1   # frasi di overlap tra chunk consecutivi
PROTECT_TABLES  = True  # tabelle emesse come chunk atomici
FIX_MAX_ITERATIONS = 3  # iterazioni massime del fix ricorsivo

Per ogni strategia è possibile definire valori diversi tramite STRATEGY_OVERRIDES. Modificare solo questo file — chunker, verify e fix si aggiornano automaticamente.


Configurazione modelli

Tutti i parametri LLM e embedding sono in config.py:

OLLAMA_MODEL = "qwen3.5:4b"      # modello LLM per la generazione
EMBED_MODEL  = "nomic-embed-text" # modello embedding (deve coincidere con l'ingestion)
TEMPERATURE  = 0.2                # 0.0 = deterministico, valori alti = più creativo
NO_THINK     = True               # True = risposta diretta (più veloce), False = con ragionamento
TOP_K        = 6                  # numero di chunk recuperati per ogni domanda
OLLAMA_URL   = "http://localhost:11434"

Se cambi EMBED_MODEL devi rieseguire l'ingestion con --force — gli embedding devono essere prodotti dallo stesso modello usato nel retrieval.


Testare il modello (senza RAG)

Verifica che il modello LLM risponda correttamente prima di coinvolgere la pipeline:

.venv/bin/python ollama/test_ollama.py

Il modello usato è quello configurato in config.py (OLLAMA_MODEL).
Digita exit per uscire.


Retrieval puro (senza generazione)

Utile per verificare che i chunk giusti vengano recuperati prima di diagnosticare risposte sbagliate:

.venv/bin/python retrieve.py --stem <nome>

# Modifica il numero di chunk restituiti
.venv/bin/python retrieve.py --stem <nome> --top-k 10

Nel loop interattivo:

Comando Effetto
<query> Mostra i chunk più simili con score di similarità (testo troncato)
<query> -f Testo completo dei chunk
exit Termina

RAG interattivo

Risponde a domande in linguaggio naturale usando i chunk indicizzati in ChromaDB:

.venv/bin/python rag.py --stem <nome>

Nel loop interattivo:

Comando Effetto
<domanda> Risposta generata dal LLM con contesto dai chunk
<domanda> -v Risposta + chunk recuperati con score di similarità
exit Termina

Test

.venv/bin/python -m pytest tests/

Riferimenti