Основна имплементација RAG-а: водич корак по корак
Овај водич прилагођен почетницима објашњава како функционише основна имплементација RAG-а, представља најбоље праксе и води вас кроз израду функционалног RAG система за командну линију помоћу језика Python, базе ChromaDB и Perplexity модела за ембединг и језичких модела.

RAG је суштинска компонента савремене инфраструктуре засноване на великим језичким моделима (LLM). Омогућавајући AI моделима приступ спољним подацима, помаже у рјешавању проблема као што су халуцинације и непотпуни подаци за обуку. То такође значи да компаније могу користити интерне базе знања које садрже осјетљиве или власничке информације.
Имплементација RAG-а може бити веома сложена. Ипак, основни RAG систем је изненађујуће лако направити. За почетнике, израда једноставне архитектуре може расвијетлити како RAG функционише у стварном свијету и пружити одскочну даску за даље експериментисање.
У овом чланку ћемо скицирати основну имплементацију RAG-а, представити најбоље праксе, а затим направити функционалан систем користећи Python, ChromaDB и два Perplexity модела за ембединг и генерисање одговора.
Процес основне имплементације RAG-а: општи преглед
Основни RAG систем има три главне компоненте: оркестратор, извор информација и LLM. У типичном току рада корисник уноси промпт, а оркестратор га прилагођава како би претражио све повезане изворе информација. Пронађене информације се затим додају оригиналном улазном контексту и шаљу LLM-у како би се могао генерисати одговор.
Приликом израде своје RAG имплементације мораћете узети у обзир сљедеће кораке:
- Индексирање и ембединг: У овој фази ваши документи се претварају у извор информација који оркестратор може претраживати. Један од најчешћих начина да се то уради јесте израда векторског индекса који се може претраживати. Користићемо намјенски Perplexity модел за претварање сегмената ваших докумената у ембединге. Ембединге ћемо затим чувати у ChromaDB, популарној векторској бази података отвореног кода.
- Оркестрација: Ово је апликација која се налази између спољног извора информација (у нашем случају векторске базе података) и LLM-а. Направићемо једноставну Python скрипту која ће имати улогу оркестратора.
- Проналажење и генерисање: Када корисник постави питање путем интерфејса за ћаскање, оркестратор ће га преузети, покренути векторску претрагу и прослиједити проширени улаз LLM-у. Умјесто израде намјенског фронтенда, за слање промптова нашем Python оркестратору користићемо командну линију.
Најбоље праксе: шта чини RAG имплементацију ефикасном?
Постоји више типова RAG архитектуре, а појединачни случајеви употребе захтијевају различите приступе. Ипак, низ најбољих пракси примјењује се у свим случајевима и обезбјеђује тачне, исплативе и скалабилне системе који се лако одржавају.
Сљедеће најбоље праксе примјењују се на све типове RAG имплементације:
- Обезбиједите чист пајплајн за унос података: Изворни подаци треба да буду што чистији прије индексирања. Такође треба да користите модел за ембединг прилагођен вашем садржају.
- Користите хибридну претрагу: Најбоље методе проналажења, било да је ријеч о претрази векторске базе података, веб претрази путем API-ја, обиласку графа знања, претрази по кључним ријечима или другим методама, разликују се у зависности од случаја употребе. Избор праве комбинације важан је за смањење трошкова.
- Процијените свој систем: Након имплементације, систем треба процијенити према три кључна мјерила: тачности, релевантности и латенцији. Тачност се односи на чињеничну исправност, релевантност на примјењивост пронађених информација на корисничке упите, а латенција на брзину којом се информације проналазе.
- Безбједно поступајте са информацијама: Ако се ваш RAG систем ослања на приватне интерне информације, побрините се да се оне безбједно чувају и да се приступ интерфејсу система контролише. API кључеве никада не треба дијелити.
Основна имплементација RAG-а: водич у 7 корака
У овом водичу направићемо апликацију за командну линију која одговара на питања о једном документу. Користићемо Python, ChromaDB и Perplexity API.
Циљ није направити RAG систем спреман за продукцију. Ово је, прије свега, водич прилагођен почетницима, осмишљен да илуструје како основна RAG архитектура функционише у пракси.
Корак 1: Инсталирајте софтвер
Провјерите да ли је на вашем рачунару инсталирано сљедеће и да ли имате налог за Perplexity API:
- Python: Ово је програмски језик који ћемо користити за израду оркестратора који ће координирати ток података између модела за ембединг, базе ChromaDB и платформе Perplexity.
- Visual Studio: Visual Studio ћемо користити као уређивач кода. Након инсталације, отворите панел Extensions и преузмите екстензију Python.
- Налог за Perplexity API: Perplexity ће обезбиједити и модел за ембединг (који ваше податке претвара у векторске ембединге) и LLM који ће обрадити проширени промпт. За ово вам није потребан плаћени налог, мада ће бити потрошена мала количина кредита.
Корак 2: Направите фасциклу пројекта
Почните тако што ћете направити фасциклу под називом rag-project и отворити је у VS Code-у избором опције File > Open Folder. Затим отворите интегрисани терминал путем Terminal > New Terminal.
Унесите сљедеће да бисте направили виртуелно Python окружење:
py -3.12 -m venv .venvСада је потребно инсталирати четири Python библиотеке: perplexityai, chromadb, python-dotenv и numpy. Perplexity SDK ће вам омогућити повезивање са Perplexity моделима путем API-ја. ChromaDB гради векторску базу података и радиће локално. Python-dotenv безбједно учитава ваше API кључеве из локалне датотеке, а NumPy је потребан током процеса уноса података.
Инсталирајте их сљедећом командом:
.\.venv\Scripts\python.exe -m pip install perplexityai chromadb python-dotenv numpyКорак 3: Подесите датотеке
Додајте сљедеће датотеке у rag-project (коријенски директоријум пројекта) избором опције New File… на бочној траци Explorer:
- index.py: Ово је апликација која ће индексирати ваш документ. Можете је поново покренути да бисте додали још текста.
- rag.py: Ово је Python апликација која ће имати улогу оркестратора.
- document.txt: Ова датотека ће садржати документацију коју ћете претворити у векторску базу података.
- .env: Овдје ћете чувати свој Perplexity API кључ.
У датотеку .env унесите сљедеће:
PERPLEXITY_API_KEY=your_api_key_hereЗамијените your_api_key_here својим стварним кључем. Да бисте то урадили, отворите почетну контролну таблу Perplexity API Console и изаберите Create an API key. Чувајте овај API кључ у тајности.
Користићемо два модела: Perplexity модел pplx-embed-v1-0.6b за ембединг наше документације прије отпремања у ChromaDB и GPT-5.6-Luna (којем се приступа путем Perplexity API-ја), који ће обрађивати пронађене информације.
У датотеку document.txt додајте текст који ће ваш RAG пајплајн проналазити. Ако немате документ при руци, за овај водич користите збирку Songs of Innocence and of Experience Вилијама Блејка са сајта Project Gutenberg. То је кратак, лако разумљив текст који је у јавном домену.
Корак 4: Напишите програм за индексирање
Копирајте и залијепите код у наставку у датотеку index.py. Сваки поднаслов укратко објашњава шта ради сегмент кода који слиједи. Ово је програм који ће ваш изворни материјал претворити у векторске ембединге и сачувати их у ChromaDB бази података користећи Perplexity модел за ембединг pplx-embed-v1-0.6b и библиотеку NumPy.
Ево шта програм ради:
- Отвара датотеку document.txt.
- Дијели текст на сегменте који се преклапају.
- Шаље те сегменте Perplexity моделу за ембединг pplx-embed-v1-0.6b.
- Декодира и нормализује враћене векторе помоћу NumPy-ја, Python библиотеке функција за рачунање.
- Чува векторе и оригиналне сегменте у ChromaDB бази података (видјећете да се она појављује у директоријуму вашег пројекта).
Подешен је тако да не индексира поново ваш документ сваки пут када га покренете. Ако додате нове информације у датотеку document.txt, програм ће креирати ембединге само за нови текст.
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. Напишите оркестратор за RAG систем
Копирајте и залијепите код у наставку у датотеку rag.py. Ово је потпуна, али минимална RAG имплементација која користи Perplexity SDK и функционалност локалне векторске базе података ChromaDB.
Ево шта ће се десити када покренете програм:
- Повезује се са платформом Perplexity и вашом новом ChromaDB базом података.
- Провјерава да ли база података садржи индексиране документе.
- Прихвата питање од корисника.
- Шаље питање Perplexity моделу за ембединг.
- Декодира и нормализује добијени ембединг помоћу NumPy-ја.
- Претражује ChromaDB базу како би пронашао три најсличнија сегмента документа.
- Саставља промпт који садржи пронађене сегменте и питање корисника.
- Шаље промпт моделу GPT-5.6 Luna путем Perplexity Agent API-ја.
- Приказује одговор и чека сљедеће питање.
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: Покрените апликације
У PowerShell терминалу у VS Code-у унесите сљедеће да бисте креирали ембединге за садржај датотеке document.txt:
.\.venv\Scripts\python.exe index.pyАко је ваш документ успјешно индексиран, требало би да видите излаз сличан овом:
Indexing complete!
Unchanged chunks: 0
New or modified chunks: 58
Removed chunks: 0
Total stored chunks: 58Сада је вријеме да покренете главну апликацију оркестратора. Унесите ову команду:
.\.venv\Scripts\python.exe rag.pyАко се успјешно покрене, видјећете сљедеће:
Connected to existing ChromaDB database.
Stored chunks: 58
Ask a question (or type exit): Сада можете постављати питања на која ће се одговори заснивати на векторској бази података коју сте направили, на примјер:
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: Разумијте шта сте направили
Систем који сте направили садржи два кључна пајплајна присутна у свакој RAG архитектури: пајплајн за индексирање, односно „унос“, и пајплајн за проналажење и генерисање.
Ваша основна RAG имплементација сада ради сљедеће:
- Векторско складиштење: Ембединзи се на основу ваше датотеке знања чувају у ChromaDB бази података у вашем локалном окружењу.
- Инкрементално индексирање: За непромијењене сегменте документа ембединзи се не креирају поново, а документ можете ажурирати кад год пожелите.
- Семантичко проналажење: ChromaDB проналази сегменте на основу векторске сличности (на захтјев оркестратора).
- Генерисање утемељених одговора: LLM добија пронађене одломке као контекст и укључује их у одговор.
- Независно индексирање и постављање упита: Можете постављати питања без поновне обраде цијелог текста из ваше датотеке знања.
- Повезивање са моделом путем API-ја: Сви одговори се генеришу помоћу модела GPT-5.6 Luna путем платформе Perplexity, а не помоћу модела који ради на вашем рачунару.
Сљедећи кораци: како даље развити ову имплементацију
Циљ овог водича је израда једноставне, основне имплементације. Он обухвата неке од кључних компоненти RAG архитектуре присутних у савременим системима. Ако желите ићи даље, постоје различити начини да је надоградите.
Ево неколико идеја за проширење обима ваше имплементације:
- Експериментишите са LangChain-ом: LangChain је један од најпопуларнијих оркестрационих оквира отвореног кода. Садржи унапријед направљене компоненте за израду апликација које могу покретати сложене RAG пајплајне.
- Проширите функционалност претраге: Комбинујте густу векторску претрагу са лексичком претрагом (по кључним ријечима), као што је BM25. Додавање веб претраге путем Perplexity Search API-ја омогућило би вам и да одговоре утемељите на актуелним подацима.
- Додајте модел за поновно рангирање: Интегришите модел за поновно рангирање који рангира пронађене одломке у односу на почетни промпт и бира најрелевантније за укључивање у улазни контекст који се доставља LLM-у.
- Направите адаптивни RAG систем: Адаптивни RAG користи LLM или класификатор (компоненту унутар оркестратора) да би одредио који метод проналажења треба користити у модуларном RAG систему. Израда таквог система добар је начин да истражите напредније RAG имплементације.
Иако све ово може звучати сложено, имајте на уму да водеће AI платформе као што је Perplexity могу пружити напредну помоћ при кодирању. Одличне су за личне пројекте и експериментисање, а трошкови се могу одржати релативно ниским.
Напомена: У овом водичу користи се модел GPT-5.6 Luna. Доступност модела се може промијенити, па ћете можда морати ажурирати API позив.