Un’azienda mette in piedi un assistente che risponde alle domande sui propri manuali interni. Il collaudo va bene: «come si configura la VPN?» restituisce la pagina giusta, il modello sintetizza, tutti applaudono. Due settimane dopo arriva la prima domanda vera di un dipendente spazientito: «il client mi dà errore 809, cosa faccio?». Il sistema pesca tre paragrafi che parlano genericamente di connessioni sicure, nessuno menziona l’errore 809, e il modello — costretto a rispondere con quel poco — inventa una procedura che non esiste. Il documento con la soluzione era nel database. Semplicemente, non è stato trovato. È il punto cieco del RAG ingenuo, ed è quasi sempre un problema di recupero, non di generazione.
Riscrittura della domanda, reranking, Self-RAG e RAG agentico sono trattati nel libro.
Dove il RAG da manuale si rompe
Ripassiamo la versione base, quella di ogni tutorial. Si spezzano i documenti in pezzi (chunk), si trasforma ogni pezzo in un vettore con un modello di embedding, si salva tutto in un database vettoriale. Quando arriva una domanda, la si trasforma nello stesso spazio vettoriale, si cercano i k pezzi più vicini per similarità semantica e li si incolla nel prompt del modello. Semplice, elegante, e sorprendentemente fragile.
Fragile perché scarica tutto il peso su un singolo passaggio: la vicinanza tra il vettore della domanda e quello del pezzo giusto. Ma la domanda dell’utente è spesso mal posta — ellittica, gergale, piena di sottintesi. La similarità semantica premia i testi che «parlano dello stesso argomento in generale», non quelli che contengono la risposta esatta. E un codice d’errore come 809, che per un embedding è quasi rumore, per l’utente è tutto. Il RAG avanzato non è una tecnica sola: è la decisione di non fidarsi di quell’unico passaggio, e di circondarlo di controlli. Tre in particolare.
Query rewriting: sistemare la domanda prima di cercare
La prima mossa è non cercare mai con la domanda grezza dell’utente. Un modello linguistico può riscriverla prima che tocchi il database. Le varianti utili sono poche e concrete. La riscrittura vera e propria trasforma «e per il mio, invece?» — che da solo non significa niente — nella domanda autoconclusiva ricostruita dal contesto della conversazione. La decomposizione spezza una domanda composta («differenze di prezzo e di garanzia tra i due piani») in sotto-domande separate, ciascuna cercata per conto proprio. La generazione multi-query produce tre o quattro riformulazioni della stessa domanda e le lancia tutte, allargando la rete.
C’è poi un trucco controintuitivo che funziona sorprendentemente bene: invece di cercare con la domanda, si chiede al modello di immaginare la risposta ideale — anche inventata di sana pianta — e si cerca con quella. Il ragionamento è questo: una risposta plausibile assomiglia, nello spazio degli embedding, ai documenti che contengono la risposta vera, molto più di quanto ci assomigli una domanda. È come cercare un libro in biblioteca portando non il titolo, ma un paragrafo scritto di getto su come dovrebbe suonare: si finisce nello scaffale giusto anche senza conoscere l’autore.
La domanda dell’utente è un punto di partenza, non una query. Il primo compito del sistema è tradurla in qualcosa che il database sappia davvero cercare.
Hybrid search: due modi di cercare che sbagliano in punti diversi
Qui entra il secondo controllo, ed è il più sottovalutato. Esistono due famiglie di ricerca testuale, con debolezze complementari. La ricerca densa — quella per embedding — coglie il significato: capisce che «automobile» e «vettura» sono la stessa cosa, che «come stampo un documento» e «istruzioni per la stampante» si somigliano. Ma è opaca sui termini rari ed esatti: nomi propri, codici, sigle, numeri di versione. La ricerca sparsa — la vecchia gloria BM25, che conta le parole in comune pesandole per la loro rarità — fa l’opposto: trova al primo colpo errore 809 o art. 13, ma è cieca di fronte ai sinonimi. Chiedi «auto elettrica» e non ti restituisce il documento che dice solo «veicolo a batteria».
L’hybrid search le fa girare entrambe e ne fonde i risultati. La ricetta standard è quasi banale nella sua semplicità: la reciprocal rank fusion. Non serve nemmeno che i due sistemi restituiscano punteggi confrontabili — cosa notoriamente difficile, dato che una distanza coseno e un punteggio BM25 vivono su scale diverse. Si guarda solo la posizione di ogni documento in ciascuna classifica: chi compare in alto in almeno una delle due liste prende un punteggio combinato alto e sopravvive. È il pragmatismo di due bibliotecari diversi che confrontano gli appunti — uno ricorda i libri per argomento, l’altro per titolo esatto — e insieme sbagliano molto meno di ciascuno da solo.
Lo schema: la pipeline con il reranker
Vale la pena vedere l’intero flusso in un’immagine, perché il terzo controllo — il reranker — ha senso solo alla luce di dove si colloca: alla fine, come filtro finale su tutto ciò che i passaggi precedenti hanno raccolto con generosità.
La pipeline del RAG avanzato: la domanda viene riscritta, cercata in parallelo con due metodi complementari, i risultati vengono fusi in una lista ampia di candidati e infine il reranker ne promuove solo una manciata. Si recupera in abbondanza, si filtra con precisione.
Il reranker: un secondo lettore più lento e più attento
C’è una tensione al cuore del recupero: recall contro precisione. Vuoi essere sicuro che il documento giusto sia tra quelli pescati — recall alto: pesca in abbondanza, magari cinquanta pezzi — ma vuoi anche che i pochi pezzi che finiscono nel prompt siano quelli davvero pertinenti — precisione alta — perché la finestra di contesto è limitata e ogni pezzo irrilevante distrae il modello. Le due cose tirano in direzioni opposte.
Il reranker scioglie la tensione dividendo il lavoro in due tempi. Il recupero iniziale usa dei bi-encoder: la domanda e ogni documento vengono trasformati in vettori separatamente, e i vettori dei documenti sono precalcolati una volta per tutte. Velocissimo su milioni di pezzi, ma la domanda e il documento non si «guardano» mai davvero: si confrontano solo i loro riassunti vettoriali. Il reranker è invece un cross-encoder: prende la coppia domanda-documento insieme, la dà in pasto a un modello che legge entrambe parola per parola e produce un punteggio di pertinenza molto più affidabile. Il costo è che va rieseguito per ogni coppia — impensabile su un milione di documenti, perfettamente sostenibile sulle cinquanta candidature sopravvissute alla fusione. Bi-encoder come buttafuori all’ingresso, cross-encoder come esaminatore all’ultima porta.
Cosa portarsi a casa
Il messaggio pratico è che quando un sistema RAG «non capisce», quasi mai il problema è il modello linguistico, e quasi mai la soluzione è sostituirlo con uno più grande. Il problema è a monte: il pezzo giusto non è arrivato nel contesto. Prima di toccare il modello conviene guardare il recupero, e conviene farlo in quest’ordine, dal più economico al più costoso. La ricerca ibrida è quasi gratis e risolve da sola la maggior parte dei casi in cui codici, sigle e nomi propri vanno persi. Il reranking costa qualche decina di millisecondi in più per domanda e alza la precisione in modo netto. La riscrittura delle query costa una chiamata al modello aggiuntiva, e conviene attivarla dove le domande sono ellittiche o conversazionali. Nessuna delle tre è una trovata sofisticata: sono tre modi di non fidarsi di un singolo passaggio fragile. E vale la pena conoscerle perché il divario tra un RAG da demo e uno che regge le domande vere — quelle scritte male, di fretta, da chi ha davvero un problema — sta quasi tutto qui.

I commenti sono riservati agli iscritti.
Accedi per commentare