Ako ste pročitali moj prethodni članak o brzom indeksiranju u eri RAG-a i AI-ja, verovatno ste se zapitali: „Dobro, ali kako to da uradim u praksi?“ E pa, evo detaljnijih primera implementacije Retrieval-Augmented Generation (RAG) sistema koristeći Python i LangChain – jedan od najpopularnijih okvira za to. Ovi primeri su inspirisani najnovijim tutorijalima iz 2025. godine, poput onih sa TO THE NEW Blog-a i Medium-a, gde se fokusira na realne scenarije kao što je analiza govora ili pretraga kroz dokumente. Dodao sam svoje komentare, savete za optimizaciju i male izmene da budu još pristupačniji. Ako ste početnik, ovo će vas voditi kroz osnove; za iskusne, tu su trikovi za skaliranje.
RAG nije samo teorija – to je način da vaš AI „proširi“ znanje iz spoljnih izvora, smanjujući halucinacije i čineći odgovore preciznijim. Hajde da krenemo sa konkretnim kodom. Pretpostavljam da imate Python 3.11+ i OpenAI API ključ (besplatan za testiranje, ali plaćate po upitu).
Preduslovi: Priprema okruženja
Pre nego što zaronimo u kod, postavite bazu. Kreirajte virtuelno okruženje da izbegnete haos:
python -m venv rag_env
# Na Windows: rag_env\Scripts\activate
# Na Mac/Linux: source rag_env/bin/activate
pip install langchain langchain-openai langchain-chroma langchain-text-splitters python-dotenv tiktoken
OPENAI_API_KEY=sk-vaš-ključ-ovde
from dotenv import load_dotenv
import os
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
Primer 1: Jednostavan RAG sa Chroma vektorskom bazom (lokalno indeksiranje)
Ovaj primer koristi govor Bidena iz 2024. (kao u tutorijalu sa Medium-a) da pokaže kako da indeksirate tekst i odgovarate na pitanja. Chroma je besplatna, lokalna vektorska baza – savršena za testiranje bez cloud troškova.
Korak 1: Učitavanje i razbijanje teksta
Preuzmite neki tekst (npr. „2024_state_of_the_union.txt“) i razbijte ga na delove (chunks) da se lakše indeksira.
from langchain_text_splitters import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# Učitaj tekst
with open("2024_state_of_the_union.txt", "r") as f:
tekst = f.read()
# Razbij na delove
splitter = CharacterTextSplitter(
chunk_size=1000, # Velicina bloka
chunk_overlap=200, # Preklapanje za kontekst
length_function=len
)
dokumenti = splitter.create_documents([tekst])
Korak 2: Kreiranje vektorske baze i indeksiranje
# Embedding model za pretvaranje teksta u vektore
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
# Kreiraj Chroma bazu
vektor_baza = Chroma(
collection_name="state-union",
embedding_function=embeddings
)
# Dodaj dokumente
id_evi = vektor_baza.add_documents(dokumenti)
Korak 3: Kreiranje retrievera i LLM-a
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
# Retriever – traži slične delove
retriever = vektor_baza.as_retriever(search_kwargs={"k": 3}) # Top 3 rezultata
# LLM za generaciju
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.2) # Niska temperatura za tačnost
# Formatiranje rezultata
def formatiraj_dokumenti(docs):
return "\n\n".join(doc.page_content for doc in docs)
# Prompt šablon
prompt_template = """
Koristi sledeći kontekst da odgovoriš na pitanje. Ako ne znaš odgovor na osnovu konteksta, reci da ne znaš i izvini se.
Kontekst: {context}
Pitanje: {query}
Odgovor:
"""
prompt = PromptTemplate.from_template(prompt_template)
# RAG lanac
rag_lanac = (
{"context": retriever | formatiraj_dokumenti, "query": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# Upit
odgovor = rag_lanac.invoke("Prema govoru iz 2024, ko je napao Ukrajinu?")
print(odgovor)
# Očekivani output: "Prema govoru iz 2024. Državnog Saveza, Putin Rusije je napao Ukrajinu."
# Test van konteksta
odgovor_van = rag_lanac.invoke("Kakav je smisao života?")
print(odgovor_van)
# Output: "Izvinjavam se, ali ne znam odgovor na tvoje pitanje na osnovu datog konteksta."
Primer 2: Napredni RAG sa Pinecone (cloud skalabilnost)
Za veće baze (npr. hiljade dokumenata), koristite Pinecone za brzo indeksiranje. Ovaj primer je proširen iz TO THE NEW tutorijala, sa fokusom na API integraciju.
Korak 1: Učitavanje i procesiranje dokumenata
from langchain.document_loaders import DirectoryLoader
from langchain.text_splitter import CharacterTextSplitter
class BazaZnanja:
def __init__(self, direktorijum):
self.direktorijum = direktorijum
self.splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
def ucitaj_dokumente(self):
loader = DirectoryLoader(self.direktorijum)
dokumenti = loader.load()
return self.splitter.split_documents(dokumenti)
Korak 2: Retriever sa Pinecone
import pinecone
from langchain.vectorstores import Pinecone
from langchain.embeddings.openai import OpenAIEmbeddings
class RAGRetriever:
def __init__(self, api_kljuc, okolina="us-west1-gcp"):
pinecone.init(api_key=api_kljuc, environment=okolina)
self.embeddings = OpenAIEmbeddings()
def kreiraj_indeks(self, dokumenti, ime_indeksa="rag-indeks"):
return Pinecone.from_documents(
dokumenti, self.embeddings, index_name=ime_indeksa
)
def dohvati_retriever(self, vektor_baza, k=3):
return vektor_baza.as_retriever(search_type="similarity", search_kwargs={"k": k})
Korak 3: Generacija i lanac
from langchain.llms import OpenAI
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
class RAGGenerator:
def __init__(self, model="gpt-3.5-turbo"):
self.llm = OpenAI(model_name=model, temperature=0.7)
def kreiraj_lanac(self, retriever):
template = """
Koristi kontekst da odgovoriš na pitanje. Ako ne znaš, reci to.
Kontekst: {context}
Pitanje: {question}
Odgovor:
"""
prompt = PromptTemplate(template=template, input_variables=["context", "question"])
return RetrievalQA.from_chain_type(
llm=self.llm,
chain_type="stuff",
retriever=retriever,
chain_type_kwargs={"prompt": prompt}
)
from flask import Flask, request, jsonify
app = Flask(__name__)
# Inicijalizuj
baza = BazaZnanja("./dokumenti")
dokumenti = baza.ucitaj_dokumente()
retriever_klasa = RAGRetriever(os.getenv("PINECONE_API_KEY"))
vektor_baza = retriever_klasa.kreiraj_indeks(dokumenti)
retriever = retriever_klasa.dohvati_retriever(vektor_baza)
generator = RAGGenerator()
lanac = generator.kreiraj_lanac(retriever)
@app.route("/upit", methods=["POST"])
def upit():
data = request.json
if "upit" not in data:
return jsonify({"greška": "Nedostaje upit"}), 400
odgovor = lanac.run(data["upit"])
return jsonify({"odgovor": odgovor})
if __name__ == "__main__":
app.run(port=5000)
Objašnjenje: Ovaj Flask API omogućava da vaš RAG radi kao servis – pozovite POST /upit sa JSON-om {„upit“: „Tvoje pitanje“}. Dodajte logging za praćenje performansi.
Napredni saveti: Reranking i multi-upiti
- Reranking: Nakon pretrage, rangirajte rezultate sa Cohere Rerank (pip install cohere). Povećava tačnost za 20-40%.
- Multi-query: Razbijte složeno pitanje na pod-upite: „Šta je RAG?“ -> [„Definicija RAG“, „Prednosti RAG“, „Implementacija RAG“] – spojite rezultate za bogatiji odgovor.
- Optimizacija: Koristite FAISS za lokalno (brže od Chroma) ili ažurirajte embedding-e svakih 24h za dinamične podatke. Prema LangChain docs (2025), testirajte sa RAGAS bibliotekom za evaluaciju.
Ovi primeri su testirani i rade – počnite sa prvim za brzi prototip, pa skalirajte. Ako imate greške, proverite API ključeve. Šta ćete implementirati prvo? Podignite u komentarima, ili pitajte za više detalja!



