Large Language Models (LLM) som GPT-4 och Claude Àr extraordinÀrt kraftfulla, men de lider av en fundamental begrÀnsning: deras kunskap Àr frusen vid trÀningstillfÀllet. Retrieval-Augmented Generation (RAG) löser exakt detta problem genom att kombinera LLM:ers generativa kraft med förmÄgan att hÀmta information frÄn externa kÀllor.
Problemet: LLM-begrÀnsningar
- Statisk kunskap: En LLM vet bara vad den sÄg under trÀning.
- Hallucinationer: NĂ€r en LLM inte vet svaret tenderar den att fabricera ett.
- Ingen Ätkomst till privat data: Ett generiskt LLM har ingen Ätkomst till din interna dokumentation.
Vad Àr RAG?
RAG Àr en arkitektur som berikar prompten med information hÀmtad frÄn en extern kunskapsbas.
Hur RAG Fungerar
Fas 1: Indexering
Fas 2: Retrieval + Generation
- FrÄgan omvandlas till en embedding.
- Vector Store hittar de mest liknande chunkarna.
- De hÀmtade chunkarna infogas i prompten som kontext.
- LLM:en genererar ett svar baserat pÄ kontexten.
Bygga en RAG Pipeline med LangChain
pip install langchain langchain-openai langchain-community chromadb
Steg 1-5: Ladda, Splitta, Skapa Embeddings, HĂ€mta, Generera
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?")
Avancerade RAG-tekniker
Multi-Query, 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])
BĂ€sta Praxis
- VÀlj rÀtt chunkstorlek: Experimentera med 500-1500 tokens.
- AnvÀnd dokumentmetadata: LÀgg till kÀlla, datum och kategori.
- UtvÀrdera kvalitet: AnvÀnd ramverk som RAGAS.
- Hantera dokumentuppdateringar: Implementera en re-ingest pipeline.
- LÀgg till en re-ranker: AnvÀnd en re-ranking-modell.
Slutsats
RAG har blivit standardarkitekturen för AI-applikationer som behöver Ätkomst till specifik, aktuell kunskap. LangChain förenklar implementeringen avsevÀrt.