RAG (Retrieval-Augmented Generation) to jedna z najważniejszych technik stosowanych w praktycznym wdrażaniu dużych modeli językowych (LLM). Rozwiązuje fundamentalny problem: LLM nie wiedzą wszystkiego, a to, co wiedzą, może być nieaktualne. RAG łączy potęgę generowania tekstu z precyzją wyszukiwania w dedykowanej bazie wiedzy.

Problem, który RAG rozwiązuje

LLM — takie jak ChatGPT, Claude czy Gemini — mają trzy fundamentalne ograniczenia:

  1. Data odcięcia — wiedza modelu kończy się w momencie zakończenia treningu. Model wytrenowany do stycznia 2025 nie wie o wydarzeniach z marca 2025
  2. Halucynacje — model „nie wie, czego nie wie" i generuje fałszywe informacje brzmiące wiarygodnie
  3. Brak wiedzy prywatnej — model nie ma dostępu do wewnętrznych dokumentów firmy, baz danych, regulaminów

RAG rozwiązuje wszystkie trzy problemy: model nie musi „pamiętać" informacji — może je wyszukać w zewnętrznej bazie wiedzy i wygenerować odpowiedź na ich podstawie.

Architektura RAG — jak to działa?

System RAG składa się z dwóch faz:

Faza 1: Retrieval (wyszukiwanie)

  1. Pytanie użytkownika jest zamieniane na embedding (wektor liczbowy) przez model embeddingowy
  2. Baza wiedzy — wcześniej przetworzone dokumenty, również zamienione na embeddingi i zapisane w bazie wektorowej
  3. Wyszukiwanie — system szuka dokumentów (lub fragmentów dokumentów) z embeddingami najbardziej podobnymi do embeddingu pytania (cosine similarity)
  4. Wynik — top-K najbardziej relevantnych fragmentów (typowo 3–10)

Faza 2: Augmented Generation (wzbogacone generowanie)

  1. Odnalezione fragmenty dokumentów są dołączane do promptu jako kontekst
  2. LLM generuje odpowiedź na podstawie dostarczonych fragmentów, nie wyłącznie z własnej pamięci
  3. Idealnie model cytuje źródła i odmawia odpowiedzi, gdy kontekst nie zawiera relevantnych informacji

Prompt RAG — typowa struktura

Kontekst:
[Fragment dokumentu 1]
[Fragment dokumentu 2]
[Fragment dokumentu 3]

Pytanie użytkownika: [pytanie]

Odpowiedz na pytanie WYŁĄCZNIE na podstawie podanego kontekstu.
Jeśli kontekst nie zawiera odpowiedzi, powiedz „Nie znalazłem tej informacji".

Kluczowe komponenty systemu RAG

1. Chunking — dzielenie dokumentów

Dokumenty źródłowe są zbyt długie, żeby podawać je w całości. Dzielimy je na fragmenty (chunki):

  • Fixed-size chunks — fragmenty o stałej długości (np. 500 tokenów). Proste, ale mogą przeciąć zdania
  • Recursive character splitting — dzielenie na akapity, potem zdania, zachowując granice semantyczne
  • Semantic chunking — podział na fragmenty na podstawie zmian tematycznych (wymaga modelu embeddingowego)
  • Overlap — nakładanie się fragmentów (np. 50 tokenów) zapobiegające utracie kontekstu na granicach

Rozmiar chunka to kluczowy hiperparametr: za duży = mało precyzyjne wyszukiwanie; za mały = utrata kontekstu.

2. Embeddingi — wektorowa reprezentacja tekstu

Model embeddingowy zamienia tekst na wektory liczbowe w przestrzeni wielowymiarowej (typowo 768–3072 wymiarów). Podobne semantycznie fragmenty mają bliskie wektory.

Popularne modele embeddingowe:

  • OpenAI text-embedding-3-large — 3072 wymiary, wielojęzyczny
  • Cohere Embed v3 — zoptymalizowany pod RAG
  • BGE-M3 — open-source, wielojęzyczny
  • E5-mistral-7b — duży, precyzyjny model embeddingowy

3. Baza wektorowa (Vector Database)

Specjalizowana baza danych przechowująca embeddingi i umożliwiająca szybkie wyszukiwanie najbliższych sąsiadów (ANN — Approximate Nearest Neighbors):

  • Pinecone — w pełni zarządzana, SaaS
  • Weaviate — open-source, hybrydowe wyszukiwanie
  • ChromaDB — lekka, idealna do prototypów
  • Qdrant — wydajna, open-source, napisana w Rust
  • pgvector — rozszerzenie PostgreSQL — RAG bez dodatkowej bazy danych

4. Reranking — poprawianie jakości wyników

Wyszukiwanie embeddingowe (semantic search) to przybliżenie. Reranker — osobny model — ocenia dopasowanie każdego fragmentu do pytania i przesortowuje wyniki. ## GraphRAG i Agentic RAG (trendy 2024-2026)

GraphRAG (Microsoft Research, 2024) — kluczowa ewolucja RAG: ekstrakcja encji i relacji do grafu wiedzy (Neo4j), LLM nawiguje po grafie zamiast tylko przeglądać chunki. Lepszy dla pytań wymagających wieloetapowego rozumowania o relacjach. Open-source: LightRAG (2025) — lżejsza alternatywa.

Agentic RAG — agent decyduje kiedy i czego szukać, zamiast zawsze uruchamiać retrieval. Używa tool calling, może wielokrotnie iterować zapytania. Frameworki: LangGraph, AutoGen.

Rerankery

Modele rerankerów: Cohere Rerank 3 (2024), BGE-Reranker v2-m3, Voyage Rerank-2, Jina Reranker v2. Hybrid search (BM25 + vector) to standard produkcyjny 2025.

Pipeline: embedding search (top-20) → reranker (top-5) → LLM.

Zaawansowane wzorce RAG

RAG Fusion

Zamiast jednego zapytania generuje wiele wariantów pytania (query expansion) i wyszukuje dokumenty dla każdego. Wyniki są łączone (reciprocal rank fusion). Poprawia recall — zmniejsza ryzyko pominięcia relevantnego dokumentu.

Hypothetical Document Embedding (HyDE)

LLM generuje hipotetyczną odpowiedź na pytanie. Embedding tej odpowiedzi jest używany do wyszukiwania — zamiast embeddingu pytania. Intuicja: odpowiedź jest semantycznie bliższa dokumentowi źródłowemu niż pytanie.

Self-RAG

Model sam decyduje, czy potrzebuje zewnętrznej wiedzy. Jeśli pytanie dotyczy wiedzy ogólnej (np. „co to jest DNA?"), model odpowiada z pamięci. Jeśli specjalistycznej — uruchamia retrieval. Zmniejsza latencję i koszty.

Agentic RAG

Agent AI dynamicznie decyduje o strategii wyszukiwania: które źródła odpytać, ile dokumentów pobrać, czy potrzebne jest doprecyzowanie pytania. Korzysta z wielu baz wiedzy, API i narzędzi.

RAG vs. Fine-tuning — kiedy co?

Kryterium RAG Fine-tuning
Aktualizacja wiedzy Natychmiastowa (dodaj dokument) Wymaga ponownego treningu
Koszt Niski (embedding + baza wektorowa) Wysoki (GPU, dane treningowe)
Halucynacje Zmniejsza (grounding w źródłach) Nie eliminuje
Styl odpowiedzi Zależy od promptu Zmienia wewnętrzne zachowanie modelu
Wiedza specjalistyczna Dobra (jeśli jest w dokumentach) Lepsza dla specjalistycznej terminologii
Skalowalność wiedzy Miliony dokumentów Ograniczona pojemnością modelu

Reguła kciuka: RAG do wiedzy (co model powinien wiedzieć), fine-tuning do zachowania (jak model powinien odpowiadać).

Wyzwania i ograniczenia RAG

1. Jakość dokumentów = jakość odpowiedzi

„Garbage in, garbage out". Jeśli baza wiedzy zawiera nieaktualne, sprzeczne lub niekompletne informacje, RAG je powieli.

2. Okno kontekstu

Nawet z RAG kontekst jest ograniczony. Jeśli odpowiedź wymaga informacji rozproszonych po 50 dokumentach, a okno kontekstu mieści 10 fragmentów — model nie zobaczy pełnego obrazu.

3. Lost in the middle

Badania pokazują, że LLM lepiej wykorzystują informacje z początku i końca kontekstu, „gubiąc" informacje ze środka. Kolejność fragmentów w prompcie RAG ma znaczenie.

4. Wielojęzyczność

Wyszukiwanie cross-lingwalne (pytanie po polsku, dokumenty po angielsku) wymaga wielojęzycznych modeli embeddingowych. Jakość spada dla języków niedoreprezentowanych w danych treningowych.

End-to-end pipeline RAG w Pythonie

Kompletny przykład działającego systemu RAG z LangChain (najpopularniejsza biblioteka):

from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA

# 1. Załaduj dokumenty
docs = TextLoader("knowledge_base.txt").load()

# 2. Podziel na chunki (~500 znaków, 50 znaków overlap)
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", ". ", " "]
)
chunks = splitter.split_documents(docs)

# 3. Embed i zapisz w bazie wektorowej
vectorstore = Chroma.from_documents(
    chunks,
    OpenAIEmbeddings(model="text-embedding-3-small"),
    persist_directory="./chroma_db"
)

# 4. Retrieve + Generate
qa = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-4o-mini", temperature=0),
    retriever=vectorstore.as_retriever(search_kwargs={"k": 4}),
    return_source_documents=True
)

# 5. Pytanie → odpowiedź na podstawie dokumentów
result = qa({"query": "Jakie są kluczowe pojęcia uczenia ze wzmocnieniem?"})
print(result["result"])
for doc in result["source_documents"]:
    print("\nŹródło:", doc.metadata)

Czysty Python — bez frameworka

Dla pełnej kontroli, RAG bez LangChain (bardziej production-ready, mniej magii):

from openai import OpenAI
import numpy as np

client = OpenAI()

# Embedduj dokumenty (raz)
def embed(texts: list[str]) -> np.ndarray:
    res = client.embeddings.create(model="text-embedding-3-small", input=texts)
    return np.array([d.embedding for d in res.data])

docs = ["Q-learning to algorytm RL...", "Transformery wykorzystują attention..."]
doc_embs = embed(docs)

# Retrieve
def retrieve(query: str, k: int = 3) -> list[str]:
    q_emb = embed([query])[0]
    sims = doc_embs @ q_emb / (np.linalg.norm(doc_embs, axis=1) * np.linalg.norm(q_emb))
    top_idx = np.argsort(sims)[::-1][:k]
    return [docs[i] for i in top_idx]

# Generate
def rag_answer(query: str) -> str:
    context = "\n\n".join(retrieve(query))
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": f"Odpowiadaj na podstawie kontekstu:\n{context}"},
            {"role": "user", "content": query}
        ]
    )
    return response.choices[0].message.content

print(rag_answer("Czym jest Q-learning?"))

Hybrydowe wyszukiwanie — semantyczne + keyword (BM25)

from rank_bm25 import BM25Okapi
import numpy as np

# Tokenizuj dla BM25
tokenized_docs = [d.lower().split() for d in docs]
bm25 = BM25Okapi(tokenized_docs)

def hybrid_retrieve(query: str, alpha: float = 0.5, k: int = 4) -> list[str]:
    # Semantic scores
    q_emb = embed([query])[0]
    sem_scores = doc_embs @ q_emb / (np.linalg.norm(doc_embs, axis=1) * np.linalg.norm(q_emb))
    # BM25 scores
    bm_scores = np.array(bm25.get_scores(query.lower().split()))
    # Normalize i połącz (alpha * semantyczne + (1-alpha) * BM25)
    sem_norm = (sem_scores - sem_scores.min()) / (sem_scores.max() - sem_scores.min() + 1e-9)
    bm_norm = (bm_scores - bm_scores.min()) / (bm_scores.max() - bm_scores.min() + 1e-9)
    final = alpha * sem_norm + (1 - alpha) * bm_norm
    top_idx = np.argsort(final)[::-1][:k]
    return [docs[i] for i in top_idx]

Hybrydowe podejście (Reciprocal Rank Fusion, BM25 + embeddingi) jest standardem produkcyjnym — czysto semantyczne wyszukiwanie zawodzi przy zapytaniach z konkretnymi nazwami własnymi (numery wersji, kody błędów, nazwiska).

Podsumowanie

RAG to most między potęgą generatywną LLM a precyzją informacji specyficznych dla Twojej organizacji. Zamiast próbować „wpychać" wiedzę do modelu przez fine-tuning, RAG pozwala LLM korzystać z zewnętrznych źródeł w czasie rzeczywistym — jak człowiek korzysta z encyklopedii czy Google.

W praktyce wdrożeniowej RAG to nie „podłącz bazę i gotowe" — to system wymagający starannego doboru chunkingu, modeli embeddingowych, bazy wektorowej i promptów. Ale dobrze zaprojektowany RAG dramatycznie zmniejsza halucynacje, umożliwia aktualizację wiedzy bez ponownego treningu i otwiera drzwi do budowania specjalistycznych asystentów AI na własnych danych.