Haystack: End-to-End NLP-Framework
Was dieser Artikel behandelt
- Was Haystack ist und wie Pipelines funktionieren.
- Die Rollen von Document Store, Retriever, PromptBuilder und Generator.
- Wie Du Dokumente in einen InMemoryDocumentStore lädst.
- Den Aufbau einer RAG-Pipeline mit Ollama.
- Typische Fehler und Stolpersteine beim Einstieg in Haystack 2.x.
Einleitung
Haystack ist ein Open-Source-Framework für Python, mit dem Du Pipelines für Natural Language Processing baust. Der Fokus liegt auf Suchanwendungen, Question Answering und RAG. Statt viel Klebe-Code zu schreiben, verbindest Du vorgefertigte Komponenten in einer Pipeline. Jede Komponente hat Eingänge und Ausgänge, die Du über definierte Verbindungen miteinander koppelst.
Haystack 2.x hat die Architektur deutlich vereinfacht. Die zentrale Idee ist klar: Dokumente speichern, passende Dokumente finden, einen Prompt bauen und ein Sprachmodell antworten lassen. Das Framework bietet dafür Komponenten wie InMemoryDocumentStore, InMemoryBM25Retriever, PromptBuilder und OllamaGenerator.
Warum brauche ich Haystack?
Sobald Du mehrere Schritte kombinieren musst, wächst eine reine API-Lösung schnell unübersichtlich. Haystack hilft Dir, den Prozess sichtbar zu machen. Du siehst, wie Daten durch die Pipeline fließen, welche Komponenten beteiligt sind und wo Du ansetzen kannst, um Ergebnisse zu verbessern.
Der modulare Aufbau macht Experimente einfach. Du kannst einen Retriever austauschen, ein anderes Embedding-Modell testen oder einen anderen Generator verwenden, ohne die gesamte Anwendung neu zu schreiben. Außerdem lässt sich Haystack hervorragend mit Ollama betreiben, um Kosten und Datenschutzbedenken aus dem Weg zu gehen.
Haystack kurz erklärt
Haystack baut auf wenigen zentralen Konzepten auf:
- Document: Ein Textobjekt mit Inhalt und optionalen Metadaten.
- Document Store: Speicher für viele Document-Objekte.
- Component: Ein Pipeline-Baustein mit definierten Eingängen und Ausgängen.
- Pipeline: Ein gerichteter Graph aus verbundenen Components.
- Retriever: Findet relevante Dokumente aus einem Document Store.
- Reader: Ein Modell, das Antworten aus Dokumenten extrahiert.
- PromptBuilder: Baut aus Vorlagen und Variablen einen Prompt.
- Generator: Ein Sprachmodell, das Text erzeugt.
- Embedder: Berechnet Embeddings für Dokumente oder Anfragen.
Die Pipeline ist das Herzstück. Du fügst Components hinzu, verbindest deren Ausgänge und startest den Ablauf mit pipeline.run().
Für wen ist dieser Artikel gedacht?
Dieser Artikel richtet sich an Entwickler mit Python-Grundkenntnissen. Du brauchst kein Experte für NLP, solltest aber verstehen, wie man Pakete installiert und einfache Skripte ausführt. Wenn Du bereits LangChain oder LlamaIndex kennst, wird Dir der modulare Aufbau vertraut vorkommen.
Neulinge profitieren davon, dass Haystack den Ablauf in sichtbare Schritte zerlegt. Wer tiefer in RAG einsteigen möchte, findet Ergänzungen in RAG Grundlagen und Lokales RAG.
Wichtige Begriffe
| Begriff | Bedeutung |
|---|---|
| Document | Ein Textblock mit Metadaten, der im Document Store liegt. |
| Document Store | Speicher, der viele Dokumente verwaltet und durchsucht. |
| Component | Ein einzelner Pipeline-Baustein mit Eingängen und Ausgängen. |
| Pipeline | Ein Verbund aus Components, der Daten verarbeitet. |
| Retriever | Component, die Dokumente zu einer Anfrage findet. |
| PromptBuilder | Baut einen Prompt aus einer Vorlage und Variablen. |
| Generator | Ein LLM, das aus einem Prompt Text erzeugt. |
| Embedder | Berechnet Vektoren für Dokumente oder Queries. |
| Reader | Modell, das Dokumente liest und Antworten herauszieht. |
Installation
Für Haystack 2.x mit Ollama brauchst Du folgende Pakete:
pip install haystack-ai ollama-haystack
Für PDFs ergänze:
pip install pypdf
Stelle sicher, dass Ollama läuft und das gewünschte Modell bereitliegt. Zum Beispiel:
ollama pull llama3.2
ollama pull nomic-embed-text
Dokumente im Store ablegen
Bevor Du eine RAG-Pipeline baust, musst Du Dokumente in einen Document Store laden. Der InMemoryDocumentStore reicht für den Start vollkommen.
from haystack import Document
from haystack.document_stores.in_memory import InMemoryDocumentStore
document_store = InMemoryDocumentStore()
dokumente = [
Document(content="LlamaIndex fokussiert sich stark auf RAG und Indexing."),
Document(content="Haystack ist ein modulares NLP-Framework für Pipelines."),
Document(content="LangChain bietet Chains, Tools und Agenten."),
]
document_store.write_documents(dokumente)
print(f"Anzahl Dokumente: {document_store.count_documents()}")
Für den produktiven Betrieb kannst Du InMemoryDocumentStore gegen andere Stores wie Elasticsearch, OpenSearch oder Weaviate austauschen. In einem lokalen Test reicht der Speicher im RAM.
Eine einfache Such-Pipeline
Mit einem Retriever kannst Du Dokumente durchsuchen, ohne ein Sprachmodell zu verwenden. BM25 ist ein klassischer Retriever, der auf Wortübereinstimmungen basiert.
from haystack import Pipeline
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
retriever = InMemoryBM25Retriever(document_store=document_store)
pipeline = Pipeline()
pipeline.add_component("retriever", retriever)
ergebnis = pipeline.run({"retriever": {"query": "Was ist Haystack?"}})
for doc in ergebnis["retriever"]["documents"]:
print(doc.content)
Dieses Beispiel zeigt das Pipeline-Muster: Komponente hinzufügen, Parameter übergeben, Ergebnis auslesen. Für semantische Suche tauschst Du den Retriever später gegen einen Embedding-Retriever aus.
RAG-Pipeline mit Ollama
Eine vollständige RAG-Pipeline verbindet Retrieval, Promptbau und Generierung. Der PromptBuilder verwendet eine Jinja-Vorlage, in die gefundene Dokumente und die Frage eingesetzt werden.
from haystack import Pipeline
from haystack.components.builders.prompt_builder import PromptBuilder
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
from haystack_integrations.components.generators.ollama import OllamaGenerator
template = """
Beantworte die Frage ausschließlich anhand des Kontexts.
Kontext:
{% for document in documents %}
{{ document.content }}
{% endfor %}
Frage: {{ query }}
Antwort:
"""
document_store = InMemoryDocumentStore()
document_store.write_documents(dokumente)
pipeline = Pipeline()
pipeline.add_component("retriever", InMemoryBM25Retriever(document_store=document_store))
pipeline.add_component("prompt_builder", PromptBuilder(template=template))
pipeline.add_component("llm", OllamaGenerator(model="llama3.2", url="http://localhost:11434"))
pipeline.connect("retriever", "prompt_builder.documents")
pipeline.connect("prompt_builder", "llm")
frage = "Was macht Haystack besonders?"
antwort = pipeline.run({"retriever": {"query": frage}, "prompt_builder": {"query": frage}})
print(antwort["llm"]["replies"][0])
Diese Pipeline durchläuft vier Schritte: Retrieval der passenden Dokumente, Zusammenbau des Prompts, Aufruf des lokalen Modells und Ausgabe der Antwort. Du kannst das Template anpassen, um das Verhalten des Modells zu steuern.
Mit Embeddings arbeiten
Wenn Du semantische Suche brauchst, berechnest Du Embeddings für Deine Dokumente und verwendest einen Embedding-Retriever. Dafür nutzt Du OllamaDocumentEmbedder und OllamaTextEmbedder.
from haystack import Document, Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack_integrations.components.embedders.ollama import OllamaDocumentEmbedder, OllamaTextEmbedder
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
document_store = InMemoryDocumentStore()
embedder = OllamaDocumentEmbedder(model="nomic-embed-text")
dokumente = [
Document(content="Python ist eine vielseitige Programmiersprache."),
Document(content="JavaScript wird häufig für Webanwendungen genutzt."),
]
dokumente_mit_embeddings = embedder.run(documents=dokumente)["documents"]
document_store.write_documents(dokumente_mit_embeddings)
query_embedder = OllamaTextEmbedder(model="nomic-embed-text")
retriever = InMemoryEmbeddingRetriever(document_store=document_store)
pipeline = Pipeline()
pipeline.add_component("query_embedder", query_embedder)
pipeline.add_component("retriever", retriever)
pipeline.connect("query_embedder", "retriever.query_embedding")
ergebnis = pipeline.run({"query_embedder": {"text": "Wozu eignet sich Python?"}})
for doc in ergebnis["retriever"]["documents"]:
print(doc.content)
Diese Variante findet inhaltlich ähnliche Dokumente, selbst wenn die Frage andere Worte nutzt als der gespeicherte Text. Mehr dazu erfährst Du in Embedding-Modelle und Vektordatenbanken.
Pipeline-Verbindungen verstehen
Die Verbindungen in Haystack sind einfach zu lesen: pipeline.connect("komponente_a", "komponente_b.eingang"). Dabei wird der Ausgang von A mit einem bestimmten Eingang von B verbunden. Fehlende Verbindungen führen zu Fehlern, deshalb lohnt es sich, den Pipeline-Graphen vor dem ersten Lauf zu prüfen.
Du kannst Pipelines auch serialisieren und wiederverwenden. pipeline.dumps() liefert eine YAML-Repräsentation. Damit kannst Du eine fertige Pipeline speichern, versionieren oder mit anderen teilen.
Typische Stolpersteine
- Falsche Imports: Haystack 2.x nutzt andere Pfade als Version 1.x. Achte auf
haystackstatthaystackmit alten Modulnamen. - Verbindungen vergessen: Jede Component muss mit
pipeline.connectan den passenden Eingang angebunden werden. - Falsche Eingangsnamen:
prompt_builder.documentsundprompt_builder.promptsind unterschiedlich. Prüfe die Dokumentation. - Template-Fehler: Jinja-Vorlagen müssen gültig sein. Ein vergessenes
{% endfor %}führt zu einem Syntaxfehler. - Modell nicht verfügbar: Stelle sicher, dass Ollama läuft und das gewählte Modell bereits gepullt wurde.
- URL falsch: Der Standard-Port für Ollama ist 11434.
urlmuss aufhttp://localhost:11434zeigen. - Dokumente nicht geschrieben: Ein leerer Document Store liefert keine Treffer. Überprüfe
document_store.count_documents(). - Timeout zu niedrig: Lokale Modelle brauchen Zeit. Erhöhe Timeouts, falls Anfragen abbrechen.
Hardware, Kosten und Sicherheit
Haystack selbst ist kostenlos. Kosten entstehen über Infrastruktur oder Cloud-APIs. Lokal zahlst Du für Strom und Hardware. Ein 7B-Modell läuft bei Quantisierung oft auf 8 GB VRAM. Für kleine Testmengen reicht sogar CPU-Betrieb, dauert aber länger.
Sicherheit beginnt beim Document Store. Wenn Du sensible Inhalte indexierst, achte auf Zugriffsrechte und verschlüsselte Speicherung. Öffentlich erreichbare Ollama-Instanzen solltest Du vermeiden. Betreibe alles, was vertrauliche Daten verarbeitet, in einem geschützten Netzwerk.
Weiterführende Links
- Entwicklungs-Tools Übersicht für weitere Frameworks.
- LlamaIndex für RAG und Indexing.
- LangChain für Chains und Agenten.
- Lokales RAG für den Gesamtkontext.
- RAG Grundlagen für die Theorie.
- Vektordatenbanken zur Auswahl eines Speichers.
- Embedding-Modelle für Hintergründe zu Embeddings.
- Ollama für den lokalen Modellbetrieb.
- Was ist ein KI-Agent für Agentenkonzepte.
FAQ
Ist Haystack kostenlos?
Ja, das Framework ist Open Source. Kosten entstehen nur für Modelle, Infrastruktur oder Cloud-APIs.
Was ist der Unterschied zwischen Haystack 1.x und 2.x?
Haystack 2.x ist neu aufgebaut und orientiert sich an Components und Pipelines. Viele alte Importpfade funktionieren nicht mehr.
Kann ich Haystack lokal betreiben?
Ja. Mit Ollama und dem Paket ollama-haystack bleiben alle Aufrufe lokal.
Welche Retriever gibt es?
Haystack bietet BM25- und Embedding-Retriever, aber auch spezialisierte Retriever für Elasticsearch, OpenSearch und andere Stores.
Was ist ein PromptBuilder?
Der PromptBuilder fügt Variablen wie gefundene Dokumente und Fragen in eine Vorlage ein und erstellt den finalen Prompt.
Brauche ich Python-Kenntnisse?
Ja, die meisten Beispiele setzen Python voraus. Grundlagen reichen für den Einstieg.
Kann ich Pipelines speichern?
Ja. Mit pipeline.dumps() erhältst Du eine YAML-Repräsentation, die Du später wieder laden kannst.
Welche Dokumente kann Haystack verarbeiten?
Über Converter und Preprocessor lassen sich PDFs, Textdateien, Word-Dokumente und viele weitere Formate einlesen.
Was ist der Vorteil gegenüber LangChain?
Haystack fokussiert sich auf sichtbare Pipelines und Retriever-Reader-Ketten. LangChain bietet mehr Freiheitsgrade für Agenten und Chains.
Wie kann ich meine Ergebnisse verbessern?
Experimentiere mit verschiedenen Retrievern, Splitter-Einstellungen, Prompt-Templates und Modellen. Die Qualität des Embeddings ist oft entscheidend.
Gibt es eine grafische Oberfläche?
Haystack selbst ist textbasiert, lässt sich aber gut in Streamlit, FastAPI oder Jupyter-Notebooks einbinden.
Was passiert, wenn kein passendes Dokument gefunden wird?
Der Prompt bleibt dann leer oder enthält keine passenden Kontexte. Das Modell antwortet aus seinem Trainingswissen, was bei lokalen Modellen oft halluziniert. Prüfe immer die Trefferqualität.
Quellen
- Haystack Documentation: https://docs.haystack.deepset.ai/
- Haystack GitHub: https://github.com/deepset-ai/haystack
- Ollama Haystack Integration: https://docs.haystack.deepset.ai/docs/ollamagenerator
- Haystack Pipelines: https://docs.haystack.deepset.ai/docs/pipelines
- Haystack Components: https://docs.haystack.deepset.ai/docs/components


