Skip to content
BotServBotServ
HaystackPipelineRetrieverGeneratorRAGPython

Haystack: End-to-End NLP-Framework

Haystack: Pipelines, Retriever, Reader, Generators. Wie Du Such- und RAG-Pipelines mit Haystack baust und lokal betreibst.

S

schutzgeist

7 min read
Haystack NLP Framework

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

BegriffBedeutung
DocumentEin Textblock mit Metadaten, der im Document Store liegt.
Document StoreSpeicher, der viele Dokumente verwaltet und durchsucht.
ComponentEin einzelner Pipeline-Baustein mit Eingängen und Ausgängen.
PipelineEin Verbund aus Components, der Daten verarbeitet.
RetrieverComponent, die Dokumente zu einer Anfrage findet.
PromptBuilderBaut einen Prompt aus einer Vorlage und Variablen.
GeneratorEin LLM, das aus einem Prompt Text erzeugt.
EmbedderBerechnet Vektoren für Dokumente oder Queries.
ReaderModell, 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 haystack statt haystack mit alten Modulnamen.
  • Verbindungen vergessen: Jede Component muss mit pipeline.connect an den passenden Eingang angebunden werden.
  • Falsche Eingangsnamen: prompt_builder.documents und prompt_builder.prompt sind 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. url muss auf http://localhost:11434 zeigen.
  • 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.

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

Zurück zum KI Blog
Share:

Ähnliche Beiträge