← Resources
TUTORIAL · 2026-02-12
Costruisci una pipeline RAG di produzione senza LangChain (2026)
Puoi realizzare una pipeline RAG production-grade in poche centinaia di righe componendo SDK del provider, pgvector e un reranker direttamente. Salta le astrazioni di LangChain finché non hai un'esigenza concreta che risolvano davvero.
Perché i team stanno smontando LangChain nel 2026
Entro il 2026, rimuovere LangChain dalla produzione è diventato un pattern di engineering riconoscibile, con postmortem pubblici da team che un tempo lo evangelizzavano. L'insieme delle lamentele è coerente: astrazioni stratificate che oscurano ciò che viene effettivamente inviato al modello, frequenti breaking change tra versioni minor e sessioni di debugging che si trasformano in spedizioni speleologiche tra classi wrapper.
Lo spostamento sottostante è che gli SDK dei provider sono diventati buoni. Gli SDK di OpenAI, Anthropic e Google ora offrono streaming first-class, output strutturati, tool call e batching. Voyage, Cohere e Jina espongono endpoint REST puliti per embedding e reranking. Postgres con pgvector gestisce ricerca ANN fino a circa 10M di vettori senza un database vettoriale dedicato.
Per la maggior parte dei carichi RAG, il framework che volevi nel 2023 è ora quattro chiamate di funzione e una query SQL. Il default ragionevole nel 2026 è iniziare con gli SDK grezzi, aggiungere una sottile astrazione di pipeline quando senti un dolore reale e trattare i framework heavyweight come opt-in.
I cinque stage di cui ogni pipeline RAG ha bisogno
Ogni sistema RAG di produzione, indipendentemente dal framework, si scompone negli stessi cinque stage. Nominarli esplicitamente rende il codice più facile da testare e sostituire a pezzi.
- Ingest: carica i documenti sorgente, normalizza l'encoding, rimuovi il boilerplate.
- Chunk: dividi in unità di retrieval con ID stabili e metadati di sorgente.
- Embed e index: codifica i chunk in un vector store, insieme a un indice lessicale per ricerca ibrida.
- Retrieve e rerank: estrai un insieme ampio di candidati, poi restringi con un reranker cross-encoder.
- Generate e cite: assembla un prompt con il contesto recuperato e restituisce le risposte con l'attribuzione della sorgente.
Mantieni ogni stage come una funzione pura con input e output tipizzati. Lo stage di retrieval non deve sapere quale LLM genererà; lo stage di generazione non deve sapere quale modello di embedding è stato usato. Questa separazione è ciò che i framework promettono e raramente mantengono, perché accoppiano gli stage attraverso oggetti chain opachi. Scriverla da zero richiede un pomeriggio e rimuove una categoria di rischio sugli upgrade.
Strategie di chunking: semantica, ricorsiva e agentica
Il chunking è dove si vince o si perde la maggior parte della qualità RAG. Tre pattern dominano nel 2026.
Lo split ricorsivo per carattere su una gerarchia di separatori (paragrafi, frasi, poi caratteri) è la baseline. È veloce, deterministico e abbastanza buono per la prosa. Il chunking semantico fa l'embedding dei candidati di split e fonde chunk adiacenti i cui embedding sono vicini, producendo unità topicamente coerenti a un maggior costo di ingest. Il chunking agentico chiede a un piccolo LLM di proporre punti di split per documenti strutturati come contratti o trascrizioni, dove titoli e confini di turno contano più del conteggio dei caratteri.
def recursive_chunk(text, max_chars=1200, overlap=150):
seps = ["\n\n", "\n", ". ", " "]
def split(s, depth=0):
if len(s) <= max_chars or depth == len(seps):
return [s]
parts, sep = [], seps[depth]
for p in s.split(sep):
parts.extend(split(p, depth + 1))
return parts
raw = split(text)
return [raw[i] + raw[i+1][:overlap] for i in range(len(raw)-1)] + [raw[-1]]
Inizia ricorsivo, misura, poi passa al semantico solo sulle classi di documento dove la valutazione mostra che paga.
Embedding e reranker: Voyage, BGE e Cohere
Il quadro 2026 per i retriever è più chiaro di un anno fa. Voyage AI, ora parte di MongoDB, offre voyage-3-large come solido modello denso general-purpose e ha rilasciato la famiglia voyage-4 a inizio 2026 con una variante mixture-of-experts puntata sulla cima della leaderboard RTEB. Cohere embed-v4 è l'altro frontrunner di produzione. Per il self-hosting open-weight, bge-m3 di BAAI rimane il default: un singolo modello che supporta retrieval denso, sparso e multi-vector in oltre 100 lingue, con un contesto da 8192 token.
Per il reranking, Cohere rerank-v3.5 è il cavallo da lavoro: un modello multilingua, chunk da 4096 token e circa 80-150 ms di latenza p50 su payload tipici. Voyage rerank-2 è competitivo e si integra in modo pulito se già usi embedding Voyage.
La regola pratica: scegli un embedder denso, un reranker, e congela la coppia dietro un'interfaccia. Cambiarli più tardi costa un reindex, non una riscrittura.
Cablare retrieval, generazione e citazioni
Con pgvector ottieni ricerca ibrida e citazioni in SQL semplice. Memorizza i chunk con il loro document ID, embedding e un tsvector per il recall lessicale. Recupera un insieme ampio di candidati, fai il rerank, poi passa i top N nell'LLM con ID di sorgente espliciti che il modello è istruito a citare.
import psycopg, voyageai, cohere
vo, co = voyageai.Client(), cohere.Client()
def retrieve(query, k=40, top_n=8):
qvec = vo.embed([query], model="voyage-3-large").embeddings[0]
with psycopg.connect(DSN) as conn:
rows = conn.execute(
"SELECT id, doc_id, text FROM chunks ORDER BY embedding <=> %s LIMIT %s",
(qvec, k)).fetchall()
docs = [r[2] for r in rows]
ranked = co.rerank(model="rerank-v3.5", query=query, documents=docs, top_n=top_n)
return [rows[r.index] for r in ranked.results]
```
Per pgvector, usa di default un indice HNSW con m=16 e ef_construction=64, aggiungi un prefilter tenant o di recency così la scansione ANN parte ristretta, e abbina sempre `ORDER BY embedding <=> $1` a un `LIMIT`. Passa i chunk recuperati all'LLM con i loro ID e istruisci il modello a emettere marker di citazione; risolvi quei marker negli URL sorgente in un passaggio di postprocess.
Valutazione: hit rate, MRR e faithfulness
Una pipeline RAG senza una harness di valutazione è un'ipotesi. Costruisci la harness prima di fare qualsiasi tuning. Il kit minimo è un set di query etichettate da 100 a 500 esempi che coprano i tipi di domanda che ti aspetti davvero, più tre metriche.
L'hit rate a K risponde se il chunk corretto è entrato nell'insieme candidati, il che isola la qualità di retrieval. Il mean reciprocal rank cattura quanto in alto è stato classificato il chunk giusto, che è ciò per cui il reranker è pagato. La faithfulness, valutata da un judge LLM istruito a confrontare ogni claim generato con i chunk citati, cattura se il modello ha allucinato oltre il suo contesto.
Esegui la harness su ogni cambio: una nuova dimensione di chunk, un embedder diverso, una modifica al prompt. Traccia le tre metriche nel tempo nella stessa dashboard. Quando un cambio migliora il MRR ma affossa la faithfulness, il reranker sta facendo emergere distrattori e il prompt di generazione ha bisogno di guardrail, non di altro tuning di retrieval.
Quando passare a un orchestratore gestito
Le pipeline scritte a mano rimangono mantenibili finché un solo team le possiede e il conteggio degli stage è piccolo. Il punto in cui un orchestratore gestito ripaga è quando i non-ingegneri devono tunare il retrieval, quando esegui molte pipeline in parallelo per diverse classi di documento o quando vuoi configurazioni versionate e routing A/B senza un redeploy.
A quel punto, la scelta è tra framework heavyweight come LlamaIndex o Haystack e piattaforme config-driven che espongono gli stage di retrieval come unità dichiarative. osStudio, l'editor di orchestrazione no-code in osFoundry, segue il secondo approccio: i cinque stage qui sopra sono oggetti di configurazione di prima classe con embedding e reranking Voyage gestiti dietro un singolo proxy, così mantieni il BYOK lato LLM ed eviti il lock-in del framework lato retrieval.
La domanda utile non è framework versus no-framework. È se la configurazione della tua pipeline merita di essere codice, configurazione o UI, e quella risposta cambia man mano che il team cresce.
Frequently asked questions
- Mi serve davvero un database vettoriale per il RAG?
- Probabilmente no finché non superi diversi milioni di vettori. Postgres con pgvector gestisce comodamente fino a circa 10 milioni di vettori con un indice HNSW, ricerca ibrida via tsvector e filtri SQL standard per tenancy e recency. Erediti backup, replicazione e controllo degli accessi dal database che già operi. I database vettoriali dedicati come Qdrant, Milvus o Weaviate diventano sensati a livello operativo quando ti servono indici shardati su scala di miliardi, filtraggio specializzato a QPS molto alti o feature come retrieval multi-vector che pgvector non eguaglia ancora. Inizia con pgvector e migra solo quando un collo di bottiglia misurato lo impone.
- Un reranker vale davvero la latenza?
- Per la maggior parte dei carichi retrieval-heavy, sì. Un reranker cross-encoder come Cohere rerank-v3.5 o Voyage rerank-2 tipicamente aggiunge da 80 a 200 millisecondi di p50 su un insieme candidati di 40-100 chunk, e alza coerentemente il mean reciprocal rank del 10-30 percento rispetto al solo retrieval denso. La latenza si nasconde dietro qualsiasi chiamata LLM segua, che di solito domina il budget visibile all'utente. Salta il reranker solo per flussi latency-critical stile autocomplete sotto i 200 millisecondi end-to-end, o quando il tuo insieme candidati è già abbastanza piccolo da rendere affidabile il ranking denso.
- Come gestisco l'overlap tra chunk senza gonfiare lo storage?
- Usa piccoli overlap del 10-15 percento della dimensione del chunk, memorizzati come offset di carattere nel documento sorgente piuttosto che come testo duplicato. Al momento del retrieval puoi opzionalmente recuperare il chunk vicino per espansione del contesto. Questo mantiene snello l'indice ed evita di pagare due volte per gli stessi token durante l'embedding. Se ti serve contesto più ricco per la generazione, funziona bene un pattern parent-document: indicizza piccoli chunk per la precisione del retrieval, poi risolvi gli hit al loro parent section prima di passarli all'LLM. Il lookup del parent è una singola query indicizzata e aggiunge latenza trascurabile.
- Qual è il modo più semplice per valutare la qualità del RAG?
- Costruisci un set etichettato di 100-200 query rappresentative con gli ID dei chunk che dovrebbero essere recuperati. Calcola hit rate a K e mean reciprocal rank dal solo stage di retrieval, il che isola la qualità del retriever dal rumore della generazione. Per la faithfulness, usa un judge LLM istruito a confrontare ogni claim generato con i chunk citati e valutare grounded versus unsupported. Esegui i tre numeri su ogni cambio significativo e tratta le regressioni come bloccanti. Questo setup a tre metriche cattura nella pratica la maggioranza delle regressioni RAG ed evita la trappola di ottimizzare un numero mentre silenziosamente ne peggiori un altro.
Sources