Paprastas RAG diegimas: vadovas žingsnis po žingsnio

Šiame pradedantiesiems skirtame vadove paaiškinama, kaip veikia paprastas RAG diegimas, aptariama geriausia praktika ir žingsnis po žingsnio parodoma, kaip sukurti veikiančią komandų eilutės RAG sistemą naudojant Python, ChromaDB bei Perplexity įterpinių ir kalbos modelius.

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 yra esminis šiuolaikinės LLM pagrįstos infrastruktūros komponentas. Leisdamas DI modeliams pasiekti išorinius duomenis, jis padeda spręsti tokias problemas kaip haliucinacijos ir neišsamūs mokymo duomenys. Be to, įmonės gali naudoti vidines žinių bazes, kuriose yra jautrios ar konfidencialios informacijos.

RAG diegimas gali būti labai sudėtingas. Tačiau paprastą RAG sistemą sukurti stebėtinai lengva. Pradedantiesiems paprastos architektūros sukūrimas gali padėti suprasti, kaip RAG veikia realiame pasaulyje, ir tapti atspirties tašku tolesniems eksperimentams.

Šiame straipsnyje apžvelgsime paprasto RAG diegimo struktūrą, aptarsime geriausią praktiką ir sukursime veikiančią sistemą naudodami Python, ChromaDB ir du Perplexity modelius – įterpiniams kurti ir atsakymams generuoti.

Paprasto RAG diegimo procesas: bendra apžvalga

Paprastą RAG sistemą sudaro trys pagrindiniai komponentai: orkestratorius, informacijos šaltinis ir LLM. Įprastoje darbo eigoje naudotojas įveda užklausą, o orkestratorius ją pritaiko, kad galėtų ieškoti visuose prijungtuose informacijos šaltiniuose. Tada gauta informacija pridedama prie pradinio įvesties konteksto ir perduodama LLM, kad būtų sugeneruotas atsakymas.

Kurdami savo RAG diegimą turėsite atsižvelgti į šiuos etapus:

  1. Indeksavimas ir įterpinių kūrimas: Šiame etape jūsų dokumentai paverčiami informacijos šaltiniu, kuriame orkestratorius gali ieškoti. Vienas dažniausių būdų tai padaryti – sukurti vektorinį indeksą, kuriame galima ieškoti. Jūsų dokumentų fragmentams paversti įterpiniais naudosime specialų Perplexity modelį. Tada įterpinius saugosime populiarioje atvirojo kodo vektorinėje duomenų bazėje ChromaDB.
  2. Orkestravimas: Tai programa, esanti tarp išorinio informacijos šaltinio (mūsų atveju – vektorinės duomenų bazės) ir LLM. Sukursime paprastą Python scenarijų, kuris atliks orkestratoriaus vaidmenį.
  3. Paieška ir generavimas: Kai naudotojas užduoda klausimą per pokalbių sąsają, orkestratorius jį priima, atlieka vektorinę paiešką ir perduoda išplėstą įvestį LLM. Užuot kūrę atskirą naudotojo sąsają, su Python orkestratoriumi bendrausime per komandų eilutę.

Geriausia praktika: kas lemia veiksmingą RAG diegimą?

Yra įvairių RAG architektūros tipų, o skirtingiems naudojimo atvejams reikia skirtingų metodų. Vis dėlto daugelis geriausios praktikos principų taikomi visais atvejais ir užtikrina tikslias, ekonomiškas, keičiamo mastelio ir lengvai prižiūrimas sistemas.

Toliau pateikti geriausios praktikos principai taikomi visų tipų RAG diegimams:

  • Užtikrinkite švarų duomenų įkėlimo konvejerį: Prieš indeksuojant šaltinio duomenys turėtų būti kuo švaresni. Taip pat turėtumėte naudoti jūsų turiniui tinkamą įterpinių modelį.
  • Naudokite hibridinę paiešką: Geriausi paieškos metodai – ar tai būtų paieška vektorinėje duomenų bazėje, API pagrįsta žiniatinklio paieška, žinių grafo naršymas, paieška pagal raktinius žodžius, ar kiti metodai – priklauso nuo naudojimo atvejo. Norint sumažinti sąnaudas, svarbu pasirinkti tinkamą jų derinį.
  • Įvertinkite savo sistemą: Įdiegę sistemą turėtumėte ją įvertinti pagal tris pagrindinius rodiklius: tikslumą, aktualumą ir delsą. Tikslumas reiškia faktinį teisingumą, aktualumas – gautos informacijos tinkamumą naudotojų užklausoms, o delsa – greitį, kuriuo informacija gaunama.
  • Saugiai tvarkykite informaciją: Jei jūsų RAG sistema naudoja privačią vidinę informaciją, užtikrinkite, kad ji būtų patikimai apsaugota, o prieiga prie sistemos sąsajos – valdoma. Niekada nesidalykite API raktais.

Paprastas RAG diegimas: 7 žingsnių vadovas

Šiame vadove sukursime komandų eilutės programą, kuri atsako į klausimus apie vieną dokumentą. Naudosime Python, ChromaDB ir Perplexity API.

Tikslas – ne sukurti gamybinei aplinkai paruoštą RAG sistemą. Tai pradedantiesiems skirtas vadovas, kuriuo siekiama parodyti, kaip paprasta RAG architektūra veikia praktikoje.

1 žingsnis: įdiekite programinę įrangą

Įsitikinkite, kad kompiuteryje įdiegta toliau nurodyta programinė įranga ir kad turite Perplexity API paskyrą:

  • Python: Tai programavimo kalba, kuria kursime orkestratorių, koordinuosiantį duomenų srautą tarp įterpinių modelio, ChromaDB ir Perplexity.
  • Visual Studio: Kaip kodo redaktorių naudosime Visual Studio. Įdiegę atidarykite skydelį Extensions ir atsisiųskite plėtinį Python.
  • Perplexity API paskyra: Perplexity pateiks ir įterpinių modelį (kuris paverčia jūsų duomenis vektoriniais įterpiniais), ir LLM, kuris apdoros išplėstą užklausą. Tam nereikia mokamos paskyros, tačiau bus sunaudota šiek tiek kreditų.

2 žingsnis: sukurkite projekto aplanką

Pirmiausia sukurkite aplanką pavadinimu rag-project ir atidarykite jį programoje VS Code pasirinkdami File > Open Folder. Tada atidarykite integruotą terminalą pasirinkdami Terminal > New Terminal.

Įveskite toliau pateiktą komandą, kad sukurtumėte virtualią Python aplinką:

bash
py -3.12 -m venv .venv

Dabar reikia įdiegti keturias Python bibliotekas: perplexityai, chromadb, python-dotenv ir numpy. Perplexity SDK leis jums prisijungti prie Perplexity modelių per API. ChromaDB sukuria vektorinę duomenų bazę ir veiks jūsų kompiuteryje. Python-dotenv saugiai įkelia jūsų API raktus iš vietinio failo, o NumPy reikalinga duomenų įkėlimo proceso metu.

Įdiekite jas šia komanda:

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

3 žingsnis: paruoškite failus

Pridėkite šiuos failus į rag-project (projekto šakninį aplanką) šoninėje juostoje Explorer pasirinkdami New File…:

  • index.py: Tai programa, kuri indeksuos jūsų dokumentą. Galite ją paleisti iš naujo, kad pridėtumėte daugiau teksto.
  • rag.py: Tai Python programa, kuri atliks orkestratoriaus vaidmenį.
  • document.txt: Šiame faile bus dokumentacija, kurią paversite vektorine duomenų baze.
  • .env: Čia laikysite savo Perplexity API raktą.

Faile .env įveskite toliau pateiktą tekstą:

plaintext
PERPLEXITY_API_KEY=your_api_key_here

Pakeiskite your_api_key_here savo tikruoju raktu. Tam reikės atidaryti Perplexity API Console pagrindinį prietaisų skydelį ir pasirinkti Create an API key. Niekam neatskleiskite šio API rakto.

Naudosime du modelius: Perplexity modelį pplx-embed-v1-0.6b, kuriuo prieš įkeldami dokumentaciją į ChromaDB paversime ją įterpiniais, ir GPT-5.6-Luna (pasiekiamą per Perplexity API), kuris apdoros gautą informaciją.

Į document.txt įrašykite tekstą, iš kurio jūsų RAG konvejeris gaus informaciją. Jei neturite po ranka tinkamo dokumento, šiam vadovui naudokite Williamo Blake'o rinkinį Songs of Innocence and of Experience iš Project Gutenberg. Tai trumpas, lengvai suprantamas viešojo naudojimo tekstas.

4 žingsnis: parašykite indeksavimo programą

Nukopijuokite toliau pateiktą kodą ir įklijuokite jį į index.py. Kiekviena paantraštė trumpai paaiškina, ką daro po jos einantis kodo segmentas. Ši programa pavers jūsų šaltinio medžiagą vektoriniais įterpiniais ir išsaugos juos ChromaDB duomenų bazėje, naudodama Perplexity įterpinių modelį pplx-embed-v1-0.6b ir NumPy biblioteką.

Štai ką daro programa:

  1. Atidaro document.txt.
  2. Padalija tekstą į persidengiančius fragmentus.
  3. Siunčia tuos fragmentus Perplexity įterpinių modeliui pplx-embed-v1-0.6b.
  4. Iškoduoja ir normalizuoja grąžintus vektorius naudodama NumPy – Python skaičiavimo funkcijų biblioteką.
  5. Išsaugo vektorius ir pradinius fragmentus ChromaDB duomenų bazėje (ji atsiras jūsų projekto kataloge).

Ji sukonfigūruota taip, kad iš naujo neindeksuotų jūsų dokumento kiekvieną kartą ją paleidus. Jei papildysite informaciją faile document.txt, ji pavers įterpiniais tik naują 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 žingsnis. Parašykite RAG sistemos orkestratorių

Nukopijuokite toliau pateiktą kodą ir įklijuokite jį į rag.py. Tai išbaigtas, bet minimalus RAG diegimas, kuriame naudojami Perplexity SDK ir ChromaDB vietinės vektorinės duomenų bazės funkcijos.

Štai kas vyks paleidus programą:

  1. Prisijungia prie Perplexity ir jūsų naujos ChromaDB duomenų bazės.
  2. Patikrina, ar duomenų bazėje yra indeksuotų dokumentų.
  3. Priima naudotojo klausimą.
  4. Siunčia klausimą Perplexity įterpinių modeliui.
  5. Iškoduoja ir normalizuoja gautą įterpinį naudodama NumPy.
  6. ChromaDB duomenų bazėje ieško trijų panašiausių dokumento fragmentų.
  7. Sudaro užklausą, kurioje yra gauti fragmentai ir naudotojo klausimas.
  8. Siunčia užklausą modeliui GPT-5.6 Luna per Perplexity Agent API.
  9. Parodo atsakymą ir laukia kito klausimo.
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 žingsnis: paleiskite programas

VS Code PowerShell terminale įveskite toliau pateiktą komandą, kad paverstumėte failo document.txt turinį įterpiniais:

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

Jei dokumentas sėkmingai suindeksuotas, turėtumėte pamatyti panašią išvestį:

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

Dabar metas paleisti pagrindinę orkestratoriaus programą. Įveskite šią komandą:

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

Jei paleidimas bus sėkmingas, pamatysite štai ką:

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

Dabar galite užduoti klausimus, į kuriuos bus atsakoma remiantis jūsų sukurta vektorine duomenų baze, pavyzdžiui:

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 žingsnis: supraskite, ką sukūrėte

Jūsų sukurtoje sistemoje yra du pagrindiniai konvejeriai, būdingi kiekvienai RAG architektūrai: indeksavimo, arba „įkėlimo“, konvejeris ir paieškos bei generavimo konvejeris.

Jūsų paprastas RAG diegimas dabar atlieka visa tai:

  • Vektorių saugojimas: Įterpiniai, sukurti pagal jūsų žinių failą, išsaugomi ChromaDB duomenų bazėje jūsų vietinėje aplinkoje.
  • Inkrementinis indeksavimas: Nepakitę dokumento fragmentai iš naujo nepaverčiami įterpiniais, o dokumentą galite atnaujinti kada tik norite.
  • Semantinė paieška: ChromaDB randa fragmentus pagal vektorių panašumą (paiešką inicijuoja orkestratorius).
  • Šaltiniais pagrįstų atsakymų generavimas: LLM gauna rastas ištraukas kaip kontekstą ir panaudoja jas atsakyme.
  • Atskiras indeksavimas ir užklausos: Galite užduoti klausimus iš naujo neapdorodami viso jūsų žinių faile esančio teksto.
  • Prisijungimas prie modelio per API: Visi atsakymai generuojami naudojant modelį GPT-5.6 Luna per Perplexity, o ne jūsų kompiuteryje veikiantį modelį.

Tolesni žingsniai: kaip toliau plėtoti šį diegimą

Šio vadovo tikslas – sukurti nesudėtingą, paprastą diegimą. Jame aptariami kai kurie pagrindiniai RAG architektūros komponentai, naudojami šiuolaikinėse sistemose. Jei norite žengti toliau, jį galima plėtoti įvairiais būdais.

Štai keletas idėjų, kaip išplėsti savo diegimo galimybes:

  • Eksperimentuokite su LangChain: LangChain yra vienas populiariausių atvirojo kodo orkestravimo karkasų. Jame yra iš anksto paruoštų komponentų, skirtų kurti programas, galinčias vykdyti sudėtingus RAG konvejerius.
  • Išplėskite paieškos galimybes: Derinkite tankiųjų vektorių paiešką su leksine (raktinių žodžių) paieška, pavyzdžiui, BM25. Pridėję žiniatinklio paiešką per Perplexity Search API, taip pat galėtumėte grįsti atsakymus naujausiais duomenimis.
  • Pridėkite pakartotinio reitingavimo modelį: Integruokite pakartotinio reitingavimo modelį, kuris surikiuoja rastas ištraukas pagal pradinę užklausą ir atrenka aktualiausias, kad jos būtų įtrauktos į LLM pateikiamą įvesties kontekstą.
  • Sukurkite adaptyviąją RAG sistemą: Adaptyvusis RAG naudoja LLM arba klasifikatorių (orkestratoriaus komponentą), kad nustatytų, kurį paieškos metodą naudoti modulinėje RAG sistemoje. Tokios sistemos kūrimas – puikus būdas susipažinti su sudėtingesniais RAG diegimais.

Nors visa tai gali skambėti sudėtingai, nepamirškite, kad populiarios DI platformos, pavyzdžiui, Perplexity, gali suteikti pažangią pagalbą programuojant. Jos puikiai tinka asmeniniams projektams ir eksperimentams, o išlaidas galima išlaikyti gana mažas.

Pastaba: šiame vadove naudojamas GPT-5.6 Luna. Modelių prieinamumas gali keistis, todėl gali tekti atnaujinti API iškvietimą.