Osnovna implementacija RAG-a: vodič korak po korak
Ovaj vodič prilagođen početnicima objašnjava kako funkcionira osnovna implementacija RAG-a, opisuje najbolje prakse i vodi vas kroz izradu funkcionalnog RAG sustava za naredbeni redak pomoću Pythona, ChromaDB-a te Perplexityjevih modela za ugrađivanje i jezičnih modela.

RAG je ključna sastavnica suvremene infrastrukture temeljene na LLM-ovima. Budući da AI modelima omogućuje pristup vanjskim podacima, pomaže u rješavanju problema poput halucinacija i nepotpunih podataka za treniranje. To također znači da tvrtke mogu koristiti interne baze znanja koje sadrže osjetljive ili vlasničke informacije.
Implementacija RAG-a može biti vrlo složena. Ipak, osnovni RAG sustav iznenađujuće je jednostavno izgraditi. Početnicima izrada jednostavne arhitekture može razjasniti kako RAG funkcionira u stvarnom svijetu i poslužiti kao odskočna daska za daljnje eksperimentiranje.
U ovom ćemo članku prikazati osnovnu implementaciju RAG-a, objasniti najbolje prakse, a zatim izgraditi funkcionalan sustav pomoću Pythona, ChromaDB-a i dvaju Perplexityjevih modela za ugrađivanje i generiranje odgovora.
Postupak osnovne implementacije RAG-a: opći pregled
Osnovni RAG sustav ima tri glavne komponente: orkestrator, izvor informacija i LLM. U tipičnom tijeku rada korisnik unosi upit, a orkestrator ga prilagođava kako bi pretražio sve povezane izvore informacija. Dohvaćene informacije zatim se dodaju izvornom ulaznom kontekstu i šalju LLM-u kako bi se mogao generirati odgovor.
Pri izradi svoje implementacije RAG-a morat ćete uzeti u obzir sljedeće korake:
- Indeksiranje i ugrađivanje: U ovoj se fazi vaši dokumenti pretvaraju u izvor informacija koji orkestrator može pretraživati. Jedan od najčešćih načina da se to postigne jest izrada pretraživog vektorskog indeksa. Upotrijebit ćemo namjenski Perplexityjev model kako bismo segmente vaših dokumenata pretvorili u ugradnje (embeddings). Ugradnje ćemo zatim pohraniti u ChromaDB, popularnu vektorsku bazu podataka otvorenog koda.
- Orkestracija: To je aplikacija koja se nalazi između vanjskog izvora informacija (u našem slučaju vektorske baze podataka) i LLM-a. Izradit ćemo jednostavnu Python skriptu koja će služiti kao orkestrator.
- Dohvaćanje i generiranje: Kada korisnik postavi pitanje putem chat sučelja, orkestrator će ga preuzeti, pokrenuti vektorsko pretraživanje i proslijediti prošireni ulaz LLM-u. Umjesto izrade namjenskog korisničkog sučelja, za komunikaciju s našim Python orkestratorom upotrebljavat ćemo naredbeni redak.
Najbolje prakse: što čini učinkovitu implementaciju RAG-a?
Postoji više vrsta RAG arhitekture, a pojedini slučajevi upotrebe zahtijevaju različite pristupe. Ipak, niz najboljih praksi primjenjuje se u svim slučajevima i osigurava točne, troškovno učinkovite, skalabilne i lako održive sustave.
Sljedeće najbolje prakse primjenjuju se na sve vrste implementacije RAG-a:
- Osigurajte čist cjevovod za unos podataka: Izvorni podaci trebaju biti što čišći prije indeksiranja. Također biste trebali koristiti model za ugrađivanje prikladan za vaš sadržaj.
- Koristite hibridno pretraživanje: Najbolje metode dohvaćanja, bilo da je riječ o pretraživanju vektorske baze podataka, web-pretraživanju putem API-ja, obilasku grafa znanja, pretraživanju po ključnim riječima ili drugim metodama, razlikuju se ovisno o slučaju upotrebe. Odabir prave kombinacije važan je za smanjenje troškova.
- Procijenite svoj sustav: Nakon implementacije trebali biste ga vrednovati prema trima ključnim mjerilima: točnosti, relevantnosti i latenciji. Točnost se odnosi na činjeničnu ispravnost, relevantnost na primjenjivost dohvaćenih informacija na korisničke upite, a latencija na brzinu kojom se informacije dohvaćaju.
- Postupajte s informacijama sigurno: Ako se vaš RAG sustav oslanja na privatne interne informacije, pobrinite se da su sigurno pohranjene i da se upravlja pristupom sučelju sustava. API ključevi nikada se ne smiju dijeliti.
Osnovna implementacija RAG-a: vodič u 7 koraka
U ovom ćemo vodiču izraditi aplikaciju za naredbeni redak koja odgovara na pitanja o jednom dokumentu. Upotrijebit ćemo Python, ChromaDB i Perplexity API.
Cilj nije izgraditi RAG sustav spreman za produkciju. Riječ je o vodiču prilagođenom početnicima, osmišljenom kako bi pokazao kako osnovna RAG arhitektura funkcionira u praksi.
1. korak: instalirajte softver
Provjerite jesu li na vašem računalu instalirani sljedeći programi i imate li račun za Perplexity API:
- Python: To je programski jezik koji ćemo upotrijebiti za izradu orkestratora koji će koordinirati protok podataka između modela za ugrađivanje, ChromaDB-a i Perplexityja.
- Visual Studio: Visual Studio upotrijebit ćemo kao uređivač koda. Nakon instalacije otvorite ploču Extensions i preuzmite proširenje Python.
- Račun za Perplexity API: Perplexity će osigurati i model za ugrađivanje (koji vaše podatke pretvara u vektorske ugradnje) i LLM koji će obraditi prošireni upit. Za to vam ne treba plaćeni račun, iako ćete potrošiti malu količinu kredita.
2. korak: izradite mapu projekta
Za početak izradite mapu naziva rag-project i otvorite je u VS Codeu odabirom File > Open Folder. Zatim otvorite integrirani terminal putem Terminal > New Terminal.
Unesite sljedeće kako biste izradili virtualno Python okruženje:
py -3.12 -m venv .venvSada trebate instalirati četiri Python biblioteke: perplexityai, chromadb, python-dotenv i numpy. Perplexity SDK omogućit će vam povezivanje s Perplexityjevim modelima putem API-ja. ChromaDB izrađuje vektorsku bazu podataka i radit će lokalno. Python-dotenv sigurno učitava vaše API ključeve iz lokalne datoteke, a NumPy je potreban tijekom procesa unosa podataka.
Instalirajte ih sljedećom naredbom:
.\.venv\Scripts\python.exe -m pip install perplexityai chromadb python-dotenv numpy3. korak: postavite datoteke
Dodajte sljedeće datoteke u rag-project (korijenski direktorij projekta) odabirom opcije New File… u bočnoj traci Explorer:
- index.py: To je aplikacija koja će indeksirati vaš dokument. Možete je ponovno pokrenuti kako biste dodali još teksta.
- rag.py: To je Python aplikacija koja će služiti kao orkestrator.
- document.txt: Sadržavat će dokumentaciju koju ćete pretvoriti u vektorsku bazu podataka.
- .env: Ovdje ćete čuvati svoj Perplexity API ključ.
U datoteku .env unesite sljedeće:
PERPLEXITY_API_KEY=your_api_key_hereZamijenite your_api_key_here svojim stvarnim ključem. Da biste to učinili, otvorite početnu nadzornu ploču u Perplexity API Consoleu i odaberite Create an API key. Čuvajte ovaj API ključ u tajnosti.
Upotrebljavat ćemo dva modela: Perplexityjev pplx-embed-v1-0.6b za ugrađivanje dokumentacije prije prijenosa u ChromaDB i GPT-5.6-Luna (kojemu se pristupa putem Perplexityjeva API-ja), koji će obrađivati dohvaćene informacije.
U datoteku document.txt dodajte tekst koji će vaš RAG cjevovod dohvaćati. Ako nemate dokument pri ruci, za ovaj vodič upotrijebite zbirku Songs of Innocence and of Experience Williama Blakea iz Projekta Gutenberg. Riječ je o kratkom, lako razumljivom tekstu koji je u javnom vlasništvu.
4. korak: napišite program za indeksiranje
Kopirajte i zalijepite kod u nastavku u datoteku index.py. Svaki podnaslov ukratko objašnjava što radi segment koda koji slijedi. To je program koji će vaš izvorni materijal pretvoriti u vektorske ugradnje i pohraniti ih u bazu podataka ChromaDB pomoću Perplexityjeva modela za ugrađivanje pplx-embed-v1-0.6b i biblioteke NumPy.
Evo što program radi:
- Otvara datoteku document.txt.
- Dijeli tekst na segmente koji se preklapaju.
- Šalje te segmente Perplexityjevu modelu za ugrađivanje pplx-embed-v1-0.6b.
- Dekodira i normalizira vraćene vektore pomoću NumPyja, Python biblioteke računskih funkcija.
- Pohranjuje vektore i izvorne segmente u bazu podataka ChromaDB (vidjet ćete da se pojavila u direktoriju projekta).
Postavljen je tako da ne indeksira ponovno vaš dokument pri svakom pokretanju. Ako dodate informacije u datoteku document.txt, generirat će ugradnje samo za novi tekst.
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())5. korak: napišite orkestrator za RAG sustav
Kopirajte i zalijepite kod u nastavku u datoteku rag.py. Riječ je o potpunoj, ali minimalnoj implementaciji RAG-a koja koristi Perplexity SDK i funkcionalnost lokalne vektorske baze podataka ChromaDB.
Evo što će se dogoditi kada pokrenete program:
- Povezuje se s Perplexityjem i vašom novom bazom podataka ChromaDB.
- Provjerava sadrži li baza podataka indeksirane dokumente.
- Prima pitanje od korisnika.
- Šalje pitanje Perplexityjevu modelu za ugrađivanje.
- Dekodira i normalizira dobivenu ugradnju pomoću NumPyja.
- Pretražuje ChromaDB kako bi pronašao tri najsličnija segmenta dokumenta.
- Sastavlja upit koji sadrži dohvaćene segmente i korisnikovo pitanje.
- Šalje upit modelu GPT-5.6 Luna putem Perplexityjeva Agent API-ja.
- Prikazuje odgovor i čeka sljedeće pitanje.
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)6. korak: pokrenite aplikacije
U PowerShell terminalu u VS Codeu unesite sljedeće kako biste generirali ugradnje za sadržaj datoteke document.txt:
.\.venv\Scripts\python.exe index.pyAko je vaš dokument uspješno indeksiran, trebali biste vidjeti izlaz sličan ovome:
Indexing complete!
Unchanged chunks: 0
New or modified chunks: 58
Removed chunks: 0
Total stored chunks: 58Sada je vrijeme da pokrenete glavnu aplikaciju orkestratora. Unesite ovu naredbu:
.\.venv\Scripts\python.exe rag.pyAko se uspješno pokrene, vidjet ćete sljedeće:
Connected to existing ChromaDB database.
Stored chunks: 58
Ask a question (or type exit): Sada možete postavljati pitanja na koja će se odgovarati na temelju vektorske baze podataka koju ste izradili, primjerice:
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.7. korak: shvatite što ste izgradili
Sustav koji ste izgradili sadrži dva ključna cjevovoda prisutna u svakoj RAG arhitekturi: cjevovod za indeksiranje, odnosno „unos podataka“, te cjevovod za dohvaćanje i generiranje.
Vaša osnovna implementacija RAG-a sada radi sve sljedeće:
- Vektorska pohrana: Ugradnje se na temelju vaše datoteke znanja spremaju u bazu podataka ChromaDB u vašem lokalnom okruženju.
- Inkrementalno indeksiranje: Za nepromijenjene segmente dokumenta ugradnje se ne generiraju ponovno, a dokument možete ažurirati kad god želite.
- Semantičko dohvaćanje: ChromaDB dohvaća segmente na temelju vektorske sličnosti (na zahtjev orkestratora).
- Generiranje utemeljenih odgovora: LLM prima dohvaćene odlomke kao kontekst i uključuje ih u odgovor.
- Neovisno indeksiranje i postavljanje upita: Možete postavljati pitanja bez ponovne obrade cijelog teksta iz vaše datoteke znanja.
- Povezivanje s modelom putem API-ja: Svi se odgovori generiraju pomoću modela GPT-5.6 Luna putem Perplexityja, a ne pomoću modela koji radi na vašem računalu.
Sljedeći koraci: kako dodatno razviti ovu implementaciju
Cilj ovog vodiča jest izgraditi jednostavnu, osnovnu implementaciju. Obuhvaća neke od ključnih komponenti RAG arhitekture prisutnih u suvremenim sustavima. Ako želite ići dalje, postoje razni načini na koje je možete nadograditi.
Evo nekoliko ideja za proširenje opsega vaše implementacije:
- Eksperimentirajte s LangChainom: LangChain jedan je od najpopularnijih okvira za orkestraciju otvorenog koda. Sadrži unaprijed izrađene komponente za izradu aplikacija koje mogu pokretati složene RAG cjevovode.
- Proširite funkcionalnost pretraživanja: Kombinirajte pretraživanje gustih vektora s leksičkim pretraživanjem (po ključnim riječima), primjerice BM25. Dodavanjem web-pretraživanja putem Perplexity Search API-ja također biste mogli utemeljiti odgovore na aktualnim podacima.
- Dodajte model za ponovno rangiranje: Integrirajte model za ponovno rangiranje koji rangira dohvaćene odlomke u odnosu na početni upit i odabire najrelevantnije za uključivanje u ulazni kontekst koji se prosljeđuje LLM-u.
- Izgradite adaptivni RAG sustav: Adaptivni RAG koristi LLM ili klasifikator (komponentu unutar orkestratora) kako bi odredio koju metodu dohvaćanja upotrijebiti u modularnom RAG sustavu. Izrada takvog sustava dobar je način za istraživanje naprednijih implementacija RAG-a.
Iako sve to može zvučati složeno, imajte na umu da vodeće AI platforme poput Perplexityja mogu pružiti naprednu pomoć pri programiranju. Izvrsne su za osobne projekte i eksperimentiranje, a troškovi se mogu održati relativno niskima.
Napomena: u ovom se vodiču koristi model GPT-5.6 Luna. Dostupnost modela može se promijeniti pa ćete možda morati ažurirati poziv API-ja.