Zurück

RAG Workshop Guide

Eigene Dokumente mit KI durchsuchen: lokaler RAG-Ansatz mit ChromaDB & Ollama

Was ist RAG?

Retrieval-Augmented Generation kombiniert ein Sprachmodell mit einer durchsuchbaren Wissensbasis. Statt sich auf das Trainingswissen des LLM zu verlassen, werden zur jeweiligen Frage passende Textabschnitte aus Ihren Dokumenten gesucht und dem Modell als Kontext mitgegeben.

Für die Patentpraxis bedeutet das: aktenbasiert antworten mit Belegen, ohne dass die Akten das Kontextfenster sprengen, und ohne dass sie das Modell neu trainieren müssen.

Wann brauchen Sie RAG?

  • Sie haben eine große Dokumentensammlung (Akten, EPA-Bescheide, Fachliteratur, interne Gutachten).
  • Sie wollen mit Quellenbezug antworten lassen („Zitat + Fundstelle").
  • Die Gesamtdokumentation passt nicht ins Kontextfenster selbst der größten Modelle.
  • Die Daten sind vertraulich und sollen das Haus nicht verlassen.
  • Sie brauchen reproduzierbare Ergebnisse, die sich an prüfbaren Belegstellen messen lassen.

Keine RAG brauchen Sie, wenn das Dokument ohnehin ins Kontextfenster passt (z.B. eine einzelne Patentschrift). Dann einfach komplett mitgeben.

Bestandteile einer RAG-Pipeline

  1. Chunking: Dokumente werden in Abschnitte von typisch 500-1500 Token zerlegt. Zu klein = fehlender Kontext, zu groß = verwaschene Treffer. Überlappung (100-200 Token) stellt sicher, dass Merkmale an Grenzen nicht verloren gehen.
  2. Embedding: Jeder Chunk wird durch ein Embedding-Modell in einen Vektor (z.B. 1024 Dimensionen) umgewandelt, der die Bedeutung numerisch kodiert. Ähnliche Inhalte landen nahe beieinander.
  3. Vector Store: Eine Datenbank (ChromaDB, Qdrant, pgvector) speichert die Vektoren mit Metadaten (Dateiname, Seitenzahl, Absatz).
  4. Retrieval: Bei einer Frage wird diese ebenfalls embeddet, und die k ähnlichsten Chunks werden herausgesucht (typisch k = 4-10).
  5. Generation: Die gefundenen Chunks werden dem LLM als Kontext vorangestellt. Das LLM antwortet mit Bezug auf diese Stellen.
  6. Citation: Metadaten werden mitgegeben, damit das Modell Fundstellen zitieren kann („siehe Absatz 23 der Patentschrift X").

Lokales Setup: ChromaDB + Ollama

Vollständig lokaler Stack: keine Daten verlassen den Rechner. Voraussetzung: Python 3.10+, 16 GB RAM, optional GPU.

1. Ollama installieren und Modelle ziehen

# Windows/Mac: Installer von ollama.com
# Linux:
curl -fsSL https://ollama.com/install.sh | sh

# Generator-Modell (antwortet auf Fragen)
ollama pull llama3.3:70b-instruct
# oder kleiner:
ollama pull llama3.2:3b-instruct

# Embedding-Modell (erzeugt Vektoren)
ollama pull nomic-embed-text

2. Python-Umgebung

python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install chromadb ollama pypdf langchain-text-splitters

3. Dokumente indexieren

import chromadb
import ollama
from pypdf import PdfReader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from pathlib import Path

client = chromadb.PersistentClient(path="./rag-db")
collection = client.get_or_create_collection("patente")

splitter = RecursiveCharacterTextSplitter(
    chunk_size=1200, chunk_overlap=150
)

for pdf_path in Path("./akten").glob("*.pdf"):
    text = "\n".join(p.extract_text() or "" for p in PdfReader(pdf_path).pages)
    chunks = splitter.split_text(text)
    for i, chunk in enumerate(chunks):
        emb = ollama.embeddings(model="nomic-embed-text", prompt=chunk)
        collection.add(
            documents=[chunk],
            embeddings=[emb["embedding"]],
            metadatas=[{"source": pdf_path.name, "chunk": i}],
            ids=[f"{pdf_path.stem}-{i}"],
        )
print("Indexierung abgeschlossen.")

4. Abfrage mit Quellenbezug

def ask(question: str, k: int = 5) -> str:
    q_emb = ollama.embeddings(model="nomic-embed-text", prompt=question)
    hits = collection.query(query_embeddings=[q_emb["embedding"]], n_results=k)

    context = "\n\n".join(
        f"[Quelle: {m['source']} · Chunk {m['chunk']}]\n{d}"
        for d, m in zip(hits["documents"][0], hits["metadatas"][0])
    )
    prompt = f"""Beantworte die Frage ausschließlich anhand des Kontexts.
Zitiere für jede Aussage die Quelle in der Form [Quelle: ...].
Wenn der Kontext keine Antwort enthält, antworte mit: "Im Material nicht enthalten."

# Kontext:
{context}

# Frage:
{question}"""
    resp = ollama.chat(
        model="llama3.3:70b-instruct",
        messages=[{"role": "user", "content": prompt}],
    )
    return resp["message"]["content"]

print(ask("Welche Merkmale offenbart D1 zu Merkmal 1.3?"))

Anwendungsbeispiel: Einspruchs-Akte durchsuchen

Scenario: Sie haben 40 Dokumente (EP-Schrift, D1-D8, Einspruchsschriftsatz, Erwiderung). Typische Fragen:

  • „Wo behauptet der Einsprechende eine Vorwegnahme von Merkmal 1.4?"
  • „Welche Passagen in D3 befassen sich mit dem Aufgabenfeld des Patents?"
  • „Hat der Patentinhaber in der Erwiderung eine Einschränkung auf einen bestimmten Wertebereich vorgenommen?"

Jede Antwort enthält die Fundstelle (Datei + Seite), so dass die manuelle Nachprüfung trivial ist.

Fortgeschrittene Techniken

Hybrid Search

Kombiniert Vektorsuche mit klassischer BM25-Keyword-Suche. Wichtig bei Fachbegriffen (Aktenzeichen, CPC-Klassen), die Embeddings nicht verlässlich unterscheiden.

Reranking

Nach dem Retrieval wird ein zweites Modell (Cross-Encoder) auf die Top-20-Treffer angewendet, das präziser bewertet. Verbessert Qualität deutlich.

Metadata-Filter

Filter nach Mandat, Jahr, Dokumenttyp direkt auf der Vektor-DB. Hält die Suche mandatsbezogen und schnell.

Structured Chunking

Statt starrer Längen an Absatzgrenzen oder PatG-Paragrafen trennen. Beugt mitten-im-Satz-Chunks vor.

Fallstricke

  • PDF-Extraktion: Gescannte PDFs liefern keinen Text. Vor dem Indexieren OCR (Tesseract, Azure Document Intelligence) laufen lassen.
  • Embedding-Bias: Allgemeine Embeddings verstehen Patentjargon nicht perfekt. Prüfen Sie, ob Fachbegriffe zusammengefunden werden.
  • Halluzination trotz Kontext: Immer „Antworte NUR anhand des Kontexts" im Prompt und explizite Quellenangabe erzwingen.
  • Chunking-Grenzen: Ein Merkmal verteilt auf zwei Chunks kann nur mit Überlappung oder größerer k-Zahl gefunden werden.
  • Aktualisierung: Neue Dokumente gezielt hinzufügen statt die ganze DB neu zu bauen.

Inhalte teilweise KI-generiert, kuratiert von Sebastian Goebel. Dies ist keine Rechtsberatung, sondern Trainingsmaterial für meine Workshops. Keine Gewährleistung für Richtigkeit oder Vollständigkeit. Keine Haftung. Software wird ohne Mängelgewähr bereitgestellt.