Introduzione al RAG AI in locale
Un contratto di fornitura, una cartella clinica, il manuale interno di un reparto: sono documenti che non vuoi caricare su un servizio di terzi solo per fare una domanda. Un sistema RAG AI locale risolve il problema. Il modello linguistico gira sul tuo computer, cerca nei tuoi PDF i passaggi pertinenti e risponde citando file e pagina. Nessun byte lascia la macchina.
Il progetto che costruiamo usa Ollama v0.40.8 (pubblicata il 21 ottobre 2026), Python, il database vettoriale Chroma e, come interfaccia opzionale, Open WebUI v0.12.3. In circa 60 minuti, con 12 passi e meno di 300 righe di codice, otterrai uno script di indicizzazione incrementale, un assistente da riga di comando che ammette quando non trova la risposta, uno script di valutazione e una chat web per colleghi meno a loro agio col terminale.
Cos’è il RAG e perché usarlo in locale
Meccanismo di base
RAG sta per retrieval‑augmented generation, cioè generazione aumentata dal recupero. Il processo è semplice:
- Trasformi i documenti in vettori numerici (gli embedding) che catturano il significato di ogni brano.
- Quando arriva una domanda, trasformi anche quella in un vettore.
- Cerchi i brani più vicini e li incolli nel prompt del modello.
- Il modello legge i passaggi giusti e li riassume; se i passaggi non bastano, un buon prompt lo costringe ad ammettere l’incapacità.
Tre motivi pratici per il locale
Riservatezza: i dati restano sul disco e la rete non serve.
Costo prevedibile: non paghi per token mentre rileggi cento volte lo stesso manuale.
Controllo: scegli tu modello, versione e soglie; il comportamento non cambia da un giorno all’altro per aggiornamenti del fornitore.
Perché Ollama è la scelta naturale
Nel 2025 Stack Overflow ha rilevato, nel suo sondaggio sugli sviluppatori, che il 14,4 % degli intervistati ha indicato Ollama tra le tecnologie utilizzate. Nella sezione sull’IA la stessa indagine afferma: “Il 51,1 % degli sviluppatori che costruiscono agenti utilizza Ollama, rendendolo il framework più usato tra quelli rilevati.” (Stack Overflow Developer Survey 2025).
Sul versante aziendale, McKinsey ha scritto nel rapporto The State of AI 2025 che l’ 88 % degli intervistati dichiara un uso regolare dell’intelligenza artificiale in almeno una funzione aziendale. In sostanza, la domanda non è più se usare l’IA sui documenti, ma dove far girare i dati mentre lo fai.
Ollama oggi ha due anime: il runtime locale, quello che useremo, e Ollama Cloud, un servizio ospitato con piani a pagamento. Secondo gli annunci di fine agosto 2026, i piani Pro, Max e Team sono passati a una tariffazione per token con crediti inclusi. Per un sistema RAG privato conta una sola regola: i modelli il cui nome termina con il suffisso :cloud inviano le richieste ai server di Ollama. Quelli senza suffisso girano sul tuo hardware. Più avanti blocchiamo il suffisso via codice, così un errore di battitura non spedisce un contratto in rete.
Prerequisiti: versioni, hardware e competenze
Prima di installare qualunque cosa, controlla la tabella dei componenti. Le versioni di Ollama e Open WebUI sono quelle confermate dalle pagine ufficiali al 22 ottobre 2026. Per le librerie Python non fissiamo numeri: la regola è installare l’ultima release disponibile, far passare i test del passo 11 e poi congelare tutto con pip freeze. Un tutorial che copia numeri di versione da un’altra epoca produce ambienti che non partono.
| Componente | Versione | Ruolo e note |
|---|---|---|
| Ollama | v0.40.8 (21 ottobre 2026) | Runtime locale per chat ed embedding, espone le API su 127.0.0.1:11434 |
| Python | 3.11 o successivo | Versione indicata nell’installazione standard di Open WebUI |
| Open WebUI | v0.12.3 (16 ottobre 2026) | Interfaccia chat opzionale, passo 12 |
| Chroma | Client Python, licenza Apache 2.0 | Database vettoriale su file, nessun server da gestire |
| pypdf | Ultima release | Estrazione del testo dai PDF con livello testuale |
| Modello di chat | tag gemma4 | Famiglia Gemma 4, scegli la taglia adatta alla tua RAM dalla libreria Ollama |
| Modello di embedding | tag nomic-embed-text | Sostituibile via variabile d’ambiente, ma ogni cambio richiede la reindicizzazione |
| RAM | 16 GB consigliati | Indicazione pratica per modelli di taglia media, non un requisito ufficiale |
| Spazio su disco | Circa 20 GB liberi | Modelli, indice vettoriale e ambiente virtuale |
Servono competenze di base: sapere aprire un terminale, creare un ambiente virtuale Python e leggere un traceback. Non serve esperienza con il machine learning. Una GPU accelera molto la generazione ma non è obbligatoria: su un portatile moderno con 16 GB di RAM un modello di taglia piccola o media risponde in tempi accettabili, con latenze che dipendono dal modello e dall’hardware, e che conviene misurare sul proprio caso.
Tieni a portata di mano anche tre PDF di prova con un vero livello di testo, cioè documenti in cui riesci a selezionare le parole col cursore. Se hai solo scansioni, leggi la sezione sugli errori comuni: serve un passaggio di OCR prima di cominciare.
Architettura del progetto e costi reali
Il sistema ha due fasi distinte.
Indicizzazione
L’indicizzazione gira una volta (e poi a ogni nuovo PDF): legge i file, estrae il testo pagina per pagina, lo spezza in blocchi da circa 1 200 caratteri con una sovrapposizione di 200, calcola l’embedding di ogni blocco con Ollama e salva testo, vettore e metadati in Chroma.
Interrogazione
L’interrogazione gira a ogni domanda: calcola l’embedding della domanda, chiede a Chroma i cinque blocchi più vicini, scarta quelli oltre una soglia di distanza, costruisce un prompt con i brani numerati e lo passa al modello di chat, che risponde in streaming citando file e pagina.
La struttura finale della cartella è questa:
rag-privato/├── .venv/ ambiente virtuale Python
├── documenti/ i tuoi PDF (mai nel repository Git)
├── chroma_db/ indice vettoriale persistente
├── domande.json batteria di domande per la valutazione
├── requirements.txt
├── config.py parametri e client Ollama
├── ingest.py estrazione, chunking, embedding, indicizzazione
├── ask.py retrieval, prompt, generazione, fonti
└── eval.py misura quanti passaggi giusti recupera il sistema
Confronto costi: locale vs ospitato
| Voce | Percorso locale | Alternativa ospitata |
|---|---|---|
| Runtime LLM | Ollama in locale, nessun canone di licenza | Ollama Pro: 20 $/mese con 60 $ di crediti mensili inclusi |
| Piani superiori | Non servono | Max con 300 $ di crediti mensili, Team da 500 $/mese con 1 000 $ di crediti condivisi |
| Database vettoriale | Chroma locale, Apache 2.0, gratuito | Chroma Cloud: 5 $ di crediti gratuiti per iniziare, poi tariffa a consumo |
| Interfaccia chat | Open WebUI self‑hosted, gratuito | Licenza Enterprise per rebranding e white‑label, prezzo su richiesta |
| Parsing PDF avanzato | pypdf, gratuito | LlamaParse: 10 000 crediti gratuiti al mese, poi 1 000 crediti = 1,25 $ |
| Dove restano i documenti | Sul tuo disco | Sui server del fornitore |
Leggi l’ultima riga due volte. I servizi ospitati hanno senso quando non hai hardware o i documenti non sono sensibili.
Guida passo‑passo al setup
1. Preparazione dell’ambiente
Installa Python 3.11+, crea un virtualenv (python -m venv .venv) e attivalo. Poi esegui pip install -r requirements.txt per installare Chroma, pypdf e le altre dipendenze.
2. Installazione di Ollama
Scarica il binario per il tuo OS da ollama.com, verifica la versione con ollama --version (deve restituire v0.40.8). Avvia il servizio con ollama serve; ascolterà su 127.0.0.1:11434.
3. Scaricare i modelli
Usa i comandi ollama pull gemma4 per il modello di chat e ollama pull nomic-embed-text per l’embedding. Assicurati che i nomi non includano il suffisso :cloud.
4. Configurazione di Chroma
Il client Python di Chroma crea una cartella chroma_db dove salva gli embedding. Non è necessario avviare un server separato.
5. Script di ingestione (ingest.py)
Lo script legge tutti i PDF in documenti/, usa pypdf per estrarre il testo, lo suddivide in chunk da 1 200 caratteri con sovrapposizione di 200, invia ogni chunk a Ollama per l’embedding e li inserisce in Chroma con metadati {file, pagina, offset}.
6. Script di interrogazione (ask.py)
Riceve una domanda dalla riga di comando, calcola il suo embedding, interroga Chroma per i 5 chunk più vicini, filtra con una soglia di distanza (default 0.3), costruisce il prompt numerato e lo passa al modello gemma4. Il risultato viene stampato in streaming e include riferimenti “Fonte: documento.pdf, pagina 12”.
7. Valutazione (eval.py)
Carica domande.json contenente coppie {question, expected_sources}, esegue ask.py su ciascuna e calcola precisione, recall e tasso di “non risposta”.
8. Installazione opzionale di Open WebUI
Clona il repository open-webui, avvialo con Docker o direttamente con python -m open_webui. Configura il client Ollama puntando a http://127.0.0.1:11434. Ora i colleghi possono interagire via browser.
Gestione di errori comuni
- PDF senza testo: i file sono scansioni; usa un OCR (es. Tesseract) prima di ingestire.
- Embedding fallito: verifica che Ollama sia in esecuzione e che il modello di embedding sia corretto; controlla i log per errori di memoria.
- Soglia di distanza troppo bassa: il prompt potrebbe ricevere pochi o nessun chunk; aumenta la soglia o il numero di chunk restituiti.
- Modello cloud per errore di battitura: aggiungi una verifica in
config.pyche blocchi tutti i nomi con:cloud.
Conclusioni e prospettive future
Costruire un RAG AI in locale con Ollama dimostra che è possibile mantenere la riservatezza dei dati, ridurre i costi operativi e avere pieno controllo sul ciclo di vita del modello. Il setup richiede pochi strumenti, ma offre una base solida per estensioni future: integrazione di retrieval multimodale (immagini, audio), aggiunta di un layer di caching per domande frequenti, o sperimentazione di modelli di embedding più recenti.
Man mano che Ollama rilascerà versioni più ottimizzate e che i modelli open‑source cresceranno in capacità, il divario tra soluzioni cloud e locali si ridurrà ulteriormente, rendendo il RAG AI in locale la scelta di default per organizzazioni che trattano informazioni sensibili.
