Великі мовні моделі (LLM) такі як GPT-4 та Claude надзвичайно потужні, але мають фундаментальне обмеження: їхні знання заморожені на момент навчання. Retrieval-Augmented Generation (RAG) вирішує саме цю проблему, поєднуючи генеративну потужність LLM з можливістю отримувати інформацію з зовнішніх джерел.
Проблема: Обмеження LLM
- Статичні знання: LLM знає лише те, що бачив під час навчання.
- Галюцинації: Коли LLM не знає відповіді, він має тенденцію вигадувати.
- Немає доступу до приватних даних: Загальний LLM не має доступу до вашої внутрішньої документації.
Що таке RAG?
RAG - це архітектура, яка збагачує промпт інформацією, отриманою з зовнішньої бази знань.
Як Працює RAG
Фаза 1: Індексація
Фаза 2: Retrieval + Generation
- Запитання перетворюється на embedding.
- Vector Store знаходить найбільш схожі чанки.
- Отримані чанки вставляються у промпт як контекст.
- LLM генерує відповідь на основі контексту.
Побудова RAG Pipeline з LangChain
pip install langchain langchain-openai langchain-community chromadb
from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader, DirectoryLoader, TextLoader pdf_loader = PyPDFLoader("docs/manual.pdf") pdf_docs = pdf_loader.load() web_loader = WebBaseLoader("https://docs.example.com/guide") web_docs = web_loader.load() dir_loader = DirectoryLoader("./knowledge_base", glob="**/*.md", loader_cls=TextLoader) md_docs = dir_loader.load() all_docs = pdf_docs + web_docs + md_docs
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)
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") retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 4})
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(""" Answer the question based only on the provided context. If the context does not contain enough information, say you don't know. Context: {context} Question: {question} Answer: """) 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("How does authentication work in the system?")
Просунуті Техніки RAG
Multi-Query Retrieval, Contextual Compression, Hybrid Search та Conversational RAG.
from langchain.retrievers import MultiQueryRetriever multi_retriever = MultiQueryRetriever.from_llm(retriever=vectorstore.as_retriever(), llm=llm)
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])
Найкращі Практики
- Обирайте правильний розмір чанка: Експериментуйте з 500-1500 токенами.
- Використовуйте метадані документів: Додавайте джерело, дату та категорію.
- Оцінюйте якість: Використовуйте фреймворки як RAGAS.
- Керуйте оновленнями документів: Реалізуйте пайплайн повторної інгестії.
- Додайте re-ranker: Використовуйте модель re-ranking після початкового пошуку.
Висновок
RAG став стандартною архітектурою для AI-додатків, що потребують доступу до специфічних, актуальних знань. LangChain значно спрощує реалізацію.