Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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_MODELdevi 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
conversione/README.md— dettagli sulla pipeline PDF→Markdown e sui tipi di documento supportatiingestion/README.md— configurazione embedding, scelta modello, regole --force