04 - Retrieval-Augmented Generation
Inizia da qui: RAG passo-passo.
Dopo la lezione: approfondimento su RAG in produzione.
Architettura
flowchart LR
D[Documenti] --> C[Parsing + chunking]
C --> E[Embedding]
E --> I[(Indice + metadati)]
Q[Domanda] --> R[Query rewrite]
R --> H[Hybrid retrieval]
I --> H
H --> X[Reranking]
X --> G[LLM con citazioni]
G --> A[Risposta o astensione]
Il RAG ha almeno due sistemi da valutare separatamente:
- retrieval: ha recuperato evidenza rilevante?
- generation: la risposta è fedele all'evidenza?
Decisioni fondamentali
Parsing e chunking
Chunk per struttura semantica, non solo ogni N caratteri. Conserva titolo, sezione, fonte, timestamp, permessi e posizione. Overlap e chunk enormi possono aumentare rumore e costo.
Retrieval
- dense retrieval cattura similarità semantica;
- BM25 cattura parole esatte, codici e nomi;
- hybrid combina i due ranking;
- reranker migliora precisione sui candidati;
- filtri metadata applicano tenant, permessi, lingua e validità temporale.
Risposta
Il modello deve citare chunk identificabili, distinguere evidenza da inferenza e astenersi quando il contesto è insufficiente. Le autorizzazioni si applicano prima del retrieval, non nel prompt.
Esempio di contratto
from dataclasses import dataclass
from typing import Protocol
@dataclass(frozen=True)
class Document:
id: str
text: str
source: str
score: float
class Retriever(Protocol):
async def search(
self, query: str, *, tenant_id: str, limit: int = 8
) -> list[Document]: ...
La funzione RAG dipende da Retriever, non da un database vettoriale specifico.
Metriche
| Layer | Metriche |
|---|---|
| Retrieval | Recall@k, Precision@k, MRR, NDCG |
| Generation | faithfulness, correctness, citation precision/recall |
| Sistema | answer rate, latency p95, costo/query, error rate |
| Prodotto | task completion, escalation, feedback corretto |
Costruisci un golden set con domanda, fonti rilevanti, risposta attesa e casi senza risposta. La "LLM-as-judge" aiuta, ma va calibrata su giudizi umani.
Laboratorio
Costruisci un assistente su 20-50 documenti tecnici.
- Ingestion idempotente con hash, metadati e versionamento.
- Due strategie di chunking.
- BM25 come baseline, dense e hybrid come candidati.
- Golden set di almeno 40 domande, 10 delle quali senza risposta.
- Confronto Recall@5, faithfulness, p95 e costo.
- Citazioni verificabili e astensione esplicita.
- Test di prompt injection contenuta nei documenti.
- Filtro obbligatorio per
tenant_id.
Esperimento minimo: cambia una sola variabile alla volta e salva configurazione e metriche. Non scegliere la pipeline guardando esempi manuali.
Criterio di successo: Recall@5 >= 0,85 sulle query answerable/autorizzate, zero risultati non autorizzati e ogni affermazione fattuale contiene una citazione valida oppure il sistema si astiene. Misura separatamente i casi senza risposta.
Failure mode
Chunk errato, documento non parsato, embedding mismatch, filtri mancanti, query ambigua, retrieval rumoroso, contesto perso nel mezzo, citazione inventata, indice stale, injection dal documento e autorizzazione applicata troppo tardi.