4.5 KiB
RAG from Scratch
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.
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.
Setup
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Java 11+ richiesto per la conversione (opendataloader-pdf):
sudo apt install default-jdk # Ubuntu/Debian/WSL
java -version # verifica
Vedi ollama/README.md per l'installazione di Ollama e il download dei modelli.
Workflow
1. Converti il PDF
python conversione/pipeline.py --stem <nome>
Produce conversione/<stem>/clean.md. Vedi 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
python step-5/chunker.py --stem <nome>
4. Verifica e fix chunk
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
python step-8/ingest.py --stem <nome>
Vedi step-8/README.md. Usa --force se hai cambiato EMBED_MODEL o i chunk.
6. Interroga
python rag.py --stem <nome> # risposta LLM
python retrieve.py --stem <nome> # retrieval puro (debug)
Configurazione (config.py)
| 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 |
Se cambi
EMBED_MODEL, rieseguistep-8/ingest.py --stem <nome> --force.
Principi
Atomico — ogni fase fa una cosa sola; se si rompe qualcosa sai esattamente dove.
Verificabile — ogni fase ha un criterio di completamento oggettivo prima di procedere.
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.