Aggiornato a novembre 2026 · CODLAB Team
Risposta diretta: Un sistema Retrieval-Augmented Generation (RAG) affidabile non nasce scegliendo un modello linguistico più grande, ma progettando con rigore la fase di ricerca: chunking strutturale con metadati, retrieval ibrido lessicale e vettoriale in PostgreSQL, reranking cross-encoder, soglie di distanza per il rifiuto esplicito delle domande prive di fonti e verifica delle citazioni su corpora multilingua (DE/IT/EN).
Perché la ricerca applicata sul RAG inizia prima del modello linguistico
Quando un assistente documentale interno fornisce una risposta imprecisa o incompleta durante una prova aziendale, l'attenzione cade quasi sempre sul modello generativo. Nel metodo di ingegneria e ricerca applicata che adottiamo in CODLAB su IA sovrana e gestione dei dati la diagnosi delle cause parte invece uno stadio più a monte, nella fase di recupero (retrieval): un modello può scrivere in modo scorrevole e sbagliare comunque nel merito se il recupero gli consegna tabelle troncate, revisioni superate oppure paragrafi semanticamente vicini ma riferiti a un impianto o a una clausola differente.
Il paradigma Retrieval-Augmented Generation è stato formalizzato da Patrick Lewis et al. (2020) per affiancare alla memoria parametrica dei modelli neurali un indice documentale esplicito e aggiornabile (Lewis et al., NeurIPS 2020, arXiv:2005.11401). Per le imprese industriali, gli studi professionali e le strutture regolamentate del Mittelstand europeo, questa separazione trasforma la domanda di ricerca: non «quale modello ricorda più nozioni generali», bensì «a quali condizioni architetturali la ricerca individua con regolarità i passaggi autorizzati — e quando il sistema riconosce in modo deterministico che manca una base documentale sufficiente?».
La distinzione metodologica tra qualità del recupero e fedeltà della generazione è alla base delle nostre CODLAB Engineering Notes, a partire dalla nota Valutare un sistema RAG: separare retrieval e risposte. In questo articolo analizziamo i singoli mattoni di una pipeline RAG moderna e il metodo sperimentale per verificarli sul proprio patrimonio informativo.
1. Chunking strutturale contro finestre rigide di caratteri
Ogni indicizzazione parte dalla suddivisione dei documenti in frammenti recuperabili (chunk). Nei prototipi rapidi il testo viene spesso tagliato ogni N token con una sovrapposizione fissa. Nei manuali di manutenzione, nelle procedure operative o nei contratti, tuttavia, il taglio meccanico spezza proprio i legami logici da cui dipende la correttezza tecnica:
- Tabelle e valori limite: separare l'intestazione dalle righe interne priva pressioni, coppie di serraggio o termini contrattuali delle rispettive unità di misura e condizioni di validità.
- Regole ed eccezioni: se la regola generale chiude il paragrafo 4.1 e la deroga («non si applica in caso di...») apre il paragrafo 4.2, una finestra fissa genera un frammento autonomo che suggerisce l'esatto opposto della procedura approvata.
- Contesto di revisione: senza metadati strutturali allegati al singolo frammento non è più possibile distinguere una direttiva vigente da una bozza storica.
Per i patrimoni documentali complessi progettiamo perciò nella nostra architettura di destinazione il chunking come trasformazione strutturale anziché come mero conteggio di caratteri: il percorso dei titoli (titolo del documento → capitolo → sottocapitolo) e le tabelle complete di intestazioni restano associati esplicitamente al frammento. Qui distinguiamo con chiarezza tra questa architettura aziendale di destinazione e il sobrio assistente di riferimento (ragbot) nel codice di codlab.de (la cui demo pubblica di chat è spenta da ottobre 2026, con codice e dati conservati): poiché tale modulo è progettato per pagine web sintetiche, il comando rag_ingest converte l'HTML in testo lineare e segmenta per frasi e caratteri con sovrapposizione, senza metadati di gerarchia dei titoli. Nel codice di ragbot è invece implementata l'idempotenza tramite hash SHA-256: il modello Django DocumentChunk archivia source_url, source_title, chunk_index e il campo indicizzato content_hash, saltando i passaggi invariati nelle re-indicizzazioni e ricalcolando solo le sezioni modificate.
Evitiamo volutamente di spacciare una dimensione fissa del chunk come ricetta universale: l'ampiezza ottimale è una variabile sperimentale da misurare sul singolo corpus, bilanciando la precisione puntuale dei frammenti brevi con la coerenza contestuale dei blocchi più estesi.
2. Ricerca vettoriale, ricerca lessicale e retrieval ibrido in PostgreSQL
Le rappresentazioni vettoriali dense (Dense Passage Retrieval, cfr. Karpukhin et al., 2020, arXiv:2004.04906) proiettano frasi e paragrafi in uno spazio continuo in cui formulazioni sinonimiche risultano vicine. Se un tecnico chiede ad esempio «riavvio dopo arresto di emergenza», la similarità coseno può individuare anche il paragrafo intitolato «ripristino della catena di sicurezza». Per la ricerca approssimata dei vicini più prossimi (ANN) in PostgreSQL utilizziamo l'estensione pgvector con indice HNSW (Hierarchical Navigable Small World, cfr. Malkov & Yashunin, arXiv:1603.09320).
Nell'assistente di riferimento (ragbot) questo livello vettoriale è definito nell'ORM di Django (1536 dimensioni, HnswIndex con m=16, ef_construction=64 e operatore vector_cosine_ops) ed esegue unicamente ricerca coseno senza colonne full-text né campi multi-tenant. Nei contesti tecnici e normativi aziendali la sola ricerca vettoriale soffre però di un limite noto: codici ricambio (BG-4410-RevC), riferimenti a norme (DIN EN ISO 13849-1), codici di allarme o articoli di legge vengono spesso compressi dai modelli di embedding in intorni semantici imprecisi.
Nella nostra architettura aziendale di destinazione estendiamo perciò questa base PostgreSQL al retrieval ibrido, senza introdurre un database vettoriale separato che creerebbe disallineamenti di permessi e backup rispetto al database applicativo. All'interno della medesima istanza PostgreSQL operano due canali complementari sotto gli stessi vincoli di autorizzazione:
- Canale semantico: ricerca ANN tramite
pgvectorcon distanza coseno per intercettare parafrasi e concetti correlati. - Canale lessicale: ricerca full-text nativa di PostgreSQL basata su
tsvector,tsquerye indici GIN (PostgreSQL Documentation, Chapter 12: Full Text Search), affiancata da filtri relazionali esatti per codici articolo, pratiche e stato di validità.
Le liste di candidati vengono poi combinate tramite fusione basata sul rango (come Reciprocal Rank Fusion) prima di costruire il prompt. L'interazione tra filtri per tenant, query planner di PostgreSQL e scansione dell'indice HNSW — incluso il motivo per cui una clausola WHERE selettiva può ridurre il recall se non si verificano ef_search e le scansioni iterative dell'indice (che richiedono pgvector ≥ 0.8.0) — è documentata nella nota pgvector con Django: verificare filtri e recall.
# Architettura di destinazione multi-tenant (estensione rispetto al modello di riferimento ragbot privo di tenant_id):
# Filtro deterministico dei permessi PRIMA del calcolo della distanza e della soglia
allowed_chunks = EnterpriseDocumentChunk.objects.filter(
tenant_id=active_tenant.id,
collection__in=user_permitted_collections,
).exclude(embedding=None)
candidates = (
allowed_chunks
.annotate(distance=CosineDistance("embedding", query_vector))
.order_by("distance")[:candidate_pool_size]
)
verified_hits = [c for c in candidates if c.distance is not None and c.distance <= max_distance]
3. Reranking cross-encoder e il problema «Lost in the Middle»
Con l'aumento della finestra di contesto dei modelli moderni può sembrare allettante inserire nel prompt 40 o 60 passaggi estratti lasciando scegliere al modello. Lo studio empirico di Nelson F. Liu et al. mostra perché questa scorciatoia penalizza precisione e tempi di risposta (Liu et al., «Lost in the Middle: How Language Models Use Long Contexts», arXiv:2307.03172): i modelli linguistici sfruttano bene le informazioni poste all'inizio e alla fine del contesto, ma perdono sensibilmente accuratezza quando il dettaglio decisivo si trova nella fascia centrale. Contemporaneamente crescono latenza, occupazione della KV-cache e rischio di passaggi contraddittori.
Un'architettura a due stadi supera il problema tramite reranking con cross-encoder (cfr. Nogueira & Cho, 2019, arXiv:1901.04085):
- Stadio 1 (selezione rapida): il retrieval ibrido restringe l'archivio autorizzato a un insieme circoscritto di candidati (ad esempio Top-25 fino a Top-40); la latenza effettiva di query non è una costante universale, ma dipende da dimensione del corpus, parametri HNSW (
m,ef_search), selettività dei filtri e hardware, e va misurata sul dataset reale. Poiché i bi-encoder codificano domanda e documento separatamente, le interazioni fini tra token non sono ancora valutate. - Stadio 2 (riordinamento fine): un modello cross-encoder valuta congiuntamente domanda e singolo passaggio attraverso tutti i livelli di attenzione, promuovendo nel prompt finale solo i pochi estratti realmente pertinenti e deduplicati.
Altrettanto essenziale è una soglia esplicita di rilevanza. Nell'assistente di riferimento (ragbot) nel codice di codlab.de la logica di recupero scarta tutti i frammenti con distanza coseno superiore a 0.62 (MAX_DISTANCE = 0.62 su recupero Top-5). Se nessun passaggio supera il filtro, il backend non interpella il modello generativo per indovinare, ma restituisce un rifiuto trasparente invitando al contatto diretto. Nei processi aziendali, l'astensione controllata è un requisito ingegneristico primario.
4. Citazioni, grounding e perché un rimando numerico non basta
Mostrare riferimenti cliccabili come [1] o [2] è ormai prassi diffusa. Anche il nostro assistente di riferimento (ragbot) nel codice di codlab.de numera i blocchi di contesto, deduplica gli URL delle fonti e vincola il modello a rispondere solo in base ad essi. Nella ricerca applicata distinguiamo però con nettezza tra formato della citazione e effettivo ancoraggio testuale (grounding / faithfulness).
Un modello può apporre un marcatore [1] formalmente valido omettendo una condizione restrittiva presente nella fonte [1], oppure fondendo indebitamente due frasi riferite a casi distinti. Inoltre i documenti recuperati vanno sempre trattati come dati non attendibili che possono contenere istruzioni anomale o conflittuali, tema approfondito nella nota RAG: le fonti come dati non attendibili.
Nei protocolli di verifica scomponiamo quindi ogni risposta in affermazioni elementari e controlliamo che ciascuna sia effettivamente sostenuta dal testo citato, incluse eventuali limitazioni operative.
5. Archivi documentali multilingua (DE/IT/EN) nelle imprese europee
Molte aziende manifatturiere e di servizi tra Germania, Italia e mercati internazionali lavorano ogni giorno su tre lingue: direttive interne in tedesco, specifiche tecniche di fornitori italiani in italiano e schede componenti o software in inglese. Un sistema RAG progettato per una sola lingua mostra subito due punti di rottura: la ricerca lessicale fallisce tra lingue diverse e la traduzione improvvisata di termini tecnici introduce ambiguità.
Per i corpora multilingua (DE/IT/EN) adottiamo tre accorgimenti combinabili:
- Embedding multilingua con metadato esplicito della lingua: i modelli vettoriali multilingua allineano concetti equivalenti tra tedesco, italiano e inglese mantenendo tracciata la lingua originale di ciascun documento.
- Espansione controllata tramite glossario aziendale: sigle interne, nomi di componenti e termini regolatori vengono mappati prima della ricerca per preservare l'efficacia del canale lessicale.
- Trasparenza linguistica in uscita: la risposta viene redatta nella lingua della domanda ma dichiara il titolo e la lingua originale della fonte citata, consentendo agli specialisti la verifica sul testo autentico. I controlli ingegneristici su localizzazione, URL e metadati sono descritti anche in Django i18n: verificare lingua, URL e metadati.
6. Protocollo sperimentale sintetico per decisori tecnici
Nota metodologica: lo scenario seguente è interamente sintetico e ha scopo esclusivamente illustrativo; non descrive un progetto cliente né risultati misurati presso clienti.
Immaginiamo un'azienda metalmeccanica che intenda offrire ai tecnici di assistenza una ricerca interna su manuali di manutenzione (tedesco), schede elettroniche (inglese) e verbali di collaudo fornitori (italiano). Prima di qualsiasi estensione su larga scala impostiamo una verifica riproducibile:
- Perimetro del corpus di prova: selezione di 30–50 documenti approvati, includendo intenzionalmente due revisioni dello stesso manuale e un documento riservato per il test negativo sui permessi.
- Catalogo di domande con passaggi attesi: raccolta di quesiti reali di assistenza — codici errore esatti, domande trasversali DE/IT/EN, versioni in conflitto e domande prive di risposta nel corpus.
- Confronto misurato delle varianti: valutazione separata del recupero vettoriale puro rispetto al retrieval ibrido con reranking su Recall@k dei passaggi attesi, correttezza dell'astensione e fedeltà delle singole affermazioni.
- Criteri di rilascio documentati: il passaggio a un pilota operativo avviene solo quando il recupero è riproducibile e l'isolamento dei permessi è verificato a livello di database.
Il perimetro operativo di questi progetti è descritto nella pagina Assistenti documentali. Per discutere come impostare una verifica tecnica sul vostro patrimonio documentale potete contattarci tramite Contatto e richiesta progetto.
Approfondimenti nella serie di ricerca: per misurare in modo riproducibile recupero e fedeltà delle risposte in presenza di decodifica non deterministica rimandiamo all'articolo su esecuzioni ripetute e metriche separate per sistemi IA stocastici; per le difese architetturali contro istruzioni ostili nei documenti recuperati si veda l'analisi su Indirect Prompt Injection e confini tra le fonti.
Fonti primarie verificate
- Lewis, P. et al. (2020): Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (NeurIPS 2020, arXiv:2005.11401).
- Karpukhin, V. et al. (2020): Dense Passage Retrieval for Open-Domain Question Answering (EMNLP 2020, arXiv:2004.04906).
- Malkov, Yu. A. & Yashunin, D. A. (2016/2018): Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs (arXiv:1603.09320).
- Nogueira, R. & Cho, K. (2019): Passage Re-ranking with BERT (arXiv:1901.04085).
- Liu, N. F. et al. (2023/2024): Lost in the Middle: How Language Models Use Long Contexts (TACL, arXiv:2307.03172).
- PostgreSQL Global Development Group: PostgreSQL Documentation — Chapter 12: Full Text Search e pgvector v0.8.0.
Domande frequenti (FAQ)
Le finestre di contesto estese restano soggette al fenomeno Lost in the Middle, aumentano latenza e memoria KV-cache a ogni richiesta e non sostituiscono il controllo degli accessi per ruolo, il filtro delle revisioni e la tracciabilità delle fonti su migliaia di documenti.
Nella maggior parte degli scenari aziendali no: PostgreSQL con pgvector (indice HNSW) e Full Text Search nativa consente di gestire ricerca semantica, ricerca lessicale, filtri relazionali e permessi per tenant in un unico database transazionale.
La soglia scarta i frammenti troppo distanti dalla domanda. Se nessun passaggio autorizzato rientra nel limite stabilito, il sistema rifiuta la risposta in modo trasparente anziché lasciare improvvisare il modello linguistico senza fonti.
Si combinano modelli di embedding multilingua con un glossario tecnico controllato per codici e termini di dominio, generando la risposta nella lingua dell’utente ma indicando sempre il documento originale citato.
Guida operativa correlata (in tedesco): KI-Dokumentensuche auf Ihren eigenen Daten: Was vor dem Pilot geklärt sein sollte.