RAG e LLM nel 2026: Retrieval-Augmented Generation per colloqui di Data Science
Guida ai colloqui RAG per data science nel 2026. Pipeline RAG, vector database, chunking semantico, embedding, RAG agentico e Graph RAG.

Nel 2026, la Retrieval-Augmented Generation (RAG) si è consolidata come una delle competenze più richieste nei colloqui tecnici per posizioni di data science e machine learning. Questa architettura, che combina la potenza dei Large Language Models (LLM) con sistemi di recupero di informazioni, permette di superare le limitazioni intrinseche dei modelli generativi, come le allucinazioni e la conoscenza statica. I recruiter cercano candidati che non solo comprendano i principi teorici, ma che sappiano anche implementare pipeline RAG robuste e scalabili in ambienti di produzione.
RAG (Retrieval-Augmented Generation) è un'architettura che migliora le risposte degli LLM recuperando dinamicamente documenti rilevanti da una knowledge base prima della generazione, riducendo le allucinazioni e permettendo l'accesso a dati aggiornati.
Architettura della Pipeline RAG
Una pipeline RAG standard si compone di due fasi principali: una fase offline di indicizzazione e una fase online di query. Durante l'indicizzazione, i documenti vengono suddivisi in chunk, convertiti in embedding vettoriali e memorizzati in un vector store. Durante la fase di query, il sistema recupera i chunk più rilevanti e li passa come contesto all'LLM per generare una risposta.
La comprensione di questo flusso rappresenta la base di qualsiasi discussione tecnica durante un colloquio. Gli intervistatori valutano la capacità del candidato di spiegare ogni componente e le scelte architetturali che ne derivano.
# rag_pipeline.py
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
# Offline: ingest documents into the vector store
def build_index(documents: list[str]) -> Chroma:
splitter = RecursiveCharacterTextSplitter(
chunk_size=512, # tokens per chunk
chunk_overlap=64, # overlap preserves context at boundaries
separators=["\n\n", "\n", ". ", " "]
)
chunks = splitter.create_documents(documents)
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
return Chroma.from_documents(chunks, embeddings)
# Online: retrieve + generate
def query(vectorstore: Chroma, question: str) -> str:
retriever = vectorstore.as_retriever(
search_type="mmr", # Maximal Marginal Relevance for diversity
search_kwargs={"k": 5, "fetch_k": 20}
)
prompt = ChatPromptTemplate.from_template(
"Answer based on this context only:\n{context}\n\nQuestion: {question}"
)
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| ChatOpenAI(model="gpt-4o", temperature=0)
)
return chain.invoke(question).contentL'utilizzo di search_type="mmr" garantisce diversità nei risultati di retrieval, evitando che chunk ridondanti occupino la finestra di contesto dell'LLM.
Strategie di Chunking
La suddivisione dei documenti in chunk rappresenta una delle decisioni più critiche nell'implementazione di un sistema RAG. Un chunking inadeguato può compromettere l'intero sistema: chunk troppo piccoli perdono il contesto semantico, mentre chunk troppo grandi diluiscono la rilevanza e consumano token preziosi nella finestra di contesto dell'LLM.
Le strategie di chunking si dividono in tre categorie principali. Il chunking a dimensione fissa suddivide il testo in segmenti di lunghezza predefinita (tipicamente 256-512 token), semplice da implementare ma semanticamente inconsapevole. Il chunking semantico identifica i punti di rottura tematica analizzando la similarità tra frasi consecutive. Il late chunking applica il modello transformer all'intero documento prima di suddividerlo, preservando le dipendenze a lungo raggio.
# semantic_chunking.py
import numpy as np
from sentence_transformers import SentenceTransformer
def semantic_chunk(text: str, threshold: float = 0.3) -> list[str]:
"""Split text where semantic similarity drops below threshold."""
model = SentenceTransformer("all-MiniLM-L6-v2")
sentences = text.split(". ")
embeddings = model.encode(sentences)
chunks, current_chunk = [], [sentences[0]]
for i in range(1, len(sentences)):
# Cosine similarity between consecutive sentences
sim = np.dot(embeddings[i-1], embeddings[i]) / (
np.linalg.norm(embeddings[i-1]) * np.linalg.norm(embeddings[i])
)
if sim < threshold: # topic shift detected
chunks.append(". ".join(current_chunk))
current_chunk = [sentences[i]]
else:
current_chunk.append(sentences[i])
chunks.append(". ".join(current_chunk)) # final chunk
return chunksL'aspetto chiave per i colloqui: la dimensione dei chunk è un trade-off tra precisione e recall. Chunk piccoli (100 token) migliorano la precisione del retrieval ma frammentano il contesto. Chunk grandi (1000 token) preservano il contesto ma diluiscono la specificità dell'embedding. La maggior parte dei sistemi in produzione si attesta tra 256 e 512 token con sovrapposizione del 10-20%.
Vector Database ed Embedding
La scelta del vector database e del modello di embedding influenza direttamente le prestazioni del sistema RAG. I modelli di embedding nel 2026 si sono consolidati attorno ad alcune opzioni ad alte prestazioni. Il modello text-embedding-3-large di OpenAI (3072 dimensioni) e alternative open-source come bge-m3 di BAAI o embed-v4 di Cohere offrono un retrieval multilingue di alto livello.
| Database | Indicizzazione | Gestito | Punto di forza | |----------|----------------|---------|----------------| | Pinecone | Proprietario | Si | Semplicità, scaling serverless | | Weaviate | HNSW | Si/Self | Ricerca ibrida (vettoriale + BM25) | | Milvus | IVF, HNSW | Si/Self | Dataset su scala miliardaria | | Qdrant | HNSW | Si/Self | Filtraggio + storage payload | | pgvector | IVF, HNSW | Self | Integrazione PostgreSQL |
Per le discussioni durante i colloqui, il punto critico è la comprensione dell'algoritmo HNSW (Hierarchical Navigable Small World): costruisce un grafo multilivello dove ogni nodo è connesso ai suoi vicini più prossimi, consentendo una ricerca in O(log n) a fronte di un maggiore utilizzo di memoria.
Pronto a superare i tuoi colloqui su Data Science & ML?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
Retrieval Ibrido: Dense e Sparse Combinati
La ricerca vettoriale pura fallisce con le corrispondenze esatte di keyword e i termini rari. La ricerca lessicale pura (BM25) non coglie la similarità semantica. Il retrieval ibrido combina entrambi gli approcci, e nel 2026 rappresenta lo standard per i sistemi RAG in produzione.
Il pattern standard utilizza Reciprocal Rank Fusion (RRF) per unire i risultati classificati da entrambi i retriever:
# hybrid_retrieval.py
from rank_bm25 import BM25Okapi
import numpy as np
def reciprocal_rank_fusion(
dense_results: list[str],
sparse_results: list[str],
k: int = 60
) -> list[str]:
"""Merge dense (vector) and sparse (BM25) results using RRF."""
scores: dict[str, float] = {}
for rank, doc_id in enumerate(dense_results):
scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
for rank, doc_id in enumerate(sparse_results):
scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
# Sort by combined RRF score, highest first
return sorted(scores.keys(), key=lambda d: scores[d], reverse=True)Il retrieval ibrido risolve il problema del "vocabulary mismatch", dove un utente chiede informazioni sulla "cancellazione di un abbonamento" ma il documento rilevante utilizza il termine "procedura di disdetta del servizio". BM25 cattura la sovrapposizione esatta dei termini, mentre la ricerca vettoriale coglie la relazione semantica.
Reranking per Migliorare la Precisione
Il retrieval restituisce candidati. Il reranking li ordina per rilevanza effettiva. I cross-encoder reranker come Cohere Rerank o bge-reranker-v2.5-gemma2-lightweight valutano ogni coppia query-documento congiuntamente, producendo score di rilevanza molto più accurati rispetto alla similarità bi-encoder.
La pipeline di retrieval a due stadi — ampio recall di prima fase (top 50-100 candidati via vettore + BM25), poi reranking preciso (top 5-10 per il prompt) — è lo standard nei sistemi di produzione.
I cross-encoder sono più accurati dei bi-encoder perché elaborano query e documento insieme attraverso tutti i layer del transformer. I bi-encoder li incorporano indipendentemente, perdendo segnali di interazione a grana fine. Il compromesso è la velocità: i cross-encoder non possono essere pre-indicizzati.
RAG Agentico con LangGraph
Il RAG naive recupera una volta e genera. Il RAG agentico tratta l'LLM come un agente di ragionamento che decide quando recuperare, cosa recuperare e se il contesto recuperato è sufficiente.
Nel 2026, il RAG agentico è il pattern dominante per query complesse che richiedono ragionamento multi-step. L'agente può:
- Auto-valutarsi: Verificare se i documenti recuperati rispondono alla domanda
- Riformulare: Riscrivere la query di ricerca se i risultati iniziali sono insufficienti
- Instradare: Scegliere tra diverse fonti di conoscenza (vector DB, database SQL, API)
- Verificare: Incrociare i fatti attraverso più passaggi recuperati
# agentic_rag.py
from langgraph.graph import StateGraph, END
from typing import TypedDict
class RAGState(TypedDict):
question: str
documents: list[str]
generation: str
retries: int
def retrieve(state: RAGState) -> RAGState:
"""Retrieve documents from vector store."""
docs = vectorstore.similarity_search(state["question"], k=5)
return {"documents": [d.page_content for d in docs]}
def grade_documents(state: RAGState) -> str:
"""Decide if documents are relevant enough to answer."""
prompt = f"Are these documents relevant to: {state['question']}?\n"
prompt += "\n".join(state["documents"])
relevance = llm.invoke(prompt) # returns 'relevant' or 'not_relevant'
return "generate" if "relevant" in relevance.content else "rewrite"
def rewrite_query(state: RAGState) -> RAGState:
"""Reformulate the query for better retrieval."""
new_query = llm.invoke(
f"Rewrite this query for better search results: {state['question']}"
)
return {"question": new_query.content, "retries": state["retries"] + 1}
# Build the agent graph
workflow = StateGraph(RAGState)
workflow.add_node("retrieve", retrieve)
workflow.add_node("grade", grade_documents) # conditional routing
workflow.add_node("rewrite", rewrite_query)
workflow.add_node("generate", generate_answer)
workflow.set_entry_point("retrieve")
workflow.add_edge("retrieve", "grade")
workflow.add_conditional_edges("grade", grade_documents,
{"generate": "generate", "rewrite": "rewrite"})
workflow.add_edge("rewrite", "retrieve") # retry loop
workflow.add_edge("generate", END)Questo pattern — recuperare, valutare, eventualmente riscrivere e riprovare — è noto come Corrective RAG (CRAG). Il framework LangGraph modella il workflow come un grafo ciclico diretto con branching condizionale, rendendo semplice l'aggiunta di step di verifica o checkpoint con intervento umano.
Graph RAG: Recupero Strutturato della Conoscenza
Graph RAG estrae entità e relazioni dai documenti in un knowledge graph, quindi interroga sia il grafo che il vector store. Questa architettura riduce le allucinazioni nelle query fattuali ancorando le risposte in relazioni esplicite tra entità anziché nella similarità di testo non strutturato.
Graph RAG eccelle nelle domande di ragionamento multi-hop come "Quale team guida il progetto che utilizza il framework menzionato nel documento X?" — query che richiedono di collegare fatti attraverso più documenti. La ricerca vettoriale pura ha difficoltà in questi casi perché nessun singolo chunk contiene la risposta completa.
Graph RAG migliora significativamente l'accuratezza fattuale (fino al 40% di riduzione delle allucinazioni su query con molte entità) ma richiede una pipeline di entity extraction matura. Un'estrazione imprecisa produce un grafo impreciso, che può degradare i risultati al di sotto del RAG naive.
Metriche di Valutazione per Sistemi RAG
La valutazione RAG si divide in metriche di retrieval e metriche di generazione. Entrambe devono essere misurate indipendentemente per diagnosticare i guasti.
Metriche di retrieval:
- Recall@k: I documenti rilevanti sono apparsi nei top-k risultati?
- MRR (Mean Reciprocal Rank): Quanto in alto è classificato il primo risultato rilevante?
- NDCG: Il ranking corrisponde all'ordinamento di rilevanza ideale?
Metriche di generazione:
- Faithfulness: La risposta utilizza solo informazioni dal contesto recuperato? (Misura le allucinazioni)
- Answer Relevance: La risposta affronta la domanda originale?
- Context Precision: I chunk recuperati vengono effettivamente utilizzati nella risposta?
Framework come Ragas e DeepEval automatizzano queste valutazioni utilizzando pattern LLM-as-judge.
Modalità di Guasto in Produzione
I sistemi RAG falliscono in modi prevedibili. Conoscere questi pattern è essenziale sia per i colloqui che per il deployment reale.
Inquinamento della finestra di contesto: Si verifica quando troppi chunk recuperati diluiscono il segnale rilevante. L'LLM riceve 10 chunk ma solo 2 contengono informazioni utili. La soluzione: utilizzare un reranker per filtrare e ridurre il top-k del retriever.
Artefatti di chunking: Si verificano quando lo splitting a dimensione fissa spezza frasi, tabelle o blocchi di codice a metà elemento. Il chunking semantico o lo splitting document-aware risolve questo problema.
Embedding drift: Emerge quando il modello di embedding viene aggiornato ma il vector store contiene ancora embedding del vecchio modello. Soluzione: ri-embeddare l'intero corpus dopo ogni cambio di modello.
Indici obsoleti: Forniscono informazioni datate perché la pipeline di ingestione è rimasta indietro rispetto agli aggiornamenti dei documenti.
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.
Conclusione
- RAG combina il retrieval (ricerca vettoriale su una knowledge base) con la generazione LLM per produrre risposte fondate e fattuali senza riaddestrare il modello
- La strategia di chunking ha il maggiore impatto sulla qualità del retrieval — il chunking semantico e il late chunking superano lo splitting a dimensione fissa nella maggior parte dei casi
- Il retrieval ibrido (vettori densi + BM25 sparso) con Reciprocal Rank Fusion è lo standard di produzione, risolvendo il problema del vocabulary mismatch
- I reranker cross-encoder aggiungono un livello di precisione dopo il retrieval ampio, elaborando solo un piccolo set di candidati
- Il RAG agentico (recuperare, valutare, riscrivere, riprovare) e il Graph RAG (estrazione di relazioni tra entità) rappresentano i due maggiori progressi architetturali nel 2026
- La valutazione deve separare le metriche di retrieval (Recall@k, MRR) dalle metriche di generazione (Faithfulness, Answer Relevance) per diagnosticare dove la pipeline si interrompe
- I guasti di produzione più comuni — inquinamento del contesto, artefatti di chunking, embedding drift, indici obsoleti — hanno tutti soluzioni semplici una volta identificati
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.
Tag
Condividi
Articoli correlati

Feature Engineering per Machine Learning: Tecniche e Domande da Colloquio 2026
Guida completa al feature engineering per machine learning: tecniche di selezione, trasformazione e domande frequenti nei colloqui data science 2026.

Top 25 Domande di Colloquio per Data Scientist nel 2026
Le 25 domande più frequenti nei colloqui per data scientist nel 2026, con risposte dettagliate, esempi di codice Python e strategie per affrontare ogni argomento con sicurezza.

Hugging Face Transformers nel 2026: NLP, Fine-Tuning e Domande per Colloqui di Data Science
Guida completa a Hugging Face Transformers v5: architettura API, fine-tuning con LoRA, quantizzazione e le domande NLP più frequenti nei colloqui di data science nel 2026.