Vienkārša RAG ieviešana: pamācība soli pa solim

Šajā iesācējiem draudzīgajā pamācībā ir paskaidrots, kā darbojas vienkārša RAG ieviešana, apskatīta labākā prakse un soli pa solim parādīts, kā izveidot funkcionējošu komandrindas RAG sistēmu ar Python, ChromaDB un Perplexity iegulumu un valodas modeļiem.

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 ir būtisks mūsdienu uz LLM balstītas infrastruktūras komponents. Ļaujot MI modeļiem piekļūt ārējiem datiem, tas palīdz risināt tādas problēmas kā halucinācijas un nepilnīgi apmācības dati. Tas arī nozīmē, ka uzņēmumi var izmantot iekšējās zināšanu bāzes, kurās ir sensitīva vai uzņēmumam piederoša informācija.

RAG ieviešana var būt ļoti sarežģīta. Tomēr vienkāršu RAG sistēmu izveidot ir pārsteidzoši viegli. Iesācējiem vienkāršas arhitektūras izveide var palīdzēt saprast, kā RAG darbojas reālajā pasaulē, un kalpot par atspēriena punktu turpmākiem eksperimentiem.

Šajā rakstā mēs ieskicēsim vienkāršu RAG ieviešanu, apskatīsim labāko praksi un pēc tam izveidosim funkcionējošu sistēmu, izmantojot Python, ChromaDB un divus Perplexity modeļus — iegulumu izveidei un atbilžu ģenerēšanai.

Vienkāršas RAG ieviešanas process: vispārīgs pārskats

Vienkāršai RAG sistēmai ir trīs galvenie komponenti: orķestrētājs, informācijas avots un LLM. Tipiskā darbplūsmā lietotājs ievada uzvedni, un orķestrētājs to pārveido, lai veiktu meklēšanu visos pievienotajos informācijas avotos. Pēc tam izgūtā informācija tiek pievienota sākotnējās ievades kontekstam un nosūtīta LLM, lai varētu ģenerēt atbildi.

Veidojot savu RAG ieviešanu, jums būs jāņem vērā šādi soļi:

  1. Indeksēšana un iegulumu izveide: Šajā posmā jūsu dokumenti tiek pārveidoti informācijas avotā, kurā orķestrētājs var veikt meklēšanu. Viens no izplatītākajiem veidiem, kā to izdarīt, ir izveidot meklējamu vektoru indeksu. Mēs izmantosim īpašu Perplexity modeli, lai pārveidotu jūsu dokumentu fragmentus iegulumos. Pēc tam iegulumus saglabāsim ChromaDB — populārā atvērtā pirmkoda vektoru datubāzē.
  2. Orķestrēšana: Šī ir lietojumprogramma, kas atrodas starp ārējo informācijas avotu (mūsu gadījumā — vektoru datubāzi) un LLM. Mēs izveidosim vienkāršu Python skriptu, kas darbosies kā orķestrētājs.
  3. Izguve un ģenerēšana: Kad lietotājs uzdod jautājumu tērzēšanas saskarnē, orķestrētājs to saņems, veiks vektoru meklēšanu un nodos paplašināto ievadi LLM. Tā vietā, lai veidotu atsevišķu lietotāja saskarni, saziņai ar mūsu Python orķestrētāju izmantosim komandrindu.

Labākā prakse: kas padara RAG ieviešanu efektīvu?

Pastāv vairāki RAG arhitektūras veidi, un dažādiem lietošanas gadījumiem nepieciešamas atšķirīgas pieejas. Tomēr vairāki labākās prakses principi ir piemērojami visos gadījumos un nodrošina precīzas, izmaksu ziņā efektīvas, mērogojamas un viegli uzturamas sistēmas.

Šie labākās prakses principi attiecas uz visiem RAG ieviešanas veidiem:

  • Nodrošiniet tīru datu uzņemšanas konveijeru: Pirms indeksēšanas avota datiem jābūt pēc iespējas tīrākiem. Jāizmanto arī jūsu saturam piemērots iegulumu modelis.
  • Izmantojiet hibrīdmeklēšanu: Labākās izguves metodes — vai tā būtu meklēšana vektoru datubāzē, uz API balstīta tīmekļa meklēšana, zināšanu grafa šķērsošana, atslēgvārdu meklēšana vai citas metodes — atšķiras atkarībā no lietošanas gadījuma. Pareizas kombinācijas izvēle ir svarīga izmaksu samazināšanai.
  • Novērtējiet savu sistēmu: Pēc ieviešanas jānovērtē trīs pamatrādītāji: precizitāte, atbilstība un latentums. Precizitāte attiecas uz faktu pareizību, atbilstība — uz to, cik izgūtā informācija ir piemērojama lietotāju vaicājumiem, bet latentums — uz ātrumu, ar kādu informācija tiek izgūta.
  • Apstrādājiet informāciju droši: Ja jūsu RAG sistēma izmanto privātu iekšējo informāciju, nodrošiniet, lai tā tiktu glabāta droši un piekļuve sistēmas saskarnei tiktu pārvaldīta. API atslēgas nekad nedrīkst kopīgot ar citiem.

Vienkārša RAG ieviešana: pamācība 7 soļos

Šajā pamācībā mēs izveidosim komandrindas lietojumprogrammu, kas atbild uz jautājumiem par vienu dokumentu. Izmantosim Python, ChromaDB un Perplexity API.

Mērķis nav izveidot ražošanai gatavu RAG sistēmu. Drīzāk tā ir iesācējiem draudzīga pamācība, kas paredzēta, lai ilustrētu, kā elementāra RAG arhitektūra darbojas praksē.

1. solis: instalējiet programmatūru

Pārliecinieties, ka datorā ir instalēts tālāk norādītais un jums ir Perplexity API konts:

  • Python: Šo programmēšanas valodu izmantosim, lai izveidotu orķestrētāju, kas koordinēs datu plūsmu starp iegulumu modeli, ChromaDB un Perplexity.
  • Visual Studio: Kā koda redaktoru izmantosim Visual Studio. Pēc instalēšanas atveriet paneli Extensions un lejupielādējiet paplašinājumu Python.
  • Perplexity API konts: Perplexity nodrošinās gan iegulumu modeli (kas pārveido jūsu datus vektoru iegulumos), gan LLM, kas apstrādās paplašināto uzvedni. Tam nav nepieciešams maksas konts, lai gan tiks iztērēts neliels kredītu apjoms.

2. solis: izveidojiet projekta mapi

Vispirms izveidojiet mapi ar nosaukumu rag-project un atveriet to VS Code, atlasot File > Open Folder. Pēc tam atveriet integrēto termināli, izmantojot Terminal > New Terminal.

Ievadiet tālāk norādīto, lai izveidotu Python virtuālo vidi:

bash
py -3.12 -m venv .venv

Tagad jāinstalē četras Python bibliotēkas: perplexityai, chromadb, python-dotenv un numpy. Perplexity SDK ļaus jums izveidot savienojumu ar Perplexity modeļiem, izmantojot API. ChromaDB izveido vektoru datubāzi un darbosies lokāli. Python-dotenv droši ielādē jūsu API atslēgas no lokāla faila, un NumPy ir nepieciešams datu uzņemšanas procesā.

Instalējiet tās ar šo komandu:

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

3. solis: sagatavojiet failus

Pievienojiet mapē rag-project (projekta saknes direktorijā) šādus failus, sānjoslā Explorer atlasot New File…:

  • index.py: Šī ir lietojumprogramma, kas indeksēs jūsu dokumentu. Varat to palaist atkārtoti, lai pievienotu papildu tekstu.
  • rag.py: Šī ir Python lietojumprogramma, kas darbosies kā orķestrētājs.
  • document.txt: Šajā failā būs dokumentācija, ko pārveidosiet vektoru datubāzē.
  • .env: Šeit glabāsiet savu Perplexity API atslēgu.

Failā .env ievadiet šo:

plaintext
PERPLEXITY_API_KEY=your_api_key_here

Aizstājiet your_api_key_here ar savu īsto atslēgu. Lai to iegūtu, atveriet Perplexity API Console sākuma informācijas paneli un atlasiet Create an API key. Neizpaudiet šo API atslēgu citiem.

Mēs izmantosim divus modeļus: Perplexity pplx-embed-v1-0.6b, lai izveidotu dokumentācijas iegulumus pirms to augšupielādes ChromaDB datubāzē, un GPT-5.6-Luna (pieejams, izmantojot Perplexity API), kas apstrādās izgūto informāciju.

Failā document.txt pievienojiet tekstu, ko izgūs jūsu RAG konveijers. Ja jums nav pieejama piemērota dokumenta, šajā pamācībā izmantojiet Viljama Bleika darbu Songs of Innocence and of Experience no Project Gutenberg. Tas ir īss, viegli saprotams teksts, kas ir publiskajā domēnā.

4. solis: uzrakstiet indeksēšanas programmu

Nokopējiet tālāk redzamo kodu un ielīmējiet to failā index.py. Katrā apakšvirsrakstā ir īss skaidrojums par to, ko dara nākamais koda segments. Šī ir programma, kas, izmantojot Perplexity iegulumu modeli pplx-embed-v1-0.6b un bibliotēku NumPy, pārveidos jūsu avota materiālu vektoru iegulumos un saglabās tos ChromaDB datubāzē.

Lūk, ko dara programma:

  1. Atver failu document.txt.
  2. Sadala tekstu fragmentos, kas daļēji pārklājas.
  3. Nosūta šos fragmentus Perplexity iegulumu modelim pplx-embed-v1-0.6b.
  4. Dekodē un normalizē atgrieztos vektorus, izmantojot NumPy — Python skaitļošanas funkciju bibliotēku.
  5. Saglabā vektorus un sākotnējos fragmentus ChromaDB datubāzē (tā parādīsies jūsu projekta direktorijā).

Programma ir iestatīta tā, lai dokuments netiktu indeksēts no jauna katru reizi, kad to palaižat. Ja papildināsiet informāciju failā document.txt, iegulumi tiks izveidoti tikai jaunajam tekstam.

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. solis. Uzrakstiet RAG sistēmas orķestrētāju

Nokopējiet tālāk redzamo kodu un ielīmējiet to failā rag.py. Tā ir pilnīga, taču minimāla RAG ieviešana, kas izmanto Perplexity SDK un ChromaDB lokālās vektoru datubāzes funkcionalitāti.

Lūk, kas notiks, kad palaidīsiet programmu:

  1. Izveido savienojumu ar Perplexity un jūsu jauno ChromaDB datubāzi.
  2. Pārbauda, vai datubāzē ir indeksēti dokumenti.
  3. Pieņem lietotāja jautājumu.
  4. Nosūta jautājumu Perplexity iegulumu modelim.
  5. Dekodē un normalizē iegūto iegulumu, izmantojot NumPy.
  6. Meklē ChromaDB datubāzē trīs līdzīgākos dokumenta fragmentus.
  7. Izveido uzvedni, kurā ietverti izgūtie fragmenti un lietotāja jautājums.
  8. Nosūta uzvedni modelim GPT-5.6 Luna, izmantojot Perplexity Agent API.
  9. Parāda atbildi un gaida nākamo jautājumu.
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. solis: palaidiet lietojumprogrammas

VS Code PowerShell terminālī ievadiet tālāk norādīto, lai izveidotu iegulumus faila document.txt saturam:

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

Ja dokuments ir veiksmīgi indeksēts, jums vajadzētu redzēt līdzīgu izvadi:

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

Tagad ir laiks palaist galveno orķestrētāja lietojumprogrammu. Ievadiet šo komandu:

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

Ja palaišana būs veiksmīga, redzēsiet šo:

plaintext
Connected to existing ChromaDB database. Stored chunks: 58 Ask a question (or type exit):

Tagad varat uzdot jautājumus, uz kuriem atbildes tiks meklētas jūsu izveidotajā vektoru datubāzē, piemēram:

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. solis: izprotiet, ko esat izveidojuši

Jūsu izveidotajā sistēmā ir divi pamata konveijeri, kas ir katrā RAG arhitektūrā: indeksēšanas jeb „datu uzņemšanas” konveijers un izguves un ģenerēšanas konveijers.

Jūsu vienkāršā RAG ieviešana tagad veic visu tālāk minēto:

  • Vektoru glabāšana: Iegulumi, kas izveidoti no jūsu zināšanu faila, tiek saglabāti ChromaDB datubāzē jūsu lokālajā vidē.
  • Inkrementāla indeksēšana: Nemainītajiem dokumenta fragmentiem iegulumi netiek veidoti atkārtoti, un dokumentu varat atjaunināt jebkurā laikā.
  • Semantiskā izguve: ChromaDB izgūst fragmentus, pamatojoties uz vektoru līdzību (pēc orķestrētāja pieprasījuma).
  • Pamatotu atbilžu ģenerēšana: LLM saņem izgūtos fragmentus kā kontekstu un iekļauj tos atbildē.
  • Neatkarīga indeksēšana un vaicāšana: Varat uzdot jautājumus, atkārtoti neapstrādājot visu zināšanu failā ietverto tekstu.
  • Savienojums ar modeli, izmantojot API: Visas atbildes tiek ģenerētas ar GPT-5.6 Luna, izmantojot Perplexity, nevis ar modeli, kas darbojas jūsu datorā.

Nākamie soļi: kā attīstīt šo ieviešanu tālāk

Šīs pamācības mērķis ir izveidot vienkāršu, pamata līmeņa ieviešanu. Tā aptver dažus no galvenajiem RAG arhitektūras komponentiem, kas sastopami mūsdienu sistēmās. Ja vēlaties iet tālāk, ir dažādi veidi, kā to papildināt.

Šeit ir dažas idejas, kā paplašināt savas ieviešanas tvērumu:

  • Eksperimentējiet ar LangChain: LangChain ir viens no populārākajiem atvērtā pirmkoda orķestrēšanas ietvariem. Tajā ir iepriekš sagatavoti komponenti tādu lietojumprogrammu izveidei, kas spēj darbināt sarežģītus RAG konveijerus.
  • Paplašiniet meklēšanas funkcionalitāti: Apvienojiet blīvo vektoru meklēšanu ar leksisko (atslēgvārdu) meklēšanu, piemēram, BM25. Pievienojot tīmekļa meklēšanu, izmantojot Perplexity Search API, varētu arī pamatot atbildes ar aktuāliem datiem.
  • Pievienojiet atkārtotas ranžēšanas modeli: Integrējiet atkārtotas ranžēšanas modeli, kas sarindo izgūtos fragmentus pēc to atbilstības sākotnējai uzvednei un atlasa visatbilstošākos, lai tos iekļautu LLM sniegtajā ievades kontekstā.
  • Izveidojiet adaptīvu RAG sistēmu: Adaptīvā RAG izmanto vai nu LLM, vai klasifikatoru (orķestrētāja komponentu), lai noteiktu, kuru izguves metodi izmantot modulārā RAG sistēmā. Šādas sistēmas izveide ir labs veids, kā izpētīt sarežģītākas RAG ieviešanas.

Lai gan tas viss var šķist sarežģīti, ņemiet vērā, ka populāras MI platformas, piemēram, Perplexity, var sniegt progresīvu palīdzību programmēšanā. Tās lieliski noder personīgiem projektiem un eksperimentiem, un izmaksas var saglabāt samērā zemas.

Piezīme. Šajā pamācībā tiek izmantots GPT-5.6 Luna. Modeļu pieejamība var mainīties, tāpēc, iespējams, būs jāatjaunina API izsaukums.