Wer heute eine Retrieval-Augmented-Generation-Anwendung produktionsreif bauen will, stößt fast automatisch auf drei Namen: LangChain, LlamaIndex und Haystack. Während die ersten beiden in der deutschen Tech-Szene längst Standardvokabular sind, bleibt Haystack oft das am meisten unterschätzte der drei Frameworks, obwohl es von einem Berliner Unternehmen stammt und laut GitHub-API aktuell 26.646 Sterne sowie 3.227 Forks zählt (Stand 3. Oktober 2026). Mit Version 3.3.0, veröffentlicht am 1. Oktober 2026, bringt das Framework von deepset eine ausgereifte Pipeline-Architektur mit, die explizit für Produktionsumgebungen entwickelt wurde. In diesem Tutorial richten wir Haystack von Grund auf ein, bauen eine komplette RAG-Pipeline mit Qdrant als Vektordatenbank und zeigen, wie Sie lokale Modelle über Ollama oder Cloud-APIs wie OpenAI und Anthropic anbinden.

Das Ziel am Ende dieses Artikels: ein lauffähiges Python-Projekt, das Dokumente einliest, in eine Vektordatenbank schreibt, bei einer Nutzerfrage die passenden Textstellen findet und daraus mit einem Sprachmodell eine Antwort generiert. Dazwischen liegen 12 konkrete Schritte, mehrere vollständige Code-Beispiele, eine Vergleichstabelle zu LangChain und LlamaIndex sowie eine Liste der häufigsten Stolperfallen, die uns beim Testen begegnet sind.

Dieses Tutorial richtet sich an Entwicklerinnen und Entwickler, die bereits mit Python arbeiten und entweder eine erste RAG-Anwendung bauen oder von einem anderen Framework zu Haystack wechseln wollen. Vorkenntnisse zu Vektordatenbanken oder Embeddings sind hilfreich, aber nicht zwingend nötig, da wir jeden Begriff bei seinem ersten Auftauchen kurz erklären. Wer bereits produktiv mit LangChain oder LlamaIndex arbeitet, wird viele Konzepte wiedererkennen, allerdings mit einer deutlich strikteren, typisierten Pipeline-Syntax.

Was ist Haystack? Deepsets Open-Source-Framework im Überblick

Haystack ist ein Open-Source-Framework für den Bau von KI-Orchestrierungs-Pipelines in Python, entwickelt vom Berliner Unternehmen deepset. Laut der offiziellen GitHub-Beschreibung handelt es sich um ein “Open-source AI orchestration framework for building context-engineered, production-ready LLM applications”, das modulare Pipelines und Agenten-Workflows mit expliziter Kontrolle über Retrieval, Routing, Memory und Generierung ermöglicht. deepset launchte Haystack bereits im Dezember 2019 und sammelte 2023 eine Series-B-Finanzierung von 30 Millionen US-Dollar unter Führung von Balderton Capital ein, um das Framework und die dazugehörige deepset-Cloud-Plattform weiterzuentwickeln.

Das Quellcode-Repository auf GitHub steht unter der Apache-2.0-Lizenz, ist also auch kommerziell frei nutzbar. Mit Version 3.3.0 benötigt Haystack mindestens Python 3.10, laut PyPI-Metadaten ist Version 3.4.0 bereits als Entwicklungs-Build in Arbeit. Kern des Frameworks sind drei Konzepte: Pipelines verketten einzelne Verarbeitungsschritte zu einem ausführbaren Workflow, Components sind die wiederverwendbaren Bausteine innerhalb einer Pipeline (etwa Retriever, Embedder oder Generator), und DocumentStores übernehmen die Speicherung und Indexierung von Dokumenten und Vektoren. Laut dem offiziellen GitHub-Repository haystack-core-integrations pflegt deepset aktuell 107 offizielle Integrationen, darunter Anbindungen an Qdrant, Weaviate, Elasticsearch, OpenSearch, Pinecone, Chroma, pgvector, MongoDB Atlas, Azure AI Search und Supabase als Document Stores sowie an OpenAI, Anthropic, Mistral, Amazon Bedrock, Google Gen AI, Ollama, llama.cpp, vLLM, Hugging Face und Cohere als Modell-Provider. Auch eine Integration für das Model Context Protocol (MCP) ist bereits Teil des Ökosystems.

Die offizielle Dokumentation beschreibt den Einstieg so: “It contains instructions for installing Haystack, building your first RAG pipeline, and creating a tool-calling Agent.” (Haystack Documentation). Genau diesen Dreischritt bilden wir im Folgenden nach, nur ausführlicher und mit einer persistenten Vektordatenbank statt eines reinen In-Memory-Beispiels.

Wer setzt Haystack heute ein?

deepset positioniert Haystack explizit als Enterprise-taugliches Framework, nicht als reines Experimentier-Tool. In eigenen Fallstudien nennt das Unternehmen Organisationen wie Airbus, die Europäische Kommission, Oxford University Press, The Economist und die Bundeswehr als Nutzer von Haystack-basierten Lösungen. Eine Bosch-Fallstudie beschreibt einen Haystack-gestützten Assistenten, der von mehr als 600 Mitarbeitenden im Rahmen einer SAP-Migration genutzt wird. Wichtig für die Einordnung: Diese Fallstudien unterscheiden nicht immer trennscharf zwischen dem offenen Haystack-Framework und deepsets kommerzieller Cloud-Plattform, die zusätzliche Enterprise-Funktionen wie Hosting, Nutzerverwaltung und Support bietet. Für dieses Tutorial brauchen Sie ausschließlich das freie, selbst gehostete Framework.

Dass gerade europäische Institutionen auf Haystack setzen, hat auch einen strukturellen Grund: deepset selbst sitzt in Berlin und wirbt aktiv mit Datenverarbeitung nach europäischen Standards, ein Argument, das für Behörden und regulierte Branchen im DACH-Raum oft schwerer wiegt als reine Benchmark-Werte. Für Teams, die zusätzlich Wert auf nachvollziehbare KI-Sicherheit legen, lohnt sich ergänzend ein Blick in unsere Artikel zum Thema KI und Machine Learning auf shattered.io.

Für kleinere Teams und einzelne Entwickler ist die Enterprise-Ausrichtung kein Hindernis: Dieselbe Pipeline-Architektur, die bei Airbus oder der Bundeswehr im Hintergrund läuft, lässt sich eins zu eins auf ein internes Dokumentations-Tool mit wenigen hundert Dokumenten übertragen. Der Unterschied liegt meist nicht im Code, sondern im Betriebsaufwand: Während ein Konzern eine hochverfügbare Qdrant-Cluster-Installation mit mehreren Knoten betreibt, reicht für ein kleines Team oft ein einzelner Docker-Container, wie wir ihn in diesem Tutorial einsetzen. Genau diese Skalierbarkeit nach oben wie nach unten, ohne den Pipeline-Code grundlegend ändern zu müssen, ist einer der Gründe, warum deepset das Framework von Beginn an für den produktiven Einsatz statt für reine Forschungsprototypen konzipiert hat.

Haystack vs. LangChain vs. LlamaIndex: Wo liegen die Unterschiede?

Bevor Sie Zeit in die Einrichtung investieren, lohnt sich ein Blick auf die Abgrenzung. Alle drei Frameworks lösen ähnliche Probleme, setzen aber unterschiedliche Schwerpunkte. LangChain bietet das breiteste Ökosystem an Model-Wrappern, Tools und Agenten-Abstraktionen, ändert seine APIs aber auch vergleichsweise häufig. LlamaIndex ist stark auf Datenaufnahme, Indexierung und die Anbindung von LLMs an strukturierte oder private Datenquellen ausgerichtet, wie unser Tutorial zu LlamaIndex mit Qdrant zeigt. Haystack dagegen setzt auf explizite, typisierte und inspizierbare Pipelines mit starkem Fokus auf Produktionsbetrieb, Evaluierung und Enterprise-Deployments. Für Teams, die bereits eine Pipeline in Produktion betreiben und nach einer zweiten Meinung zur Architektur suchen, lohnt sich zudem ein Blick in unser Tutorial zum generellen Aufbau einer RAG-Pipeline, das die Konzepte framework-unabhängig erklärt.

KriteriumHaystack 3.3.0LangChainLlamaIndex
Herstellerdeepset (Berlin)LangChain Inc.LlamaIndex Inc.
LizenzApache 2.0MITMIT
GitHub-Sterne (Kernrepo)26.646über 146.000groß, datenfokussiert
KernabstraktionPipeline + ComponentChain + AgentIndex + Query Engine
StärkeProduktionsreife, ObservabilityBreites Tool-ÖkosystemDatenanbindung, Indexierung
Installationsbefehlpip install haystack-aipip install langchainpip install llama-index
Python-Mindestversion3.103.93.9

Die GitHub-Sternezahlen für LangChain stammen aus unserem separaten Setup-Tutorial und sind nicht direkt mit Haystack vergleichbar, da LangChain mehrere Repositories bündelt. Entscheidender als die Sternezahl ist für die meisten Teams die Frage, wie viel Kontrolle sie über die Pipeline-Logik behalten wollen. Wer eine Pipeline bauen will, die sich wie ein Diagramm aus Knoten lesen lässt und sich sauber testen lässt, ist bei Haystack an der richtigen Adresse. Wer dagegen schnell mit vielen verschiedenen Tool-Integrationen experimentieren will, findet in LangChain oder LangGraph mehr vorgefertigte Bausteine.

Ein praktischer Unterschied zeigt sich auch beim Debugging: Da jede Haystack-Pipeline ein gerichteter azyklischer Graph (DAG) aus klar benannten Komponenten ist, lässt sich der Datenfluss zwischen zwei Schritten gezielt inspizieren, indem man eine Pipeline nur bis zu einer bestimmten Komponente ausführt. Bei stark verschachtelten LangChain-Chains ist dieser Schritt oft aufwendiger, weil Zwischenergebnisse tiefer in der Objektstruktur verschachtelt sind. Für Teams mit mehreren Entwicklern, die gemeinsam an einer Pipeline arbeiten, ist diese Explizitheit häufig der ausschlaggebende Grund für die Wahl von Haystack, auch wenn das Framework dafür etwas mehr Boilerplate-Code beim Aufbau der Pipeline verlangt.

Voraussetzungen: Diese Tools brauchen Sie vorher

Für dieses Tutorial reicht ein normaler Entwickler-Laptop. Eine GPU ist nicht zwingend nötig, beschleunigt aber die lokale Embedding-Berechnung spürbar. Folgende Komponenten sollten vor dem ersten Schritt installiert sein:

KomponenteMindestversionZweck
Python3.10 oder neuerLaufzeitumgebung für Haystack 3.3.0
pip23.0 oder neuerPaketinstallation
Docker / Docker Compose24.0 oder neuerBetrieb des Qdrant-Containers
haystack-ai3.3.0Kern-Framework
qdrant-haystackaktuelle VersionQdrant-Document-Store-Integration
sentence-transformersaktuelle VersionLokale Embedding-Modelle
Ollama (optional)aktuelle VersionLokales LLM statt Cloud-API
OpenAI- oder Anthropic-API-Key (optional)–Cloud-basierte Generierung

Wenn Sie bereits ein Tutorial zu RAG-Pipelines auf shattered.io durchgearbeitet haben, kennen Sie die Grundbegriffe Retriever, Embedding und Generator bereits. Falls nicht: Ein Retriever sucht in einer Dokumentensammlung nach den Textstücken, die zu einer Frage passen, ein Embedding-Modell wandelt Text in Vektoren um, und der Generator formuliert aus den gefundenen Textstellen und der Originalfrage eine Antwort.

Zur Hardware-Einordnung: Das in diesem Tutorial verwendete mehrsprachige Embedding-Modell belegt im Arbeitsspeicher rund 1 bis 2 Gigabyte, läuft aber auch ohne GPU in akzeptabler Geschwindigkeit für kleinere Dokumentenmengen bis in den niedrigen vierstelligen Bereich. Für größere Produktionsdatenbestände mit mehreren hunderttausend Chunks empfiehlt sich entweder eine GPU für die Embedding-Berechnung oder ein gehosteter Embedding-Dienst, um die Indexierungszeit im Rahmen zu halten. Qdrant selbst lässt sich sowohl lokal im Docker-Container als auch als verwalteter Cloud-Dienst betreiben, für dieses Tutorial reicht die lokale Variante vollständig aus.

Schritt 1 und 2: Python-Umgebung einrichten und Haystack installieren

Legen Sie zunächst ein isoliertes virtuelles Environment an, damit Haystack-Abhängigkeiten nicht mit anderen Projekten kollidieren. Anschließend installieren Sie das Kernpaket sowie die beiden Integrationen, die wir im Tutorial brauchen: die Qdrant-Anbindung für den Document Store und Sentence-Transformers für lokale Embeddings.

mkdir haystack-rag-tutorial && cd haystack-rag-tutorial
python3 -m venv .venv
source .venv/bin/activate   # unter Windows: .venv\Scripts\activate

pip install --upgrade pip
pip install haystack-ai qdrant-haystack sentence-transformers python-dotenv

Die genaue Paketversion sowie alle Abhängigkeiten können Sie jederzeit auf der offiziellen PyPI-Seite von haystack-ai nachschlagen, bevor Sie mit der Installation beginnen. Prüfen Sie direkt im Anschluss, ob die Installation funktioniert hat und welche Version tatsächlich installiert wurde:

python3 -c "import haystack; print(haystack.__version__)"
# Erwartete Ausgabe: 3.3.0 (oder neuer)

Falls die Installation mit einem Kompilierfehler abbricht, liegt das in den meisten Fällen an einer zu alten Python-Version. Da Haystack 3.3.0 mindestens Python 3.10 voraussetzt, hilft hier ein Blick auf python3 --version vor der Fehlersuche in den Abhängigkeiten. Auf Linux-Systemen mit mehreren parallel installierten Python-Versionen hat es sich bewährt, das virtuelle Environment explizit mit dem gewünschten Interpreter anzulegen, etwa über python3.12 -m venv .venv, statt sich auf den systemweiten Standard-Python zu verlassen.

Schritt 3: Projektstruktur anlegen und Konfiguration vorbereiten

Eine saubere Projektstruktur erspart später Kopfschmerzen, besonders wenn die Pipeline wächst. Legen Sie einen Ordner für Ihre Quelldokumente an und eine .env-Datei für API-Keys, die niemals ins Git-Repository eingecheckt werden sollte. Die Trennung zwischen Indexierungs-Skript und Abfrage-Skript ist dabei bewusst gewählt: In der Praxis läuft die Indexierung meist nur einmal oder in regelmäßigen Abständen, etwa nachts per Cronjob, während die Abfrage-Pipeline kontinuierlich auf Nutzeranfragen reagiert. Wer beides in einem einzigen Skript vermischt, erschwert sich später die getrennte Skalierung beider Teile.

haystack-rag-tutorial/
├── .venv/
├── .env
├── data/
│   └── dokumente/
├── indexing_pipeline.py
├── rag_pipeline.py
└── requirements.txt

Tragen Sie in die .env-Datei die Zugangsdaten ein, die Sie später brauchen, etwa für OpenAI oder Anthropic. Wer komplett lokal mit Ollama arbeitet, kann diesen Schritt überspringen.

OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
QDRANT_URL=http://localhost:6333

Schritt 4: Dokumente laden und mit dem Converter aufbereiten

Legen Sie ein paar Textdateien in data/dokumente/ ab, zum Beispiel interne FAQ-Texte, Produktdokumentation oder Protokolle. Haystack bringt für die meisten Formate fertige Converter-Komponenten mit, etwa für PDF, Markdown oder HTML. Für dieses Tutorial reicht der einfache TextFileToDocument-Converter, gefolgt von einem DocumentSplitter, der lange Texte in kleinere, embeddingfähige Abschnitte zerlegt.

Die Größe der Textabschnitte (Chunks) beeinflusst die Antwortqualität direkt: Zu große Chunks verwässern die Relevanz der Suche, zu kleine Chunks reißen Zusammenhänge auseinander. Ein guter Startwert für deutschsprachige Fließtexte liegt bei 200 bis 300 Wörtern pro Chunk mit einer Überlappung von etwa 20 Wörtern. Bei technischen Dokumenten mit vielen Tabellen oder Aufzählungen lohnt sich ein zweiter Testlauf mit kleineren Chunks um die 100 Wörter, da lange Absätze sonst mehrere unabhängige Informationen vermischen und der Retriever in der Folge thematisch zu breite Treffer liefert.

Für Formate jenseits von reinem Text bringt Haystack eigene Converter-Komponenten mit, etwa PyPDFToDocument für PDF-Dateien oder MarkdownToDocument für Markdown-Dateien. Der grundsätzliche Pipeline-Aufbau bleibt dabei identisch, lediglich die Converter-Komponente am Anfang wird ausgetauscht.

Schritt 5: Qdrant als Document Store einrichten

Qdrant ist eine der 107 offiziellen Integrationen im haystack-core-integrations-Repository und eine der am häufigsten genutzten Vektordatenbanken im Haystack-Ökosystem. Starten Sie zunächst einen lokalen Qdrant-Container über Docker Compose, bevor Sie den Document Store in Python initialisieren.

docker run -d --name qdrant-haystack \
  -p 6333:6333 -p 6334:6334 \
  -v $(pwd)/qdrant_storage:/qdrant/storage \
  qdrant/qdrant:latest

Im Python-Skript indexing_pipeline.py initialisieren Sie anschließend den Document Store und die komplette Indexierungs-Pipeline aus Converter, Splitter, Embedder und Writer:

from pathlib import Path
from haystack import Pipeline
from haystack.components.converters import TextFileToDocument
from haystack.components.preprocessors import DocumentSplitter
from haystack.components.writers import DocumentWriter
from haystack.components.embedders import SentenceTransformersDocumentEmbedder
from haystack_integrations.document_stores.qdrant import QdrantDocumentStore

document_store = QdrantDocumentStore(
    url="http://localhost:6333",
    index="tutorial_dokumente",
    embedding_dim=768,
    recreate_index=True,
)

indexing = Pipeline()
indexing.add_component("converter", TextFileToDocument())
indexing.add_component("splitter", DocumentSplitter(split_by="word", split_length=250, split_overlap=20))
indexing.add_component("embedder", SentenceTransformersDocumentEmbedder(model="sentence-transformers/paraphrase-multilingual-mpnet-base-v2"))
indexing.add_component("writer", DocumentWriter(document_store=document_store))

indexing.connect("converter", "splitter")
indexing.connect("splitter", "embedder")
indexing.connect("embedder", "writer")

dateien = list(Path("data/dokumente").glob("*.txt"))
indexing.run({"converter": {"sources": dateien}})
print(f"{document_store.count_documents()} Chunks wurden indexiert.")

Beachten Sie das mehrsprachige Embedding-Modell paraphrase-multilingual-mpnet-base-v2: Für deutschsprachige Inhalte liefert es deutlich bessere Ergebnisse als rein englische Modelle, braucht dafür aber mehr Arbeitsspeicher. Beim ersten Ausführen lädt Sentence-Transformers das Modell automatisch von Hugging Face herunter und legt es lokal im Cache ab, sodass nachfolgende Läufe deutlich schneller starten. Nach erfolgreichem Lauf sollte die Konsole eine Zahl größer null ausgeben, etwa so:

$ python3 indexing_pipeline.py
Batches: 100%|██████████| 4/4 [00:02<00:00,  1.78it/s]
48 Chunks wurden indexiert.

Bleibt die Ausgabe bei 0 Chunks stehen, liegt das fast immer daran, dass der Glob-Ausdruck *.txt keine Dateien im angegebenen Ordner findet, etwa weil die Dateien in einem Unterordner liegen oder eine andere Dateiendung tragen. Ein schneller Test mit ls data/dokumente/ vor dem eigentlichen Pipeline-Lauf erspart hier unnötige Fehlersuche in der Haystack-Konfiguration selbst.

Welcher Document Store passt zu Ihrem Projekt?

Qdrant ist für dieses Tutorial eine gute Wahl, weil es sich in einem einzigen Docker-Befehl starten lässt und speziell für Vektorsuche entwickelt wurde. Es ist aber bei Weitem nicht die einzige Option im Haystack-Ökosystem. Wer bereits eine Elasticsearch- oder OpenSearch-Installation im Unternehmen betreibt, kann dieselbe Infrastruktur über die jeweilige Haystack-Integration weiterverwenden, statt zusätzlich eine neue Vektordatenbank einzuführen. Teams, die bereits auf PostgreSQL setzen, fahren häufig gut mit der pgvector-Integration, weil sie Vektorsuche und klassische relationale Abfragen in derselben Datenbank kombinieren können, ohne ein weiteres System betreiben zu müssen.

Für Cloud-native Projekte auf AWS oder Azure bieten sich dagegen die verwalteten Varianten Amazon-nahe Lösungen oder Azure AI Search an, bei denen Betrieb und Skalierung größtenteils vom Cloud-Anbieter übernommen werden. Der Wechsel zwischen diesen Optionen erfordert in Haystack lediglich den Austausch der Document-Store-Komponente, die restliche Pipeline aus Converter, Splitter, Embedder und Retriever bleibt unverändert. Diese Austauschbarkeit ist einer der praktischen Vorteile der komponentenbasierten Architektur, die deepset von Anfang an verfolgt hat.

Auch reine In-Memory-Lösungen ohne externe Infrastruktur gehören zum Repertoire: Der mitgelieferte InMemoryDocumentStore hält alle Dokumente und Vektoren im Arbeitsspeicher des Python-Prozesses und eignet sich für Prototypen, automatisierte Tests oder Demos, bei denen keine Daten über einen Prozess-Neustart hinaus erhalten bleiben müssen. Für dieses Tutorial haben wir uns bewusst für Qdrant statt für die In-Memory-Variante entschieden, weil die Persistenz von Vektoren in den meisten echten Projekten ohnehin benötigt wird und der Umstieg später entfällt.

Schritt 6 und 7: Retriever konfigurieren und Prompt-Builder aufsetzen

Mit indexierten Dokumenten können Sie nun die eigentliche Such- und Antwort-Pipeline bauen. Der Retriever übernimmt die Ähnlichkeitssuche im Vektorraum, der Prompt-Builder formatiert die gefundenen Textstellen zusammen mit der Nutzerfrage in eine Vorlage, die das Sprachmodell versteht.

from haystack.components.embedders import SentenceTransformersTextEmbedder
from haystack.components.builders import PromptBuilder
from haystack_integrations.components.retrievers.qdrant import QdrantEmbeddingRetriever

template = """
Beantworte die Frage ausschließlich anhand des folgenden Kontexts.
Wenn die Antwort nicht im Kontext steht, sage das ehrlich.

Kontext:
{% for document in documents %}
{{ document.content }}
{% endfor %}

Frage: {{ question }}
Antwort:
"""

text_embedder = SentenceTransformersTextEmbedder(model="sentence-transformers/paraphrase-multilingual-mpnet-base-v2")
retriever = QdrantEmbeddingRetriever(document_store=document_store, top_k=5)
prompt_builder = PromptBuilder(template=template)

Der Parameter top_k=5 legt fest, wie viele Chunks pro Anfrage an das Sprachmodell weitergereicht werden. Ein höherer Wert liefert mehr Kontext, erhöht aber auch die Tokenkosten und das Risiko, dass irrelevante Textstellen die Antwort verwässern. In der Praxis hat sich ein Startwert zwischen drei und sieben Chunks bewährt, der anschließend anhand realer Testfragen nachjustiert wird. Der PromptBuilder arbeitet mit Jinja2-Templates, sodass sich das Format des Kontexts, etwa mit nummerierten Quellenangaben, flexibel anpassen lässt, ohne den restlichen Pipeline-Code zu verändern.

Schritt 8: Generator anbinden – OpenAI, Anthropic oder lokal mit Ollama

Haystack abstrahiert den letzten Pipeline-Schritt, die Textgenerierung, über austauschbare Generator-Komponenten. Dank der offiziellen Integrationen lässt sich derselbe Pipeline-Aufbau mit minimalem Codeaufwand zwischen Cloud-Anbietern und lokalen Modellen umschalten.

# Variante A: Cloud-basiert mit OpenAI
from haystack.components.generators import OpenAIGenerator
generator = OpenAIGenerator(model="gpt-4o-mini")

# Variante B: komplett lokal mit Ollama
# from haystack_integrations.components.generators.ollama import OllamaGenerator
# generator = OllamaGenerator(model="llama3.1", url="http://localhost:11434")

Wer aus Datenschutzgründen keine Texte an externe APIs senden darf, nutzt die Ollama-Variante: Alle Daten bleiben dann auf dem eigenen Server. Für produktive DACH-Projekte mit Kundendaten ist das häufig die einzige praktikable Option, auch wenn lokale Modelle bei komplexen Fragen noch hinter GPT-4o oder Claude zurückbleiben können.

Ein dritter Weg führt über Anthropic, dessen Integration im haystack-core-integrations-Repository ebenfalls offiziell gepflegt wird. Der Austausch beschränkt sich dabei auf zwei Zeilen Code, die Pipeline-Struktur darüber hinaus bleibt unverändert, was den späteren Wechsel zwischen Anbietern für A/B-Tests deutlich vereinfacht. Genau diese Austauschbarkeit ist einer der Hauptgründe, warum Teams Haystack gegenüber einer direkten API-Integration ohne Framework bevorzugen.

Schritt 9 und 10: Die erste RAG-Pipeline zusammenbauen und testen

Jetzt verbinden Sie alle Komponenten zu einer vollständigen Pipeline. Die Reihenfolge der connect()-Aufrufe bestimmt, wie Daten von Komponente zu Komponente fließen: Die Nutzerfrage wird zuerst eingebettet, dann für die Suche im Document Store genutzt, die Treffer landen im Prompt-Template, und das Ergebnis geht an den Generator.

rag_pipeline = Pipeline()
rag_pipeline.add_component("text_embedder", text_embedder)
rag_pipeline.add_component("retriever", retriever)
rag_pipeline.add_component("prompt_builder", prompt_builder)
rag_pipeline.add_component("generator", generator)

rag_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
rag_pipeline.connect("retriever.documents", "prompt_builder.documents")
rag_pipeline.connect("prompt_builder.prompt", "generator.prompt")

frage = "Welche Schritte sind für die Qdrant-Einrichtung nötig?"
ergebnis = rag_pipeline.run({
    "text_embedder": {"text": frage},
    "prompt_builder": {"question": frage},
})

print(ergebnis["generator"]["replies"][0])

Bei einem erfolgreichen Testlauf gegen die in Schritt 5 indexierten Beispieldokumente sieht die Ausgabe in etwa so aus:

$ python3 rag_pipeline.py
Laut dem Dokument starten Sie zunächst einen Qdrant-Container über Docker,
initialisieren anschließend den QdrantDocumentStore mit der passenden
embedding_dim und bauen danach die Indexierungs-Pipeline aus Converter,
Splitter, Embedder und Writer auf.

Weicht die Antwort stark vom erwarteten Inhalt ab, liegt das fast immer an der Chunk-Größe aus Schritt 4 oder an einem zu niedrigen top_k-Wert, der relevante Textstellen gar nicht erst in den Kontext lässt. Ein hilfreicher Zwischenschritt beim Debuggen ist es, die Pipeline nur bis zur retriever-Komponente laufen zu lassen und die zurückgegebenen Dokumente direkt auszugeben, statt gleich den kompletten Durchlauf bis zum Generator zu prüfen. So lässt sich schnell erkennen, ob das Problem bereits bei der Suche oder erst bei der Formulierung der Antwort entsteht.

Schritt 11 und 12: Tool-Calling-Agent, MCP-Anbindung und Deployment

Mit Version 3.x hat deepset den Fokus stärker auf Agenten-Workflows gelegt, bei denen das Sprachmodell selbstständig entscheidet, welche Werkzeuge es für eine Aufgabe braucht. Über die integrierte MCP-Anbindung (Model Context Protocol) lassen sich externe Tools, etwa eine Datenbankabfrage oder eine Websuche, als aufrufbare Funktionen in die Pipeline einhängen, statt sie fest zu verdrahten. Für den produktiven Betrieb packen Sie die fertige Pipeline anschließend in eine schlanke API, etwa mit FastAPI, und containerisieren sie zusammen mit dem Qdrant-Dienst über Docker Compose. Für die Qualitätskontrolle empfiehlt sich ein fester Satz von Testfragen mit erwarteten Antworten, den Sie nach jeder Pipeline-Änderung automatisiert durchlaufen lassen, ähnlich wie es auch unser separates LLM-Benchmark-Setup-Tutorial beschreibt.

Für Logging und Observability in Produktion lohnt sich zusätzlich ein Blick auf die offizielle langfuse- oder opentelemetry-Integration aus dem Haystack-Ökosystem, mit denen sich jeder Pipeline-Lauf samt Tokenverbrauch und Latenz nachvollziehen lässt.

Beim Deployment selbst hat sich ein einfaches Muster bewährt: Die Pipeline-Initialisierung geschieht einmalig beim Start der FastAPI-Anwendung, nicht bei jeder einzelnen Anfrage, da das Laden des Embedding-Modells mehrere Sekunden dauern kann. Ein einzelner FastAPI-Endpunkt nimmt die Nutzerfrage entgegen, ruft die bereits initialisierte fragen()-Funktion auf und gibt das Ergebnis als JSON zurück. Für den produktiven Betrieb hinter einem Reverse Proxy wie Nginx oder Caddy reicht in den meisten Fällen eine einzelne Uvicorn-Instanz mit mehreren Workern aus, solange der Qdrant-Dienst als separater Container daneben läuft.

Pipelines automatisiert evaluieren mit Ragas

Eine RAG-Pipeline, die einmal gut aussieht, bleibt nicht automatisch gut, sobald sich Dokumentenbestand oder Modellversion ändern. Im haystack-core-integrations-Repository pflegt deepset dafür eine eigene Integration für ragas, ein verbreitetes Open-Source-Framework zur automatisierten Bewertung von RAG-Antworten anhand von Metriken wie Treue zum Kontext (Faithfulness), Relevanz der Antwort und Relevanz der gefundenen Textstellen. Statt Antworten manuell zu lesen, lassen sich damit nach jeder Pipeline-Änderung automatisiert Kennzahlen erzeugen, die sich über die Zeit vergleichen lassen.

pip install ragas-haystack

from haystack_integrations.components.evaluators.ragas import RagasEvaluator

evaluator = RagasEvaluator(metrics=["faithfulness", "answer_relevancy"])
evaluation = evaluator.run(
    questions=["Wie starte ich den Qdrant-Container?"],
    contexts=[["docker run -d --name qdrant-haystack -p 6333:6333 qdrant/qdrant:latest"]],
    responses=["Mit docker run und den Ports 6333 sowie 6334."],
)
print(evaluation["results"])

Für den Produktivbetrieb empfiehlt es sich, einen festen Satz von 20 bis 50 repräsentativen Testfragen mit erwarteten Antworten zu pflegen und diese Evaluierung in die Continuous-Integration-Pipeline aufzunehmen. Sinkt die Faithfulness-Metrik nach einer Änderung spürbar ab, deutet das meist auf ein Problem beim Retrieval hin, etwa eine zu aggressive Chunk-Größe oder ein falsch konfigurierter top_k-Wert, bevor überhaupt am Prompt oder Generator-Modell geschraubt wird. Alternativ zu Ragas listet dasselbe Integrations-Repository auch eine deepeval-Anbindung, die ähnliche Metriken liefert und sich für Teams eignet, die bereits mit diesem Framework arbeiten. Beide Werkzeuge ersetzen keine menschliche Stichprobenprüfung vollständig, reduzieren aber den manuellen Aufwand bei jeder neuen Pipeline-Version erheblich.

Die 5 häufigsten Fehler bei der Haystack-Einrichtung

Beim Testen für dieses Tutorial sind uns immer wieder dieselben fünf Fehler begegnet, die sich allesamt innerhalb weniger Minuten beheben lassen, sobald man weiß, wonach man suchen muss:

  • Falsche embedding_dim im Document Store: Die Dimension muss exakt zum verwendeten Embedding-Modell passen. Bei paraphrase-multilingual-mpnet-base-v2 sind das 768 Dimensionen – ein häufiger Flüchtigkeitsfehler, wenn Code aus Tutorials mit anderen Modellen kopiert wird. Qdrant quittiert eine falsche Dimension meist mit einer klaren Fehlermeldung beim Schreiben, nicht beim Start, was die Fehlersuche unnötig verzögert.
  • Vergessene recreate_index-Option: Wird recreate_index=True bei jedem Lauf gesetzt, löscht Haystack den bestehenden Qdrant-Index bei jedem Neustart, was in Produktion zu Datenverlust führen kann. Für produktive Skripte sollte dieser Parameter nach der ersten Einrichtung auf False gesetzt werden.
  • Zu kleine oder zu große Chunk-Größen: Wer den Splitter ungetestet mit Standardwerten laufen lässt, bekommt oft entweder abgeschnittene Sätze oder zu diffuse Treffer bei der Suche. Ein kurzer manueller Test mit drei bis vier echten Nutzerfragen zeigt meist schon nach wenigen Minuten, in welche Richtung die Chunk-Größe angepasst werden sollte.
  • Mischen von Python-Umgebungen: Da Haystack 3.3.0 Python 3.10 oder neuer voraussetzt, führt eine global installierte ältere Python-Version häufig zu kryptischen Importfehlern, obwohl pip install fehlerfrei durchläuft. Ein expliziter Blick in pip show haystack-ai zeigt schnell, in welchem Environment das Paket tatsächlich installiert wurde.
  • API-Keys direkt im Code statt in .env: Besonders bei Projekten, die später auf GitHub landen, ist das ein vermeidbares Sicherheitsrisiko, das sich mit python-dotenv in wenigen Zeilen beheben lässt. Ein zusätzlicher Eintrag von .env in der .gitignore-Datei verhindert, dass Schlüssel versehentlich committet werden.

Troubleshooting: 8 Probleme und ihre Lösungen

Die folgende Tabelle fasst die Probleme zusammen, die am häufigsten in Haystack-Communitys und Support-Foren auftauchen, zusammen mit der jeweils schnellsten Lösung. Bei allen Problemen gilt: Zuerst isolieren, in welcher Pipeline-Komponente der Fehler auftritt, bevor an mehreren Stellen gleichzeitig geändert wird. Haystack gibt in Fehlermeldungen fast immer den Namen der betroffenen Komponente mit aus, was die Eingrenzung erheblich erleichtert.

ProblemUrsacheLösung
ImportError bei haystack_integrationsIntegrationspaket nicht installiertSeparates Paket installieren, z. B. pip install qdrant-haystack
Connection refused auf Port 6333Qdrant-Container läuft nichtdocker ps prüfen, Container neu starten
Dimension mismatch beim Indexierenembedding_dim passt nicht zum ModellModell-Dokumentation prüfen und Wert anpassen
Leere Antworten vom GeneratorRetriever findet keine passenden Chunkstop_k erhöhen oder Chunk-Größe verkleinern
Sehr langsame IndexierungEmbedding läuft nur auf CPUGPU nutzen oder kleineres Embedding-Modell wählen
401 Unauthorized bei OpenAIGeneratorAPI-Key fehlt oder ist abgelaufen.env prüfen, load_dotenv() vor Pipeline-Start aufrufen
Pipeline-Verbindung schlägt fehl (connect error)Falscher Ausgabename zwischen KomponentenKomponenten-Ausgaben mit component.to_dict() prüfen
Ollama-Generator antwortet nichtOllama-Dienst läuft nicht oder Modell nicht geladenollama list prüfen, Modell vorher mit ollama pull laden

Tritt ein Fehler auf, der hier nicht aufgeführt ist, lohnt sich zunächst ein Blick in die GitHub-Issues des haystack-core-integrations-Repositories, da viele Integrationsprobleme bereits dokumentiert und mit einer Lösung versehen sind. Bei 154 offenen Issues im Hauptrepository (Stand Oktober 2026) ist die Wahrscheinlichkeit hoch, dass ein ähnliches Problem bereits diskutiert wurde.

Fortgeschrittene Tipps für den produktiven Einsatz

Sobald die Basis-Pipeline läuft, lohnen sich drei Erweiterungen. Erstens: Hybrid-Suche, bei der Sie die Vektorsuche mit klassischer Keyword-Suche (BM25) kombinieren. Das verbessert die Trefferquote besonders bei Fachbegriffen und Eigennamen, die Embedding-Modelle gelegentlich falsch einordnen. Zweitens: Caching auf Embedding-Ebene, damit identische Fragen nicht wiederholt neu berechnet werden müssen, was bei hohem Anfragevolumen spürbar Kosten spart. Drittens: Multimodale Pipelines, bei denen Sie neben Text auch Bilder oder Tabellen aus PDFs über die docling-Integration einlesen und durchsuchbar machen, statt sie beim Preprocessing zu verwerfen.

Für Teams, die mehrere LLM-Anbieter parallel testen wollen, bietet sich zusätzlich die litellm-Integration an, mit der sich Generator-Komponenten ohne Codeänderung zwischen über hundert Modell-Endpunkten umschalten lassen. Mehr dazu auch in unserem Tutorial zu LiteLLM.

Viertens lohnt sich ein genauerer Blick auf verteilte Pipeline-Ausführung, sobald die Anfragezahl steigt. Da jede Haystack-Pipeline zustandslos aufgebaut ist, lässt sie sich problemlos hinter mehreren Worker-Prozessen replizieren, während der Qdrant-Document-Store als zentraler, geteilter Zustand bestehen bleibt. In der Praxis bedeutet das: Die rechenintensive Embedding-Berechnung bei der Indexierung läuft idealerweise als separater Batch-Job, während die schlankere Abfrage-Pipeline mit niedriger Latenz in mehreren Instanzen hinter einem Load Balancer läuft. Diese Trennung zwischen Indexierungs- und Abfrage-Pipeline, die wir in diesem Tutorial ohnehin schon als zwei getrennte Skripte angelegt haben, zahlt sich beim Skalieren direkt aus.

Das komplette Projekt zum Nachbauen

Zum Abschluss die vollständige Projektlogik in einer Datei, die Sie direkt kopieren und anpassen können. Sie kombiniert Indexierung und Abfrage in einem Skript und eignet sich als Ausgangspunkt für ein eigenes internes Dokumentations-Tool:

import os
from pathlib import Path
from dotenv import load_dotenv
from haystack import Pipeline
from haystack.components.converters import TextFileToDocument
from haystack.components.preprocessors import DocumentSplitter
from haystack.components.writers import DocumentWriter
from haystack.components.embedders import SentenceTransformersDocumentEmbedder, SentenceTransformersTextEmbedder
from haystack.components.builders import PromptBuilder
from haystack.components.generators import OpenAIGenerator
from haystack_integrations.document_stores.qdrant import QdrantDocumentStore
from haystack_integrations.components.retrievers.qdrant import QdrantEmbeddingRetriever

load_dotenv()
MODEL = "sentence-transformers/paraphrase-multilingual-mpnet-base-v2"

document_store = QdrantDocumentStore(url="http://localhost:6333", index="tutorial_dokumente", embedding_dim=768, recreate_index=False)

def indexieren():
    pipeline = Pipeline()
    pipeline.add_component("converter", TextFileToDocument())
    pipeline.add_component("splitter", DocumentSplitter(split_by="word", split_length=250, split_overlap=20))
    pipeline.add_component("embedder", SentenceTransformersDocumentEmbedder(model=MODEL))
    pipeline.add_component("writer", DocumentWriter(document_store=document_store))
    pipeline.connect("converter", "splitter")
    pipeline.connect("splitter", "embedder")
    pipeline.connect("embedder", "writer")
    dateien = list(Path("data/dokumente").glob("*.txt"))
    pipeline.run({"converter": {"sources": dateien}})
    print(f"{document_store.count_documents()} Chunks indexiert.")

def fragen(frage: str) -> str:
    template = "Beantworte anhand des Kontexts:\n{% for d in documents %}{{ d.content }}\n{% endfor %}\nFrage: {{ question }}\nAntwort:"
    rag = Pipeline()
    rag.add_component("text_embedder", SentenceTransformersTextEmbedder(model=MODEL))
    rag.add_component("retriever", QdrantEmbeddingRetriever(document_store=document_store, top_k=5))
    rag.add_component("prompt_builder", PromptBuilder(template=template))
    rag.add_component("generator", OpenAIGenerator(model="gpt-4o-mini"))
    rag.connect("text_embedder.embedding", "retriever.query_embedding")
    rag.connect("retriever.documents", "prompt_builder.documents")
    rag.connect("prompt_builder.prompt", "generator.prompt")
    ergebnis = rag.run({"text_embedder": {"text": frage}, "prompt_builder": {"question": frage}})
    return ergebnis["generator"]["replies"][0]

if __name__ == "__main__":
    if document_store.count_documents() == 0:
        indexieren()
    print(fragen("Wie starte ich den Qdrant-Container?"))

Dieses Grundgerüst lässt sich in wenigen Schritten erweitern: ein DocumentSplitter mit satzbasierter statt wortbasierter Teilung für juristische Texte, ein zweiter Generator für A/B-Tests zwischen Modellen, oder ein FastAPI-Wrapper, der die fragen()-Funktion als REST-Endpunkt bereitstellt.

Damit haben Sie alle zwölf Schritte durchlaufen: von der Python-Umgebung über die Qdrant-Einrichtung und die erste RAG-Pipeline bis zum Tool-Calling-Agenten und der automatisierten Evaluierung. Der größte Vorteil gegenüber einer selbstgebauten Lösung ohne Framework zeigt sich erst im Betrieb, wenn einzelne Komponenten ausgetauscht, neue Datenquellen angebunden oder Modelle gewechselt werden müssen, ohne die gesamte Pipeline neu zu schreiben. Wer von hier aus weitermachen will, findet in der offiziellen Dokumentation unter docs.haystack.deepset.ai weitere Tutorials zu Themen wie Multi-Hop-Retrieval, strukturierter Datenextraktion und komplexeren Agenten-Workflows.

Häufig gestellte Fragen

Ist Haystack komplett kostenlos nutzbar?

Ja. Das Kern-Framework steht unter der Apache-2.0-Lizenz und ist auch für kommerzielle Projekte ohne Lizenzgebühren nutzbar. Kosten entstehen nur durch optional genutzte Cloud-APIs wie OpenAI oder Anthropic sowie durch deepsets separate kommerzielle Cloud-Plattform, die für dieses Tutorial nicht benötigt wird.

Brauche ich zwingend Qdrant, oder geht es auch ohne externe Vektordatenbank?

Nein. Für erste Experimente reicht der mitgelieferte InMemoryDocumentStore, der keine externe Infrastruktur benötigt. Für produktive Projekte mit persistenten Daten empfiehlt sich jedoch eine der 107 offiziellen Document-Store-Integrationen wie Qdrant, Weaviate oder pgvector.

Funktioniert Haystack auch komplett offline, ohne Cloud-APIs?

Ja. Mit der Ollama- oder llama.cpp-Integration sowie einem lokalen Embedding-Modell wie Sentence-Transformers läuft die komplette Pipeline ohne externe Netzwerkverbindung. Das ist besonders für Projekte mit strengen Datenschutzanforderungen relevant.

Welche Python-Version brauche ich mindestens?

Haystack 3.3.0 setzt laut PyPI-Metadaten mindestens Python 3.10 voraus. Ältere Python-Versionen führen bei der Installation oder beim Import zu Fehlern.

Wie unterscheidet sich Haystack 3.x von der älteren Version 2.x?

Die Pipeline- und Component-Grundarchitektur bleibt zwischen den Versionslinien weitgehend bestehen, die aktuelle Version 3.3.0 legt laut Projektbeschreibung jedoch einen stärkeren Fokus auf Agenten-Workflows, Tool-Calling und Model-Context-Protocol-Integration. Bestehende Projekte sollten vor einem Upgrade das offizielle Changelog auf GitHub prüfen.

Kann ich mehrere Sprachmodelle in derselben Pipeline kombinieren?

Ja, über die LiteLLM-Integration oder durch den Aufbau mehrerer paralleler Pipelines lassen sich verschiedene Generatoren etwa für Routing-Entscheidungen oder A/B-Tests kombinieren.

Eignet sich Haystack für deutschsprachige Anwendungsfälle?

Ja, solange ein mehrsprachiges Embedding-Modell wie paraphrase-multilingual-mpnet-base-v2 verwendet wird. Das Framework selbst ist sprachunabhängig, die Qualität hängt primär vom gewählten Embedding- und Generator-Modell ab.

Wie groß ist die Haystack-Community im Vergleich zu anderen Frameworks?

Das Kernrepository auf GitHub zählt aktuell 26.646 Sterne und 3.227 Forks, bei 154 offenen Issues. Das ist kleiner als die LangChain-Community, aber groß genug für eine aktive Weiterentwicklung mit regelmäßigen Releases, wie der Sprung von Version 3.3.0 zu bereits laufenden 3.4.0-Entwicklungs-Builds Anfang Oktober 2026 zeigt.

Was kostet deepset Cloud im Unterschied zum offenen Haystack-Framework?

Das in diesem Tutorial verwendete Haystack-Framework ist komplett kostenlos und selbst gehostet. deepset bietet zusätzlich eine kommerzielle Cloud-Plattform mit Hosting, Nutzerverwaltung und Support an, deren Preise individuell auf Anfrage vereinbart werden. Für ein erstes Projekt oder einen Proof of Concept ist die kommerzielle Plattform nicht erforderlich.

Kann Haystack auch Bilder oder Tabellen aus PDFs verarbeiten, nicht nur reinen Text?

Ja, über die offizielle docling-Integration lassen sich auch komplexere Dokumentstrukturen wie Tabellen und eingebettete Bilder aus PDFs extrahieren und für die Suche nutzbar machen. Für einen reinen Text-Anwendungsfall wie in diesem Tutorial reicht der einfachere TextFileToDocument-Converter vollkommen aus.