Τα Large Language Models (LLMs) όπως GPT-4 και Claude είναι εξαιρετικά ισχυρά, αλλά υποφέρουν από έναν θεμελιώδη περιορισμό: η γνώση τους είναι παγωμένη στη στιγμή της εκπαίδευσης. Το Retrieval-Augmented Generation (RAG) λύνει ακριβώς αυτό το πρόβλημα συνδυάζοντας τη δημιουργική δύναμη των LLMs με τη δυνατότητα ανάκτησης πληροφοριών από εξωτερικές πηγές.
Το Πρόβλημα: Περιορισμοί LLM
- Στατική γνώση: Ένα LLM γνωρίζει μόνο τι είδε κατά την εκπαίδευση.
- Ψευδαισθήσεις: Όταν ένα LLM δεν γνωρίζει την απάντηση, τείνει να κατασκευάζει μία.
- Χωρίς πρόσβαση σε ιδιωτικά δεδομένα: Ένα γενικό LLM δεν έχει πρόσβαση στην εσωτερική τεκμηρίωσή σας.
Τι είναι το RAG;
Το RAG είναι μια αρχιτεκτονική που εμπλουτίζει το prompt με πληροφορίες ανακτημένες από εξωτερική βάση γνώσεων.
Πώς Λειτουργεί το RAG
Φάση 1: Ευρετηρίαση
Φάση 2: Retrieval + Generation
- Η ερώτηση μετατρέπεται σε embedding.
- Το Vector Store βρίσκει τα πιο σχετικά chunks.
- Τα ανακτημένα chunks εισάγονται στο prompt ως πλαίσιο.
- Το 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])
Βέλτιστες Πρακτικές
- Επιλέξτε σωστό μέγεθος chunk: Πειραματιστείτε με 500-1500 tokens.
- Χρησιμοποιήστε μεταδεδομένα εγγράφων.
- Αξιολογήστε ποιότητα: Χρησιμοποιήστε RAGAS.
- Διαχειριστείτε ενημερώσεις εγγράφων.
- Προσθέστε re-ranker.
Συμπέρασμα
Το RAG έχει γίνει η τυπική αρχιτεκτονική για AI εφαρμογές που χρειάζονται πρόσβαση σε συγκεκριμένη, ενημερωμένη γνώση. Το LangChain απλοποιεί σημαντικά την υλοποίηση.