LLM वही जानता है जिस पर वह train हुआ है – लेकिन आपके notes, PDFs, code या कंपनी के docs नहीं। RAG (Retrieval-Augmented Generation) इसे ठीक करता है, model को आपके documents का उपयोग करके सवालों का जवाब देने देकर, बिना retraining के। "chat with your PDF" apps इसी तरह काम करती हैं, और आप इसे पूरी तरह अपनी मशीन पर local LLM के साथ बना सकते हैं।

यह गाइड RAG के चार moving parts समझाती है और एक working, local-first उदाहरण के साथ walkthrough देती है।

RAG के चार हिस्से

  1. Load – अपने documents (PDF, markdown, text) को text के chunks में पढ़ें।
  2. Embed – हर chunk को embedding model से vector (संख्याओं की सूची जो अर्थ capture करती है) में बदलें।
  3. Retrieve – सवाल आने पर उसे भी embed करें और उन chunks को ढूँढें जिनके vectors सबसे करीब हैं।
  4. Generate – LLM को retrieved chunks के साथ सवाल दें, और उसे सिर्फ उसी context का उपयोग करके जवाब देने दें।

यही पूरी तरकीब है। LLM आपका पूरा document set कभी नहीं देखता – सिर्फ कुछ प्रासंगिक chunks, जिन्हें वह grounded context के रूप में इस्तेमाल करता है। इसीलिए जवाब सटीक होते हैं और आपको retrain करने की ज़रूरत नहीं पड़ती।

Step 1: Load और chunk

अपने documents को कुछ सौ characters के chunks में बाँटें, थोड़े overlap के साथ। Overlap क्यों? ताकि chunk boundary पर फँसा context खो न जाए। Python में एक आसान तरीका:

import re
text = open("notes.md").read()
chunks = [text[i:i+500] for i in range(0, len(text), 400)]  # 500 chars, 100 overlap

LlamaIndex और LangChain जैसे tools out of the box smarter chunking संभाल लेते हैं, लेकिन idea वही है।

Step 2: Embed

Embedding model text को vector में बदलता है – numbers की fixed-size list – जहाँ similar meaning करीब होते हैं। छोटा embedding model किसी भी CPU पर तेज़ चलता है, इसलिए यह सस्ता है। Ollama के पास कई हैं, जैसे nomic-embed-text:

ollama pull nomic-embed-text

हर chunk को embed करें और vectors को store करें (personal use के लिए साधारण JSON या SQLite file काफ़ी है; Chroma या Qdrant जैसे vector databases scale के लिए हैं)।

Step 3: Retrieve

जब सवाल आता है, तो उसे same model से embed करें, फिर उन chunks को ढूँढें जिनके vectors सबसे similar हैं। "Similarity" आमतौर पर cosine similarity है – vectors के बीच छोटा angle मतलब ज़्यादा related meaning। Top 3–5 chunks चुनें:

import numpy as np
# assume emb(q) is the question vector, emb(chunks) is a matrix
scores = emb(chunks) @ emb(q) / (norms * norm_q)   # cosine sim
top = np.argsort(scores)[::-1][:5]                  # top 5 chunk indices

अगर सवाल और chunk में similar शब्द या concepts हैं, तो वे high rank करेंगे – इसी तरह RAG LLM को सब दिखाए बिना सही passages ढूँढ लेता है।

Step 4: Generate

अंत में, retrieved chunks को context के रूप में LLM को prompt करें। जादू instruction में है: सिर्फ इसी context का उपयोग करके जवाब दें

system: You are a helpful assistant. Answer the question using ONLY the
context below. If the answer isn't there, say you don't know.

Context:
--- chunk 3 ---
--- chunk 7 ---
--- chunk 11 ---

Question: What did the notes say about X?

Local model (जैसे Ollama के ज़रिए 7B) के साथ यह पूरी तरह offline चलता है। local AI guide बताता है कि model कैसे चलाएँ; prompting guide समझाता है कि "सिर्फ context का उपयोग करो" instruction इतनी ज़रूरी क्यों है।

एक आसान shortcut: Ollama + Open WebUI

अगर आप code नहीं लिखना चाहते, तो Open WebUI में RAG built-in है: document upload करें, और यह आपके local Ollama models के सामने खुद chunk, embed और retrieve कर देता है। यह RAG try करने का सबसे तेज़ तरीका है – ऊपर वाला "from scratch" version बताता है कि अंदर कैसे काम होता है।

RAG कब काम करता है (और कब नहीं)

Chunk size और retrieval count दो सबसे अहम knobs हैं। बहुत कम या बहुत छोटे chunks → context गायब। बहुत ज़्यादा → LLM distract हो जाता है या जवाब लंबा हो जाता है। ~500-char chunks और top-5 retrieval से शुरू करें, फिर tune करें।

निष्कर्ष

RAG है load, embed, retrieve, generate – चार steps जिन्हें आप पूरी तरह locally चला सकते हैं। यह general LLM को ऐसा model बना देता है जो सच में आपके documents जानता है, grounded, citable जवाबों के साथ और बिना retraining के। चाहे आप library इस्तेमाल करें या ऊपर वाले raw steps, concept वही है, और यह local model पर बनाई जा सकने वाली सबसे उपयोगी चीज़ों में से एक है।