spinny:~/writing $ vim rag-langchain-deep-dive.md
1~2Store sprogmodeller (LLMs) som GPT-4 og Claude er ekstraordinært kraftfulde, men lider af en fundamental begrænsning: deres viden er frosset på træningstidspunktet. **Retrieval-Augmented Generation (RAG)** løser præcis dette problem ved at kombinere den generative kraft i LLMs med evnen til at hente information fra eksterne kilder.3~4## Problemet: LLM-begrænsninger5~61. **Statisk viden**: En LLM ved kun, hvad den så under træning.72. **Hallucinationer**: Når en LLM ikke kender svaret, har den tendens til at opfinde et.83. **Ingen adgang til private data**: En generisk LLM har ingen adgang til din virksomheds interne dokumentation.9~10## Hvad er RAG?11~12```mermaid13graph LR14 User["User"] -- "Question" --> Retriever15 Retriever -- "Search relevant\ndocuments" --> VectorStore["Vector Store"]16 VectorStore -- "Relevant\ndocuments" --> Retriever17 Retriever -- "Context + Question" --> LLM18 LLM -- "Grounded\nresponse" --> User19```20~21## Sådan fungerer RAG i detaljer22~23### Fase 1: Indeksering (Dokumentindtagelse)24~25```mermaid26graph TD27 A["Documents\n(PDF, HTML, MD, DB)"] --> B["Document Loader"]28 B --> C["Text Splitter"]29 C --> D["Text Chunks"]30 D --> E["Embedding Model"]31 E --> F["Numerical Vectors"]32 F --> G["Vector Store\n(ChromaDB, Pinecone, FAISS)"]33```34~35#### 1. Dokumentindlæsning36Dokumenter kan komme fra enhver kilde: PDF-filer, websider, databaser, Markdown-filer, APIer.37~38#### 2. Tekstopdeling (Chunking)39**Text Splitter** opdeler dokumenter i mindre fragmenter kaldet *chunks*.40~41#### 3. Embedding42Hver chunk transformeres til en **numerisk vektor** (embedding) via en embedding-model.43~44#### 4. Vector Store45Vektorerne gemmes i en **Vector Store**, optimeret til **lighedssøgning**.46~47### Fase 2: Retrieval + Generation48~491. Spørgsmålet transformeres til et embedding.502. Vector Store finder de mest lignende chunks.513. De hentede chunks indsættes i prompten som kontekst.524. LLM genererer et svar baseret på den givne kontekst.53~54## Opbygning af en RAG-pipeline med LangChain55~56### Installation57~58```bash59pip install langchain langchain-openai langchain-community chromadb60```61~62### Trin 1: Indlæs dokumenter63~64```python65from langchain_community.document_loaders import (66 PyPDFLoader,67 WebBaseLoader,68 DirectoryLoader,69 TextLoader,70)71~72# Load a PDF73pdf_loader = PyPDFLoader("docs/manual.pdf")74pdf_docs = pdf_loader.load()75~76# Load a web page77web_loader = WebBaseLoader("https://docs.example.com/guide")78web_docs = web_loader.load()79~80# Load all .md files from a directory81dir_loader = DirectoryLoader("./knowledge_base", glob="**/*.md", loader_cls=TextLoader)82md_docs = dir_loader.load()83~84all_docs = pdf_docs + web_docs + md_docs85```86~87### Trin 2: Opdel dokumenter i chunks88~89```python90from langchain.text_splitter import RecursiveCharacterTextSplitter91~92text_splitter = RecursiveCharacterTextSplitter(93 chunk_size=1000,94 chunk_overlap=200,95 separators=["\n\n", "\n", ". ", " ", ""],96)97~98chunks = text_splitter.split_documents(all_docs)99print(f"Original documents: {len(all_docs)}, Chunks: {len(chunks)}")100```101~102### Trin 3: Opret embeddings og Vector Store103~104```python105from langchain_openai import OpenAIEmbeddings106from langchain_community.vectorstores import Chroma107~108embedding_model = OpenAIEmbeddings(model="text-embedding-3-small")109~110vectorstore = Chroma.from_documents(111 documents=chunks,112 embedding=embedding_model,113 persist_directory="./chroma_db",114)115```116~117### Trin 4: Opret Retriever118~119```python120retriever = vectorstore.as_retriever(121 search_type="similarity",122 search_kwargs={"k": 4},123)124~125relevant_docs = retriever.invoke("How does authentication work?")126for doc in relevant_docs:127 print(doc.page_content[:200])128 print("---")129```130~131### Trin 5: Byg RAG-kæden132~133```python134from langchain_openai import ChatOpenAI135from langchain_core.prompts import ChatPromptTemplate136from langchain_core.runnables import RunnablePassthrough137from langchain_core.output_parsers import StrOutputParser138~139llm = ChatOpenAI(model="gpt-4o", temperature=0)140~141prompt = ChatPromptTemplate.from_template("""142Answer the question based only on the provided context.143If the context does not contain enough information, say you don't know.144~145Context:146{context}147~148Question: {question}149~150Answer:151""")152~153def format_docs(docs):154 return "\n\n".join(doc.page_content for doc in docs)155~156rag_chain = (157 {"context": retriever | format_docs, "question": RunnablePassthrough()}158 | prompt159 | llm160 | StrOutputParser()161)162~163response = rag_chain.invoke("How does authentication work in the system?")164print(response)165```166~167## Avancerede RAG-teknikker168~169### Multi-Query Retrieval170~171```python172from langchain.retrievers import MultiQueryRetriever173~174multi_retriever = MultiQueryRetriever.from_llm(175 retriever=vectorstore.as_retriever(),176 llm=llm,177)178~179docs = multi_retriever.invoke("What are the security best practices?")180```181~182### Kontekstuel komprimering183~184```python185from langchain.retrievers import ContextualCompressionRetriever186from langchain.retrievers.document_compressors import LLMChainExtractor187~188compressor = LLMChainExtractor.from_llm(llm)189compression_retriever = ContextualCompressionRetriever(190 base_compressor=compressor,191 base_retriever=retriever,192)193```194~195### Hybrid søgning196~197```python198from langchain.retrievers import EnsembleRetriever199from langchain_community.retrievers import BM25Retriever200~201bm25_retriever = BM25Retriever.from_documents(chunks)202bm25_retriever.k = 4203~204semantic_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})205~206hybrid_retriever = EnsembleRetriever(207 retrievers=[bm25_retriever, semantic_retriever],208 weights=[0.4, 0.6],209)210```211~212### Konversationel RAG (med hukommelse)213~214```python215from langchain.chains import create_history_aware_retriever216from langchain_core.prompts import MessagesPlaceholder217~218contextualize_prompt = ChatPromptTemplate.from_messages([219 ("system", "Given the chat history and the user's latest question, "220 "reformulate the question so it is understandable without the history."),221 MessagesPlaceholder("chat_history"),222 ("human", "{input}"),223])224~225history_aware_retriever = create_history_aware_retriever(226 llm, retriever, contextualize_prompt227)228```229~230## Bedste praksis231~2321. **Vælg den rigtige chunk-størrelse**: Eksperimenter med forskellige størrelser (500-1500 tokens).2332. **Brug dokumentmetadata**: Tilføj kilde, dato og kategori som metadata.2343. **Evaluer kvalitet**: Brug frameworks som [RAGAS](https://docs.ragas.io/).2354. **Håndter dokumentopdateringer**: Implementer en re-ingestion pipeline.2365. **Tilføj en re-ranker**: Brug en re-ranking model efter initial retrieval.237~238## Konklusion239~240RAG er blevet standardarkitekturen for at bygge AI-applikationer, der har brug for adgang til specifik, opdateret viden. LangChain forenkler implementeringen enormt.241~242**Næste trin:**243- **Eksperimenter lokalt**: Start med ChromaDB og et par dokumenter.244- **Udforsk LangSmith**: Brug [LangSmith](https://smith.langchain.com/) til at overvåge og fejlsøge dine kæder.245- **Prøv forskellige embedding-modeller**.246- **Tjek dokumentationen**: [LangChain-dokumentationen](https://python.langchain.com/docs/) er en fremragende ressource.247~
NORMAL · rag-langchain-deep-dive.md [readonly]247 lines · :q to close