<EbeneX/>
Praxis & Anwendung · 19. Februar 2026

RAG in der Praxis: Eigene Wissensbasis für KI-Anwendungen

Baue eine KI, die auf deinen eigenen Dokumenten antwortet – Schritt für Schritt erklärt.

Über diesen Guide

Wie du mit Retrieval Augmented Generation (RAG) eine KI baust, die auf deinen eigenen Dokumenten antwortet – von der Theorie bis zur ersten funktionierenden Pipeline.

Fortgeschritten 18 Min. Lesezeit
Verstehen, warum RAG besser ist als reines Fine-Tuning für dokumentenbasierte Fragen
Die 5 Kernkomponenten einer RAG-Pipeline benennen und erklären können
Chunking-Strategien kennen und für verschiedene Dokumenttypen auswählen können
Eine einfache RAG-Pipeline mit LangChain oder LlamaIndex aufbauen können
Häufige RAG-Probleme diagnostizieren und beheben können

Warum RAG?

Stell dir vor, du hast 500 interne Dokumente – Handbücher, Policies, Meeting-Protokolle – und willst, dass eine KI Fragen dazu beantwortet. Du könntest alles in den Prompt packen, aber selbst große Kontextfenster (100.000+ Token) reichen für viele Dokumentensammlungen nicht aus. 500 Dokumente à 10 Seiten? Das sind locker 2 Millionen Token. Zu teuer, zu langsam, zu unzuverlässig.

Die Alternative: RAG – Retrieval Augmented Generation. Statt alles in den Prompt zu laden, suchst du erst die relevanten Passagen heraus und gibst dem LLM nur diese. Das Ergebnis: präzisere Antworten, niedrigere Kosten, und das System bleibt aktuell ohne Retraining.

RAG ist heute die Standardarchitektur für dokumentenbasierte KI-Anwendungen – von internen Wissensdatenbanken über Kundenservice-Bots bis zu Code-Assistenten.

Die 5 Komponenten einer RAG-Pipeline

Dokumente → [1. Chunking] → [2. Embedding] → [3. Vektordatenbank]

Nutzerfrage → [2. Embedding] → [4. Retrieval] → relevante Chunks

                                              [5. Generation] → Antwort

1. Chunking – Dokumente aufteilen

Bevor Dokumente in eine Vektordatenbank kommen, müssen sie in kleinere Einheiten aufgeteilt werden. Die Chunk-Größe ist einer der wichtigsten Parameter:

Chunk-GrößeVorteilNachteilGeeignet für
Klein (128–256 Token)Präzises RetrievalVerliert KontextFAQs, kurze Fakten
Mittel (512 Token)Gute BalanceTechnische Docs, Artikel
Groß (1024+ Token)Viel KontextRauschen im RetrievalNarrative Texte, Bücher

Overlap ist entscheidend: Ein Overlap von 10–20% stellt sicher, dass Informationen an Chunk-Grenzen nicht verloren gehen.

Token vs. Zeichen: Viele Splitter messen standardmäßig in Zeichen, nicht in Token. chunk_size=512 bedeutet dann 512 Zeichen ≈ 100–150 Token – viel kleiner als erwartet. Für token-genaues Chunking tiktoken als length_function übergeben.

from langchain.text_splitter import RecursiveCharacterTextSplitter
import tiktoken

enc = tiktoken.encoding_for_model("gpt-5")

splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=50,
    length_function=lambda t: len(enc.encode(t)),  # Token, nicht Zeichen
    separators=["\n\n", "\n", ". ", " "]
)
chunks = splitter.split_documents(documents)

PDF-Ingestion: Clean-up zuerst

PDFs sind der häufigste Schmerzpunkt. Vor dem Chunking bereinigen:

  • Zeilenumbrüche normalisieren (PDFs trennen Wörter oft mitten im Satz)
  • Silbentrennung entfernen (re.sub(r'(\w+)-\n(\w+)', r'\1\2', text))
  • Headers, Footers, Seitenzahlen herausfiltern
  • Tabellen und Abbildungen separat behandeln (oft als Bild extrahieren)

Fortgeschrittene Strategien:

  • Semantic Chunking: Chunks werden an semantischen Grenzen getrennt, nicht nach Token-Anzahl
  • Parent-Child Chunking: Kleine Chunks für Retrieval, große Parent-Chunks für Kontext
  • Hierarchisches Chunking: Dokument → Abschnitt → Absatz – Retrieval auf mehreren Ebenen

2. Embedding – Text in Vektoren

Jeder Chunk wird durch ein Embedding-Modell in einen Vektor umgewandelt – eine Liste von Zahlen, die die semantische Bedeutung repräsentiert.

from openai import OpenAI

client = OpenAI()

def embed(text: str) -> list[float]:
    response = client.embeddings.create(
        model="text-embedding-3-small",  # 1536 Dimensionen, günstig
        input=text
    )
    return response.data[0].embedding

Modell-Vergleich:

ModellDimensionenKostenQualität
text-embedding-3-small1536$0.02/1M Token★★★★☆
text-embedding-3-large3072$0.13/1M Token★★★★★
nomic-embed-text (lokal)768kostenlos★★★★☆
bge-m3 (lokal, multilingual)1024kostenlos★★★★★

Für deutsche Dokumente: bge-m3 oder multilingual-e5-large sind oft besser als OpenAI-Modelle.

3. Vektordatenbank – Vektoren speichern und suchen

Die Vektordatenbank speichert Chunks + ihre Embeddings und ermöglicht schnelle Ähnlichkeitssuche.

import chromadb

client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_or_create_collection("meine_docs")

# Chunks einpflegen
collection.add(
    documents=[chunk.page_content for chunk in chunks],
    embeddings=[embed(chunk.page_content) for chunk in chunks],
    metadatas=[chunk.metadata for chunk in chunks],
    ids=[f"chunk_{i}" for i in range(len(chunks))]
)

4. Retrieval – Relevante Chunks finden

Bei einer Nutzerfrage wird die Frage ebenfalls eingebettet und die ähnlichsten Chunks gesucht.

Reine Vektorsuche findet semantisch ähnliche Chunks, versagt aber bei exakten Begriffen (Produktnummern, Namen).

Hybrid Search kombiniert Vektorsuche mit BM25 (klassische Keyword-Suche). In den meisten Produktionsszenarien schlägt sie reine Vektorsuche – besonders bei exakten Begriffen wie Produktnummern, Gesetzesparagraphen oder Namen. Bei sehr homogener, sauber strukturierter Dokumentation (z.B. internes Wiki mit einheitlicher Terminologie) kann pure Dense Search ausreichen.

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever

# Vektorsuche
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})

# BM25 Keyword-Suche
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 5

# Hybrid: 60% Vektor, 40% BM25
ensemble = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.6, 0.4]
)

Reranking als zweiter Schritt ist in der Praxis oft der größte Hebel nach solidem Chunking – in vielen Setups bringt es spürbar bessere Antworten bei wenig Mehrkosten:

from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank

compressor = CohereRerank(model="rerank-multilingual-v3.0", top_n=3)
reranking_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=ensemble
)

5. Generation – Antwort erzeugen

Die gefundenen Chunks werden in den Prompt eingebettet und das LLM generiert die Antwort. Wichtig: Kontext und Regeln sauber trennen.

from openai import OpenAI

def rag_answer(question: str, chunks: list[dict]) -> str:
    # Chunks mit IDs für Quellen-Zitation
    context_blocks = []
    for i, chunk in enumerate(chunks):
        context_blocks.append(f"[Quelle {i+1}: {chunk['source']}]\n{chunk['text']}")
    context = "\n\n---\n\n".join(context_blocks)

    # Context Budget: max. ~2000 Token Kontext, nicht einfach k erhöhen
    # Lieber weniger, dafür hochwertige Chunks (nach Reranking)
    
    response = client.chat.completions.create(
        model="gpt-5-mini",
        messages=[
            {
                "role": "system",
                "content": "Du bist ein hilfreicher Assistent. Antworte präzise und sachlich."
                           " Wenn der Kontext widersprüchlich ist, weise darauf hin."
            },
            {
                "role": "user",  # Kontext als eigene Message, nicht im System-Prompt
                "content": f"""KONTEXT:
{context}

FRAGE: {question}

Regeln:
- Antworte ausschließlich basierend auf dem Kontext oben.
- Gib pro Aussage die Quellen-ID an (z.B. [Quelle 1]).
- Wenn die Antwort nicht im Kontext steht, sage: "Diese Information liegt mir nicht vor."""""
            }
        ]
    )
    return response.choices[0].message.content

Context Budget statt k erhöhen: Erhöhe nicht einfach k bis das Modell verwirrt ist. Budgetiere stattdessen den Kontext (z.B. max. 1500–3000 Token) und nimm die bestbewerteten Passagen nach dem Reranking. Qualität schlägt Quantität.

Query Transformations – oft unterschätzt

Nach solidem Chunking und Retrieval ist Query Transformation der nächste große Hebel:

  • Query Rewriting: Die Nutzerfrage wird vor dem Retrieval umformuliert – präziser, mit mehr Kontext. Besonders hilfreich bei kurzen oder mehrdeutigen Fragen.
  • Multi-Query Retrieval: Aus einer Frage werden 3–5 Varianten generiert, jede wird separat abgerufen, Ergebnisse werden dedupliziert. Erhöht Recall deutlich.
  • HyDE (Hypothetical Document Embeddings): Das LLM generiert eine hypothetische Antwort, deren Embedding für die Suche genutzt wird – oft besser als das Frage-Embedding direkt.
  • Self-Query + Metadaten-Filter: Das LLM extrahiert Filter aus der Frage (z.B. “Dokumente aus 2024”) und übergibt sie als Metadaten-Filter an die Vektordatenbank.
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-5-mini", temperature=0)
multi_retriever = MultiQueryRetriever.from_llm(
    retriever=vectorstore.as_retriever(),
    llm=llm
)
# Generiert automatisch mehrere Frage-Varianten und merged die Ergebnisse

Häufige Probleme und Lösungen

Problem: Das RAG findet die richtigen Chunks nicht

Diagnose: Teste Retrieval isoliert – stelle Fragen und prüfe manuell ob die zurückgegebenen Chunks relevant sind.

Ursachen und Lösungen:

  • Chunks zu groß → Chunk-Größe reduzieren
  • Embedding-Modell passt nicht zur Sprache → multilinguales Modell verwenden
  • Frage und Dokument nutzen unterschiedliche Begriffe → Hybrid Search aktivieren
  • Zu wenige Chunks abgerufen → k erhöhen (z.B. von 3 auf 8)

Problem: Das LLM halluziniert trotz richtigem Kontext

Diagnose: Faithfulness-Score mit RAGAS messen.

Lösungen:

  • System-Prompt verschärfen: „Antworte nur mit Informationen aus dem Kontext”
  • Temperatur auf 0 setzen für faktische Antworten
  • Stärkeres Modell verwenden (GPT-5 statt GPT-5-mini)
  • Kontext kürzen: Zu viele irrelevante Chunks verwirren das LLM

Problem: Antworten sind zu allgemein

Ursache: Chunks enthalten zu wenig spezifische Information.

Lösung: Metadaten in Chunks einbetten (Dokumentname, Datum, Abschnitt) und im Prompt referenzieren lassen.

Evaluation mit RAGAS

Ohne Evaluation weißt du nicht ob dein RAG gut ist. RAGAS ist der Standard:

from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision

# Testdatensatz: Fragen + erwartete Antworten + abgerufene Chunks
dataset = {
    "question": ["Was ist die Rückgabefrist?", ...],
    "answer": [rag_answer(q) for q in questions],
    "contexts": [retrieve_chunks(q) for q in questions],
    "ground_truth": ["30 Tage ab Kaufdatum", ...]
}

results = evaluate(
    dataset,
    metrics=[faithfulness, answer_relevancy, context_precision]
)
print(results)
# faithfulness: 0.87  ← Antwortet das LLM nur mit Kontext-Infos?
# answer_relevancy: 0.79  ← Beantwortet die Antwort die Frage?
# context_precision: 0.82  ← Sind die abgerufenen Chunks relevant?

Zielwerte als Orientierung (team- und datensatzabhängig):

  • Faithfulness > 0.85
  • Answer Relevancy > 0.75
  • Context Precision > 0.80

Wichtig: Absolute Zielwerte sind weniger entscheidend als ein stabiler Eval-Workflow. Baue ein “Golden Set” von 20–50 repräsentativen Fragen mit erwarteten Antworten und führe Regression-Tests bei jeder Änderung durch. Shadow Evaluation im Monitoring (Produktionsfragen automatisch bewerten) zeigt Qualitätsprobleme früh.

Von Prototyp zu Produktion

Ein funktionierender Prototyp ist ein guter Anfang – aber Produktion stellt andere Anforderungen:

  • Caching: Gleiche Fragen nicht zweimal embedden und suchen. Redis oder ein einfaches Dictionary reichen für den Start.
  • Streaming: Antworten Wort für Wort streamen statt warten bis alles fertig ist – deutlich bessere UX.
  • Metadaten-Filter: Nutzer sollen nur Dokumente sehen dürfen, für die sie berechtigt sind. Vektordatenbanken unterstützen Metadaten-Filter beim Retrieval.
  • Monitoring: Jede Anfrage loggen – Frage, abgerufene Chunks, Antwort, Latenz. Nur so erkennst du Qualitätsprobleme früh.
  • Kosten: Bei 1000 Anfragen/Tag mit je 2000 Token Kontext und GPT-5-mini: ~$3/Tag. Mit Caching und Prompt-Optimierung oft 50–70% günstiger.

Baue einen FAQ-Bot für eine PDF-Dokumentation

Nimm eine beliebige PDF-Dokumentation (z.B. ein Produkthandbuch oder eine Firmen-Policy) und baue damit eine RAG-Pipeline, die Fragen dazu beantworten kann.

  1. PDF laden und in Text umwandeln (PyMuPDF oder pdfplumber)
  2. Text in Chunks aufteilen: 512 Token, 50 Token Overlap
  3. Embeddings generieren: OpenAI text-embedding-3-small oder lokales Modell
  4. Chunks in Chroma oder FAISS speichern
  5. Retrieval testen: Stelle 5 Fragen, prüfe ob die richtigen Chunks gefunden werden
  6. Prompt bauen: System-Prompt mit Kontext + User-Frage
  7. Antwortqualität mit RAGAS evaluieren (Faithfulness + Answer Relevancy)
RAG oder Fine-Tuning – was ist besser?

Für dokumentenbasierte Fragen ist RAG fast immer besser: günstiger, aktualisierbar, nachvollziehbar. Fine-Tuning lohnt sich wenn du den Stil, die Tonalität oder domänenspezifisches Verhalten ändern willst – nicht für Faktenwissen.

Wie groß sollen meine Chunks sein?

Faustregel: 256–512 Token mit 10–20% Overlap. Für technische Dokumentation eher kleiner (256), für narrative Texte eher größer (512–1024). Wichtiger als die Größe: semantische Kohärenz – ein Chunk sollte eine abgeschlossene Idee enthalten.

Welche Vektordatenbank soll ich nehmen?

Für Prototypen: Chroma (lokal, einfach). Für Produktion mit <1M Vektoren: Qdrant oder Weaviate. Für Enterprise mit Millionen Vektoren: Pinecone oder pgvector in PostgreSQL. Wenn du schon PostgreSQL nutzt: pgvector ist oft die einfachste Wahl.

Wie messe ich ob mein RAG gut ist?

Mit RAGAS: Faithfulness (Antwortet das LLM nur mit dem was im Kontext steht?), Answer Relevancy (Beantwortet die Antwort die Frage?), Context Precision (Sind die abgerufenen Chunks relevant?). Ziel: Faithfulness > 0.8, Answer Relevancy > 0.7.

Was tun wenn das RAG halluziniert?

Erst prüfen: Retrieval-Problem oder Generation-Problem? Wenn die richtigen Chunks gefunden werden aber die Antwort falsch ist → System-Prompt verschärfen ('Antworte nur basierend auf dem Kontext'). Wenn die falschen Chunks gefunden werden → Chunking und Embedding verbessern.

  • RAG = Retrieval + Augmentation + Generation: Erst suchen, dann anreichern, dann antworten
  • Chunking-Qualität entscheidet über RAG-Qualität – zu groß verliert Fokus, zu klein verliert Kontext
  • Hybrid Search (Vektor + BM25) schlägt reine Vektorsuche in den meisten Produktionsszenarien
  • Evaluation ist nicht optional: Ohne RAGAS-Metriken weißt du nicht ob dein RAG gut ist
  • Reranking nach dem Retrieval verdoppelt oft die Antwortqualität ohne Mehrkosten