Download Latest Version v2.25.0 source code.tar.gz (14.7 MB)
Email in envelope

Get an email when there's a new version of Haystack

Home / v2.25.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md < 18 hours ago 15.7 kB
v2.25.0 source code.tar.gz < 18 hours ago 14.7 MB
v2.25.0 source code.zip < 18 hours ago 19.2 MB
Totals: 3 Items   33.9 MB 0

Release Notes

v2.25.0

Upgrade Notes

  • Removed the deprecated PipelineTemplate and PredefinedPipeline classes, along with the Pipeline.from_template() method. Users should migrate to Pipeline YAML files for similar functionality. See the [Serialization documentation](https://docs.haystack.deepset.ai/docs/serialization) for details on using YAML-based pipeline definitions.

  • Default Hugging Face pipeline task updated to ``text-generation``

The default task used by HuggingFaceLocalGenerator has been changed from text2text-generation to text-generation and the default model has been changed from "google/flan-t5-base" to "Qwen/Qwen3-0.6B".

In transformers v5+, text2text-generation is no longer available as a valid pipeline task (see: https://github.com/huggingface/transformers/pull/43256). While parts of the implementation still exist internally, it is no longer supported as a straightforward pipeline option.

How to know if you are affected

  • You are using transformers>=5.0.0.
  • You explicitly set task="text2text-generation" in HuggingFaceLocalGenerator or HuggingFaceLocalChatGenerator.

How to handle this change

  • Replace task="text2text-generation" with task="text-generation".
  • Ensure that the selected model is compatible with the text-generation pipeline (for example, causal language models).
  • If you rely on older behavior, pin transformers<5.
  • text2text-generation is now considered deprecated in Haystack and may be removed in a future release.

New Features

  • Added link_format parameter to PPTXToDocument and XLSXToDocument converters, allowing extraction of hyperlink addresses from PPTX and XLSX files.

Supported formats:

  • "markdown": [text](url)
  • "plain": text (url)
  • "none" (default): Only text is extracted, link addresses are ignored.

This follows the same pattern already available in DOCXToDocument.

  • Added a new LLM component (haystack.components.generators.chat.LLM) that provides a simplified interface for text generation powered by a large language model. The LLM component is a streamlined version of the Agent that focuses solely on single-turn text generation without tool usage. It supports system prompts, templated user prompts with required variables, streaming callbacks, and both synchronous (run) and asynchronous (run_async) execution.

Usage example: .. code:: python from haystack.components.generators.chat import LLM from haystack.components.generators.chat import OpenAIChatGenerator from haystack.dataclasses import ChatMessage

llm = LLM(
chat_generator=OpenAIChatGenerator(), system_prompt="You are a helpful translation assistant.", user_prompt="""{% message role="user"%}

Summarize the following document: {{ document }} {% endmessage %}""", required_variables=["document"], )

result = llm.run(document="The weather is lovely today and the sun is shining. ") print(result["last_message"].text)

  • Introduced the MarkdownHeaderSplitter component:
  • Splits documents into chunks at Markdown headers (#, ##, etc.), preserving header hierarchy as metadata.
  • Supports secondary splitting (by word, passage, period, or line) for further chunking after header-based splitting using Haystack's DocumentSplitter.
  • Preserves and propagates metadata such as parent headers and page numbers.
  • Handles edge cases such as documents with no headers, empty content, and non-text documents.

  • Added SearchableToolset to haystack.tools module. This new toolset enables agents to dynamically discover tools from large catalogs using keyword-based (BM25) search. Instead of exposing all tools upfront (which can overwhelm LLMs with large tool definitions), agents start with a single search_tools function and progressively discover relevant tools as needed. For smaller catalogs, it operates in passthrough mode exposing all tools directly.

Key features include configurable search threshold for automatic passthrough mode and top-k result limiting.

Example usage:

``` python from haystack.components.agents import Agent from haystack.components.generators.chat import OpenAIChatGenerator from haystack.dataclasses import ChatMessage from haystack.tools import Tool, SearchableToolset

# Create a catalog of tools catalog = [ Tool(name="get_weather", description="Get weather for a city", ...), Tool(name="search_web", description="Search the web", ...), # ... 100s more tools ] toolset = SearchableToolset(catalog=catalog)

agent = Agent(chat_generator=OpenAIChatGenerator(), tools=toolset)

# The agent is initially provided only with the search_tools tool and will use it to find relevant tools. result = agent.run(messages=[ChatMessage.from_user("What's the weather in Milan?")]) ```

  • Added user_prompt and required_variables parameters to the Agent component. You can now define a reusable Jinja2-templated user prompt at initialization or at runtime, so the Agent can be invoked with different inputs without manually constructing ChatMessage objects each time.

Example usage: .. code:: python agent = Agent( chat_generator=OpenAIChatGenerator(), tools=tools, system_prompt="You are a helpful translation assistant.", user_prompt="""{% message role="user"%} Translate the following document to {{ language }}: {{ document }} {% endmessage %}""", required_variables=["language", "document"], )

result = agent.run(language="French", document="The weather is lovely today.")

You can also combine messages with user_prompt. The rendered user prompt is appended to the provided messages, which is useful for passing prior conversation context alongside a new templated query: .. code:: python from haystack.dataclasses import ChatMessage

agent = Agent(
chat_generator=OpenAIChatGenerator(), tools=tools, system_prompt="You are a helpful translation assistant.", user_prompt="""{% message role="user"%} Now summarize the conversation in {{ language }}. {% endmessage %}""", required_variables=["language"],

)

result = agent.run(
messages=[
ChatMessage.from_user("What are the main benefits of renewable energy?"), ChatMessage.from_assistant( "Renewable energy reduces greenhouse gas emissions, decreases dependence " "on fossil fuels, and can lower long-term energy costs." ),

], language="Spanish",

)

  • Added support for Chat Messages that include files using the FileContent dataclass to OpenAIResponsesChatGenerator and AzureOpenAIResponsesChatGenerator.

Users can now pass files such as PDFs when using Haystack Chat Generators based on the Responses API.

  • User Chat Messages can now include files using the new FileContent dataclass.

Most API-based LLMs support file inputs such as PDFs (and, for some models, additional file types).

For now, this feature is implemented for OpenAIChatGenerator and AzureOpenAIChatGenerator, with support for more model providers coming soon.

For advanced PDF handling, such as reducing image size or selecting specific page ranges, we recommend using the PDFToImageContent component instead.

FileContent example:

python from haystack.components.generators.chat.openai import OpenAIChatGenerator from haystack.dataclasses.chat_message import ChatMessage from haystack.dataclasses.file_content import FileContent file_content = FileContent.from_url("https://arxiv.org/pdf/2309.08632") chat_message = ChatMessage.from_user(content_parts=[file_content, "Summarize this paper in 100 words."]) llm = OpenAIChatGenerator(model="gpt-4.1-mini") response = llm.run(messages=[chat_message])

  • Added the FileToFileContent component, which converts local files into FileContent objects. These can be embedded into ChatMessage to pass to an LLM.

  • Added document_comparison_field parameter to DocumentMRREvaluator, DocumentMAPEvaluator, and DocumentRecallEvaluator.

This allows users to compare documents using fields other than content, such as id or metadata keys (via meta.<key> syntax).

Previously, all three evaluators hardcoded doc.content for comparison, which did not work well when documents were chunked or when ground truth was identified by custom metadata fields.

Enhancement Notes

  • The LLMDocumentContentExtractor now extracts both content and metadata from image-based documents. When the LLM returns JSON, document_content fills the document body and other keys are merged into metadata; plain text is still used as content. The field content_extraction_error is no longer used and when an error occurs the field extraction_erroris added to metadata with the error message.

  • Improved the deserialization error message for pipeline components to be more actionable and human-readable. The component data dictionary is now pretty-printed as formatted JSON, and the underlying error that caused the failure is explicitly surfaced, making it easier to quickly diagnose deserialization issues.

  • EmbeddingBasedDocumentSplitter and MultiQueryEmbeddingRetriever now automatically invoke warm_up() when run() is called if they have not been warmed up yet.

  • Resolve postponed type annotations (from from __future__ import annotations) when creating component input sockets, so pipelines can correctly match compatible types. This fixes cases where connecting ChatPromptBuilder to FallbackChatGenerator failed because the generator’s annotations were interpreted as strings (for example 'list[ChatMessage]'), resulting in a PipelineConnectError due to mismatched socket types.

  • Agent components allow grouping multiple tools under a single confirmation strategy.

Here is an example of how three tools can be grouped under a BlockingConfirmationStrategy:

python confirmation_strategies = { ("tool1", "tool2", "tool3"): BlockingConfirmationStrategy() }

instead of previously needing

python confirmation_strategies = { "tool1": BlockingConfirmationStrategy(), "tool2": BlockingConfirmationStrategy(), "tool3": BlockingConfirmationStrategy() }

  • Improved ComponentTool to correctly handle components whose run method parameters are declared as top-level Optional types such as list[ChatMessage] | None. The optional wrapper is now unwrapped before checking for a from_dict method on the underlying type. As a result, when a parameter is typed as list[ChatMessage] | None and receives a list of dictionaries, ComponentTool will automatically coerce the input into a list of ChatMessage objects using ChatMessage.from_dict. If the provided value is None, the parameter is preserved as None.

  • Haystack now emits a Warning when dataclass instances (e.g. Document, ChatMessage, StreamingChunk, ByteStream, SparseEmbedding) are mutated in place. Modifying shared instances can cause unexpected behavior in other parts of the pipeline. Use dataclasses.replace to safely create updated copies instead.

Instead of modifying attributes in place:

``` python from haystack.dataclasses import Document

doc = Document(content="old text", meta={"key": "value"})

# Not recommended: can affect other parts of the pipeline doc.content = "new text" ```

Use dataclasses.replace to create a new instance with the updated values:

``` python from dataclasses import replace from haystack.dataclasses import Document

doc = Document(content="old text", meta={"key": "value"})

# Recommended: creates a new Document with updated content doc = replace(doc, content="new text") ```

Bug Fixes

  • Ensure Pipeline and AsyncPipeline deep-copies component inputs before execution so mutable outputs (e.g., Document dataclasses) shared across multiple downstream components don't get mutated by reference. This prevents side effects where one component's in-place modifications could unexpectedly affect other branches in the pipeline.

  • Fixed an issue in OpenAIChatGenerator and OpenAIResponsesChatGenerator where passing a FileContent object without a filename would raise an error. A fallback filename is now automatically used instead.

  • Ensure type display works correctly for parameterized generics when tracing is enabled. Previously, the haystack.component.input_spec and haystack.component.output_spec tag would strip the arguments present within a container type (e.g. list[str] would become "list"). Now we properly keep the arguments representation (e.g. list[str] becomes "list[str]").

  • Fixed a bug in flexible Pipeline connections that prevented automatic value conversion when the receiving component expects a Union type. For example, connecting a component returning ChatMessage to a receiver expecting list[str] | list[ChatMessage] should have worked but did not. The conversion strategy now correctly evaluates each branch of a Union receiver and picks the best match.

  • Previously, flexible pipeline connections were not robust when the sender component returned a list containing a union of types. In flexible pipeline connections, if the receiver type is str or ChatMessage, the first element of the list sent by the sender component is extracted and converted to the receiver type.

In the previous version, list[str | int] was considered compatible with str, which should not be the case. In fact, the sender component can legitimately return a list where the first element has type int, which the receiver cannot handle.

This is now fixed by ensuring that all possible element types of the sender list can be converted to the receiver type using the same conversion strategy.

  • Improved device handling when loading Hugging Face models in TransformersSimilarityRanker and ExtractiveReader.

hf_device_map is not always present anymore and is now only set when mixed-device loading is explicitly configured. The code has been updated to:

  • Check whether hf_device_map is available.
  • Fall back to the standard device attribute when it is not.

This prevents attribute errors and ensures compatibility across different transformers configurations.

  • Updated failing unit tests to align with recent mocking and transformers behavior changes.

  • PipelineRuntimeError raised by Agent now provide clearer ownership by explicitly surfacing the Agent as the failing pipeline component.

As a result:

  • component_name now resolves to the name of the Agent in the pipeline, instead of the underlying chat_generator or tool_invoker.
  • component_type now resolves to haystack.components.agents.agent.Agent instead of the concrete generator class such as haystack.components.generators.chat.openai.OpenAIChatGenerator.
  • The error message now includes an additional outer section for the Agent component.

Example of new error message:

  The following component failed to run:
  Component name: 'agent'
  Component type: 'Agent'
  Error: The following component failed to run:
  Component name: 'chat_generator'
  Component type: 'OpenAIChatGenerator'
  Error: Error code: 404 - {'error': {'message': 'The model ``gpt-4.2-mini`` does not exist or you do not have access to it.', 'type': 'invalid_request_error', 'param': None, 'code': 'model_not_found'}}

💙 Big thank you to everyone who contributed to this release!

@agnieszka-m, @Amanbig, @anakin87, @bilgeyucel, @bogdankostic, @davidsbatista, @edwiniac, @julian-risch, @kacperlukawski, @marc-mrt, @OGuggenbuehl, @OiPunk, @sjrl, @srini047, @vblagoje, @yaowubarbara

Source: README.md, updated 2026-02-26