Skip to content
BotServBotServ
HaystackPipelineRetrieverGeneratorRAGPython

Haystack: Framework NLP End-to-End

Haystack: Pipelines, Retriever, Reader, Generators. Construye y ejecuta localmente pipelines de búsqueda y RAG.

S

schutzgeist

8 min read
Haystack: Framework NLP End-to-End

Haystack: Marco de Trabajo NLP de Principio a Fin

Qué cubre este artículo

  • Qué es Haystack y cómo funcionan las pipelines.
  • Los roles de Document Store, Retriever, PromptBuilder y Generator.
  • Cómo cargar documentos en un InMemoryDocumentStore.
  • La construcción de una pipeline RAG con Ollama.
  • Errores típicos y escollos al comenzar con Haystack 2.x.

Introducción

Haystack es un framework de código abierto para Python que te permite construir pipelines de procesamiento de lenguaje natural. Se enfoca en aplicaciones de búsqueda, preguntas y respuestas, y RAG. En lugar de escribir mucho código de pegamento, conectas componentes prefabricados en una pipeline. Cada componente tiene entradas y salidas que vinculas mediante conexiones definidas.

Haystack 2.x ha simplificado significativamente la arquitectura. La idea central es clara: almacenar documentos, encontrar los documentos relevantes, construir un prompt y dejar que un modelo de lenguaje responda. El framework proporciona componentes como InMemoryDocumentStore, InMemoryBM25Retriever, PromptBuilder y OllamaGenerator.

Por qué necesitas Haystack

Tan pronto como necesitas combinar varios pasos, una solución pura basada en APIs se vuelve confusa rápidamente. Haystack te ayuda a hacer el proceso visible. Ves cómo fluyen los datos a través de la pipeline, qué componentes están involucrados y dónde puedes intervenir para mejorar los resultados.

La estructura modular facilita los experimentos. Puedes intercambiar un retriever, probar un modelo de embedding diferente o usar otro generator sin reescribir toda la aplicación. Además, Haystack funciona perfectamente con Ollama para evitar costos y preocupaciones sobre privacidad de datos.

Haystack en resumen

Haystack se construye sobre pocos conceptos centrales:

  • Document: Un objeto de texto con contenido y metadatos opcionales.
  • Document Store: Almacenamiento para muchos objetos Document.
  • Component: Un bloque de construcción de pipeline con entradas y salidas definidas.
  • Pipeline: Un gráfico dirigido de Components conectados.
  • Retriever: Encuentra documentos relevantes de un Document Store.
  • Reader: Un modelo que extrae respuestas de documentos.
  • PromptBuilder: Construye un prompt a partir de plantillas y variables.
  • Generator: Un modelo de lenguaje que genera texto.
  • Embedder: Calcula embeddings para documentos o consultas.

La pipeline es el corazón. Añades Components, conectas sus salidas y ejecutas el flujo con pipeline.run().

Para quién es este artículo

Este artículo va dirigido a desarrolladores con conocimientos básicos de Python. No necesitas ser experto en NLP, pero deberías entender cómo instalar paquetes y ejecutar scripts simples. Si ya conoces LangChain o LlamaIndex, la estructura modular te resultará familiar.

Los principiantes se benefician de que Haystack desglosa el flujo en pasos visibles. Si quieres profundizar en RAG, encontrarás ampliaciones en Fundamentos de RAG y RAG Local.

Términos importantes

TérminoSignificado
DocumentUn bloque de texto con metadatos almacenado en el Document Store.
Document StoreAlmacenamiento que gestiona y busca en muchos documentos.
ComponentUn bloque individual de construcción de pipeline con entradas y salidas.
PipelineUn conjunto de Components que procesa datos.
RetrieverComponent que encuentra documentos relevantes para una consulta.
PromptBuilderConstruye un prompt a partir de una plantilla y variables.
GeneratorUn LLM que genera texto a partir de un prompt.
EmbedderCalcula vectores para documentos o consultas.
ReaderModelo que lee documentos y extrae respuestas.

Instalación

Para Haystack 2.x con Ollama necesitas los siguientes paquetes:

pip install haystack-ai ollama-haystack

Para PDFs, agrega:

pip install pypdf

Asegúrate de que Ollama está en ejecución y el modelo deseado está disponible. Por ejemplo:

ollama pull llama3.2
ollama pull nomic-embed-text

Colocar documentos en el almacén

Antes de construir una pipeline RAG, necesitas cargar documentos en un Document Store. El InMemoryDocumentStore es perfecto para comenzar.

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()}")

Para producción, puedes reemplazar InMemoryDocumentStore con otros stores como Elasticsearch, OpenSearch o Weaviate. Para pruebas locales, almacenar en RAM es suficiente.

Una pipeline de búsqueda simple

Con un retriever puedes buscar documentos sin usar un modelo de lenguaje. BM25 es un retriever clásico que se basa en coincidencias de palabras.

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)

Este ejemplo muestra el patrón de la pipeline: añadir un componente, pasar parámetros, leer el resultado. Para búsqueda semántica, más adelante intercambias el retriever por un embedding retriever.

Pipeline RAG con Ollama

Una pipeline RAG completa conecta recuperación, construcción de prompts y generación. El PromptBuilder utiliza una plantilla Jinja donde se insertan los documentos encontrados y la pregunta.

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])

Esta pipeline recorre cuatro pasos: recuperar documentos relevantes, armar el prompt, llamar al modelo local y entregar la respuesta. Puedes ajustar la plantilla para controlar el comportamiento del modelo.

Trabajar con embeddings

Si necesitas búsqueda semántica, debes calcular embeddings para tus documentos y usar un embedding retriever. Para ello empleas OllamaDocumentEmbedder y 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)

Este enfoque encuentra documentos similares en contenido, incluso cuando la pregunta usa palabras distintas al texto almacenado. Encontrarás más información en Modelos de embedding y Bases de datos vectoriales.

Entender las conexiones de pipelines

Las conexiones en Haystack son sencillas de leer: pipeline.connect("componente_a", "componente_b.entrada"). De esta forma conectas la salida de A con una entrada específica de B. Las conexiones faltantes generan errores, por eso vale la pena verificar el grafo de la pipeline antes de la primera ejecución.

También puedes serializar y reutilizar pipelines. pipeline.dumps() proporciona una representación en YAML. Así puedes guardar una pipeline lista, versionarla o compartirla con otros.

Errores comunes

  • Importaciones incorrectas: Haystack 2.x usa rutas diferentes a la versión 1.x. Ten cuidado con haystack y nombres de módulos antiguos.
  • Conexiones olvidadas: Cada componente debe conectarse con pipeline.connect a la entrada correcta.
  • Nombres de entrada incorrectos: prompt_builder.documents y prompt_builder.prompt son diferentes. Revisa la documentación.
  • Errores en plantillas: Las plantillas Jinja deben ser válidas. Un {% endfor %} olvidado causa un error de sintaxis.
  • Modelo no disponible: Asegúrate de que Ollama se está ejecutando y de que el modelo elegido ya ha sido descargado.
  • URL incorrecta: El puerto predeterminado para Ollama es 11434. La url debe apuntar a http://localhost:11434.
  • Documentos no escritos: Un Document Store vacío no devuelve resultados. Verifica document_store.count_documents().
  • Timeout muy bajo: Los modelos locales necesitan tiempo. Aumenta los timeouts si las solicitudes se agotan.

Hardware, costos y seguridad

Haystack es gratuito. Los costos provienen de infraestructura o APIs en la nube. Localmente pagas electricidad y hardware. Un modelo de 7B generalmente se ejecuta en 8 GB de VRAM con cuantización. Para pequeños conjuntos de prueba incluso funciona en CPU, pero es más lento.

La seguridad comienza en el Document Store. Si indexas contenido sensible, presta atención a los derechos de acceso y al almacenamiento cifrado. Evita instancias de Ollama accesibles públicamente. Ejecuta todo lo que procese datos confidenciales en una red protegida.

Enlaces relacionados

Preguntas frecuentes

¿Es Haystack gratuito?

Sí, el framework es de código abierto. Los costos surgen solo por modelos, infraestructura o APIs en la nube.

¿Cuál es la diferencia entre Haystack 1.x y 2.x?

Haystack 2.x fue reconstruido desde cero y se basa en components y pipelines. Muchas rutas de importación antiguas ya no funcionan.

¿Puedo ejecutar Haystack localmente?

Sí. Con Ollama y el paquete ollama-haystack todas las llamadas permanecen locales.

¿Qué retrievers existen?

Haystack ofrece retrievers BM25 y basados en embeddings, así como retrievers especializados para Elasticsearch, OpenSearch y otros almacenes.

¿Qué es un PromptBuilder?

El PromptBuilder inserta variables como documentos encontrados y preguntas en una plantilla para crear el prompt final.

¿Necesito conocimientos de Python?

Sí, la mayoría de los ejemplos asumen Python. Los fundamentos son suficientes para empezar.

¿Puedo guardar pipelines?

Sí. Con pipeline.dumps() obtienes una representación en YAML que puedes cargar más tarde.

¿Qué documentos puede procesar Haystack?

A través de convertidores y preprocesadores puedes leer PDFs, archivos de texto, documentos de Word y muchos otros formatos.

¿Cuál es la ventaja frente a LangChain?

Haystack se enfoca en pipelines visibles y cadenas retriever-reader. LangChain ofrece más grados de libertad para agentes y chains.

¿Cómo puedo mejorar mis resultados?

Experimenta con diferentes retrievers, configuraciones de splitter, plantillas de prompt y modelos. La calidad del embedding suele ser decisiva.

¿Existe una interfaz gráfica?

Haystack en sí es basado en texto, pero se integra bien en Streamlit, FastAPI o Jupyter Notebooks.

¿Qué sucede si no se encuentra un documento adecuado?

El prompt quedará vacío o sin contextos relevantes. El modelo responderá desde su conocimiento de entrenamiento, lo que en modelos locales frecuentemente produce alucinaciones. Siempre verifica la calidad de los resultados.

Fuentes

Volver al blog
Share:

Entradas relacionadas