RAG mit Ollama: Wie Sie KI beibringen, Ihre Dokumente zu beantworten – von der Pipeline bis zur Produktion

Aktualisiert:
RAG mit Ollama: Wie Sie KI beibringen, Ihre Dokumente zu beantworten – von der Pipeline bis zur Produktion

RAG mit Ollama: Bringen Sie KI bei, Ihre Dokumente zu beantworten

Sie haben Dokumente – PDFs, Artikel, Notizen, eine Wissensdatenbank. Sie möchten Fragen stellen und Antworten speziell zu diesen Dokumenten erhalten, nicht zu allgemeinen Kenntnissen des Modells. Und das alles – lokal, ohne Daten in die Cloud zu senden.

Genau dafür gibt es RAG. In diesem Artikel – eine Erklärung des Konzepts, ein visuelles Schema der Pipeline und ein Schritt-für-Schritt-Python-Beispiel, das tatsächlich funktioniert. Und auch Muster aus der Produktion, die nicht in der Dokumentation stehen.

📚 Inhalt des Artikels

🎯 Was ist RAG – und warum ist es kein Fine-Tuning

Kurze Antwort:

RAG (Retrieval-Augmented Generation) ist eine Methode, um dem Modell Zugriff auf Ihre Dokumente zu geben, ohne das Modell selbst zu verändern. Vor jeder Anfrage findet das System relevante Fragmente aus Ihrer Datenbank und fügt sie in den Kontext ein. Das Modell antwortet basierend auf diesen Fragmenten – und nicht nur auf dem, was es während des Trainings gelernt hat.

LLMs werden auf Billionen von Tokens aus dem Internet trainiert – aber nicht auf Ihren internen Dokumenten, nicht auf Ihrer Codebasis und nicht auf den Artikeln, die Sie letzte Woche geschrieben haben. RAG schließt diese Lücke.

Analogie: Anwalt und Fall

Stellen Sie sich einen erfahrenen Anwalt vor. Er kennt Gesetze, Präzedenzfälle, allgemeine Praxis – alles, was er über Jahre gelernt hat. Aber wenn ihm ein neuer Fall gegeben wird – antwortet er nicht aus dem Gedächtnis. Er liest die Fallmaterialien, extrahiert die wichtigsten Fakten, und erst dann formuliert er eine Position, die sich auf konkrete Dokumente stützt.

Ein LLM ohne RAG ist derselbe Anwalt, der gebeten wird zu antworten, ohne Zugang zu den Fallmaterialien zu haben. Er wird etwas sagen, aber es wird eine allgemeine Meinung sein, keine Antwort auf Ihren spezifischen Fall. RAG gibt ihm diese Materialien.

Warum kein Fine-Tuning

Fine-Tuning ist das erneute Trainieren des Modells mit Ihren Daten. Klingt logisch, ist aber in der Praxis teuer, langsam und unflexibel. Wenn sich Ihre Dokumente ändern – müssen Sie erneut trainieren. Wenn Sie einen Fehler in den Daten gemacht haben – hat das Modell das Falsche "gelernt".

RAG berührt das Modell überhaupt nicht. Dokumente aktualisiert – neu indiziert in Minuten. Fehler gefunden – in der Quelle behoben. Das Modell bleibt dasselbe. Deshalb ist RAG für die meisten Aufgaben, bei denen es darum geht, "auf Dokumenten zu antworten", die richtige Wahl, nicht Fine-Tuning.

RAG vs. Fine-Tuning: Wann was wählen

Kriterium RAG Fine-Tuning
Implementierungskomplexität Niedrig – wenige Tage Hoch – Wochen
Rechenressourcen Minimal – CPU ausreichend GPU erforderlich, erhebliche Kosten
Wissensaktualisierung Neuindizierung – Minuten Neues Training – Tage
Transparenz ✔️ Sichtbar, welche Dokumente verwendet wurden ❌ Schwer zu erklären, woher die Antwort kommt
Fehler in den Daten Quelle korrigiert – fertig Neues Training von Grund auf
Geeignet für Wissensdatenbank, Dokumente, FAQs, Suche Änderung von Stil, Ton, Antwortformaten
Nicht geeignet für Änderung des Verhaltens des Modells selbst Häufig aktualisierte Dokumente

Wann RAG das Problem nicht löst

RAG ist keine Silberkugel. Es gibt mehrere Szenarien, in denen es nicht hilft:

  • ⚠️ Kurze Anfragen (1-2 Wörter) – semantische Suche bei kurzen Anfragen ist weniger präzise als Stichwortsuche. Ein Fallback ist erforderlich.
  • ⚠️ Frage geht über die Dokumente hinaus – wenn die Antwort nicht in der Datenbank vorhanden ist, sagt das Modell entweder "Ich weiß es nicht" oder beginnt zu halluzinieren. Der Prompt muss letzteres explizit verbieten.
  • ⚠️ Stil oder Verhalten des Modells ändern – hier hilft RAG nicht, das ist eine Aufgabe für Fine-Tuning oder detaillierte System-Prompts.

Fazit des Abschnitts: RAG ist die richtige Wahl, wenn es darum geht, auf spezifische Dokumente zu antworten, und diese Dokumente sich ändern oder aktualisiert werden. Fine-Tuning ist erforderlich, wenn das Verhalten des Modells selbst geändert werden soll, nicht um sein Wissen zu erweitern.

🎯 Wie die Pipeline funktioniert: vom Dokument zur Antwort

Kurze Antwort:

Die RAG-Pipeline ist in zwei unabhängige Phasen unterteilt. Indizierung – wird einmal oder bei Aktualisierung von Dokumenten durchgeführt: Dokument → Chunks → Embeddings → Vector Store. Suche und Generierung – bei jeder Benutzeranfrage: Frage → Embedding → Similarity Search → Prompt mit Kontext → Antwort. Wenn man versteht, wo was passiert – wird die Fehlersuche um ein Vielfaches einfacher.

Eines der ersten Dinge, die ich in der Praxis verstanden habe: Das Modell "liest" nie das gesamte Dokument. Es sieht nur einige Fragmente, die das System für am relevantesten hält. Die Qualität der Antwort hängt direkt von der Qualität dieser Auswahl ab.

Phase 1 – Indizierung

Die Indizierung erfolgt einmal – oder nach Zeitplan bei Aktualisierung des Inhalts. Ziel: menschlichen Text in eine Form umwandeln, die der Vector Store durchsuchen kann.

Schritt 1. Dokument lesen

Eingabeformate: PDF, HTML, Markdown, Plain Text, Webseiten. Auf diesem Schritt ist es wichtig, reinen Text ohne Markup zu erhalten. HTML-Tags, PDF-Metadaten, Steuerzeichen – all das ist Rauschen, das die Qualität der Embeddings verschlechtert. Jsoup für Java, BeautifulSoup für Python – standardmäßige Bereinigungswerkzeuge.

Schritt 2. Chunking – Aufteilung in Fragmente

Das Dokument wird in kleinere Teile – Chunks – zerlegt. Warum nicht das ganze Dokument speichern? Zwei Gründe. Erstens haben Embedding-Modelle ein Token-Limit: nomic-embed-text – 8192 Tokens, all-minilm – 256. Ein Artikel mit 5000 Wörtern passt einfach nicht hinein. Zweitens ist die Suche bei kleineren Fragmenten präziser: Wenn der gesamte Artikel als ein Vektor gespeichert wird – mittelt der Vektor alle Themen des Artikels und wird weniger spezifisch.

Standard: 512 Tokens mit einem Overlap von 50 Tokens. Overlap – ist eine absichtliche Überlappung zwischen benachbarten Chunks, damit der Gedanke an der Grenze des Fragments nicht abbricht.

Schritt 3. Embeddings

Jeder Chunk wird in einen numerischen Vektor umgewandelt – eine Liste von 768 Zahlen (für nomic-embed-text). Dieser Vektor kodiert die *Bedeutung* des Textes, nicht spezifische Wörter. Deshalb werden "schlüsselfertige Webentwicklung" und "wie man eine Website erstellt" ähnliche Vektoren haben, auch ohne gemeinsame Wörter. Genau darin liegt der Vorteil der semantischen Suche gegenüber der LIKE-Suche.

Schritt 4. Vector Store

Vektoren und der ursprüngliche Text der Chunks werden in einer Vektordatenbank gespeichert: pgvector (Erweiterung für PostgreSQL), Chroma, FAISS, Milvus oder eine andere. Wenn im Projekt bereits PostgreSQL vorhanden ist – ist pgvector die natürliche Wahl: eine Instanz der Datenbank, nichts Neues zu installieren.

Phase 2 – Suche und Generierung

Diese Phase wird bei jeder Anfrage gestartet und dauert Sekunden. Der Benutzer gibt eine Frage ein – und nach einigen Schritten erhält er eine Antwort.

Schritt 5. Embedding der Anfrage

Die Frage des Benutzers wird ebenfalls in einen Vektor umgewandelt – mit demselben Embedding-Modell, das bei der Indizierung verwendet wurde. Das ist entscheidend: Wenn Sie mit nomic-embed-text indiziert haben, muss die Anfrage ebenfalls über nomic-embed-text erfolgen. Unterschiedliche Modelle liefern inkompatible Vektoren – und die Suche wird irrelevant sein.

Schritt 6. Similarity Search

Der Vector Store findet die N nächstgelegenen Vektoren zum Anfragevektor. "Nächstgelegen" – ist die Kosinus-Ähnlichkeit oder das Skalarprodukt zwischen den Vektoren. Ergebnis: die Top-5 (oder wie viele Sie angeben) relevantesten Chunks. Ein Ähnlichkeitsschwellenwert filtert Ergebnisse unterhalb des Ähnlichkeitswerts – normalerweise beginnt man mit 0,5 und korrigiert anhand von Logs.

Schritt 7. Prompt-Erstellung

Die gefundenen Chunks werden als Kontext in den System-Prompt eingefügt. Die Qualität dieses Prompts beeinflusst direkt die Qualität der Antwort. Das Minimum, das im System-Prompt enthalten sein sollte:

Antworte NUR basierend auf dem bereitgestellten Kontext.
Wenn die Antwort nicht im Kontext enthalten ist – sage es ehrlich.
Erfinde keine Informationen, die nicht in den Dokumenten vorhanden sind.

Kontext:
{gefundene Chunks}

Ohne ein explizites Verbot des Erfindens – wird das Modell halluzinieren. Das ist kein Fehler eines bestimmten Modells, das ist das allgemeine Verhalten von LLMs.

Schritt 8. Antwortgenerierung

Das LLM (Ollama mit llama3.3, Mistral oder einem anderen Modell) generiert eine Antwort basierend auf dem Kontext aus dem vorherigen Schritt. Wichtiges Detail: Zeigen Sie dem Benutzer die Quellen – welche spezifischen Artikel oder Dokumente das System verwendet hat. Das ist Transparenz und eine Möglichkeit, zu überprüfen, woher das Modell die Informationen hat.

Fazit des Abschnitts: Zwei unabhängige Prozesse – Indizierung und Suche+Generierung. Die meisten RAG-Probleme treten entweder beim Chunking (falsche Größe) oder bei der Similarity Search (falscher Schwellenwert) oder im System-Prompt (kein Verbot von Halluzinationen) auf. Wir werden jeden im Folgenden detailliert betrachten.

🎯 Tools: LlamaIndex vs. LangChain vs. manueller Ansatz

Kurze Antwort:

Im Jahr 2026 geht die Wahl zwischen LlamaIndex und LangChain nicht um "besser", sondern darum, was Sie bauen. LlamaIndex ist auf die Arbeit mit Dokumenten spezialisiert und liefert bessere Suchergebnisse mit weniger Code. LangChain ist für komplexe Agentensysteme, bei denen RAG eine von mehreren Komponenten ist. Ein manueller Ansatz über Spring AI oder direkte REST-API – wenn Sie mit Python nicht zufrieden sind oder maximale Kontrolle über jeden Schritt wünschen.

Eine detaillierte Analyse von 2026 stellt fest: Der Vergleich "LangChain = Orchestrierung, LlamaIndex = Daten", der von den meisten Artikeln wiederholt wird – ist bereits veraltet. Beide Frameworks nähern sich an und decken ähnliche Funktionalitäten ab. Die Wahl hängt nun davon ab, wo Sie beginnen und was die Grundlage Ihrer Anwendung ist.

LlamaIndex – wenn Dokumente und Suche im Mittelpunkt stehen

LlamaIndex wurde um die Idee aufgebaut, dass das Hauptproblem darin besteht, LLMs zuverlässig mit Ihren Daten zu verbinden. Alles andere – Agenten, Pipelines, Orchestrierung – baut auf diesem Fundament auf.

Unabhängige Benchmarks zeigen: LlamaIndex ist 40% schneller als LangChain bei Document Retrieval Tasks und hat 2025 eine Genauigkeitssteigerung der Suche um +35% erhalten. Grund: Eingebaute Abstraktionen für Chunking, Re-Ranking und Context Assembly sind auf Retrieval abgestimmt – nicht auf allgemeine Pipelines.

Vorteile:

  • ✔️ Einfachster Start: 10 Zeilen für funktionierendes RAG
  • ✔️ Integriertes Re-Ranking, Hybrid-Suche (semantisch + Stichwort)
  • ✔️ Breite Liste von Datenkonnektoren über LlamaHub: PDF, HTML, Notion, Google Docs, S3, Datenbanken
  • ✔️ Flexibles Chunking: SentenceSplitter, TokenTextSplitter, SemanticSplitter – ändern Sie es mit einer Zeile
  • ✔️ Native Integration mit Ollama über separate Pakete

Nachteile:

  • ⚠️ Für komplexe Agentensysteme mit vielen externen Tools – weniger praktisch als LangChain
  • ⚠️ Dokumentation weniger vollständig als bei LangChain für untypische Szenarien

Wann wählen: Sie haben Dokumente, PDFs, eine Wissensdatenbank – Sie müssen Fragen stellen und Antworten erhalten. Blog, FAQ, interne Dokumentation des Unternehmens, technische Referenz.

LangChain – wenn RAG Teil eines komplexeren Systems ist

LangChain wurde um die Idee aufgebaut, dass der Aufbau mit LLMs ein Workflow-Problem ist: es gibt Eingabedaten, es gibt Ausgabedaten, dazwischen – Modelle, Tools, Speicher und externe Quellen, die kombiniert werden müssen. Im Jahr 2026 bedeutet dies LangGraph – ein gerichteter Graph, bei dem Knoten Funktionen sind und Kanten Übergänge zwischen Zuständen darstellen. RAG in LangChain – ist eines der Tools eines Agenten, nicht die zentrale Abstraktion.

Vorteile:

  • ✔️ Größtes Ökosystem und Community – 220% Wachstum der GitHub-Sterne im Jahr 2024
  • ✔️ LangGraph für komplexe zustandsbehaftete Agenten mit Verzweigungen und Schleifen
  • ✔️ LangSmith – Observability, Tracing, Evaluation out-of-the-box
  • ✔️ Multimodale Unterstützung ist stärker als bei LlamaIndex
  • ✔️ Besser für Konversationsgedächtnis bei langen Gesprächen

Nachteile:

  • ⚠️ Steilere Lernkurve – mehr Konzepte für einfaches RAG
  • ⚠️ Für reines Document Retrieval – mehr Code als bei LlamaIndex
  • ⚠️ Häufige Breaking Changes: das ursprüngliche LangChain wurde durch LangGraph für Produktionsszenarien ersetzt

Wann wählen: KI-Agent, der externe APIs aufruft, Code schreibt, SQL-Abfragen ausführt – und dabei auch Dokumente durchsucht. RAG ist hier nicht die Hauptaufgabe, sondern eines der Werkzeuge des Agenten.

Manueller Ansatz – maximale Kontrolle ohne Framework

Ollama REST API direkt + jede beliebige Vector DB + eigene Logik. Genau dieser Ansatz liegt Spring AI für Java zugrunde, wo das Framework fertige Abstraktionen bereitstellt, Sie aber jedes Detail der Pipeline kontrollieren.

Vorteile:

  • ✔️ Volle Kontrolle über jeden Schritt – Chunking, Scoring, Fallback-Logik
  • ✔️ Keine Abhängigkeit von Python – jede Sprache über REST API
  • ✔️ Keine Breaking Changes von externen Frameworks
  • ✔️ Benutzerdefinierte Logik, die von Frameworks nicht unterstützt wird, kann implementiert werden

Nachteile:

  • ⚠️ Mehr Code – Chunking, Batch-Indizierung, Fallback schreiben Sie selbst
  • ⚠️ Kein integriertes Re-Ranking und keine Hybrid-Suche
  • ⚠️ Mehr Zeit für die Implementierung als mit LlamaIndex

Wann wählen: Java / Spring Boot Projekt (Spring AI), ungewöhnliche Anforderungen an die Pipeline oder wenn das Framework mehr Komplexität hinzufügt als Probleme löst.

Auswahlmatrix

Aufgabe Empfehlung
Antworten auf PDFs und Dokumenten – einfacher Start LlamaIndex
Semantische Suche in einem Blog oder einer Wissensdatenbank LlamaIndex
Interne Unternehmensdokumentation, FAQs LlamaIndex
KI-Agent, der APIs und Tools aufruft LangChain / LangGraph
Komplexer Multi-Step-Workflow mit Gedächtnis LangChain / LangGraph
Java / Spring Boot Projekt Spring AI (manueller Ansatz)
Benutzerdefinierte Fallback- und Deduplizierungslogik Manueller Ansatz
Schneller Prototyp in jeder Sprache Direkte Ollama REST API

Kann man kombinieren

Ja – und das ist eine gängige Praxis in der Produktion. Contabo beschreibt einen typischen Stack von 2026: LlamaIndex als Knowledge Layer (Indizierung und Suche), LangChain als Orchestration Layer (Agenten und Workflows) und n8n oder ein eigener Service als Workflow Engine. Aber für die meisten Projekte ist ein Framework besser als zwei – weniger Abhängigkeiten, einfachere Wartung.

Fazit des Abschnitts: Wenn die Aufgabe lautet "auf Dokumenten antworten", beginnen Sie mit LlamaIndex. Wenn Sie einen komplexen KI-Agenten bauen, bei dem RAG eines der Werkzeuge ist – LangChain. Wenn Sie Java verwenden oder volle Kontrolle benötigen – Spring AI oder direkte REST-API zu Ollama.

RAG mit Ollama: Wie Sie KI beibringen, Ihre Dokumente zu beantworten – von der Pipeline bis zur Produktion

🎯 Auswahl des Modells für Embeddings: nomic-embed-text und Alternativen

Kurze Antwort:

nomic-embed-text ist die Standardwahl für Ollama: leicht (274 MB), schnell, Vektor mit 768 Dimensionen. Aber es gibt eine wichtige Einschränkung: es funktioniert schlecht mit kurzen Abfragen und nicht-lateinischen Sprachen. Für ukrainischen Text und kurze Abfragen ist ein Fallback oder ein anderes Modell erforderlich.

Ein Embedding-Modell ist das Fundament von RAG. Ein schlechtes Embedding-Modell macht die gesamte Pipeline nutzlos, unabhängig von der Qualität des LLM. Das habe ich nicht aus der Dokumentation gelernt – sondern als die Abfrage „LLM“ einen irrelevanten Artikel mit einem Score von 0,63 zurückgab und der richtige Artikel nicht einmal in die Top 5 gelangte.

Was sind Embeddings – eine Analogie zur Fotografie

Stellen Sie sich vor, Sie speichern Fotos in verschiedenen Formaten. Ein kleines Foto mit 100 × 100 Pixeln – nimmt wenig Platz ein, aber die Details sind verschwommen, ähnliche Gesichter sind schwer zu unterscheiden. Ein Foto mit 4000 × 3000 – nimmt viel mehr Platz ein, aber jedes Detail ist klar und einzigartig.

Bei Embeddings gilt die gleiche Logik. Ein Vektor ist ein „Foto“ von Text im numerischen Raum. Die Vektordimension (384, 768, 1024) ist wie die Auflösung. Ein größerer Vektor kodiert mehr Details und Nuancen der Bedeutung – und die Suche ist genauer. Aber ein größerer Vektor nimmt mehr Platz in der Datenbank ein und wird langsamer generiert.

all-minilm mit einem 384er Vektor ist ein JPEG 100 × 100: leicht und schnell, verliert aber Details. nomic-embed-text mit einem 768er Vektor ist ein JPEG 1920 × 1080: ein guter Kompromiss. mxbai-embed-large mit einem 1024er Vektor ist ein RAW-Format: maximale Detailgenauigkeit, kostet aber doppelt so viel RAM.

Und noch ein wichtiges Detail zur Foto-Analogie: Wenn Sie alle Fotos in einem Format gespeichert haben, können Sie sie nicht mit Fotos in einem anderen Format vergleichen. Genauso ist es mit Embeddings: Mit welchem Modell Sie indiziert haben – mit demselben Modell müssen Sie die Abfrage einbetten. Wenn Sie das Modell wechseln, müssen Sie die gesamte Datenbank neu indizieren.

Vergleich von Embedding-Modellen für Ollama

Modell Größe Vektor Kontext Wann geeignet Befehl
nomic-embed-text 274 MB 768 8192 Token Standardwahl, lange Dokumente ollama pull nomic-embed-text
mxbai-embed-large 669 MB 1024 512 Token Hohe Suchgenauigkeit, kurze Chunks ollama pull mxbai-embed-large
all-minilm 46 MB 384 256 Token Schwache Hardware, Geschwindigkeit wichtiger als Genauigkeit ollama pull all-minilm

Reale Einschränkungen von nomic-embed-text

Aus praktischer Erfahrung bei der Indizierung von über 500 Artikeln in vier Sprachen – nomic-embed-text hat spezifische Schwächen, die in der offiziellen Dokumentation nicht aufgeführt sind:

  • ⚠️ Kurze Abfragen (1-2 Wörter) – die Abfrage „LLM“ gab einen Score von 0,63 für einen irrelevanten Artikel zurück, und der richtige Artikel kam nicht einmal in die Top 5. Der Vektorraum des Modells kann kurze einwortige Abfragen nicht gut unterscheiden.
  • ⚠️ Nicht-lateinische Sprachen – Ukrainisch und Kyrillisch im Allgemeinen liefern eine geringere Qualität im Vergleich zu englischem Text. Die Abfrage „LLM vs RAG in 2026“ findet das Richtige (Score 0,69), aber eine kurze ukrainischsprachige Abfrage ist bereits ein Problem.
  • ⚠️ Gemischter Inhalt – wenn Dokumente in mehreren Sprachen gleichzeitig vorliegen, sinkt die Suchqualität: die Embeddings von englischem und ukrainischem Text leben in verschiedenen „Zonen“ des Vektorraums.

Praktisches Fazit: Wann nomic-embed-text ausreicht

nomic-embed-text ist gut geeignet, wenn:

  • ✔️ Dokumente hauptsächlich auf Englisch
  • ✔️ Abfragen mit 3+ Wörtern (semantische Suche)
  • ✔️ Großer Kontext benötigt wird – 8192 Token reichen für lange Artikel

Benötigt Fallback oder Ersatz, wenn:

  • ⚠️ Dokumente hauptsächlich in nicht-lateinischen Sprachen
  • ⚠️ Kurze Suchanfragen (1-2 Wörter) – fügen Sie Keyword-Fallback hinzu
  • ⚠️ Maximale Genauigkeit erforderlich ist – erwägen Sie mxbai-embed-large

Fazit des Abschnitts: Die Wahl des Embedding-Modells ist ein Kompromiss zwischen Genauigkeit, Größe und Geschwindigkeit – wie die Wahl des Fotoformats und der Auflösung. nomic-embed-text ist ein guter Start. Aber kennen Sie seine Grenzen und testen Sie immer mit echten Abfragen Ihrer Zielgruppe, bevor Sie davon ausgehen, dass die Suche „funktioniert“.

🎯 Wichtige Entscheidungen bei der Implementierung von RAG – und was zu vermeiden ist

Kurze Antwort:

Universeller funktionierender Code für RAG existiert nicht – jedes Projekt hat seine eigene Architektur, seine eigene Sprache, sein eigenes Speichermodell und seine eigenen Suchanforderungen. Aber es gibt einige Entscheidungen, die in jedem RAG-Projekt getroffen werden müssen – und typische Fallstricke bei jedem davon.

Tutorials zeigen, wie man RAG in 10 Minuten startet. Die Produktion zeigt, dass Sie die meiste dieser Zeit damit verbringen werden, Probleme zu lösen, die im Tutorial nicht vorhanden sind.

Entscheidung 1 – Wie Dokumente gelesen und bereinigt werden

Unabhängig von Sprache und Framework – am Eingang gibt es „rohen“ Text. PDF enthält Kopf- und Fußzeilen, Seitenzahlen, Formatierungsartefakte. HTML enthält Tags, Attribute, JavaScript, Werbeblöcke. All dieser Lärm gelangt in die Embeddings und reduziert die Suchqualität.

Was im Voraus entschieden werden muss:

  • ✔️ Welches Format ist das primäre und wie wird es bereinigt
  • ✔️ Muss die Struktur (Überschriften, Abschnitte) beibehalten werden oder reicht einfacher Text aus
  • ✔️ Was tun mit leeren oder sehr kurzen Dokumenten

Typischer Fallstrick: Die Bereinigung am Anfang ignorieren – und Embeddings erhalten, bei denen 30 % des Inhalts „Copyright 2024“ und „Seite 1 von 15“ sind.

Entscheidung 2 – Chunk-Größe und Aufteilungsstrategie

Es gibt keine richtige Chunk-Größe für alle Fälle. 512 Token sind Standard für Artikel. 256 für technische Dokumentation, wo jeder Absatz unabhängig ist. 1024, wenn es wichtig ist, den Kontext zwischen den Absätzen zu erhalten.

Was entschieden werden muss:

  • ✔️ Nach Token oder nach Sätzen aufteilen – unterschiedliche Ergebnisse an den Chunk-Grenzen
  • ✔️ Welcher Überlappungsgrad benötigt wird – 0, wenn Chunks unabhängig sind, 50-100 Token, wenn Gedanken zwischen den Absätzen übergehen
  • ✔️ Müssen Metadaten in jedem Chunk gespeichert werden – Titel, URL, Kategorie, Locale – zur späteren Filterung

Typischer Fallstrick: Die Chunk-Größe einmal festlegen und nie wieder überprüfen. Überprüfen Sie die tatsächlichen Chunks nach der Aufteilung – und Sie werden sehen, wo die Gedanken abbrechen.

Entscheidung 3 – Chunk-Identifikatoren

Es scheint eine Kleinigkeit zu sein – wird aber bei der Neuindizierung kritisch. Wenn bei jeder Indizierung zufällige UUIDs verwendet werden – sammelt sich die Datenbank mit Duplikaten. Nach einem Monat kann ein Dokument durch 10 Versionen derselben Chunks repräsentiert werden.

Die richtige Entscheidung ist eine deterministische ID basierend auf der document_id und der fortlaufenden Nummer des Chunks. Bei der Neuindizierung erhält derselbe Chunk dieselbe ID und wird überschrieben, anstatt dupliziert zu werden. Wie das implementiert wird – in Java über UUID.nameUUIDFromBytes(), in Python über hashlib.md5(). Die konkrete Implementierung hängt vom Stack ab – das Prinzip ist dasselbe.

Entscheidung 4 – Strategie zur Aktualisierung des Index

Wie wird bestimmt, was neu indiziert werden muss? Zwei Ansätze:

  • ✔️ Zeitstempelbasiert: Speichern Sie indexed_at und neu indizieren, wo updated_at > indexed_at. Einfach und zuverlässig – aber es gibt einen Haken: wenn @PreUpdate oder ein Trigger updated_at bei saveAll() aktualisiert und indexed_at sofort nach dem Speichern veraltet ist. Lösung: Setzen Sie indexed_at auf eine kurze Zukunft – now() + 10 Sekunden.
  • ✔️ Hash-basiert: Speichern Sie einen Hash des Inhalts und neu indizieren nur, wenn sich der Hash geändert hat. Genauer, aber schwieriger zu implementieren.

Entscheidung 5 – Batch-Indizierung

Der Versuch, 500 Dokumente in einer Anfrage zu indizieren, endet entweder mit einem Timeout von Ollama oder mit einem OOM. Batch von 10-20 Dokumenten – und bei einem Absturz machen Sie dort weiter, wo Sie aufgehört haben, und nicht von vorne. Deshalb ist indexed_at wichtiger, als es scheint – es ermöglicht dem Scheduler, dort anzuknüpfen, wo er abgestürzt ist.

Entscheidung 6 – LAZY-Loading und Transaktionen

Wenn Sie ein ORM (JPA, SQLAlchemy, ActiveRecord) verwenden – seien Sie vorsichtig mit lazy-geladenen Beziehungen während der Indizierung. Der Zugriff auf post.getTranslations() außerhalb einer Transaktion führt zu einer LazyInitializationException in JPA oder einem DetachedInstanceError in SQLAlchemy. Lösung: JOIN FETCH in der Abfrage oder explizites Laden von allem Notwendigen innerhalb der Transaktion.

Was zu vermeiden ist – kurz

  • ❌ Beginnen Sie nicht mit einem „funktionierenden Beispiel aus einem Tutorial“ direkt in der Produktion – es gibt kein Fallback, keine Batches, keine Idempotenz.
  • ❌ Ignorieren Sie die Textbereinigung vor der Indizierung nicht.
  • ❌ Verwenden Sie keine zufälligen UUIDs für Chunks, wenn Sie eine Neuindizierung planen.
  • ❌ Legen Sie den Schwellenwert nicht für immer fest – protokollieren Sie den Score und passen Sie ihn bei echten Abfragen an.
  • ❌ Glauben Sie nicht, dass Vektorsuche Keyword-Suche vollständig ersetzen wird – für kurze Abfragen ist ein Fallback erforderlich.
  • ❌ Vergessen Sie nicht, dass die Änderung des Embedding-Modells eine vollständige Neuindizierung erfordert.

Fazit des Abschnitts: RAG ist kein „Kopieren und Ausführen“. Es sind sechs architektonische Entscheidungen, von denen jede ihre Fallstricke hat. Treffen Sie diese bewusst vor Beginn der Implementierung – und Sie sparen von mehreren Stunden bis zu mehreren Tagen Debugging.

🎯 Produktionsmuster: Was in Tutorials nicht steht

Kurze Antwort:

Der Unterschied zwischen „Hello World“ RAG und Produktions-RAG sind vier Muster: Fallback auf Keyword-Suche, idempotente Indizierung, Deduplizierung von Ergebnissen und Batch-Verarbeitung. Keines davon wird in grundlegenden Tutorials erwähnt. Jedes davon entdecken Sie durch ein reales Problem.

Ich habe alle vier Muster nicht durch Dokumentation entdeckt – sondern durch konkrete Vorfälle in der Produktion. Fallback – als die Abfrage „Spring“ irrelevante Ergebnisse lieferte. Idempotenz – als nach einem Monat Arbeit des Schedulers ein Artikel 47 Mal in der Datenbank war. Deduplizierung – als die Top-5-Ergebnisse 4 Chunks aus demselben Artikel enthielten. Batch – als Ollama bei 500 Dokumenten hängen blieb.

Muster 1 – Fallback: Vektor → Keyword

Vektorsuche basiert auf semantischer Ähnlichkeit. Sie findet gut „schlüsselfertige Webentwicklung“ für die Abfrage „wie man eine Website erstellt“. Aber bei der Abfrage „Spring“ oder „RAG“ – verschwimmt die Ähnlichkeit im gesamten Vektorraum und die Genauigkeit sinkt.

Eine Regel, die in der Praxis funktioniert: Abfragen mit 1-2 Wörtern an die Keyword-Suche leiten, 3+ Wörter – an die Vektorsuche. Wenn die Vektorsuche ein leeres Ergebnis liefert – Fallback auf Keyword. Wenn die Vektorsuche mit einem Fehler abstürzt – Fallback auf Keyword. Der Benutzer bemerkt den Unterschied nicht, erhält aber immer eine Antwort.

Die Implementierung hängt vom Stack ab – aber das Prinzip ist unveränderlich: zwei Anbieter, eine Fassade, die entscheidet, welche verwendet werden soll, und ein automatischer Übergang zwischen ihnen.

Muster 2 – Idempotente Indizierung

Der Scheduler startet die Indizierung jede Nacht. Wenn bei jedem Start zufällige UUIDs für Chunks generiert werden – nach einem Monat wird derselbe Artikel durch 30 Versionen derselben Chunks repräsentiert. Die Suche liefert Duplikate, die Qualität sinkt, die Datenbank wächst grundlos.

Lösung: eine deterministische ID basierend auf der Dokumenten-ID und der fortlaufenden Nummer des Chunks. Bei der Neuindizierung erhält derselbe Chunk dieselbe ID und wird überschrieben – anstatt als neuer Eintrag hinzugefügt zu werden. Die konkrete Implementierung hängt von der Sprache ab – in Java ist es UUID.nameUUIDFromBytes(), in Python – hashlib.md5() über uuid.UUID(bytes=...). Das Prinzip ist dasselbe.

Muster 3 – Deduplizierung von Ergebnissen

Vektorsuche liefert Top-N Chunks – nicht Top-N Dokumente. Wenn ein Artikel gut zur Abfrage passt – kann er 4 von 5 Chunks in den Top 5 liefern. Der Benutzer erhält vier Links zur selben Seite.

Lösung: Nach Erhalt der Ergebnisse – Deduplizierung nach document_id. Für jedes Dokument behalten Sie nur den Chunk mit dem höchsten Score. Ergebnis: Die Top 5 enthalten immer 5 verschiedene Dokumente, nicht 5 Fragmente desselben.

Wichtig: Die Metadaten jedes Chunks müssen die document_id enthalten – ohne diese ist eine Deduplizierung nicht möglich. Denken Sie über die Metadatenstruktur nach, bevor Sie mit der Indizierung beginnen.

Muster 4 – Batch-Indizierung mit Wiederherstellung

Ollama verarbeitet Embeddings sequenziell über CPU oder GPU. Eine Anfrage für 500 Dokumente gleichzeitig – das ist entweder ein Timeout, oder ein OOM, oder einfach ein Hängenbleiben ohne Fehler.

Lösung: Batch von 10-20 Dokumenten. Aber wichtiger ist etwas anderes – nach jedem Batch sofort indexed_at für die verarbeiteten Dokumente speichern. Wenn der Prozess bei Batch 7 von 50 abstürzt – beim nächsten Start greift der Scheduler bei Batch 8 an, und beginnt nicht von vorne. Das ist der Unterschied zwischen „gestartet und hoffen“ und zuverlässiger Indizierung.

Fazit des Abschnitts: Vier Muster – Fallback, Idempotenz, Deduplizierung und Batch mit Wiederherstellung – das ist der Unterschied zwischen einem Prototyp, der auf einer Demo funktioniert, und einem System, das monatelang in der Produktion läuft. Die Implementierung ist in jedem Stack anders – die Prinzipien sind für alle gleich.

🎯 Typische Probleme: Chunking, Threshold, Halluzinationen

Drei Klassen von Problemen in RAG – und alle drei treten nur bei echten Anfragen auf, nicht bei synthetischen Tests. Falsches Chunking: Das Modell erhält Fragmente ohne Kontext. Falscher Threshold: entweder zu viel Rauschen oder nichts gefunden. Halluzinationen: Das Modell erfindet auch bei vorhandenem Kontext – aufgrund eines schwachen Prompts oder irrelevanter Chunks, die es dennoch in die Top-Ergebnisse geschafft haben.

Das Wichtigste, was ich verstanden habe: Die meisten RAG-Probleme sind ohne Score-Logging unsichtbar. Wenn du nicht siehst, welchen Ähnlichkeitswert jedes Ergebnis zurückgibt – kannst du nicht diagnostizieren, warum die Suche schlechte Antworten liefert. Füge sofort Score-Logging hinzu – und spare Stunden beim Debugging.

Problem 1 – Chunking: Wie man erkennt, dass etwas schief läuft

Symptom: Das Modell liefert Antworten, die teilweise richtig erscheinen – es gibt eine Verbindung zur Frage, aber die Details sind falsch oder abgeschnitten. Ursache: Die Chunks sind an ungünstigen Stellen geteilt, und der Gedanke bricht am Rand des Fragments ab.

Diagnose: Gib nach dem Aufteilen einige echte Chunks aus und lies sie. Wenn ein Chunk mitten im Satz beginnt oder endet – ist die Größe oder die Aufteilungsstrategie falsch.

  • ✔️ Kurze Dokumente, Blogartikel – 512 Token, Overlap 50
  • ✔️ Technische Dokumentation mit langen Abschnitten – 1024 Token, Overlap 100
  • ✔️ Code – 256-512 Token, nach Funktionen aufteilen, nicht nach Zeilen
  • ✔️ Overlap – spare nicht: 50-100 Token Überlappung garantieren, dass der Gedanke am Chunk-Rand nicht verloren geht

Problem 2 – Ähnlichkeitsschwelle (Similarity Threshold): Wie man den richtigen Wert findet

Symptom A: Das Modell antwortet selbstbewusst, aber falsch – der Threshold ist zu niedrig, irrelevante Chunks gelangen in den Kontext. Symptom B: Das Modell sagt ständig „nicht gefunden“, selbst bei offensichtlichen Fragen – der Threshold ist zu hoch, nichts besteht den Filter.

Diagnose: Logge den Score jedes Ergebnisses – und schaue dir die Verteilung an. Wenn richtige Ergebnisse einen Score von 0,55-0,65 haben – schneidet ein Threshold von 0,7 sie alle ab. Wenn irrelevante Ergebnisse einen Score von 0,55 haben – lässt ein Threshold von 0,5 Rauschen durch.

  • ✔️ Startpunkt: 0,5 – und nach den Logs echter Anfragen anpassen
  • ✔️ Kurze Anfragen (1-2 Wörter) – auf 0,4 reduzieren oder besser einen Fallback verwenden
  • ✔️ Lange semantische Anfragen – 0,65-0,7 liefert ein saubereres Ergebnis
  • ✔️ Wenn alle Ergebnisse unter dem Schwellenwert liegen – gib „nicht gefunden“ zurück anstatt eines leeren Kontexts

Problem 3 – Halluzinationen auch mit Kontext

Symptom: Das Modell liefert eine selbstbewusste Antwort, die keiner der bereitgestellten Chunks entspricht – oder kombiniert Fakten aus verschiedenen Quellen falsch. Die Ursache liegt meist nicht im Modell – sondern im Prompt oder darin, dass irrelevanter Kontext es dennoch in die Top-Ergebnisse geschafft hat.

Drei Schutzebenen:

  • ✔️ Strenger System-Prompt – explizites Verbot des Erfindens: „Antworte NUR auf Basis des bereitgestellten Kontexts. Wenn keine Antwort vorhanden ist – sage es ehrlich. Kombiniere keine Informationen aus verschiedenen Quellen, wenn sie sich widersprechen.“
  • ✔️ Score-basierter Filter – wenn der maximale Score unter den Ergebnissen unter 0,5 liegt, übergib den Kontext überhaupt nicht an die LLM. Gib „nicht gefunden“ zurück – eine ehrliche Antwort ist besser als eine selbstbewusste Halluzination.
  • ✔️ Quellen anzeigen – eine Liste von Artikeln oder Dokumenten, aus denen die Antwort stammt. Der Benutzer kann selbst überprüfen und melden, wenn etwas nicht stimmt.

Fazit des Abschnitts: Alle drei Probleme werden gleich diagnostiziert – durch Score-Logging und das Lesen echter Chunks, die in den Kontext gelangen. Füge dies vom ersten Tag an hinzu – und die meisten Fragen „warum liefert RAG schlechte Antworten“ werden eine offensichtliche Antwort erhalten.

❓ Häufig gestellte Fragen (FAQ)

Wird eine GPU für RAG mit Ollama benötigt?

Nein. Eine GPU beschleunigt die Antwortgenerierung und Embeddings, ist aber nicht zwingend erforderlich. Auf einer CPU werden Embeddings über nomic-embed-text langsamer generiert, sind aber für den Produktionseinsatz mit moderater Last durchaus machbar. Auf Apple Silicon (M1/M2/M3) – schnell, auch ohne dedizierte GPU. Mehr Details darüber, welche Modelle auf eingeschränkter Hardware wirklich laufen – Ollama auf 8 GB RAM: Welche Modelle funktionieren im Jahr 2026.

Wie viele Dokumente können indiziert werden?

Es gibt keine Beschränkungen – es hängt von der Größe des Vector Stores und des RAMs ab. pgvector kommt problemlos mit Millionen von Vektoren zurecht. In der Praxis für einen Blog mit 500 Artikeln – das sind ca. 2500 Chunks à 512 Token, nimmt wenige MB in PostgreSQL ein. Die Generierung von Embeddings über Ollama bei diesem Umfang dauert 15-30 Minuten auf einer CPU – akzeptabel für einen nächtlichen Scheduler.

RAG oder normale Volltextsuche?

Nicht „oder“, sondern „und“. RAG ist besser für semantische Anfragen mit 3+ Wörtern, bei denen der Inhalt wichtig ist – „wie optimiere ich Abfragen in PostgreSQL“ findet einen Artikel über Indizes, auch ohne exakte Wortübereinstimmung. Die Volltextsuche ist besser für kurze Anfragen (1-2 Wörter), Namen und exakte Übereinstimmungen. Die optimale Strategie ist – Vektorsuche mit automatischem Fallback auf FTS.

Wie aktualisiert man den Index bei Änderungen an Dokumenten?

Speichere indexed_at für jedes Dokument und starte die Neuindizierung, wo updated_at > indexed_at. Eine deterministische ID über einen Hash ermöglicht das Überschreiben von Chunks ohne Duplikate. Wichtiger Hinweis: Wenn die ORM updated_at automatisch aktualisiert bei saveAll() – setze indexed_at auf eine kurze Zeit in der Zukunft, damit der Scheduler nicht jedes Mal alles neu indiziert.

Welches Ollama-Modell für RAG wählen?

Für Embeddings – nomic-embed-text als Standard, mxbai-embed-large wenn höhere Genauigkeit benötigt wird. Für die Generierung von Antworten – llama3.3:8b auf 8 GB RAM oder qwen2.5:14b, wenn 16 GB vorhanden sind. Ein vollständiger Vergleich der Modelle mit Benchmarks und Empfehlungen für Aufgaben – Welches Ollama-Modell wählen im Jahr 2026: Vergleich von Llama, Qwen, DeepSeek und Mistral.

Gibt es Java-Lösungen für RAG mit Ollama?

Ja – Spring AI mit nativer Unterstützung für Ollama und pgvector. Ein reales Fallbeispiel für die Implementierung von RAG für einen Blog mit Spring AI mit spezifischen Fehlern und Lösungen, die nicht in der Dokumentation stehen – im Artikel Wie ich RAG für webscraft.org gebaut habe: Spring AI + pgvector + reale Erfahrung.

Womit anfangen, wenn man noch nie mit Ollama gearbeitet hat?

Mache dich zuerst mit der Plattform selbst vertraut – was ist Ollama, wie ist es aufgebaut und welche Aufgaben löst es. Was ist Ollama und warum Entwickler massenhaft auf lokales KI umsteigen im Jahr 2026 – ein Überblick ohne Fachjargon, mit dem man bequem beginnen kann. Danach wird RAG zum logischen nächsten Schritt.

✅ Schlussfolgerungen

RAG ist eine dieser Technologien, die bis zur ersten Implementierung komplex erscheinen und danach offensichtlich sind. Die Pipeline ist konzeptionell einfach: Dokument → Chunks → Embeddings → Suche → Antwort. Die Komplexität beginnt in den Details – und die meisten dieser Details findest du nicht in der Dokumentation, sondern durch reale Vorfälle im Produktivbetrieb.

Was ich aus der Implementierung für den Blog mitgenommen habe:

  • ✔️ Beginne mit nomic-embed-text – aber logge sofort den Score bei echten Anfragen. Für nicht-lateinische Sprachen und kurze Anfragen ist ein Fallback erforderlich – das erfährst du nicht aus der Dokumentation.
  • ✔️ Determinierte UUID für Chunks – keine zufällige. Ohne dies vervielfacht die Neuindizierung Duplikate und du verstehst nicht sofort, warum.
  • ✔️ Fallback auf Keyword-Suche – Vektorsuche ersetzt keine normale Suche, sie ergänzt sie.
  • ✔️ Batch von 10-20 Dokumenten mit Speicherung von indexed_at – damit bei einem Absturz von der Stelle fortgefahren werden kann, an der aufgehört wurde, und nicht von vorne.
  • ✔️ Strenger System-Prompt – ohne explizites Verbot des Erfindens wird das Modell halluzinieren. Das ist kein Bug eines bestimmten Modells.

Mit Ollama ist der gesamte Stack kostenlos und läuft lokal – kein einziges Dokument geht in die Cloud. Für einen Blog, interne Dokumentation oder eine unternehmensinterne Wissensdatenbank ist dies die richtige Architektur.

Wenn du mit Java und Spring Boot arbeitest – der nächste Artikel handelt genau davon. Ein reales Fallbeispiel für die Implementierung von RAG für webscraft.org mit Spring AI + pgvector: welche Fehler ich gemacht habe, welche Fallstricke ich gefunden habe und was ich anders machen würde – Wie ich RAG für webscraft.org gebaut habe: Spring AI + pgvector + reale Erfahrung.

Wenn du noch nicht mit Ollama vertraut bist – beginne mit dem Überblick über Ollama 2026.

📎 Quellen

  1. LlamaIndex: Introduction to RAG – offizielle Dokumentation
  2. Real Python: LlamaIndex in Python — A RAG Guide – praktisches Tutorial
  3. Medium: LlamaIndex for Beginners 2025 – von Null bis Produktion
  4. DEV Community: RAG mit LlamaIndex, ChromaDB und Ollama
  5. Prem AI: LangChain vs LlamaIndex 2026 — Production RAG Comparison
  6. Contabo: LlamaIndex vs LangChain — Which One to Choose in 2026
  7. Ollama: nomic-embed-text – Eigenschaften des Embedding-Modells
  8. Ollama: mxbai-embed-large – alternatives Embedding-Modell

Останні статті

Читайте більше цікавих матеріалів

Як працює AI: токени, трансформери і навчання LLM

Як працює AI: токени, трансформери і навчання LLM

Щоразу, коли ви відправляєте повідомлення в ChatGPT, Claude або Gemini, за лічені секунди відбувається щось неймовірно складне: система, навчена на трильйонах слів, прогнозує наступний токен, зважує контекст тисяч попередніх слів і генерує відповідь, яка здається осмисленою. Але як саме це працює...

Spring AI + pgvector: 6 помилок які я зробив будуючи RAG для блогу

Spring AI + pgvector: 6 помилок які я зробив будуючи RAG для блогу

Перша година після підключення Spring AI — і застосунок не стартує. NoUniqueBeanDefinitionException: expected single matching bean but found 2: ollamaChatModel, openAiChatModel. Гугл каже додати spring.ai.openai.chat.enabled=false. Не працює. Документація мовчить. Це була тільки...

RAG з Ollama: як навчити AI відповідати по твоїх документах — від пайплайну до продакшну

RAG з Ollama: як навчити AI відповідати по твоїх документах — від пайплайну до продакшну

RAG з Ollama: навчи AI відповідати по твоїх документах У тебе є документи — PDF, статті, нотатки, база знань. Ти хочеш задавати питання і отримувати відповіді саме по цих документах, а не по загальних знаннях моделі. І все це — локально, без відправки даних у хмару....

Comet проти Safari та Chrome: чи варто переходити на AI-браузер у 2026

Comet проти Safari та Chrome: чи варто переходити на AI-браузер у 2026

Щороку з'являються десятки нових браузерів — і майже всі зникають непомітно. Але Comet від Perplexity — інший випадок. Це не чергова косметична надбудова над Chrome. Це спроба переосмислити саму роль браузера у твоєму житті. Спойлер: Comet не замінить Safari чи Chrome для...

Браузер Comet від Perplexity вийшов на iOS

Браузер Comet від Perplexity вийшов на iOS

Ми звикли до того, що браузер — це просто вікно в інтернет. Ти відкриваєш сторінку, читаєш, закриваєш. Але що, якщо браузер сам читає сторінку за тебе, знаходить потрібне і виконує завдання? Саме таку ідею просуває Perplexity зі своїм новим браузером Comet, який 18...

Контекстне вікно LLM: чому AI забуває і скільки це коштує

Контекстне вікно LLM: чому AI забуває і скільки це коштує

Ти коли-небудь помічав, що ChatGPT або Claude на початку розмови пам'ятає все ідеально, а через годину починає плутати деталі або перепитувати те, що ти вже пояснював? Це не баг — це фундаментальне обмеження, яке визначає, скільки AI може "тримати в голові" одночасно. Називається воно...