GPT-4 और Claude जैसे Large Language Models (LLMs) असाधारण रूप से शक्तिशाली हैं, लेकिन वे एक मूलभूत सीमा से ग्रस्त हैं: उनका ज्ञान ट्रेनिंग के समय जम जाता है। वे आपके आंतरिक दस्तावेज़ों, आपके डेटाबेस या वास्तविक समय की जानकारी तक नहीं पहुँच सकते। Retrieval-Augmented Generation (RAG) LLMs की जनरेटिव शक्ति को बाहरी स्रोतों से जानकारी प्राप्त करने की क्षमता के साथ जोड़कर इस समस्या को हल करती है।
समस्या: LLMs की सीमाएं
RAG के बारे में बात करने से पहले, यह समझना ज़रूरी है कि हमें इसकी आवश्यकता क्यों है।
- स्थिर ज्ञान: एक LLM केवल वही जानता है जो उसने ट्रेनिंग के दौरान देखा। यदि आप उसके कटऑफ के बाद हुई किसी घटना के बारे में पूछते हैं, तो वह उत्तर नहीं दे सकता।
- हैलुसिनेशन: जब LLM को उत्तर नहीं पता होता, तो वह एक गढ़ने की प्रवृत्ति रखता है, विश्वसनीय लेकिन पूरी तरह से गलत जानकारी उत्पन्न करता है।
- निजी डेटा तक पहुँच नहीं: एक सामान्य LLM के पास आपकी कंपनी के आंतरिक दस्तावेज़ों, टिकट या कोडबेस तक पहुँच नहीं है।
RAG क्वेरी के समय बाहरी स्रोतों से प्राप्त प्रासंगिक संदर्भ प्रदान करके इन तीनों समस्याओं का समाधान करती है।
RAG क्या है?
Retrieval-Augmented Generation एक आर्किटेक्चर है जो LLM को भेजे गए प्रॉम्प्ट को बाहरी ज्ञान आधार से प्राप्त जानकारी से समृद्ध करती है। मॉडल के पैरामेट्रिक ज्ञान पर पूरी तरह निर्भर रहने के बजाय, RAG पहले प्रासंगिक जानकारी खोजती है और फिर उसे प्रॉम्प्ट में इंजेक्ट करती है, जिससे मॉडल सटीक, आधारित प्रतिक्रियाएं उत्पन्न कर सकता है।
RAG विस्तार से कैसे काम करता है
RAG आर्किटेक्चर दो मुख्य चरणों से बना है: इंडेक्सिंग (ऑफलाइन) और रिट्रीवल + जनरेशन (ऑनलाइन)।
चरण 1: इंडेक्सिंग (दस्तावेज़ इंजेशन)
इंडेक्सिंग चरण आपके दस्तावेज़ों को सिमेंटिक खोज के लिए तैयार करता है। इसमें चार कदम शामिल हैं।
1. दस्तावेज़ लोडिंग
दस्तावेज़ किसी भी स्रोत से आ सकते हैं: PDF फाइलें, वेब पेज, डेटाबेस, Markdown फाइलें, APIs। डॉक्यूमेंट लोडर इन दस्तावेज़ों को पढ़ता है और उन्हें संरचित टेक्स्ट में बदलता है।
2. टेक्स्ट स्प्लिटिंग (चंकिंग)
LLMs की कॉन्टेक्स्ट विंडो सीमित होती है, और दस्तावेज़ बहुत लंबे हो सकते हैं। टेक्स्ट स्प्लिटर दस्तावेज़ों को चंक्स नामक छोटे टुकड़ों में विभाजित करता है। चंकिंग की गुणवत्ता महत्वपूर्ण है: बहुत छोटे चंक्स संदर्भ खो देते हैं, बहुत बड़े चंक्स प्रासंगिकता को कम करते हैं।
सबसे आम रणनीतियां हैं:
- रिकर्सिव कैरेक्टर स्प्लिटिंग:
\n\n,\n,.जैसे सेपरेटर्स का उपयोग करके टेक्स्ट को रिकर्सिव रूप से विभाजित करता है, दस्तावेज़ संरचना का सम्मान करता है। - सिमेंटिक स्प्लिटिंग: टेक्स्ट में प्राकृतिक ब्रेकपॉइंट खोजने के लिए एम्बेडिंग का उपयोग करता है।
- चंक ओवरलैप: सीमाओं पर संदर्भ को संरक्षित करने के लिए लगातार चंक्स के बीच ओवरलैप शामिल करता है।
3. एम्बेडिंग
प्रत्येक चंक को एम्बेडिंग मॉडल (जैसे OpenAI का text-embedding-3-small) के माध्यम से एक संख्यात्मक वेक्टर (एम्बेडिंग) में बदला जाता है। ये वेक्टर टेक्स्ट के सिमेंटिक अर्थ को कैप्चर करते हैं: समान अर्थ वाले वाक्यों के वेक्टर बहुआयामी स्थान में पास होंगे।
4. वेक्टर स्टोर
वेक्टर ChromaDB, Pinecone, Weaviate या FAISS जैसे वेक्टर स्टोर (वेक्टर डेटाबेस) में सहेजे जाते हैं। यह डेटाबेस समानता खोज के लिए अनुकूलित है: एक क्वेरी दिए जाने पर, यह सबसे समान वेक्टर (और इसलिए सबसे प्रासंगिक टेक्स्ट चंक्स) खोजता है।
चरण 2: रिट्रीवल + जनरेशन
जब उपयोगकर्ता प्रश्न पूछता है:
- प्रश्न को उसी एम्बेडिंग मॉडल का उपयोग करके एम्बेडिंग में बदला जाता है।
- वेक्टर स्टोर समानता खोज (आमतौर पर कोसाइन समानता या यूक्लिडियन दूरी) के माध्यम से सबसे समान चंक्स खोजता है।
- प्राप्त चंक्स को संदर्भ के रूप में प्रॉम्प्ट में डाला जाता है।
- LLM प्रदान किए गए संदर्भ के आधार पर उत्तर उत्पन्न करता है।
LangChain के साथ RAG पाइपलाइन बनाना
LangChain LLM-आधारित एप्लिकेशन बनाने के लिए सबसे लोकप्रिय Python (और JavaScript) फ्रेमवर्क है। यह RAG पाइपलाइन के प्रत्येक घटक के लिए उच्च-स्तरीय एब्स्ट्रैक्शन प्रदान करता है।
इंस्टॉलेशन
pip install langchain langchain-openai langchain-community chromadb
स्टेप 1: दस्तावेज़ लोड करें
LangChain विभिन्न डेटा स्रोतों के लिए दर्जनों डॉक्यूमेंट लोडर प्रदान करता है।
from langchain_community.document_loaders import ( PyPDFLoader, WebBaseLoader, DirectoryLoader, TextLoader, ) # एक PDF लोड करें pdf_loader = PyPDFLoader("docs/manual.pdf") pdf_docs = pdf_loader.load() # एक वेब पेज लोड करें web_loader = WebBaseLoader("https://docs.example.com/guide") web_docs = web_loader.load() # एक डायरेक्टरी से सभी .md फाइलें लोड करें dir_loader = DirectoryLoader("./knowledge_base", glob="**/*.md", loader_cls=TextLoader) md_docs = dir_loader.load() all_docs = pdf_docs + web_docs + md_docs
स्टेप 2: दस्तावेज़ों को चंक्स में विभाजित करें
from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200, separators=["\n\n", "\n", ". ", " ", ""], ) chunks = text_splitter.split_documents(all_docs) print(f"मूल दस्तावेज़: {len(all_docs)}, चंक्स: {len(chunks)}")
chunk_overlap पैरामीटर महत्वपूर्ण है: यह लगातार चंक्स के बीच ओवरलैप बनाता है ताकि सीमाओं पर संदर्भ न खोए।
स्टेप 3: एम्बेडिंग और वेक्टर स्टोर बनाएं
from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma embedding_model = OpenAIEmbeddings(model="text-embedding-3-small") vectorstore = Chroma.from_documents( documents=chunks, embedding=embedding_model, persist_directory="./chroma_db", )
स्टेप 4: रिट्रीवर बनाएं
रिट्रीवर वह घटक है जो, एक क्वेरी दिए जाने पर, वेक्टर स्टोर से सबसे प्रासंगिक चंक्स प्राप्त करता है।
retriever = vectorstore.as_retriever( search_type="similarity", search_kwargs={"k": 4}, ) relevant_docs = retriever.invoke("प्रमाणीकरण कैसे काम करता है?") for doc in relevant_docs: print(doc.page_content[:200]) print("---")
स्टेप 5: RAG चेन बनाएं
अब सब कुछ एक LLM और प्रॉम्प्ट टेम्पलेट के साथ जोड़ते हैं।
from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_core.output_parsers import StrOutputParser llm = ChatOpenAI(model="gpt-4o", temperature=0) prompt = ChatPromptTemplate.from_template(""" केवल प्रदान किए गए संदर्भ के आधार पर प्रश्न का उत्तर दें। यदि संदर्भ में पर्याप्त जानकारी नहीं है, तो कहें कि आप नहीं जानते। संदर्भ: {context} प्रश्न: {question} उत्तर: """) def format_docs(docs): return "\n\n".join(doc.page_content for doc in docs) rag_chain = ( {"context": retriever | format_docs, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser() ) response = rag_chain.invoke("सिस्टम में प्रमाणीकरण कैसे काम करता है?") print(response)
उन्नत RAG तकनीकें
बुनियादी पाइपलाइन अच्छी तरह काम करती है, लेकिन उत्तर की गुणवत्ता में उल्लेखनीय सुधार करने के लिए कई तकनीकें हैं।
मल्टी-क्वेरी रिट्रीवल
कभी-कभी उपयोगकर्ता की क्वेरी अस्पष्ट होती है या दस्तावेज़ों में प्रयुक्त भाषा से मेल नहीं खाती। मल्टी-क्वेरी रिट्रीवर कई दृष्टिकोणों को कैप्चर करने के लिए मूल प्रश्न के वेरिएंट स्वचालित रूप से उत्पन्न करता है।
from langchain.retrievers import MultiQueryRetriever multi_retriever = MultiQueryRetriever.from_llm( retriever=vectorstore.as_retriever(), llm=llm, ) docs = multi_retriever.invoke("सुरक्षा की सर्वोत्तम प्रथाएं क्या हैं?")
कॉन्टेक्स्चुअल कम्प्रेशन
चंक की सारी सामग्री क्वेरी के लिए प्रासंगिक नहीं होती। कॉन्टेक्स्चुअल कम्प्रेशन रिट्रीवर प्रत्येक प्राप्त चंक से केवल प्रासंगिक भागों को निकालने के लिए LLM का उपयोग करता है।
from langchain.retrievers import ContextualCompressionRetriever from langchain.retrievers.document_compressors import LLMChainExtractor compressor = LLMChainExtractor.from_llm(llm) compression_retriever = ContextualCompressionRetriever( base_compressor=compressor, base_retriever=retriever, )
हाइब्रिड सर्च
शुद्ध सिमेंटिक खोज हमेशा इष्टतम नहीं होती। हाइब्रिड सर्च बेहतर परिणाम प्राप्त करने के लिए सिमेंटिक खोज (एम्बेडिंग) को लेक्सिकल खोज (BM25, कीवर्ड मैचिंग) के साथ जोड़ती है।
from langchain.retrievers import EnsembleRetriever from langchain_community.retrievers import BM25Retriever bm25_retriever = BM25Retriever.from_documents(chunks) bm25_retriever.k = 4 semantic_retriever = vectorstore.as_retriever(search_kwargs={"k": 4}) hybrid_retriever = EnsembleRetriever( retrievers=[bm25_retriever, semantic_retriever], weights=[0.4, 0.6], )
कन्वर्सेशनल RAG (मेमोरी के साथ)
बातचीत के संदर्भ को याद रखने वाला RAG चैटबॉट बनाने के लिए, एक मेमोरी जोड़ना आवश्यक है जो बातचीत के इतिहास को ध्यान में रखते हुए उपयोगकर्ता के प्रश्नों को पुनर्निर्मित करे।
from langchain.chains import create_history_aware_retriever from langchain_core.prompts import MessagesPlaceholder contextualize_prompt = ChatPromptTemplate.from_messages([ ("system", "चैट इतिहास और उपयोगकर्ता के नवीनतम प्रश्न को देखते हुए, " "प्रश्न को इस तरह पुनर्निर्मित करें कि यह इतिहास के बिना भी समझ में आए।"), MessagesPlaceholder("chat_history"), ("human", "{input}"), ]) history_aware_retriever = create_history_aware_retriever( llm, retriever, contextualize_prompt )
सर्वोत्तम प्रथाएं
- सही चंक आकार चुनें: विभिन्न आकारों (500-1500 टोकन) के साथ प्रयोग करें। सटीक उत्तरों के लिए छोटे चंक्स, व्यापक संदर्भ के लिए बड़े चंक्स।
- दस्तावेज़ मेटाडेटा का उपयोग करें: स्रोत, तिथि और श्रेणी को चंक्स में मेटाडेटा के रूप में जोड़ें। यह रिट्रीवल के दौरान परिणामों को फिल्टर करने की अनुमति देता है।
- गुणवत्ता का मूल्यांकन करें: faithfulness, relevancy और context precision जैसे मेट्रिक्स मापने के लिए RAGAS जैसे फ्रेमवर्क का उपयोग करें।
- दस्तावेज़ अपडेट प्रबंधित करें: वेक्टर स्टोर को अपने डेटा स्रोतों के साथ सिंक्रनाइज़ रखने के लिए री-इंजेशन पाइपलाइन लागू करें।
- री-रैंकर जोड़ें: प्रारंभिक रिट्रीवल के बाद, वास्तविक प्रासंगिकता के आधार पर परिणामों को पुनर्क्रमित करने के लिए री-रैंकिंग मॉडल (जैसे Cohere Rerank) का उपयोग करें।
निष्कर्ष
RAG विशिष्ट, अद्यतन ज्ञान तक पहुँच की आवश्यकता वाले AI एप्लिकेशन बनाने के लिए मानक आर्किटेक्चर बन गई है। LangChain पाइपलाइन के प्रत्येक घटक के लिए एब्स्ट्रैक्शन प्रदान करके कार्यान्वयन को बहुत सरल बनाता है।
अगले कदम:
- स्थानीय रूप से प्रयोग करें: पाइपलाइन से परिचित होने के लिए ChromaDB और कुछ दस्तावेज़ों से शुरू करें।
- LangSmith का अन्वेषण करें: प्रोडक्शन में अपनी चेन की निगरानी और डिबगिंग के लिए LangSmith का उपयोग करें।
- विभिन्न एम्बेडिंग मॉडल आज़माएं:
text-embedding-3-small,text-embedding-3-largeऔर Sentence Transformers के ओपन-सोर्स मॉडल की तुलना करें। - दस्तावेज़ देखें: LangChain दस्तावेज़ एक उत्कृष्ट और लगातार अपडेट होने वाला संसाधन है।