Základná implementácia RAG: návod krok za krokom

Tento návod pre začiatočníkov vysvetľuje, ako funguje základná implementácia RAG, predstavuje osvedčené postupy a krok za krokom vás prevedie vytvorením funkčného systému RAG pre príkazový riadok pomocou jazyka Python, ChromaDB a embeddingových a jazykových modelov Perplexity.

Basic RAG implementation process diagram: the interface sends input to the orchestrator, which retrieves data from a vector database, builds the input context for the LLM, and returns the output to the interface.

RAG je nevyhnutnou súčasťou modernej infraštruktúry založenej na LLM. Tým, že modelom AI umožňuje pristupovať k externým dátam, pomáha riešiť problémy, ako sú halucinácie a neúplné trénovacie dáta. Firmy vďaka nemu môžu využívať aj interné databázy znalostí, ktoré obsahujú citlivé alebo proprietárne informácie.

Implementácia RAG môže byť veľmi zložitá. Základný systém RAG sa však dá zostaviť prekvapivo ľahko. Začiatočníkom môže jednoduchá architektúra objasniť, ako RAG funguje v praxi, a poslúžiť ako odrazový mostík na ďalšie experimentovanie.

V tomto článku načrtneme základnú implementáciu RAG, prejdeme si osvedčené postupy a potom zostavíme funkčný systém pomocou jazyka Python, ChromaDB a dvoch modelov Perplexity – jedného na tvorbu embeddingov a druhého na generovanie odpovedí.

Proces základnej implementácie RAG: celkový prehľad

Základný systém RAG má tri hlavné komponenty: orchestrátor, zdroj informácií a LLM. V typickom pracovnom postupe používateľ zadá prompt a orchestrátor ho upraví tak, aby mohol prehľadať všetky pripojené zdroje informácií. Získané informácie sa potom pridajú k pôvodnému vstupnému kontextu a odošlú do LLM, ktorý vygeneruje odpoveď.

Pri zostavovaní vlastnej implementácie RAG budete musieť zohľadniť tieto kroky:

  1. Indexovanie a tvorba embeddingov: V tejto fáze sa vaše dokumenty premenia na zdroj informácií, ktorý môže orchestrátor prehľadávať. Jedným z najbežnejších spôsobov je vytvorenie prehľadávateľného vektorového indexu. Na prevod úsekov dokumentov na embeddingy použijeme špecializovaný model od Perplexity. Embeddingy potom uložíme do ChromaDB, populárnej open-source vektorovej databázy.
  2. Orchestrácia: Ide o aplikáciu, ktorá stojí medzi externým zdrojom informácií (v našom prípade vektorovou databázou) a LLM. Ako orchestrátor nám poslúži jednoduchý skript v jazyku Python.
  3. Získavanie a generovanie: Keď používateľ položí otázku cez chatové rozhranie, orchestrátor ju prevezme, spustí vektorové vyhľadávanie a rozšírený vstup odovzdá LLM. Namiesto vytvárania samostatného frontendu budeme s naším orchestrátorom v jazyku Python komunikovať prostredníctvom príkazového riadka.

Osvedčené postupy: čo robí implementáciu RAG efektívnou?

Existuje viacero typov architektúry RAG a jednotlivé prípady použitia si vyžadujú odlišné prístupy. Niektoré osvedčené postupy však platia vo všetkých prípadoch a zaručujú, že systémy budú presné, nákladovo efektívne, škálovateľné a ľahko udržiavateľné.

Pre všetky typy implementácie RAG platia tieto osvedčené postupy:

  • Zabezpečte čistý proces načítavania dát: Zdrojové dáta by mali byť pred indexovaním čo najčistejšie. Mali by ste tiež použiť embeddingový model vhodný pre váš obsah.
  • Používajte hybridné vyhľadávanie: Najlepšie metódy získavania informácií – či už ide o vyhľadávanie vo vektorovej databáze, webové vyhľadávanie cez API, prechádzanie znalostného grafu, vyhľadávanie podľa kľúčových slov alebo iné metódy – sa líšia v závislosti od prípadu použitia. Výber správnej kombinácie je dôležitý na minimalizáciu nákladov.
  • Vyhodnoťte svoj systém: Po implementácii by ste mali systém vyhodnotiť podľa troch základných ukazovateľov: presnosti, relevantnosti a latencie. Presnosť označuje faktickú správnosť, relevantnosť vhodnosť získaných informácií pre dopyty používateľov a latencia rýchlosť, akou sa informácie získavajú.
  • Zaobchádzajte s informáciami bezpečne: Ak váš systém RAG čerpá zo súkromných interných informácií, zabezpečte ich bezpečné uloženie a spravujte prístup k rozhraniu systému. Kľúče API nikdy nezdieľajte.

Základná implementácia RAG: návod v 7 krokoch

V tomto návode vytvoríme aplikáciu pre príkazový riadok, ktorá odpovedá na otázky o jednom dokumente. Použijeme jazyk Python, ChromaDB a Perplexity API.

Cieľom nie je vytvoriť systém RAG pripravený na produkčné nasadenie. Ide skôr o návod pre začiatočníkov, ktorý má ukázať, ako jednoduchá architektúra RAG funguje v praxi.

Krok 1: Nainštalujte softvér

Uistite sa, že máte v počítači nainštalované nasledujúce nástroje a že máte účet Perplexity API:

  • Python: Ide o programovací jazyk, v ktorom vytvoríme orchestrátor koordinujúci tok dát medzi embeddingovým modelom, ChromaDB a Perplexity.
  • Visual Studio: Ako editor kódu použijeme Visual Studio. Po nainštalovaní otvorte panel Extensions a stiahnite si rozšírenie Python.
  • Účet Perplexity API: Perplexity poskytne embeddingový model (ktorý premení vaše dáta na vektorové embeddingy) aj LLM, ktorý spracuje rozšírený prompt. Nepotrebujete na to platený účet, spotrebujete však malé množstvo kreditov.

Krok 2: Vytvorte priečinok projektu

Najprv vytvorte priečinok s názvom rag-project a otvorte ho vo VS Code výberom položky File > Open Folder. Potom otvorte integrovaný terminál cez Terminal > New Terminal.

Zadaním nasledujúceho príkazu vytvorte virtuálne prostredie pre Python:

bash
py -3.12 -m venv .venv

Teraz musíte nainštalovať štyri knižnice jazyka Python: perplexityai, chromadb, python-dotenv a numpy. Perplexity SDK vám umožní pripojiť sa k modelom Perplexity cez API. ChromaDB vytvorí vektorovú databázu a bude bežať lokálne. Python-dotenv bezpečne načíta vaše kľúče API z lokálneho súboru a NumPy je potrebný pri načítavaní dát.

Nainštalujte ich týmto príkazom:

bash
.\.venv\Scripts\python.exe -m pip install perplexityai chromadb python-dotenv numpy

Krok 3: Pripravte si súbory

Do priečinka rag-project (koreňový adresár projektu) pridajte nasledujúce súbory výberom možnosti New File… na bočnom paneli Explorer:

  • index.py: Toto je aplikácia, ktorá zaindexuje váš dokument. Ak chcete pridať ďalší text, môžete ju spustiť znova.
  • rag.py: Toto je aplikácia v jazyku Python, ktorá bude fungovať ako orchestrátor.
  • document.txt: Tento súbor bude obsahovať dokumentáciu, ktorú prevediete do vektorovej databázy.
  • .env: Sem uložíte svoj kľúč Perplexity API.

Do súboru .env zadajte tento obsah:

plaintext
PERPLEXITY_API_KEY=your_api_key_here

Nahraďte your_api_key_here svojím skutočným kľúčom. Získate ho tak, že prejdete na domovský panel v Perplexity API Console a vyberiete možnosť Create an API key. Tento kľúč API uchovávajte v tajnosti.

Použijeme dva modely: pplx-embed-v1-0.6b od Perplexity na vytvorenie embeddingov našej dokumentácie pred jej nahraním do ChromaDB a GPT-5.6-Luna (dostupný cez API Perplexity), ktorý spracuje získané informácie.

Do súboru document.txt pridajte text, ktorý bude váš systém RAG vyhľadávať. Ak nemáte po ruke vhodný dokument, použite v tomto návode dielo Williama Blakea Songs of Innocence and of Experience z knižnice Project Gutenberg. Ide o krátky, ľahko zrozumiteľný text, ktorý je voľným dielom.

Krok 4: Napíšte indexovací program

Skopírujte nižšie uvedený kód a vložte ho do súboru index.py. Každý podnadpis stručne vysvetľuje, čo robí nasledujúca časť kódu. Tento program prevedie váš zdrojový materiál na vektorové embeddingy a uloží ich do databázy ChromaDB pomocou embeddingového modelu Perplexity pplx-embed-v1-0.6b a knižnice NumPy.

Program robí toto:

  1. Otvorí súbor document.txt.
  2. Rozdelí text na prekrývajúce sa úseky.
  3. Odošle tieto úseky do embeddingového modelu pplx-embed-v1-0.6b od Perplexity.
  4. Dekóduje a normalizuje vrátené vektory pomocou NumPy, knižnice výpočtových funkcií pre Python.
  5. Uloží vektory a pôvodné úseky do databázy ChromaDB (zobrazí sa v adresári vášho projektu).

Program je nastavený tak, aby dokument pri každom spustení znova neindexoval. Ak do súboru document.txt pridáte ďalšie informácie, vytvorí embeddingy iba pre nový text.

python
from pathlib import Path from collections import defaultdict, deque from hashlib import sha256 import base64 import numpy as np import chromadb from dotenv import load_dotenv from perplexity import Perplexity # 1. Connect to Perplexity and ChromaDB load_dotenv() ai = Perplexity() db = chromadb.PersistentClient(path="./rag_database_perplexity") collection = db.get_or_create_collection( name="documents", metadata={"hnsw:space": "cosine"} ) # Convert Perplexity's encoded embeddings into numerical vectors def decode_embedding(encoded): vector = np.frombuffer(base64.b64decode(encoded), dtype=np.int8).astype(np.float32) norm = np.linalg.norm(vector) if norm == 0: raise ValueError("Received a zero-length embedding vector.") return (vector / norm).tolist() # 2. Read the document and split it into chunks text = Path("document.txt").read_text(encoding="utf-8") words = text.split() chunk_size = 180 overlap = 30 step = chunk_size - overlap chunks = [" ".join(words[i:i + chunk_size]) for i in range(0, len(words), step)] if not chunks: raise ValueError("document.txt is empty.") # 3. Retrieve the chunks already stored in ChromaDB existing = collection.get(include=["documents"]) stored_chunks = defaultdict(deque) existing_ids = set(existing["ids"]) for chunk_id, document in zip(existing["ids"], existing["documents"]): stored_chunks[document].append(chunk_id) # 4. Identify unchanged and new chunks new_chunks = [] new_ids = [] kept_ids = set() unchanged = 0 for chunk in chunks: if stored_chunks[chunk]: chunk_id = stored_chunks[chunk].popleft() kept_ids.add(chunk_id) unchanged += 1 else: chunk_hash = sha256(chunk.encode("utf-8")).hexdigest() chunk_id = f"chunk-{chunk_hash}" suffix = 1 while chunk_id in existing_ids or chunk_id in kept_ids or chunk_id in new_ids: chunk_id = f"chunk-{chunk_hash}-{suffix}" suffix += 1 new_chunks.append(chunk) new_ids.append(chunk_id) kept_ids.add(chunk_id) # 5. Generate embeddings in batches of up to 100 chunks batch_size = 100 for i in range(0, len(new_chunks), batch_size): batch_chunks = new_chunks[i:i + batch_size] batch_ids = new_ids[i:i + batch_size] embeddings = ai.embeddings.create( model="pplx-embed-v1-0.6b", input=batch_chunks, encoding_format="base64_int8" ) vectors = [decode_embedding(item.embedding) for item in embeddings.data] # 6. Store each batch in ChromaDB collection.upsert( ids=batch_ids, documents=batch_chunks, embeddings=vectors ) print(f"Indexed batch {(i // batch_size) + 1}") # 7. Remove outdated chunks old_ids = [chunk_id for chunk_id in existing["ids"] if chunk_id not in kept_ids] if old_ids: collection.delete(ids=old_ids) # 8. Display indexing results print("Indexing complete!") print("Unchanged chunks:", unchanged) print("New or modified chunks:", len(new_chunks)) print("Removed chunks:", len(old_ids)) print("Total stored chunks:", collection.count())

Krok 5. Napíšte orchestrátor pre systém RAG

Skopírujte nižšie uvedený kód a vložte ho do súboru rag.py. Ide o úplnú, no minimalistickú implementáciu RAG, ktorá využíva Perplexity SDK a funkcie lokálnej vektorovej databázy ChromaDB.

Toto sa stane, keď program spustíte:

  1. Pripojí sa k Perplexity a k vašej novej databáze ChromaDB.
  2. Overí, či databáza obsahuje zaindexované dokumenty.
  3. Prijme otázku od používateľa.
  4. Odošle otázku do embeddingového modelu Perplexity.
  5. Dekóduje a normalizuje výsledný embedding pomocou NumPy.
  6. Vyhľadá v ChromaDB tri najpodobnejšie úseky dokumentu.
  7. Zostaví prompt obsahujúci získané úseky a otázku používateľa.
  8. Odošle prompt do modelu GPT-5.6 Luna cez Agent API od Perplexity.
  9. Zobrazí odpoveď a čaká na ďalšiu otázku.
python
import base64 import numpy as np import chromadb from dotenv import load_dotenv from perplexity import Perplexity # 1. Connect to Perplexity and the existing ChromaDB database load_dotenv() ai = Perplexity() db = chromadb.PersistentClient(path="./rag_database_perplexity") collection = db.get_collection("documents") # Convert Perplexity's encoded embeddings into numerical vectors def decode_embedding(encoded): vector = np.frombuffer(base64.b64decode(encoded), dtype=np.int8).astype(np.float32) norm = np.linalg.norm(vector) if norm == 0: raise ValueError("Received a zero-length embedding vector.") return (vector / norm).tolist() # 2. Check that the database contains indexed documents count = collection.count() if count == 0: raise ValueError("The database is empty. Run index.py first.") print("Connected to existing ChromaDB database.") print("Stored chunks:", count) # 3. Accept questions from the user while True: question = input("\nAsk a question (or type exit): ") if question.lower().strip() == "exit": break if not question.strip(): continue # 4. Convert the question into a Perplexity embedding question_response = ai.embeddings.create( model="pplx-embed-v1-0.6b", input=[question], encoding_format="base64_int8" ) question_vector = decode_embedding(question_response.data[0].embedding) # 5. Retrieve the most similar document chunks from ChromaDB results = collection.query( query_embeddings=[question_vector], n_results=min(3, count) ) context = "\n\n".join(results["documents"][0]) # 6. Construct a prompt and send it to the fixed LLM response = ai.responses.create( model="openai/gpt-5.6-luna", instructions=( "Answer using only the supplied document excerpts. " "Do not use external information. " "If the answer is not present, say you don't know." ), input=f"Document excerpts:\n{context}\n\nQuestion: {question}" ) # 7. Display the answer print("\nAnswer:\n", response.output_text)

Krok 6: Spustite aplikácie

V termináli PowerShell vo VS Code zadajte nasledujúci príkaz, ktorým vytvoríte embeddingy obsahu súboru document.txt:

bash
.\.venv\Scripts\python.exe index.py

Ak sa dokument úspešne zaindexoval, mali by ste vidieť výstup podobný tomuto:

plaintext
Indexing complete! Unchanged chunks: 0 New or modified chunks: 58 Removed chunks: 0 Total stored chunks: 58

Teraz je čas spustiť hlavnú aplikáciu orchestrátora. Zadajte tento príkaz:

bash
.\.venv\Scripts\python.exe rag.py

Ak sa aplikácia úspešne spustí, zobrazí sa toto:

plaintext
Connected to existing ChromaDB database. Stored chunks: 58 Ask a question (or type exit):

Teraz môžete klásť otázky, pri ktorých bude systém čerpať z vytvorenej vektorovej databázy, napríklad:

plaintext
Ask a question (or type exit): What animals does William Blake talk about? Answer: The excerpts mention sheep, lambs, birds, beasts, wolves, tigers, and a lion.

Krok 7: Pochopte, čo ste vytvorili

Systém, ktorý ste vytvorili, obsahuje dva základné pipeliny prítomné v každej architektúre RAG: indexovací pipeline, nazývaný aj pipeline na „načítavanie“ dát, a pipeline na získavanie a generovanie.

Vaša základná implementácia RAG teraz zvláda všetko toto:

  • Vektorové úložisko: Embeddingy vytvorené z vášho znalostného súboru sa ukladajú do databázy ChromaDB vo vašom lokálnom prostredí.
  • Inkrementálne indexovanie: Pre nezmenené úseky dokumentu sa embeddingy znova nevytvárajú a dokument môžete aktualizovať, kedykoľvek budete chcieť.
  • Sémantické vyhľadávanie: ChromaDB vyhľadáva úseky na základe vektorovej podobnosti (na podnet orchestrátora).
  • Generovanie podložených odpovedí: LLM dostane získané pasáže ako kontext a začlení ich do odpovede.
  • Nezávislé indexovanie a dopytovanie: Môžete klásť otázky bez toho, aby bolo potrebné znova spracovať celý text vo vašom znalostnom súbore.
  • Pripojenie modelu cez API: Všetky odpovede generuje model GPT-5.6 Luna cez Perplexity, nie model bežiaci na vašom počítači.

Ďalšie kroky: ako túto implementáciu rozšíriť

Cieľom tohto návodu je vytvoriť jednoduchú, základnú implementáciu. Pokrýva niektoré zo základných komponentov architektúry RAG, ktoré nájdete v moderných systémoch. Ak chcete ísť ďalej, môžete na nej stavať viacerými spôsobmi.

Tu je niekoľko nápadov, ako rozšíriť rozsah vašej implementácie:

  • Experimentujte s LangChain: LangChain je jeden z najpopulárnejších open-source orchestračných frameworkov. Obsahuje predpripravené komponenty na tvorbu aplikácií, ktoré dokážu spúšťať zložité pipeliny RAG.
  • Rozšírte funkcie vyhľadávania: Skombinujte husté vektorové vyhľadávanie s lexikálnym vyhľadávaním (podľa kľúčových slov), napríklad BM25. Pridanie webového vyhľadávania cez Perplexity Search API by vám tiež umožnilo podložiť odpovede aktuálnymi dátami.
  • Pridajte model na opätovné zoradenie: Integrujte model na opätovné zoradenie (reranking), ktorý ohodnotí získané pasáže vzhľadom na pôvodný prompt a vyberie tie najrelevantnejšie na zaradenie do vstupného kontextu, ktorý dostane LLM.
  • Vytvorte adaptívny systém RAG: Adaptívny RAG používa buď LLM, alebo klasifikátor (komponent v rámci orchestrátora) na určenie, ktorú metódu získavania v modulárnom systéme RAG použiť. Vytvorenie takého systému je dobrý spôsob, ako preskúmať sofistikovanejšie implementácie RAG.

Hoci to všetko môže znieť zložito, majte na pamäti, že bežné platformy AI, ako je Perplexity, dokážu poskytnúť pokročilú pomoc s programovaním. Sú výborné na osobné projekty a experimentovanie a náklady sa dajú udržať pomerne nízke.

Poznámka: V tomto návode sa používa model GPT-5.6 Luna. Dostupnosť modelov sa môže zmeniť, takže možno budete musieť aktualizovať volanie API.