RAG sui tuoi documenti: come far rispondere l'AI sui tuoi file
La prima volta che provi a far rispondere un LLM sui tuoi documenti, la tentazione è ovvia: incolli il PDF nella chat e fai la domanda. Con un file corto funziona. Poi arriva il manuale da 300 pagine, o la cartella con quaranta contratti, e il trucco crolla: non ci sta nella finestra di contesto, e anche quando ci sta il modello "annega" tra le informazioni e ti risponde con la cosa sbagliata detta con grande sicurezza.
RAG — Retrieval-Augmented Generation — è la soluzione a questo problema. L'idea in una frase: invece di dare al modello tutti i documenti, gli dai solo i pezzi rilevanti per la domanda che ha davanti. Questa guida ti porta dall'idea a una pipeline che funziona sul serio, spiegando ogni pezzo e — soprattutto — i punti dove la maggior parte dei RAG fatti in casa si rompe.
Cos'è davvero il RAG (e cosa non è)
RAG non è un modello speciale né una funzione da attivare. È un'architettura: un passaggio di recupero (retrieval) che precede la generazione. Prima di rispondere, il sistema cerca nei tuoi documenti i frammenti più pertinenti alla domanda, li mette nel prompt come contesto, e solo allora chiede al modello di rispondere basandosi su quei frammenti.
Il vantaggio non è solo tecnico. Un modello che risponde da RAG risponde su fonti che tu controlli, aggiornabili senza ri-addestrare nulla, e può citare da dove ha preso l'informazione. È la differenza tra un collega che ti risponde a memoria e uno che prima apre il faldone giusto e ti legge il paragrafo.
Quello che il RAG non è: una garanzia contro le allucinazioni. Se il recupero porta il pezzo sbagliato, il modello genererà una risposta sbagliata basata su quel pezzo. Nel RAG, il collo di bottiglia della qualità non è quasi mai la generazione: è il recupero.
I quattro pezzi della pipeline
Ogni sistema RAG, dal più semplice al più sofisticato, ha gli stessi quattro passaggi. Vale la pena capirli uno per uno, perché ognuno è un punto in cui puoi guadagnare o perdere qualità.
1. Chunking: spezzare i documenti
Non indicizzi documenti interi: li spezzi in chunk, pezzi di poche centinaia di parole. Il motivo è duplice: i pezzi corti hanno embedding più "puliti" (il significato non viene schiacciato), e devono starci nel prompt insieme agli altri.
Qui si commette il primo errore classico: spezzare a caso ogni N caratteri, tagliando le frasi a metà. Meglio spezzare su confini naturali — paragrafi, sezioni, titoli — e tenere i chunk di dimensione ragionevole (200-500 token è un buon punto di partenza). Un accorgimento utile è un piccolo overlap tra chunk vicini, così un'informazione a cavallo di due pezzi non si perde.
2. Embedding: trasformare il testo in numeri
Ogni chunk viene dato a un modello di embedding che lo trasforma in un vettore: una lista di numeri che rappresenta il suo significato. Testi che parlano di cose simili finiscono vicini in questo spazio, anche se usano parole diverse. È questo che permette di trovare "quanto costa il servizio" partendo da una domanda su "prezzo dell'abbonamento".
I vettori si salvano in un vector database (Chroma, Qdrant, pgvector se già usi Postgres). Non serve nulla di esotico per iniziare: per qualche migliaio di documenti va bene anche una soluzione locale.
3. Recupero: trovare i pezzi giusti
Alla domanda dell'utente si applica lo stesso modello di embedding, ottenendo un vettore-query. Il database restituisce i chunk i cui vettori sono più vicini — di solito i primi k (per esempio i primi 5). Questi finiscono nel prompt.
È il passaggio più delicato. Se recuperi troppo poco, ti perdi il pezzo che serve; se recuperi troppo, riempi il contesto di rumore e confondi il modello. Un pattern collaudato: recupera 20 candidati e poi rerankali con un modello dedicato (un reranker) che li riordina per pertinenza, tenendone solo i 3-5 migliori. Il reranking è tra gli interventi con il miglior rapporto qualità/costo in un RAG.
4. Generazione con grounding
Infine il modello riceve la domanda più i chunk recuperati, con un'istruzione chiara: rispondi solo in base al contesto fornito, e se la risposta non c'è, dillo. Questo è il grounding, e chiedere anche la citazione della fonte (quale chunk, quale documento) è ciò che rende una risposta RAG verificabile invece che plausibile.
Il problema del contesto perso (e come rimediare)
C'è un difetto sottile nel chunking ingenuo che vale la pena conoscere, perché spiega molti RAG "quasi giusti". Quando spezzi un documento e crei l'embedding di ogni pezzo isolato, i pezzi perdono i riferimenti al resto del testo. Un chunk che dice "la città ha più di 3,8 milioni di abitanti" non contiene la parola "Berlino", che era due paragrafi sopra: il suo embedding non "sa" di parlare di Berlino, e una domanda su Berlino potrebbe non recuperarlo mai.
Sono nate due risposte a questo problema, entrambe utili da conoscere. La contextual retrieval di Anthropic usa un LLM per aggiungere a ogni chunk una frase di contesto prima di calcolarne l'embedding (efficace ma più costosa, perché passa ogni pezzo in un modello). Il late chunking di Jina AI fa l'opposto: dà l'intero documento a un modello di embedding a contesto lungo, e solo dopo spezza la sequenza di token in chunk — così ogni pezzo eredita il contesto di tutto il documento, senza bisogno di un LLM aggiuntivo. Sono due strade diverse per lo stesso obiettivo: chunk che non dimenticano da dove vengono.
Non ti servono al primo esperimento. Ma quando il tuo RAG "manca" risposte che sai essere nei documenti, è quasi sempre qui che si nasconde il problema.
Gli errori che vedrai per primi
Tre sono quasi garantiti. Il primo: chunk troppo grandi o troppo piccoli — troppo grandi diluiscono il significato, troppo piccoli frammentano le idee. Il secondo: fidarsi del solo recupero vettoriale quando la domanda contiene un termine esatto (un codice prodotto, un nome), dove una ricerca ibrida che combina vettori e parole chiave recupera molto meglio. Il terzo, il più insidioso: nessun grounding esplicito, così il modello "completa" con la sua memoria quando il contesto non basta, e tu non te ne accorgi finché non è troppo tardi.
La regola pratica: quando una risposta è sbagliata, non toccare subito il prompt. Guarda prima quali chunk sono stati recuperati. Nove volte su dieci scoprirai che il pezzo giusto non c'era — ed è un problema di recupero, non di generazione.
Prova subito
Non costruire un sistema completo al primo colpo. Fai l'esperimento minimo che ti fa capire dove si rompe la catena:
- Prendi un solo documento che conosci bene (un tuo manuale, un regolamento, un contratto).
- Spezzalo a mano in 8-10 chunk su confini di paragrafo e incollali in un foglio.
- Scrivi 5 domande a cui sai che il documento risponde, comprese un paio "difficili" con riferimenti impliciti ("quanto dura?" senza ripetere l'oggetto).
- Per ogni domanda, scegli a mano i 2-3 chunk che ritieni rilevanti, incollali in una chat con l'istruzione «rispondi solo in base a questi estratti; se l'informazione non c'è, dillo», e verifica la risposta.
In mezz'ora avrai capito con le tue mani la cosa più importante del RAG: la qualità della risposta dipende quasi tutta dalla qualità del recupero. Quando poi automatizzerai con embedding e vector database, saprai già dove guardare quando qualcosa non torna.