Enkel RAG-implementering: en trinnvis veiledning
Denne nybegynnervennlige veiledningen forklarer hvordan en enkel RAG-implementering fungerer, går gjennom beste praksis og viser trinn for trinn hvordan du bygger et fungerende RAG-system for kommandolinjen med Python, ChromaDB og Perplexitys embedding- og språkmodeller.

RAG er en essensiell komponent i moderne LLM-basert infrastruktur. Ved å gi AI-modeller tilgang til eksterne data bidrar RAG til å løse problemer som hallusinasjoner og ufullstendige treningsdata. Det betyr også at bedrifter kan bruke interne kunnskapsbaser som inneholder sensitiv eller proprietær informasjon.
RAG-implementering kan være svært kompleks. Et enkelt RAG-system er likevel overraskende lett å bygge. For nybegynnere kan det å lage en enkel arkitektur vise hvordan RAG fungerer i praksis, og gi et springbrett for videre eksperimentering.
I denne artikkelen skisserer vi en enkel RAG-implementering, går gjennom beste praksis og bygger deretter et fungerende system med Python, ChromaDB og to Perplexity-modeller for embedding og svargenerering.
Prosessen bak en enkel RAG-implementering: en overordnet gjennomgang
Et enkelt RAG-system har tre hovedkomponenter: en orkestrator, en informasjonskilde og en LLM. I en typisk arbeidsflyt skriver brukeren inn en prompt, og orkestratoren tilpasser den for å søke i tilkoblede informasjonskilder. Den innhentede informasjonen legges deretter til i den opprinnelige inndatakonteksten og sendes til LLM-en slik at et svar kan genereres.
Du må ta høyde for disse trinnene når du bygger RAG-implementeringen din:
- Indeksering og embedding: I dette trinnet konverteres dokumentene dine til en informasjonskilde som orkestratoren kan søke i. En av de vanligste måtene å gjøre dette på er å bygge en søkbar vektorindeks. Vi bruker en dedikert modell fra Perplexity til å konvertere dokumentbitene dine til embeddinger. Deretter lagrer vi embeddingene med ChromaDB, en populær vektordatabase med åpen kildekode.
- Orkestrering: Dette er applikasjonen som ligger mellom den eksterne informasjonskilden (i vårt tilfelle en vektordatabase) og LLM-en. Vi lager et enkelt Python-skript som fungerer som orkestrator.
- Innhenting og generering: Når en bruker stiller et spørsmål via chattegrensesnittet, tar orkestratoren imot det, kjører et vektorsøk og sender de utvidede inndataene til LLM-en. Vi bruker kommandolinjen til å kommunisere med Python-orkestratoren i stedet for å bygge en egen frontend.
Beste praksis: Hva kjennetegner en effektiv RAG-implementering?
Det finnes flere typer RAG-arkitektur, og ulike brukstilfeller krever ulike tilnærminger. Likevel gjelder en rekke anbefalte fremgangsmåter uansett, og de bidrar til nøyaktige, kostnadseffektive, skalerbare og vedlikeholdbare systemer.
Følgende beste praksis gjelder for alle typer RAG-implementeringer:
- Sørg for en ren inntakspipeline: Kildedataene dine bør være så rene som mulig før indeksering. Du bør også bruke en embeddingmodell som passer til innholdet ditt.
- Bruk hybridsøk: Hvilke innhentingsmetoder som fungerer best – enten det er søk i vektordatabaser, API-basert nettsøk, traversering av kunnskapsgrafer, nøkkelordsøk eller andre metoder – varierer fra brukstilfelle til brukstilfelle. Å velge riktig kombinasjon er viktig for å holde kostnadene nede.
- Evaluer systemet ditt: Etter implementeringen bør du evaluere systemet ut fra tre sentrale mål: nøyaktighet, relevans og latens. Nøyaktighet handler om faktisk korrekthet, relevans om hvor godt den innhentede informasjonen passer til brukernes spørsmål, og latens om hvor raskt informasjonen hentes.
- Håndter informasjon sikkert: Hvis RAG-systemet ditt bruker privat intern informasjon, må du sørge for at den lagres sikkert, og at tilgangen til systemgrensesnittet styres. API-nøkler skal aldri deles.
Enkel RAG-implementering: veiledning i 7 trinn
I denne veiledningen bygger vi en kommandolinjeapplikasjon som svarer på spørsmål om ett enkelt dokument. Vi bruker Python, ChromaDB og Perplexity API.
Målet er ikke å bygge et produksjonsklart RAG-system. Dette er snarere en nybegynnervennlig veiledning som skal vise hvordan en enkel RAG-arkitektur fungerer i praksis.
Trinn 1: Installer programvare
Sørg for at følgende er installert på datamaskinen din, og at du har en Perplexity API-konto:
- Python: Dette er programmeringsspråket vi bruker til å bygge orkestratoren, som skal koordinere dataflyten mellom embeddingmodellen, ChromaDB og Perplexity.
- Visual Studio: Vi bruker Visual Studio som koderedigeringsprogram. Når det er installert, åpner du Extensions-panelet og laster ned Python-utvidelsen.
- Perplexity API-konto: Perplexity leverer både embeddingmodellen (som gjør dataene dine om til vektorembeddinger) og LLM-en som skal behandle den utvidede prompten. Du trenger ikke en betalt konto for dette, men det vil gå med en liten mengde kreditter.
Trinn 2: Opprett en prosjektmappe
Start med å opprette en mappe med navnet rag-project og åpne den i VS Code ved å velge File > Open Folder. Åpne deretter den integrerte terminalen via Terminal > New Terminal.
Skriv inn følgende for å opprette et virtuelt Python-miljø:
py -3.12 -m venv .venvNå må du installere fire Python-biblioteker: perplexityai, chromadb, python-dotenv og numpy. Med Perplexity SDK kan du koble deg til Perplexitys modeller via API. ChromaDB bygger vektordatabasen og kjører lokalt. Python-dotenv laster API-nøklene dine sikkert fra en lokal fil, og NumPy trengs under inntaksprosessen.
Installer disse med følgende kommando:
.\.venv\Scripts\python.exe -m pip install perplexityai chromadb python-dotenv numpyTrinn 3: Konfigurer filene dine
Legg til følgende filer i rag-project (prosjektroten) ved å velge New File… i Explorer-sidefeltet:
- index.py: Dette er applikasjonen som skal indeksere dokumentet ditt. Du kan kjøre den på nytt for å legge til mer tekst.
- rag.py: Dette er Python-applikasjonen som skal fungere som orkestrator.
- document.txt: Denne filen skal inneholde dokumentasjonen du skal konvertere til en vektordatabase.
- .env: Her oppbevarer du API-nøkkelen din for Perplexity.
Skriv inn følgende i .env:
PERPLEXITY_API_KEY=your_api_key_hereErstatt your_api_key_here med den faktiske nøkkelen din. For å få en nøkkel går du til startsiden i Perplexity API Console og velger Create an API key. Hold denne API-nøkkelen privat.
Vi bruker to modeller: Perplexitys pplx-embed-v1-0.6b til å lage embeddinger av dokumentasjonen før den lastes opp til ChromaDB, og GPT-5.6-Luna (via Perplexitys API), som skal behandle den innhentede informasjonen.
I document.txt legger du inn teksten som RAG-pipelinen skal hente informasjon fra. Hvis du ikke har et dokument for hånden, kan du bruke William Blakes Songs of Innocence and of Experience fra Project Gutenberg i denne veiledningen. Det er en kort og lettfattelig tekst som har falt i det fri.
Trinn 4: Skriv indekseringsprogrammet
Kopier og lim inn koden nedenfor i index.py. Hver underoverskrift gir en kort forklaring av hva det påfølgende kodesegmentet gjør. Dette er programmet som konverterer kildematerialet ditt til vektorembeddinger og lagrer dem i en ChromaDB-database ved hjelp av Perplexitys embeddingmodell, pplx-embed-v1-0.6b, og NumPy-biblioteket.
Dette gjør programmet:
- Åpner document.txt.
- Deler teksten opp i overlappende biter.
- Sender disse bitene til Perplexitys embeddingmodell pplx-embed-v1-0.6b.
- Dekoder og normaliserer de returnerte vektorene med NumPy, et Python-bibliotek med beregningsfunksjoner.
- Lagrer vektorene og de opprinnelige bitene i en ChromaDB-database (du vil se den dukke opp i prosjektmappen din).
Programmet er satt opp slik at det ikke indekserer dokumentet ditt på nytt hver gang du kjører det. Hvis du legger til mer informasjon i document.txt, lager det bare embeddinger av den nye teksten.
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())Trinn 5. Skriv orkestratoren for RAG-systemet
Kopier og lim inn koden nedenfor i rag.py. Dette er en komplett, men minimal RAG-implementering som bruker Perplexity SDK og ChromaDBs funksjonalitet for lokal vektordatabase.
Dette skjer når du kjører programmet:
- Kobler til Perplexity og den nye ChromaDB-databasen din.
- Kontrollerer at databasen inneholder indekserte dokumenter.
- Tar imot et spørsmål fra brukeren.
- Sender spørsmålet til Perplexitys embeddingmodell.
- Dekoder og normaliserer den resulterende embeddingen med NumPy.
- Søker i ChromaDB etter de tre dokumentbitene som ligner mest.
- Bygger en prompt som inneholder de innhentede bitene og brukerens spørsmål.
- Sender prompten til GPT-5.6 Luna via Perplexitys Agent API.
- Viser svaret og venter på neste spørsmål.
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)Trinn 6: Kjør applikasjonene
Skriv inn følgende i PowerShell-terminalen i VS Code for å lage embeddinger av innholdet i document.txt:
.\.venv\Scripts\python.exe index.pyHvis dokumentet er indeksert uten problemer, bør du se utdata som ligner på dette:
Indexing complete!
Unchanged chunks: 0
New or modified chunks: 58
Removed chunks: 0
Total stored chunks: 58Nå er det på tide å kjøre hovedapplikasjonen, orkestratoren. Skriv inn denne kommandoen:
.\.venv\Scripts\python.exe rag.pyHvis den kjører som den skal, ser du følgende:
Connected to existing ChromaDB database.
Stored chunks: 58
Ask a question (or type exit): Nå kan du stille spørsmål som henter svar fra vektordatabasen du har laget, for eksempel:
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.Trinn 7: Forstå hva du har bygget
Systemet du har bygget, inneholder de to kjernepipelinene som finnes i alle RAG-arkitekturer: en indekserings- eller «inntaks»-pipeline og en pipeline for innhenting og generering.
Den enkle RAG-implementeringen din gjør nå alt dette:
- Vektorlagring: Embeddinger basert på kunnskapsfilen din lagres i ChromaDB-databasen i ditt lokale miljø.
- Inkrementell indeksering: Det lages ikke nye embeddinger av uendrede dokumentbiter, og du kan oppdatere dokumentet når du vil.
- Semantisk innhenting: ChromaDB henter biter basert på vektorlikhet (initiert av orkestratoren).
- Forankret svargenerering: LLM-en mottar innhentede tekstutdrag som kontekst og bruker dem i svaret.
- Uavhengig indeksering og spørring: Du kan stille spørsmål uten å behandle all teksten i kunnskapsfilen din på nytt.
- API-basert modelltilkobling: Alle svar genereres med GPT-5.6 Luna via Perplexity i stedet for med en modell som kjører på maskinen din.
Neste steg: Slik videreutvikler du implementeringen
Målet med denne veiledningen er å bygge en enkel og grunnleggende implementering. Den dekker noen av de sentrale komponentene i RAG-arkitekturen som finnes i moderne systemer. Hvis du vil gå lenger, kan du bygge videre på den på flere måter.
Her er noen ideer til hvordan du kan utvide omfanget av implementeringen din:
- Eksperimenter med LangChain: LangChain er et av de mest populære orkestreringsrammeverkene med åpen kildekode. Det inneholder ferdigbygde komponenter for å bygge apper som kan kjøre komplekse RAG-pipelines.
- Utvid søkefunksjonaliteten: Kombiner tett vektorsøk med leksikalsk søk (nøkkelordsøk), for eksempel BM25. Ved å legge til nettsøk via Perplexity Search API kan du også forankre svarene i oppdaterte data.
- Legg til en omrangeringsmodell: Integrer en omrangeringsmodell som rangerer de innhentede tekstutdragene opp mot den opprinnelige prompten og velger ut de mest relevante for inndatakonteksten som sendes til LLM-en.
- Bygg et adaptivt RAG-system: Adaptiv RAG bruker enten en LLM eller en klassifikator (en komponent i orkestratoren) til å avgjøre hvilken innhentingsmetode som skal brukes i et modulært RAG-system. Å bygge et slikt system er en god måte å utforske mer avanserte RAG-implementeringer på.
Selv om alt dette kan høres komplisert ut, er det verdt å huske at utbredte AI-plattformer som Perplexity kan gi avansert hjelp med koding. De egner seg utmerket til personlige prosjekter og eksperimentering, og kostnadene kan holdes relativt lave.
Merk: Denne veiledningen bruker GPT-5.6 Luna. Modelltilgjengeligheten kan endre seg, så du må kanskje oppdatere API-kallet.