RAG keresés implementálása saját dokumentumokkal.

A RAG keresés alapjai: saját dokumentumok intelligens lekérdezése fejlesztőknek

Bevezetés: Az információáradat kihívása

Az olyan nagy nyelvi modellek (LLM-ek) mint a GPT, mélyreható tudással rendelkeznek, de egy kritikus korlátjuk van: nincs hozzáférésük a legfrissebb információkhoz, cégek belső dokumentumaihoz, vagy speciális szakterületek adataihoz. Itt jön képbe a RAG (Retrieval-Augmented Generation), ami kombinálja a nyelvi modellek kreatív generálási képességét egy külső tudásbázis precíz lekérdezésével. Gyakorlatilag a modell „fülét” szúrjuk a saját dokumentumainkhoz. Ez a technika lehetővé teszi, hogy AI-alkalmazásaink relevánsan válaszoljanak kérdésekre a céges wikik, termékdokumentációk, vagy bármilyen szöveges adathalmaz alapján, anélkül, hogy újra kéne tanítani a modellt.

Miért pont a RAG?

A RAG nem csupán egy trend, hanem alapvető előnyt kínál: 1. Kontextusos pontosság: A válaszok nem általánosak, hanem konkrétan a megadott dokumentumokra épülnek. 2. Költséghatékonyság: Lényegesen olcsóbb és gyorsabb, mint a modellek finomhangolása (fine-tuning) nagymennyiségű adattal. 3. Frissítés egyszerűsége: Új információt egyszerűen adunk hozzá a tudásbázishoz, nem kell újratanítani a teljes modellt. 4. Forráshivatkozás: Megtudhatjuk, mely dokumentumrészletek alapján készült a válasz, növelve a megbízhatóságot.

Hogyan működik a RAG? Háromlépcsős folyamat

A RAG-rendszer három fő fázisból áll: előkészítés, lekérdezés és generálás.

1. Lépés: Az előkészítés – Embedding-ek készítése

Először digitalizálnunk kell tudásunkat. A dokumentumokat (PDF, Word, markdown stb.) kisebb, értelmes szövegrészekre (chunk-okra) bontjuk. Ezután minden egyes szövegrészletből létrehozunk egy numerikus vektort, egy úgynevezett embedding-et. Az embedding egy sűrű vektor, mely a szöveg szemantikai jelentését rögzíti. A hasonló tartalmú szövegek embedding-jei a vektortérben közel helyezkednek el. Ezeket az embedding-eket egy vektoradatbázisban (pl. Pinecone, Weaviate, Chroma, pgvector) tároljuk el, együtt az eredeti szövegrészlettel.

2. Lépés: A lekérdezés – Releváns kontextus megtalálása

Amikor a felhasználó feltesz egy kérdést (pl. „Mi a cég szabadságolási politikája?”), akkor a rendszer: 1. Ugyanazzal a modellel létrehoz egy embedding-et a kérdésből. 2. Végrehajt egy vektorhasonlósági keresést a vektortérben, hogy megtalálja a kérdés embedding-jéhez leginkább hasonló (legtöbbször koszinusz-hasonlóság alapján) dokumentum-chunk-okat. 3. Visszaadja a legfontosabb 3-5 szövegrészletet.

3. Lépés: A generálás – Válasz összeállítása

A lekérdezett releváns szövegrészleteket (a „kontextust”) és az eredeti felhasználói kérdést együtt („rendszerutasítás”, kontextus, kérdés) bedobjuk az LLM-nek (pl. GPT-4, Llama 3, Claude). A modell feladata, hogy a megadott kontextus alapján, azon belül maradva, összeállítson egy koherens választ.

Gyakorlati példa: Python kód RAG prototípushoz

Az alábbi példa a langchain keretrendszert használja, ami nagyban leegyszerűsíti a folyamatot. Feltételezzük, hogy már rendelkezünk egy OpenAI API kulccsal és telepítettük a szükséges csomagokat (pip install langchain langchain-openai langchain-community chromadb tiktoken).

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

# 1. Dokumentum betöltése és feldarabolása
loader = TextLoader("./sajat_dokumentum.txt", encoding="utf-8")
documents = loader.load()

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,  # Karakterek száma egy chunk-ban
    chunk_overlap=200, # Overlap a kontextus megtartásához
    separators=["\n\n", "\n", " ", ""]
)
chunks = text_splitter.split_documents(documents)

# 2. Embedding-ek létrehozása és vektortár létrehozása
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./adatbazis"  # Embedding-ek helyi tárolása
)

# 3. Retrieval és Q&A lánc összeállítása
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=vectorstore.as_retriever(search_kwargs={"k":扣3}), # Top 3 találat
    chain_type="stuff",  # Egyszerűen "belemasszírozza" a kontextust a promptba
    return_source_documents=True  # Forráshivatkozások
)

# 4. Kérdés feltevése
query = "Mi a főbb előnye a RAG megközelítésnek?"
result = qa_chain.invoke({"query": query})

print("Válasz:", result["result"])
print("\nForrások:")
for doc in result["source_documents"]:
    print(f"- {doc.metadata['source']} (oldal/ rész: {doc.metadata.get('page', 'N/A')})")

Gyakori buktatók és tanulságok

1. Rossz chunk-olás: Túl nagy chunk (elveszik a relevancia), túl kicsi chunk (elveszik a kontextus). Próbáld ki a 500-1500 karakter közötti tartományt, és használj overlapot. 2. Gyenge embedding modell: A keresés minősége alapvetően az embedding modelltől függ. Az text-embedding-3-small jó kiindulás, speciálisabb nyelvekhez érdemes domain-specifikus modelleket keresni. 3. Kontextustúlzsúfolás: Túl sok chunk beküldése az LLM-nek meghaladhatja a token limitet és összezavarhatja. Korlátozd a lekérdezett chunk-ok számát (k paraméter). 4. Elveszett metaadatok: Mindig mentsd el a chunk-ok metaadatait (forrásfájl, oldalszám, fejezet). Ez elengedhetetlen a forráshivatkozáshoz és a felhasználói bizalom építéséhez. 5. „Nem tudom” kérdések kezelése: A modell néha túl magabiztosan kohálhat választ olyan információkra, amik nincsenek a kontextusban. Használj „csak a megadott kontextusban keresd a választ” stílusú rendszerpromptokat, és implementálj egy bizalomérték-alapú szűrőt.

Összegzés

A RAG hatékony eszköz arra, hogy nagy nyelvi modelleket kapcsoljunk a szervezet egyedi tudásához. A kulcs az adatok megfelelő előkészítésében (chunk-olás, embedding), egy megfelelő vektortár kiválasztásában és a retrieval-generálás folyamat finomhangolásában rejlik. AI development projektjeink során a RAG lehetővé teszi, hogy gyorsan, költséghatékonyan és megbízhatóan építsünk olyan alkalmazásokat, melyek nem csak általános információkat adnak, hanem konkrétan a saját dokumentumaink bölcsességét használják fel.

Az első lépés a gyakorlatban: válassz egy SDK-t (pl. LangChain, LlamaIndex), egy vektortárat (kezdésnek a helyi Chroma kiváló), és kísérletezz egyetlen PDF fájllal. A találatok minőségén és a modell válaszain finomhangolva gyorsan érezhető eredményeket érhetsz el.