RAG: Retrieval-Augmented Generation Explained
I Model de limbă mare (LLM) ele reprezintă una dintre inovaţiile tehnologice cele mai perturbatoare din ultimii ani: GPT-4, Claude, Gemeni și Llama pot scrie cod, rezuma documente, răspunde la întrebări complexe și chiar argumentează probleme abstracte. Cu toate acestea, ei suferă de un defect structural care le limitează drastic aplicabilitatea contexte profesionale: halucinații.
Când un LLM nu știe răspunsul, nu spune „Nu știu”. În schimb, generați text plauzibil dar complet fals, pe atât de sigur pe cât prezintă fapte verificabile. Într-un cadru comercial, juridic sau medical, acest comportament este inacceptabil. Solutia mai eficient și mai matur la această problemă se numește Recuperare-Augmented Generation (RAG).
În acest prim articol al seriei Inginerie AI și RAG avansat, vom pleca de la bază: ce este RAG, cum funcționează, de ce rezolvă problema halucinațiilor și cum să construiți un sistem RAG funcțional de la zero. Când ați terminat, veți avea o înțelegere cunoștințe solide ale întregii arhitecturi și vei fi gata să aprofundezi fiecare componentă individuală în articolele ulterioare.
Prezentare generală a seriei
| # | Articol | Concentrează-te |
|---|---|---|
| 1 | Sunteți aici - a explicat RAG | Fundamente și arhitectură completă |
| 2 | Înglobări și căutare semantică | Cum textele devin vectori |
| 3 | Baza de date vectorială în profunzime | Stocare, indexare, căutare de similaritate |
| 4 | RAG cu LangChain și Python | Implementare practică de la capăt la capăt |
| 5 | Recuperare hibridă și reclasificare | Cuvânt cheie hibrid + căutare semantică |
| 6 | Fereastra context și inginerie promptă | Optimizați contextul pentru LLM |
| 7 | RAG în producție | Scalare, monitorizare, evaluare |
| 8 | Grafice de cunoștințe și RAG-uri | Grafice de cunoștințe + regăsire |
| 9 | Sisteme multi-agenți | Agenți AI colaborativi |
| 10 | Viitorul RAG | Tendințe, cercetare și următorii pași |
Ce vei învăța
- Ce este RAG și ce problemă fundamentală rezolvă pentru LLMs
- Arhitectura completă: de la pregătirea documentelor până la generarea răspunsului
- Cum funcționează înglobările, stocările de vectori și căutările de similaritate
- Strategiile de fragmentare și compromisurile lor
- Cum să construiți un sistem RAG funcțional minim cu Python
- Diferențele dintre Naive RAG și Advanced RAG
- Când să utilizați RAG vs reglaj fin vs inginerie promptă
1. Problema halucinațiilor la LLM
Pentru a înțelege de ce este necesar RAG, trebuie mai întâi să înțelegem problema pe care o rezolvă. Modelele de limbaj mari sunt în esență modele probabilistice ale limbajului: având în vedere un text de intrare, ei prezic cea mai probabilă secvență de jetoane ca o continuare. Această arhitectură, bazată pe mecanismul de Atenţie de Transformers, produce rezultate extraordinare dar are o limitare intrinsecă: modelul nu „știe” nimic în sens uman a termenului. Generați text plauzibil din punct de vedere statistic pe baza modelelor învățate antrenamentul.
Cele trei probleme structurale ale LLM
| Problemă | Descriere | Impact practic |
|---|---|---|
| Cutofă de cunoștințe | Cunoștințele sunt înghețate la data antrenamentului | Nu există informații despre evenimente recente sau date de proprietate |
| Halucinații | Generați răspunsuri plauzibile, dar complet fabricate | Informații false prezentate cu mare încredere |
| Fără ghilimele | El nu poate indica sursa declarațiilor sale | Imposibil de verificat corectitudinea răspunsurilor |
| Fără date private | Nu cunoaște documentația internă a companiei | Inutil pentru cazuri specifice de utilizare fără context |
Halucinațiile nu sunt un bug unic: ele sunt o consecință directă a arhitecturii. Când modelul nu are suficiente informații pentru a răspunde, nu returnează o eroare. În schimb, generează cea mai probabilă continuare a textului, care poate fi complet inventat. Modelul a fost antrenat pentru a produce text fluent, coerent, nu pentru fi corect din punct de vedere faptic.
Exemple concrete de halucinații
Pentru a înțelege gravitatea problemei, să luăm în considerare scenariile reale în care apar halucinații au consecințe semnificative:
- Domeniul de aplicare legal: Un LLM ar putea cita hotărâri inexistente sau legi niciodată promulgate cu numere de articole credibile, dar inventate
- Domeniul medical: Poate sugera doze incorecte de medicamente sau interacțiuni medicamentoase nedocumentate
- Documentatie tehnica: Poate descrie API-uri cu parametri care nu există sau caracteristici care nu au fost niciodată implementate
- Asistență clienți: Ei ar putea inventa politici ale companiei, proceduri de returnare sau garanții inexistente
Statisticile confirmă amploarea problemei: ratele halucinațiilor variază semnificativ pe domenii, cu domenii de specialitate precum medicina si dreptul care inregistreaza rate de 10-20% chiar si cu cele mai avansate modele. RAG reprezintă tehnica cel mai eficient în atenuarea acestei probleme, cu reduceri documentate de până la 71%.
2. Ce este RAG: Definiție și origini
Recuperare-Augmented Generation (RAG) este o paradigmă arhitecturală care combină un sistem de regăsirea informațiilor (recuperare document) cu un șablon generative (LLM) pentru a produce răspunsuri bazate pe date reale. Conceptul a fost formalizat în 2020 de Patrick Lewis și colegii de la Meta AI în lucrarea fundamentală „Generație de recuperare sporită pentru sarcini NLP intensive în cunoștințe”.
Perspectiva cheie este simplă: în loc să-i ceară modelului să-și „amintească” toate informatii din pregatirea sa, ii punem la dispozitie documentele relevante in momentul de generație. Acest proces se numește împământare: generarea ancorelor la surse concrete şi verificabile.
LLM TRADIZIONALE:
Domanda utente ──────────────────> [LLM] ──> Risposta
|
Basata SOLO su training data
Rischio allucinazione: ALTO
RAG (Retrieval-Augmented Generation):
Domanda utente ──> [RETRIEVAL] ──> Documenti rilevanti
| |
| v
└───────> [LLM + Contesto] ──> Risposta con citazioni
|
Basata su DATI REALI recuperati
Rischio allucinazione: BASSO
Analogie: examenul de carte deschisă
Imaginează-ți un examen universitar. LLM tradițional este ca un student care trebuie să răspundă pe de rost: știe multe, dar poate să se încurce sau să inventeze detalii. RAG este ca o examen carte deschisă: elevul își poate consulta notițele și cărțile înainte de a răspunde. Răspunsul va fi mai precis și mai verificabil pentru că este fondat pe surse concrete.
Conceptul de împământare este crucial: fiecare afirmație din răspunsul generat poate fi urmărit până la un document specific din baza de cunoștințe. Aceasta înseamnă că:
- Răspunsurile sunt verificabil: Puteți verifica documentul sursă
- Răspunsurile sunt actualizabil: Prin actualizarea documentelor, răspunsurile se schimbă automat
- Răspunsurile sunt controlabil: tu decizi ce documente poate consulta sistemul
- Răspunsurile sunt trasabil: Puteți include citate cu referire la sursă
3. Cum funcționează RAG: conducta completă
Un sistem RAG este alcătuit din două macrofaze: conductă de indexare, care întocmește documente ocazional (sau periodic), și cel conductă de interogări, care gestionează interogările utilizatorilor în timp real.
3.1 Indexarea conductei (faza offline)
Faza de indexare transformă documentele brute într-o structură optimizată pentru căutare semantică. Constă din patru pași succesivi:
[Documenti Sorgente]
| PDF, HTML, Markdown, CSV, database, API, email...
v
[1. DOCUMENT LOADING]
| Estrazione del testo grezzo dai formati sorgente
| Preservazione dei metadati (autore, data, titolo)
v
[2. CHUNKING (Text Splitting)]
| Divisione in frammenti di dimensione gestibile
| Strategie: fixed-size, semantic, recursive
| Overlap tra chunk per preservare contesto
v
[3. EMBEDDING]
| Trasformazione di ogni chunk in un vettore numerico
| Modelli: OpenAI, Sentence Transformers, Cohere
| Dimensioni tipiche: 384, 768, 1536, 3072
v
[4. VECTOR STORE]
| Salvataggio dei vettori in un database specializzato
| Indexing per ricerca veloce (HNSW, IVF)
| ChromaDB, Pinecone, Weaviate, Milvus, Qdrant
v
[Knowledge Base Pronta per le Query]
3.2 Conducta de interogări (faza online)
Când un utilizator pune o întrebare, canalul de interogări intră în acțiune pentru a găsi cele mai relevante documente și generează un răspuns bine întemeiat:
[Domanda dell'Utente]
| "Come configuro l'autenticazione OAuth nella nostra app?"
v
[1. QUERY EMBEDDING]
| La domanda viene trasformata in vettore
| Stesso modello usato nell'indicizzazione!
v
[2. SIMILARITY SEARCH]
| Ricerca dei chunk più simili nel vector store
| Metriche: cosine similarity, L2, dot product
| Restituisce i top-k risultati (tipicamente k=3..10)
v
[3. CONTEXT ASSEMBLY]
| I chunk recuperati vengono assemblati in un contesto
| Ordinamento per rilevanza, deduplicazione
v
[4. PROMPT CONSTRUCTION]
| Costruzione del prompt con contesto + domanda
| Template: "Basandoti sui seguenti documenti, rispondi..."
v
[5. LLM GENERATION]
| Il modello genera la risposta basandosi sul contesto
| Può includere citazioni ai documenti sorgente
v
[Risposta Fondata + Citazioni]
Regula fundamentală: consistența înglobărilor
E' obligatoriu utilizați același model de încorporare în ambele indexare decât în faza de interogare. Diferite modele produc spații vectoriale incompatibil: vectorii generați de un model nu sunt comparabili cu cei a altuia. Schimbarea modelului de încorporare necesită o reindexare completă a tuturor documentelor.
4. Procesarea documentelor: fragmentare și pregătire
Il în bucăţire este una dintre cele mai critice faze ale întregii conducte RAG. Calitatea rezultatelor depinde în mare măsură de modul în care sunt împărțite documentele. Bucățile care sunt prea mari diluează semnalul semantic și pierd spațiu în fereastra de context al LLM. Bucățile care sunt prea mici pierd contextul necesar pentru a fi înțelese.
4.1 Dimensiuni fixe
Cea mai simplă strategie: împărțiți textul în blocuri de dimensiune fixă (de exemplu, 500 de jetoane) cu o suprapunere opțională între bucăți consecutive.
Fixed-Size Chunking parametri
| Parametru | Descriere | Valoare tipică |
|---|---|---|
| chunk_size | Dimensiunea maximă a fiecărei bucăți în jetoane sau caractere | 300-500 de jetoane |
| chunk_overlap | Suprapunere între bucăți consecutive | 10-20% din dimensiunea bucății |
| separator | Caracter/șir folosit pentru a împărți | "\n\n", "\n", " " |
Documento originale (1500 token):
"Lorem ipsum dolor sit amet... [1500 token di testo]"
Con chunk_size=500 e overlap=50:
Chunk 1: token 1-500 ────────────┐
Chunk 2: token 451-950 ──┐ overlap │
Chunk 3: token 901-1400 ──┘ │
Chunk 4: token 1351-1500 │
────────────┘
L'overlap garantisce che il contesto ai bordi non venga perso.
4.2 Divizarea caracterelor recursive
Strategie mai sofisticată care încearcă să divizeze respectând structura documentului. Utilizați o ierarhie de separatori: mai întâi încercați să împărțiți la paragrafe ("\n\n"), apoi prin rânduri ("\n"), apoi prin propoziții (". "), în cele din urmă prin cuvinte (" "). Acest lucru păstrează contextul semantic mai bine decât dimensiunea fixă.
4.3 Chunking semantic
Cea mai avansată strategie: utilizați încorporațiile în sine pentru a determina unde să divizați. Calculați asemănarea dintre propozițiile consecutive și creați o nouă bucată atunci când asemănarea scade sub un prag, indicând o schimbare de subiect. Produce bucăți de dimensiune variabil dar coerent din punct de vedere semantic.
Compararea strategiilor de fragmentare
| Strategie | calitate | Complexitate | Când să-l folosești |
|---|---|---|---|
| Dimensiune fixă | De bază | Minim | Prototipări, documente omogene |
| Recursiv | Bun | Scăzut | Scop general, documente structurate |
| Semantică | Excelent | Ridicat | Documente eterogene necesare de înaltă calitate |
Importanța metadatelor
Fiecare bucată ar trebui să poarte cu ea zei metadate: titlul documentului, autor, data, sectiune, pagina. Aceste metadate sunt esențiale pentru filtrare în timpul căutării dvs. și pentru a genera citații precise în răspunsul dvs. O bucată fără metadatele sunt ca un paragraf fără context.
5. Embeddings: Transformarea textului în vectori
The înglobări ele sunt inima matematică a RAG. O încorporare este a reprezentare numerică (un vector de numere zecimale) care surprinde sens semantic a unui text. Două propoziții cu sens similar vor avea vectori „în apropiere” în spațiul multidimensional, indiferent de cuvintele folosite.
INPUT: Frase di testo
OUTPUT: Vettore di numeri decimali (es. 1536 dimensioni)
Esempio:
"Il gatto dorme sul divano" --> [0.23, -0.45, 0.67, 0.12, -0.89, ...]
"Il felino riposa sul sofa" --> [0.22, -0.44, 0.68, 0.11, -0.88, ...]
^^ Vettori molto SIMILI (stesso significato)
"Il prezzo dell'oro sale" --> [-0.56, 0.78, -0.12, 0.91, 0.34, ...]
^^ Vettore molto DIVERSO (significato diverso)
Modelul de încorporare este o rețea neuronală antrenată pe cantități uriașe de text pentru învață relațiile semantice dintre cuvinte, propoziții și concepte. Nu pur și simplu produce o reprezentare sintactică (cum ar fi bag-of-words sau TF-IDF), dar captează sensul profunzimea textului.
Modele majore de încorporare (2025-2026)
| Model | Dimensiuni | Furnizorii | Cost orientativ |
|---|---|---|---|
text-embedding-3-small |
1536 | OpenAI | ~0,02 USD/1 milion de jetoane |
text-embedding-3-large |
3072 | OpenAI | ~0,13 USD/1 milion de jetoane |
voyage-3-large |
1024 | Voyage AI | ~0,06 USD/1 milion de jetoane |
all-MiniLM-L6-v2 |
384 | HuggingFace | Gratuit (auto-găzduit) |
nomic-embed-text |
768 | Ollama (local) | Gratuit (local) |
embed-v4 |
1024 | Coere | ~0,10 USD/1 milion de jetoane |
Alegerea modelului de încorporare depinde de cazul de utilizare: cele mai mari modele (3072 dimensiuni) oferă o reprezentare mai bogată dar costă mai mult din punct de vedere al stocare și calcul. Pentru multe cazuri de utilizare, modelele de mărime 768-1536 oferă un compromis excelent între calitate și cost.
6. Vector Store: Baza de date pentru încorporare
Un magazin de vectori (sau baza de date vectoriala) este o baza de date specializata pentru stocați, indexați și căutați vectori de dimensiuni mari. Spre deosebire de baze de date tradiționale care caută potriviri exacte (SQL WHERE), un magazin de vectori caută mai mulți transportatori asemănătoare la cea a interogării.
6.1 Valori de similaritate
Căutarea în magazin de vectori se bazează pe valorile distanței/similarității dintre vectori. Cele mai comune trei valori sunt:
Compararea valorilor de similaritate
| Metric | Gamă | Descriere | Când să-l folosești |
|---|---|---|---|
| Asemănarea cosinusului | [-1, 1] | Măsoară unghiul dintre doi vectori, ignoră mărimea | Implicit pentru majoritatea cazurilor (recomandat) |
| Distanța euclidiană (L2) | [0, +inf) | Distanța geometrică în spațiu, sensibilă la magnitudine | Când mărimea vectorilor este semnificativă |
| Produs punct | (-inf, +inf) | Produs scalar, combină direcția și magnitudinea | Vectori deja normalizați, Căutare Internă Maximă de Produs |
6.2 Prezentare generală a bazelor de date vectoriale
Piața bazelor de date vectoriale a explodat odată cu adoptarea RAG. Iată o prezentare generală dintre principalele instrumente disponibile:
Comparația bazei de date vectoriale
| Baze de date | Tip | Limbă | Ideal pentru |
|---|---|---|---|
| ChromaDB | Încorporat / Server | Piton | Prototipări, dezvoltare locală, seturi mici de date |
| Cone de pin | Cloud gestionat | Multi-limbi | Producție, autoscaling, zero-ops |
| Weaviate | Auto-găzduit / Cloud | Go | Căutare hibridă, multi-chiriere, GraphQL |
| Milvus | Auto-găzduit / Cloud | Go / C++ | Volume mari, performante ridicate, intreprindere |
| Qdrant | Auto-găzduit / Cloud | Rugini | Performanță, filtrare avansată, API REST |
| pgvector | Extensia PostgreSQL | C | Stivă PostgreSQL existentă, date relaționale + vector |
| FAISS | Bibliotecă în memorie | C++ / Python | Cercetare, benchmark, optimizare maximă |
Pentru a începe, ChromaDB este cea mai simplă alegere: se instalează cu pip, funcționează în memorie sau persistent pe disc și se integrează nativ cu LangChain. Pentru producție, Pinecone (gestionat) și Qdrant (self-hosted) sunt printre opțiuni cele mai populare.
7. Preluare: Căutarea documentelor relevante
Faza de regăsire este momentul în care vine întrebarea utilizatorului transformat într-un vector și comparat cu toți vectorii din magazinul de vectori pentru a găsi cele mai relevante bucăți. Acest proces are loc în milisecunde chiar și cu milioane documente indexate, datorită algoritmilor de indexare aproximativă precum HNSW (Lumea mică navigabilă ierarhică).
Query: "Come configuro OAuth nella nostra app?"
|
v
[1] Embedding della query ──> [0.34, -0.21, 0.56, ...]
|
v
[2] Similarity Search nel Vector Store
| Confronta il vettore della query con tutti i vettori salvati
| Usa cosine similarity come metrica
|
v
[3] Top-K Results (es. k=5)
|
| Score: 0.92 - "Configurazione OAuth 2.0 per applicazioni web..."
| Score: 0.87 - "Guida ai flussi di autenticazione OAuth..."
| Score: 0.83 - "Impostazione dei redirect URI per OAuth..."
| Score: 0.76 - "Confronto tra OAuth e SAML per SSO..."
| Score: 0.71 - "Sicurezza delle API con token JWT..."
|
v
[4] Filtering e Reranking (opzionale)
| Filtra per metadati (data, categoria, fonte)
| Reranking con modello cross-encoder
|
v
[Chunk Rilevanti Pronti per il Prompt]
7.1 Parametrul Top-K
Parametrul sus-k determină câte bucăți sunt recuperate. Alegerea este un compromis:
- K prea mic (1-2): Riscul de a pierde informații relevante
- K prea mare (20+): Prea mult zgomot în context, risipă de jetoane, risc de confuzie a modelului
- K optim (3-7): Echilibru bun între acoperire și precizie
7.2 Scor de relevanță
Fiecare rezultat are un scor de relevanță (scor de relevanță). Bucățile cu scoruri mici ar trebui filtrate pentru că adaugă zgomot fără valoare. Un prag comun este 0,7 pentru asemănarea cosinusului: totul de mai jos este aruncat. În practică, pragul optim depinde de domeniu și trebuie calibrat experimental.
8. Generație: Construirea răspunsului cu LLM
Etapa finală a conductei RAG: bucățile recuperate sunt asamblate în a context structurat și inserat în promptul LLM împreună cu întrebarea utilizatorului. Modelul generează răspunsul bazat exclusiv pe (sau predominant) pe contextul oferit.
8.1 Șablonul prompt
Un șablon bun de prompt RAG ar trebui să instruiască modelul să:
- Utilizare Singur informații din contextul oferit
- Recunoaste cand nu gasesti raspunsul in acte
- Citați sursele ori de câte ori este posibil
- Nu inventați informații care nu sunt în context
Sei un assistente tecnico. Rispondi alle domande SOLO basandoti
sul contesto fornito. Se la risposta non è presente nel contesto,
rispondi "Non ho trovato informazioni sufficienti nei documenti
disponibili."
CONTESTO:
---
{context}
---
DOMANDA: {question}
ISTRUZIONI:
1. Rispondi in modo chiaro e conciso
2. Cita il documento sorgente tra parentesi quadre [Fonte: nome_doc]
3. Se il contesto non contiene la risposta, dillo esplicitamente
4. Non inventare informazioni non presenti nel contesto
RISPOSTA:
8.2 Urmărirea citațiilor
Una dintre cele mai valoroase caracteristici ale RAG este capacitatea de a urmări citările. Fiecare fragment din context poate fi etichetat cu un identificator (de exemplu, [DOC-1], [DOC-2]) iar modelul este instruit să facă referire la acești identificatori în răspuns. Aceasta permite utilizatorului să verifice fiecare declarație consultând documentul original.
Fereastra de context și limite
Cantitatea de context pe care o puteți insera este limitată fereastră de context a modelului LLM. Dacă bucățile recuperate depășesc limita, va trebui să selectați numai cele mai relevante sau rezumați-le. Modele moderne precum GPT-4o (token 128K) și Claude 3.5 (200K tokens) au ferestre de context foarte mari, dar chiar și așa, inserând prea mult context irelevant degradează calitatea răspunsurilor (așa-numita problemă „lost in the middle”).
9. Arhitectura RAG completă: Prezentare generală
Acum că ne-am uitat la fiecare componentă individual, să asamblam arhitectura complet cu un sistem RAG de la capăt la capăt:
FASE OFFLINE (Indicizzazione)
┌──────────────────────────────────────────────────────┐
│ │
│ [Documenti] ──> [Loader] ──> [Chunker] │
│ PDF, HTML Estrazione Divisione │
│ MD, CSV testo in frammenti │
│ │ │
│ v │
│ [Embedding Model] │
│ Testo ──> Vettore │
│ │ │
│ v │
│ [Vector Store] │
│ ChromaDB, Pinecone │
│ Weaviate, Qdrant │
│ │
└──────────────────────────────────────────────────────┘
FASE ONLINE (Query)
┌──────────────────────────────────────────────────────┐
│ │
│ [Domanda Utente] │
│ │ │
│ v │
│ [Query Embedding] ──> [Similarity Search] │
│ Stesso modello Top-K chunk │
│ dell'indicizzazione │ │
│ v │
│ [Context Assembly] │
│ Chunk + Metadati │
│ │ │
│ v │
│ [Prompt Template + Contesto + Domanda] │
│ │ │
│ v │
│ [LLM] │
│ GPT-4, Claude │
│ Llama, Gemini │
│ │ │
│ v │
│ [Risposta con Citazioni] │
│ │
└──────────────────────────────────────────────────────┘
Membrii și responsabilitățile
| Componentă | Responsabilitate | Instrumente tipice |
|---|---|---|
| Încărcător de documente | Încărcați documente din diferite surse | Încărcătoare LangChain, Nestructurate, LlamaIndex |
| Divizor de text | Împărțiți documentele în bucăți optime | RecursiveCharacterTextSplitter, SemanticChunker |
| Model de încorporare | Transformarea textului în vectori semantici | Încorporare OpenAI, Transformatori de propoziții, Cohere |
| Magazin de vectori | Stocați și indexați vectori | ChromaDB, Pinecone, Qdrant, pgvector |
| Retrievers | Căutați cele mai relevante bucăți | Căutare de similaritate, MMR, recuperare hibridă |
| LLM | Generați răspunsul final din context | GPT-4o, Claude 3.5, Llama 3, Gemini Pro |
10. Exemplu practic: RAG minim cu Python
Să construim un sistem RAG funcțional cu cod minim necesar. Vom folosi LangChain ca un cadru de orchestrare, OpenAI pentru înglobare și generare, e ChromaDB ca magazin local de vectori.
10.1 Configurarea proiectului
# Crea un ambiente virtuale
python -m venv rag-env
source rag-env/bin/activate # Linux/Mac
# Installa le dipendenze
pip install langchain langchain-openai langchain-community
pip install chromadb
pip install pypdf # Per caricare PDF
10.2 Conducta de indexare
import os
from langchain_community.document_loaders import (
PyPDFLoader,
TextLoader,
DirectoryLoader
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# Configura la API key
os.environ["OPENAI_API_KEY"] = "sk-..."
# 1. DOCUMENT LOADING
# Carica tutti i PDF da una cartella
loader = DirectoryLoader(
"./documenti/",
glob="**/*.pdf",
loader_cls=PyPDFLoader
)
documents = loader.load()
print(f"Caricati {len(documents)} documenti")
# 2. CHUNKING
# Divisione ricorsiva con overlap
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 500 caratteri per chunk
chunk_overlap=50, # 50 caratteri di overlap
length_function=len,
separators=["\n\n", "\n", ". ", " ", ""]
)
chunks = text_splitter.split_documents(documents)
print(f"Creati {len(chunks)} chunk")
# 3. EMBEDDING + 4. VECTOR STORE
# Crea gli embeddings e salvali in ChromaDB
embedding_model = OpenAIEmbeddings(
model="text-embedding-3-small"
)
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embedding_model,
persist_directory="./chroma_db",
collection_name="documenti_aziendali"
)
print("Vector store creato e salvato su disco")
10.3 Interogare Pipeline
import os
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
os.environ["OPENAI_API_KEY"] = "sk-..."
# Carica il vector store esistente
embedding_model = OpenAIEmbeddings(
model="text-embedding-3-small"
)
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=embedding_model,
collection_name="documenti_aziendali"
)
# Configura il retriever
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 5} # Recupera i 5 chunk più simili
)
# Definisci il prompt template
prompt_template = PromptTemplate(
template="""Sei un assistente tecnico esperto.
Rispondi alla domanda basandoti SOLO sul contesto fornito.
Se non trovi la risposta nel contesto, dillo esplicitamente.
CONTESTO:
{context}
DOMANDA: {question}
RISPOSTA (con citazioni ai documenti fonte):""",
input_variables=["context", "question"]
)
# Crea la chain RAG
llm = ChatOpenAI(
model="gpt-4o",
temperature=0 # Deterministic per risposte fattuali
)
rag_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # Inserisci tutti i chunk nel prompt
retriever=retriever,
return_source_documents=True,
chain_type_kwargs={
"prompt": prompt_template
}
)
# Esegui una query
result = rag_chain.invoke(
{"query": "Come configuro l'autenticazione OAuth?"}
)
# Stampa la risposta
print("RISPOSTA:")
print(result["result"])
print("\nFONTI:")
for doc in result["source_documents"]:
print(f" - {doc.metadata.get('source', 'N/A')}"
f" (pagina {doc.metadata.get('page', 'N/A')})")
Rezultat așteptat
RISPOSTA:
Per configurare l'autenticazione OAuth nella nostra applicazione,
segui questi passaggi:
1. Registra l'app nel provider OAuth (Google, GitHub, etc.)
2. Configura i redirect URI nel file config.yaml [Fonte: guida-oauth.pdf]
3. Implementa il flusso Authorization Code [Fonte: architettura-auth.pdf]
...
FONTI:
- documenti/guida-oauth.pdf (pagina 12)
- documenti/architettura-auth.pdf (pagina 5)
- documenti/faq-sicurezza.pdf (pagina 3)
10.4 Structura proiectului
rag-project/
├── documenti/ # I tuoi documenti sorgente
│ ├── guida-oauth.pdf
│ ├── architettura.pdf
│ └── faq.pdf
├── chroma_db/ # Vector store persistente (generato)
├── indexing.py # Script di indicizzazione
├── query.py # Script di query
├── requirements.txt # Dipendenze
└── .env # API keys (mai committare!)
11. RAG naiv vs RAG avansat
Sistemul pe care l-am construit până acum este ceea ce îl numește comunitatea RAG naiv: o implementare simplă și simplă, care funcționează surprinzător de bine pentru multe cazuri de utilizare. Cu toate acestea, există limitări ale tehnicilor RAG avansat ei caută a depăși.
11.1 Limitări ale RAG naiv
- Nepotrivire interogare-document: Întrebarea dvs. poate folosi termeni diferiți decât documentele. „Cum să vă resetați parola?” vs documentul „Procedura de recuperare a acreditărilor”
- Probleme legate de limitele porțiunilor: Informațiile relevante ar putea fi împărțite între două bucăți consecutive
- Pierdut în mijloc: LLM tinde să acorde mai multă greutate bucăților de la începutul și sfârșitul contextului, neglijându-le pe cele centrale
- Limitarea unui singur salt: Nu poate răspunde la întrebări care necesită rezumate din mai multe documente
11.2 Tehnici avansate RAG
Evoluție de la Naive la Advanced RAG
| Tehnică | Problemă Rezolvată | Cum funcționează |
|---|---|---|
| Rescrierea interogărilor | Interogări ambigue sau prost formulate | LLM rescrie interogarea într-o formă mai potrivită pentru recuperare |
| HyDE | Nepotrivire interogare-document | Generați un document ipotetic din interogare, apoi căutați documente similare |
| Reclasificare | Rezultatele nu sunt sortate optim | Un model cu codificare încrucișată reordonează rezultatele în funcție de relevanță |
| Interogare multiplă | O singură perspectivă de cercetare | Generați variante de interogare pentru a extinde acoperirea |
| Self-RAG | Când recuperarea nu este necesară | Modelul decide în mod autonom dacă și când să recupereze |
| RAG Multi-Hop | Întrebări complexe în mai mulți pași | Lanț de regăsiri iterative pentru a construi raționamentul compus |
| Căutare hibridă | Limitele căutării semantice numai | Combinați căutarea semantică (vectorală) cu cuvinte cheie (BM25) |
| Graficul RAG | Relații complexe între entități | Utilizați grafice de cunoștințe pentru a naviga în relații și contexte structurate |
NAIVE RAG:
Query ──> Embedding ──> Search ──> Top-K ──> LLM ──> Risposta
ADVANCED RAG:
Query ──> [Query Analysis]
│
├──> Query Rewriting ──> Embedding ──> Search ─┐
├──> HyDE Generation ──> Embedding ──> Search ─┤
└──> Multi-Query ──────> Embedding ──> Search ─┘
│
[Merge + Deduplica]
│
[Reranker Model]
│
[Context Compression]
│
[LLM + Citazioni]
│
[Risposta Verificata]
Vom aprofunda fiecare dintre aceste tehnici în articolele ulterioare din serie, mai ales în articolul despre Recuperare hibridă și reclasificare.
12. Când să utilizați RAG: Cadrul de decizie
RAG nu este răspunsul la toate problemele. Există trei abordări principale pentru personalizați comportamentul unui LLM, fiecare cu avantaje și limitări distincte. Alegerea depinde de cazul specific de utilizare.
RAG vs reglaj fin vs inginerie promptă
| Criteriu | Inginerie promptă | CÂRPĂ | Reglaj fin |
|---|---|---|---|
| Costul initial | Minim | Mediu | Ridicat |
| Datele necesare | Nimeni | Baza de cunoștințe | Set de date de antrenament |
| Actualizare | Imediat (schimbare promptă) | Rapid (actualizare documente) | Lent (re-antrenament) |
| Latența | Scăzut | Media (recuperare + generare) | Scăzut |
| Acuratețea faptică | Depinde de model | Ridicat (pe baza de documente) | Medie (depinde de antrenament) |
| Citable | Nici unul | Ridicat (surse de urmărire) | Nici unul |
| Complexitate | Scăzut | Medie | Ridicat |
12.1 Arborele decizional practic
Hai bisogno di personalizzare un LLM?
│
├── I dati cambiano frequentemente? (documenti, policy, catalogo)
│ └── SI ──> RAG
│ (I dati si aggiornano senza re-training)
│
├── Serve citare le fonti?
│ └── SI ──> RAG
│ (Tracciabilita delle risposte)
│
├── Il dominio è stabile e ben definito?
│ ├── Hai un grande dataset di training?
│ │ └── SI ──> Fine-Tuning
│ │ (Personalizzazione profonda del comportamento)
│ └── NO ──> RAG oppure Prompt Engineering
│
├── Serve solo cambiare tono/formato/stile?
│ └── SI ──> Prompt Engineering
│ (Nessuna infrastruttura aggiuntiva)
│
└── Serve ragionamento complesso su dati proprietari?
└── SI ──> RAG + Fine-Tuning (Approccio Ibrido)
(Il meglio di entrambi i mondi)
Regula de aur
Abordarea recomandată de comunitatea de inginerie AI urmează o scară de complexitate ascendent: începeți cu promptul de inginerie, apoi trece la CÂRPĂ dacă sunt necesare date sau citări externe și luați în considerare reglaj fin numai când primele două abordări sunt insuficiente. Această progresie minimizează costul și complexitate, maximizând rentabilitatea investiției.
12.2 Cazuri de utilizare ideale pentru RAG
- Chatbot de afaceri: Ei răspund pe baza documentației interne
- Căutare semantică: Găsiți documente relevante pentru sens, nu doar cuvinte cheie
- Întrebări și răspunsuri din baza de cunoștințe: Întrebări frecvente dinamice care se actualizează cu documente
- Asistenți juridici: Raspunsuri bazate pe reglementari si jurisprudenta
- Suport tehnic: Rezoluții bazate pe bilete anterioare și manuale
- Analiza documentara: Extrageți informații din rapoarte, contracte, lucrări științifice
12.3 Când NU trebuie folosit RAG
- Sarcini creative: Scriere creativă, brainstorming, generare de idei (șablonul trebuie să fie gratuit)
- Conversatie generala: Chatbot social unde nu sunt necesare date specifice
- Sarcini cu puține date: Dacă aveți doar câteva documente, o inginerie promptă ar putea fi suficientă
- Răspunsuri strânse în timp real: Dacă latența de recuperare este inacceptabilă (sub 50 ms)
13. Piața RAG: cifre și tendințe
RAG nu mai este un concept academic: a devenit o arhitectură de producție adoptată pe scară largă. Cifrele pieței confirmă importanța sa strategică.
RAG în cifre (2024-2030)
| Metric | Dat |
|---|---|
| Piața globală RAG (2024) | ~1,2 miliarde USD |
| Proiecția pieței (2030) | ~11 miliarde USD |
| Rata anuală de creștere (CAGR) | 49,1% (2025-2030) |
| Adoptarea întreprinderii | 30-60% din cazurile de utilizare LLM folosesc RAG |
| Reducerea halucinațiilor | Până la 71% cu RAG bine implementat |
| Cadre dominante | 80,5% folosesc FAISS sau Elasticsearch |
Industriile care stimulează adoptarea sunt cele juridice, medicale, de asistență pentru clienți și servicii financiar, adică toate acele domenii în care acuratețea faptică și citabilitatea a surselor sunt cerințe nenegociabile. Tendința în 2025-2026 se schimbă de la experimentare la producția pe scară largă, cu un accent tot mai mare pe conformitatea, monitorizarea și calitatea datelor.
14. Concluzii și pașii următori
În acest articol am construit o înțelegere cuprinzătoare a RAG: de la problemă care rezolvă (halucinațiile LLM-urilor) la arhitectura end-to-end, trecând prin fiecare componentă a conductei. Am văzut o implementare practică funcțională și am comparat RAG cu alternative (ajustare fină, inginerie promptă).
Rezumatul conceptelor cheie
- CÂRPĂ combină regăsirea și generarea pentru a produce răspunsuri bazate pe date reale
- La conductă de indexare transforma documentele în vectori: Încărcare, Diviziune, Încorporare, Stocare
- La conductă de interogări găsiți și utilizați documente relevante: încorporare, căutare, asamblare, generare
- Il în bucăţire este una dintre cele mai critice decizii: afectează direct calitatea regăsirii
- The înglobări ele surprind sensul semantic al textului în vectori numerici
- I magazin de vectori fac posibile căutări similare pe milioane de documente
- RAG avansat introduce tehnici precum reranking, HyDE și multi-hop pentru a depăși limitările Naive RAG
- RAG este ideal atunci când este nevoie răspunsuri actualizate, verificabile și citate
Articolul următor: Înglobări și căutare semantică
În următorul articol al seriei vom aprofunda cea mai fascinantă componentă a RAG: el înglobări. Vom vedea cum funcționează în interior, cum să alegem modelul corect, cum să-i evaluăm calitatea și cum să optimizați căutarea semantică. Vom explora, de asemenea, metricile de evaluare și tehnicile de evaluare comparativă pentru măsurare performanța sistemului dvs. de recuperare.
Seria AI Engineering și Advanced RAG
| Articol | Subiect |
|---|---|
| 01 - Ești aici | RAG: Retrieval-Augmented Generation Explained |
| 02 - Următorul | Înglobări și căutare semantică în profunzime |
| 03 | Baza de date vectorială: arhitectură și bune practici |
| 04 | Construirea unui sistem RAG cu LangChain și Python |
| 05 | Preluare hibridă: cuvânt cheie + semantică + reclasificare |
| 06 | Fereastra de context și inginerie promptă pentru RAG |
| 07 | RAG în producție: monitorizare, evaluare, scalare |
| 08 | Grafice de cunoștințe și regăsire structurată |
| 09 | Sisteme multi-agenți și RAG orchestrat |
| 10 | Viitorul RAG: tendințe și cercetare |







