Základní implementace RAG: návod krok za krokem
Tento návod pro začátečníky vysvětluje, jak funguje základní implementace RAG, probírá osvědčené postupy a provede vás sestavením funkčního systému RAG pro příkazový řádek pomocí Pythonu, ChromaDB a embeddingových a jazykových modelů Perplexity.

RAG je nezbytnou součástí moderní infrastruktury postavené na LLM. Tím, že modelům AI umožňuje přistupovat k externím datům, pomáhá řešit problémy, jako jsou halucinace a neúplná trénovací data. Firmy díky němu také mohou využívat interní znalostní báze, které obsahují citlivé nebo proprietární informace.
Implementace RAG může být velmi složitá. Základní systém RAG je však překvapivě snadné sestavit. Začátečníkům může vytvoření jednoduché architektury ukázat, jak RAG funguje v praxi, a poskytnout odrazový můstek pro další experimentování.
V tomto článku si nastíníme základní implementaci RAG, probereme osvědčené postupy a poté sestavíme funkční systém pomocí Pythonu, ChromaDB a dvou modelů Perplexity pro vytváření embeddingů a generování odpovědí.
Proces základní implementace RAG: celkový přehled
Základní systém RAG má tři hlavní součásti: orchestrátor, zdroj informací a LLM. V typickém pracovním postupu uživatel zadá prompt a orchestrátor ho upraví tak, aby mohl prohledat všechny připojené zdroje informací. Získané informace se pak přidají k původnímu vstupnímu kontextu a odešlou se do LLM, které na jejich základě vygeneruje odpověď.
Při sestavování implementace RAG budete muset počítat s těmito kroky:
- Indexování a embedding: V této fázi se vaše dokumenty převedou na zdroj informací, který může orchestrátor prohledávat. Jedním z nejběžnějších způsobů je vytvoření prohledávatelného vektorového indexu. K převodu bloků dokumentu na embeddingy použijeme specializovaný model od Perplexity. Embeddingy pak uložíme do ChromaDB, oblíbené open-source vektorové databáze.
- Orchestrace: Jde o aplikaci, která stojí mezi externím zdrojem informací (v našem případě vektorovou databází) a LLM. Jako orchestrátor vytvoříme jednoduchý skript v Pythonu.
- Vyhledávání a generování: Když uživatel položí otázku přes chatovací rozhraní, orchestrátor ji převezme, spustí vektorové vyhledávání a rozšířený vstup předá LLM. Místo vytváření samostatného frontendu budeme s naším orchestrátorem v Pythonu komunikovat pomocí promptů v příkazovém řádku.
Osvědčené postupy: čím se vyznačuje efektivní implementace RAG?
Existuje více typů architektury RAG a jednotlivé případy použití vyžadují různé přístupy. Řada osvědčených postupů však platí ve všech případech a zajišťuje přesné, nákladově efektivní, škálovatelné a snadno udržovatelné systémy.
Následující osvědčené postupy platí pro všechny typy implementace RAG:
- Zajistěte čistou pipeline pro příjem dat: Zdrojová data by měla být před indexováním co nejčistší. Měli byste také použít model pro embedding, který se hodí k vašemu obsahu.
- Používejte hybridní vyhledávání: Nejlepší metody vyhledávání – ať už jde o vyhledávání ve vektorové databázi, webové vyhledávání přes API, procházení znalostního grafu, vyhledávání podle klíčových slov, nebo jiné metody – se liší podle případu použití. Výběr správné kombinace je důležitý pro minimalizaci nákladů.
- Vyhodnocujte svůj systém: Po implementaci byste měli systém vyhodnotit podle tří klíčových měřítek: přesnosti, relevance a latence. Přesnost označuje faktickou správnost, relevance použitelnost získaných informací pro dotazy uživatelů a latence rychlost, s jakou se informace získávají.
- Zacházejte s informacemi bezpečně: Pokud váš systém RAG čerpá ze soukromých interních informací, zajistěte, aby byly bezpečně uložené a aby byl přístup k rozhraní systému řízený. Klíče API byste nikdy neměli sdílet.
Základní implementace RAG: návod v 7 krocích
V tomto návodu sestavíme aplikaci pro příkazový řádek, která odpovídá na otázky týkající se jednoho dokumentu. Použijeme Python, ChromaDB a Perplexity API.
Cílem není sestavit systém RAG připravený pro produkční nasazení. Jde spíše o návod pro začátečníky, který má ukázat, jak jednoduchá architektura RAG funguje v praxi.
Krok 1: Instalace softwaru
Ujistěte se, že máte v počítači nainstalované následující nástroje a že máte účet Perplexity API:
- Python: Jde o programovací jazyk, ve kterém sestavíme orchestrátor, jenž bude koordinovat tok dat mezi modelem pro embedding, ChromaDB a Perplexity.
- Visual Studio: Jako editor kódu použijeme Visual Studio. Po instalaci otevřete panel Extensions a stáhněte rozšíření Python.
- Účet Perplexity API: Perplexity poskytne jak model pro embedding (který převádí vaše data na vektorové embeddingy), tak LLM, které zpracuje rozšířený prompt. Placený účet k tomu nepotřebujete, spotřebujete však malé množství kreditů.
Krok 2: Vytvoření složky projektu
Začněte vytvořením složky s názvem rag-project a otevřete ji ve VS Code výběrem File > Open Folder. Poté otevřete integrovaný terminál přes Terminal > New Terminal.
Zadáním následujícího příkazu vytvořte virtuální prostředí Pythonu:
py -3.12 -m venv .venvNyní je potřeba nainstalovat čtyři knihovny Pythonu: perplexityai, chromadb, python-dotenv a numpy. Perplexity SDK vám umožní připojit se k modelům Perplexity přes API. ChromaDB vytvoří vektorovou databázi a poběží lokálně. Python-dotenv bezpečně načítá vaše klíče API z lokálního souboru a NumPy je potřeba během procesu příjmu dat.
Nainstalujte je následujícím příkazem:
.\.venv\Scripts\python.exe -m pip install perplexityai chromadb python-dotenv numpyKrok 3: Příprava souborů
Přidejte do složky rag-project (kořenového adresáře projektu) následující soubory výběrem možnosti New File… v postranním panelu Explorer:
- index.py: Jde o aplikaci, která zaindexuje váš dokument. Můžete ji spustit znovu a přidat další text.
- rag.py: Jde o aplikaci v Pythonu, která bude fungovat jako orchestrátor.
- document.txt: Bude obsahovat dokumentaci, kterou převedete na vektorovou databázi.
- .env: Sem uložíte svůj klíč Perplexity API.
Do souboru .env zadejte následující:
PERPLEXITY_API_KEY=your_api_key_hereNahraďte your_api_key_here svým skutečným klíčem. Klíč získáte tak, že přejdete na domovský dashboard v Perplexity API Console a vyberete Create an API key. Tento klíč API uchovávejte v soukromí.
Použijeme dva modely: pplx-embed-v1-0.6b od Perplexity, který před nahráním do ChromaDB vytvoří embeddingy naší dokumentace, a GPT-5.6-Luna (dostupný přes API Perplexity), který zpracuje získané informace.
Do souboru document.txt přidejte text, ze kterého bude vaše pipeline RAG získávat informace. Pokud nemáte po ruce žádný dokument, použijte pro tento návod sbírku Williama Blakea Songs of Innocence and of Experience z Projektu Gutenberg. Je to krátký, snadno srozumitelný text, který je volným dílem.
Krok 4: Napsání indexovacího programu
Zkopírujte níže uvedený kód a vložte ho do souboru index.py. Každý podnadpis stručně vysvětluje, co dělá následující část kódu. Tento program převede váš zdrojový materiál na vektorové embeddingy a uloží je do databáze ChromaDB pomocí modelu pro embedding od Perplexity, pplx-embed-v1-0.6b, a knihovny NumPy.
Program dělá toto:
- Otevře soubor document.txt.
- Rozdělí text na překrývající se bloky.
- Odešle tyto bloky do modelu pro embedding pplx-embed-v1-0.6b od Perplexity.
- Dekóduje a normalizuje vrácené vektory pomocí NumPy, knihovny výpočetních funkcí pro Python.
- Uloží vektory a původní bloky do databáze ChromaDB (uvidíte, jak se objeví v adresáři projektu).
Program je nastavený tak, aby váš dokument při každém spuštění znovu neindexoval. Pokud do souboru document.txt přidáte další informace, vytvoří embeddingy jen pro nový text.
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. Napsání orchestrátoru pro systém RAG
Zkopírujte níže uvedený kód a vložte ho do souboru rag.py. Jde o úplnou, ale minimální implementaci RAG, která využívá Perplexity SDK a funkce lokální vektorové databáze ChromaDB.
Po spuštění programu se stane toto:
- Připojí se k Perplexity a k vaší nové databázi ChromaDB.
- Zkontroluje, zda databáze obsahuje zaindexované dokumenty.
- Přijme otázku od uživatele.
- Odešle otázku do modelu pro embedding od Perplexity.
- Dekóduje a normalizuje výsledný embedding pomocí NumPy.
- Vyhledá v ChromaDB tři nejpodobnější bloky dokumentu.
- Sestaví prompt obsahující získané bloky a otázku uživatele.
- Odešle prompt modelu GPT-5.6 Luna přes Agent API od Perplexity.
- Zobrazí odpověď a počká na další otázku.
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: Spuštění aplikací
V terminálu PowerShell ve VS Code zadejte následující příkaz, abyste vytvořili embeddingy obsahu souboru document.txt:
.\.venv\Scripts\python.exe index.pyPokud byl váš dokument úspěšně zaindexován, měli byste vidět výstup podobný tomuto:
Indexing complete!
Unchanged chunks: 0
New or modified chunks: 58
Removed chunks: 0
Total stored chunks: 58Teď je čas spustit hlavní aplikaci orchestrátoru. Zadejte tento příkaz:
.\.venv\Scripts\python.exe rag.pyPokud se aplikace úspěšně spustí, uvidíte následující:
Connected to existing ChromaDB database.
Stored chunks: 58
Ask a question (or type exit): Nyní můžete klást otázky, na které systém odpoví s využitím vámi vytvořené vektorové databáze, například:
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: Pochopení toho, co jste sestavili
Systém, který jste sestavili, obsahuje dvě klíčové pipeline, jež najdete v každé architektuře RAG: indexovací pipeline (neboli pipeline pro „příjem dat“) a pipeline pro vyhledávání a generování.
Vaše základní implementace RAG teď zvládá všechno následující:
- Vektorové úložiště: Embeddingy vytvořené na základě vašeho znalostního souboru se ukládají do databáze ChromaDB ve vašem lokálním prostředí.
- Inkrementální indexování: Pro nezměněné bloky dokumentu se embeddingy znovu nevytvářejí a dokument můžete kdykoli aktualizovat.
- Sémantické vyhledávání: ChromaDB vyhledává bloky na základě vektorové podobnosti (vyhledávání spouští orchestrátor).
- Generování odpovědí podložených zdroji: LLM dostane získané pasáže jako kontext a zapracuje je do odpovědi.
- Nezávislé indexování a dotazování: Můžete klást otázky, aniž byste museli znovu zpracovávat celý text ve vašem znalostním souboru.
- Připojení k modelu přes API: Všechny odpovědi generuje GPT-5.6 Luna přes Perplexity, nikoli model běžící na vašem počítači.
Další kroky: jak tuto implementaci dále rozvinout
Cílem tohoto návodu je sestavit jednoduchou základní implementaci. Pokrývá některé klíčové součásti architektury RAG, které se vyskytují v moderních systémech. Pokud chcete jít dál, můžete na ní stavět různými způsoby.
Zde je několik nápadů, jak rozšířit rozsah vaší implementace:
- Vyzkoušejte LangChain: LangChain je jedním z nejoblíbenějších open-source orchestračních frameworků. Obsahuje předpřipravené komponenty pro vytváření aplikací, které zvládnou spouštět složité pipeline RAG.
- Rozšiřte možnosti vyhledávání: Zkombinujte husté vektorové vyhledávání s lexikálním vyhledáváním (podle klíčových slov), například BM25. Přidání webového vyhledávání přes Perplexity Search API by vám také umožnilo podložit odpovědi aktuálními daty.
- Přidejte model pro přeřazení výsledků: Integrujte model pro přeřazení (reranking), který seřadí získané pasáže podle shody s původním promptem a vybere ty nejrelevantnější pro zařazení do vstupního kontextu předávaného LLM.
- Sestavte adaptivní systém RAG: Adaptivní RAG používá buď LLM, nebo klasifikátor (komponentu v rámci orchestrátoru) k určení, kterou metodu vyhledávání v modulárním systému RAG použít. Sestavení takového systému je dobrý způsob, jak prozkoumat sofistikovanější implementace RAG.
I když to všechno může znít složitě, mějte na paměti, že běžné platformy AI, jako je Perplexity, dokážou poskytnout pokročilou pomoc s programováním. Jsou skvělé pro osobní projekty a experimentování a náklady lze udržet relativně nízké.
Poznámka: Tento návod používá GPT-5.6 Luna. Dostupnost modelů se může měnit, takže možná budete muset volání API aktualizovat.