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.

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 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:

  1. 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.
  2. 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.
  3. 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:

bash
py -3.12 -m venv .venv

Sada 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:

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

3. 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:

plaintext
PERPLEXITY_API_KEY=your_api_key_here

Zamijenite 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:

  1. Otvara datoteku document.txt.
  2. Dijeli tekst na segmente koji se preklapaju.
  3. Šalje te segmente Perplexityjevu modelu za ugrađivanje pplx-embed-v1-0.6b.
  4. Dekodira i normalizira vraćene vektore pomoću NumPyja, Python biblioteke računskih funkcija.
  5. 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.

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())

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:

  1. Povezuje se s Perplexityjem i vašom novom bazom podataka ChromaDB.
  2. Provjerava sadrži li baza podataka indeksirane dokumente.
  3. Prima pitanje od korisnika.
  4. Šalje pitanje Perplexityjevu modelu za ugrađivanje.
  5. Dekodira i normalizira dobivenu ugradnju pomoću NumPyja.
  6. Pretražuje ChromaDB kako bi pronašao tri najsličnija segmenta dokumenta.
  7. Sastavlja upit koji sadrži dohvaćene segmente i korisnikovo pitanje.
  8. Šalje upit modelu GPT-5.6 Luna putem Perplexityjeva Agent API-ja.
  9. Prikazuje odgovor i čeka sljedeće pitanje.
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)

6. korak: pokrenite aplikacije

U PowerShell terminalu u VS Codeu unesite sljedeće kako biste generirali ugradnje za sadržaj datoteke document.txt:

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

Ako je vaš dokument uspješno indeksiran, trebali biste vidjeti izlaz sličan ovome:

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

Sada je vrijeme da pokrenete glavnu aplikaciju orkestratora. Unesite ovu naredbu:

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

Ako se uspješno pokrene, vidjet ćete sljedeće:

plaintext
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:

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.

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.