Quando un sistema RAG risponde male, il riflesso è riscrivere il prompt, ridurre i chunk o cambiare embedding model. Un articolo di Towards Data Science sostiene che raramente serve: la risposta sbagliata non viene dal prompt, ma da un brick a monte che consegna al modello il context sbagliato, che il modello poi risponde fedelmente. I brick sono quattro — document parsing, question parsing, retrieval e generation — e ciascuno rompe in modo diverso. Ogni caso citato è un run reale su documenti pubblici (NIST, World Bank), riproducibile in un notebook companion.
Parsing: una tabella appiattita in rumore
Sul World Bank Commodity Markets Outlook, alla domanda sul prezzo 2025 del gas naturale (Henry Hub), una pipeline naive estrae testo piatto con get_text() e lo taglia in chunk a lunghezza fissa. La label Henry Hub finisce in un chunk e la sua cella 3.5 in un altro: il modello risponde onestamente “non presente in queste righe”, confidence 0,00. Il fix è il relational parsing: un line_df con una riga per linea di testo e il suo bounding box mantiene label e cella insieme, e la risposta diventa “$3.5 per mmbtu” a confidence 0,99.
Question: una parola che il documento non usa
Su NIST SP 800-207 (Zero Trust), la domanda sui “pillars” fallisce perché il documento chiama quei concetti tenets. Non è un problema di ranking, né lo risolve un top-k più grande: la parola cercata non esiste nel testo. Il fix è nel question parsing, che normalizza ed espande la query mappando i sinonimi di dominio (pillars → tenets, principles), portando la generation a restituire tutti e sette i tenets a confidence 0,95.
Retrieval: la risposta sotto la soglia
Su NIST CSF 2.0, la parola “Profile” compare in molte pagine ma una sola la definisce. Keyword e cosine similarity giudicano tutte le pagine ugualmente rilevanti, e quella che definisce cade sotto il cutoff del top-k: confidence 0,10. Il fix è un retrieval che instrada sulla struttura: leggendo la table of contents con un piccolo LLM, il sistema àncora la ricerca alla sezione giusta. Sul catalogo SP 800-53 di oltre 400 pagine, il retrieval naive diluisce il controllo AU-2 tra mille voci simili (risposta “NA”, 0,00), mentre il router lo individua a 0,98.
Generation: risposta sicura senza self-check
Ultimo caso: la previsione 2026 sul Brent, quando il documento si ferma al 2025. Entrambe le pipeline recuperano il context giusto, ma la generation naive in testo libero afferra il numero più vicino (il valore 2025, $79) e sbaglia con sicurezza. Il fix è un typed generation contract: uno schema con un campo complete_answer_found che il modello deve impostare, obbligandolo a segnalare “non presente” invece di riempire il vuoto.
La lezione: la cura non è un prompt migliore né un modello più grande, ma un contratto per ogni brick — forma relazionale nel parsing, vocabolario del documento nella question, mappa del documento nel retrieval, risposta tipizzata e verificabile nella generation.
In sintesi
- Le allucinazioni RAG sono quasi sempre context sbagliato consegnato da un brick a monte, non invenzioni del modello.
- Ogni brick ha il suo contratto: relational parsing, espansione della query, routing sulla struttura, output tipizzato.
- Su documenti brevi e in prosa il RAG naive regge; il divario si apre su tabelle, vocabolario di settore, lunghezza e struttura.
Fonte: Prompt Engineering Isn’t Enough: How Four Bricks of Context Engineering Stop RAG Hallucinations — https://towardsdatascience.com/prompt-engineering-isnt-enough-how-four-bricks-of-context-engineering-stop-rag-hallucinations/
Hai qualcosa da aggiungere? Unisciti alla discussione.