From 2d597107def2cf4b046634336e651e77a90c3afb Mon Sep 17 00:00:00 2001
From: sjrl <10526848+sjrl@users.noreply.github.com>
Date: Wed, 8 Jul 2026 13:20:26 +0000
Subject: [PATCH] Sync Haystack API reference on Docusaurus
---
.../reference/haystack-api/agents_api.md | 187 ++-
.../reference/haystack-api/audio_api.md | 245 ---
.../reference/haystack-api/builders_api.md | 38 +-
.../reference/haystack-api/classifiers_api.md | 247 ---
.../reference/haystack-api/connectors_api.md | 275 ----
.../reference/haystack-api/converters_api.md | 295 +---
.../haystack-api/data_classes_api.md | 114 +-
.../haystack-api/document_stores_api.md | 7 +-
.../reference/haystack-api/embedders_api.md | 1159 +++----------
.../reference/haystack-api/evaluators_api.md | 26 +-
.../reference/haystack-api/extractors_api.md | 249 +--
.../reference/haystack-api/fetchers_api.md | 32 +
.../reference/haystack-api/generators_api.md | 1453 ++++-------------
.../reference/haystack-api/hooks_api.md | 609 +++++++
.../haystack-api/human_in_the_loop_api.md | 109 ++
.../haystack-api/image_converters_api.md | 3 +-
.../reference/haystack-api/joiners_api.md | 8 +-
.../reference/haystack-api/pipeline_api.md | 418 ++---
.../haystack-api/preprocessors_api.md | 34 +-
.../reference/haystack-api/query_api.md | 58 +-
.../reference/haystack-api/rankers_api.md | 744 +--------
.../reference/haystack-api/readers_api.md | 193 ---
.../reference/haystack-api/retrievers_api.md | 137 +-
.../reference/haystack-api/routers_api.md | 424 +----
.../haystack-api/skill_stores_api.md | 254 +++
.../haystack-api/tool_components_api.md | 314 ----
.../reference/haystack-api/tools_api.md | 476 ++++--
.../reference/haystack-api/utils_api.md | 64 +-
.../reference/haystack-api/websearch_api.md | 266 ---
29 files changed, 2752 insertions(+), 5686 deletions(-)
delete mode 100644 docs-website/reference/haystack-api/audio_api.md
delete mode 100644 docs-website/reference/haystack-api/classifiers_api.md
delete mode 100644 docs-website/reference/haystack-api/connectors_api.md
create mode 100644 docs-website/reference/haystack-api/hooks_api.md
delete mode 100644 docs-website/reference/haystack-api/readers_api.md
create mode 100644 docs-website/reference/haystack-api/skill_stores_api.md
delete mode 100644 docs-website/reference/haystack-api/tool_components_api.md
delete mode 100644 docs-website/reference/haystack-api/websearch_api.md
diff --git a/docs-website/reference/haystack-api/agents_api.md b/docs-website/reference/haystack-api/agents_api.md
index b937c34d1b1..83a2b61252a 100644
--- a/docs-website/reference/haystack-api/agents_api.md
+++ b/docs-website/reference/haystack-api/agents_api.md
@@ -114,6 +114,55 @@ result = agent.run(
print(result["last_message"].text)
```
+#### Using hooks to influence the run loop
+
+Hooks are callables that receive the live `State` and run at specific points in the Agent loop:
+
+- `before_llm`: runs before each chat-generator call.
+- `before_tool`: runs after the model requests tool calls, before any tools run. After these hooks run, the Agent
+ re-reads the current last message from `state.data["messages"]`. If that message has tool calls, those calls are
+ executed. If it has no tool calls, no tools run for that step, no tool-based exit condition is triggered, and the
+ Agent loops back to the next LLM call unless `max_agent_steps` has been reached.
+- `after_tool`: runs after tools execute, once their result messages are in `state.data["messages"]`, before the
+ exit check and the next LLM call. Use it to rewrite the freshly produced tool-result messages (e.g. offload,
+ redact, truncate, or summarize results). It does not run on the plain-text exit step, where no tools run.
+- `on_exit`: runs when the Agent is about to stop on an exit condition. An `on_exit` hook can keep the Agent
+ running by setting `state.set("continue_run", True)`.
+
+Use the `@hook` decorator to build a hook from a function. This `on_exit` hook keeps the Agent running until a
+required tool has been called.
+
+```python
+from haystack.components.agents import Agent
+from haystack.components.agents.state import State
+from haystack.components.generators.chat import OpenAIChatGenerator
+from haystack.dataclasses import ChatMessage
+from haystack.hooks import hook
+from haystack.tools import tool
+from typing import Annotated
+
+
+@tool
+def save_result(content: Annotated[str, "The result to save"]) -> str:
+ """Save the final result."""
+ # Placeholder: would persist `content` to a database or the file system
+ return "saved"
+
+
+@hook
+def require_save(state: State) -> None:
+ if state.get("tool_call_counts", {}).get("save_result", 0) == 0:
+ state.set("messages", [ChatMessage.from_system("Call `save_result` before finishing.")])
+ state.set("continue_run", True) # keep the Agent running instead of stopping
+
+
+agent = Agent(
+ chat_generator=OpenAIChatGenerator(),
+ tools=[save_result],
+ hooks={"on_exit": [require_save]},
+)
+```
+
#### __init__
```python
@@ -129,10 +178,9 @@ __init__(
max_agent_steps: int = 100,
streaming_callback: StreamingCallbackT | None = None,
raise_on_tool_invocation_failure: bool = False,
- tool_invoker_kwargs: dict[str, Any] | None = None,
- confirmation_strategies: (
- dict[str | tuple[str, ...], ConfirmationStrategy] | None
- ) = None
+ tool_concurrency_limit: int = 4,
+ tool_streaming_callback_passthrough: bool = False,
+ hooks: dict[HookPoint, list[Hook]] | None = None
) -> None
```
@@ -142,11 +190,11 @@ Initialize the agent component.
- **chat_generator** (ChatGenerator) – An instance of the chat generator that your agent should use. It must support tools.
- **tools** (ToolsType | None) – A list of Tool and/or Toolset objects, or a single Toolset that the agent can use.
-- **system_prompt** (str | None) – System prompt for the agent. Can be a plain string or a Jinja2 string template.
+- **system_prompt** (str | None) – System prompt for the agent. Can be a plain string template or a Jinja2 message template.
For details on the supported template syntax, refer to the
[documentation](https://docs.haystack.deepset.ai/docs/chatpromptbuilder#string-templates).
-- **user_prompt** (str | None) – User prompt for the agent, defined as a Jinja2 string template. If provided, this is
- appended to the messages provided at runtime.
+- **user_prompt** (str | None) – User prompt for the agent. Can be a plain string template or a Jinja2 message template.
+ If provided, this is appended to the messages provided at runtime.
For details on the supported template syntax, refer to the
[documentation](https://docs.haystack.deepset.ai/docs/chatpromptbuilder#string-templates).
- **required_variables** (list\[str\] | Literal['\*'] | None) – Lists the variables that must be provided as inputs to `user_prompt` or `system_prompt`.
@@ -159,19 +207,38 @@ Initialize the agent component.
with `"type"` (required) and an optional `"handler"` for merging values across tool calls.
Tools can read from and write to state keys using `inputs_from_state` and `outputs_to_state`.
- **max_agent_steps** (int) – Maximum number of steps the agent will run before stopping. Defaults to 100.
- If the agent exceeds this number of steps, it will stop and return the current state.
+ A step is one chat-generator call plus the execution of every tool call the model requested in
+ that call (if any). If the agent reaches this number of steps it stops and returns the current state.
- **streaming_callback** (StreamingCallbackT | None) – A callback that will be invoked when a response is streamed from the LLM.
The same callback can be configured to emit tool results when a tool is called.
- **raise_on_tool_invocation_failure** (bool) – Should the agent raise an exception when a tool invocation fails?
If set to False, the exception will be turned into a chat message and passed to the LLM.
-- **tool_invoker_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments to pass to the ToolInvoker.
-- **confirmation_strategies** (dict\[str | tuple\[str, ...\], ConfirmationStrategy\] | None) – A dictionary mapping tool names to ConfirmationStrategy instances.
+- **tool_concurrency_limit** (int) – Maximum number of tool calls to execute at the same time.
+ Defaults to 4. Set to 1 to disable parallel tool execution.
+- **tool_streaming_callback_passthrough** (bool) – If True, pass the streaming callback to tools that accept it.
+- **hooks** (dict\[HookPoint, list\[Hook\]\] | None) – A dictionary mapping a hook point to a list of hooks the Agent runs at that point. Each hook
+ receives the live `State` and influences the run by mutating it in place; hooks for a hook point run in
+ list order. Valid hook points are:
+- "before_llm": Runs before each chat-generator call.
+- "before_tool": Runs after the model requests tool calls, before any tools run. After these hooks run,
+ the Agent re-reads the current last message from `state.data["messages"]`. If that message contains tool
+ calls, those calls are executed. If it does not, no tools run for that step, no tool-based exit condition
+ is triggered, and the Agent loops back to the next LLM call unless `max_agent_steps` has been reached.
+- "after_tool": Runs after tools execute, once their result messages are in `state.data["messages"]`,
+ before the exit check and the next LLM call. Use it to rewrite the freshly produced tool-result messages
+ (e.g. offload, redact, truncate, or summarize results). It does not run on the plain-text exit step,
+ where no tools run.
+- "on_exit": Runs when the Agent is about to stop on an exit condition. An "on_exit" hook can keep the
+ Agent running by setting the `continue_run` control flag (`state.set("continue_run", True)`), usually
+ alongside a message telling the model what to do next. "on_exit" hooks run when the Agent stops on an
+ exit condition, but not when it stops because `max_agent_steps` is reached.
**Raises:**
- TypeError – If the chat_generator does not support tools parameter in its run method.
-- ValueError – If the exit_conditions are not valid.
-- ValueError – If any `user_prompt` variable overlaps with the `state_schema` or `run` method parameters.
+- ValueError – If any `user_prompt` variable overlaps with the `state_schema` or `run` method parameters,
+ if a hook is registered under an unknown hook point, or if a hook is registered under a hook point it does
+ not support (via its `allowed_hook_points`).
#### warm_up
@@ -179,7 +246,31 @@ Initialize the agent component.
warm_up() -> None
```
-Warm up the Agent.
+Warm up the tools, hooks, and the underlying chat generator.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the tools, hooks, and the underlying chat generator on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the hooks' and the underlying chat generator's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the hooks' and the underlying chat generator's async resources.
#### to_dict
@@ -217,13 +308,8 @@ run(
streaming_callback: StreamingCallbackT | None = None,
*,
generation_kwargs: dict[str, Any] | None = None,
- break_point: AgentBreakpoint | None = None,
- snapshot: AgentSnapshot | None = None,
- system_prompt: str | None = None,
- user_prompt: str | None = None,
tools: ToolsType | list[str] | None = None,
- snapshot_callback: SnapshotCallback | None = None,
- confirmation_strategy_context: dict[str, Any] | None = None,
+ hook_context: dict[str, Any] | None = None,
**kwargs: Any
) -> dict[str, Any]
```
@@ -237,22 +323,12 @@ Process messages and execute tools until an exit condition is met.
The same callback can be configured to emit tool results when a tool is called.
- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for LLM. These parameters will
override the parameters passed during component initialization.
-- **break_point** (AgentBreakpoint | None) – An AgentBreakpoint, can be a Breakpoint for the "chat_generator" or a ToolBreakpoint
- for "tool_invoker".
-- **snapshot** (AgentSnapshot | None) – An `AgentSnapshot` object containing the state of a previously saved agent execution,
- used to restart the agent from where it left off.
-- **system_prompt** (str | None) – System prompt for the agent. If provided, it overrides the default system prompt.
-- **user_prompt** (str | None) – User prompt for the agent. If provided, it overrides the default user prompt and is
- appended to the messages provided at runtime.
- **tools** (ToolsType | list\[str\] | None) – Optional list of Tool objects, a Toolset, or list of tool names to use for this run.
When passing tool names, tools are selected from the Agent's originally configured tools.
-- **snapshot_callback** (SnapshotCallback | None) – Optional callback function that is invoked when a pipeline snapshot is created.
- The callback receives a `PipelineSnapshot` object and can return an optional string.
- If provided, the callback is used instead of the default file-saving behavior.
-- **confirmation_strategy_context** (dict\[str, Any\] | None) – Optional dictionary for passing request-scoped resources
- to confirmation strategies. Useful in web/server environments to provide per-request
- objects (e.g., WebSocket connections, async queues, Redis pub/sub clients) that strategies
- can use for non-blocking user interaction.
+- **hook_context** (dict\[str, Any\] | None) – Optional dictionary of request-scoped resources made available to hooks via
+ `state.data.get("hook_context")`. Useful in web/server environments to provide per-request objects
+ (e.g., WebSocket connections, async queues, Redis pub/sub clients) that a hook can use, for
+ example a ConfirmationHook driving non-blocking user interaction.
- **kwargs** (Any) – Additional data to pass to the State schema used by the Agent.
The keys must match the schema defined in the Agent's `state_schema`.
@@ -261,12 +337,14 @@ Process messages and execute tools until an exit condition is met.
- dict\[str, Any\] – A dictionary with the following keys:
- "messages": List of all messages exchanged during the agent's run.
- "last_message": The last message exchanged during the agent's run.
+- "step_count": The number of steps the agent ran. A step is one chat-generator call plus the
+ execution of every tool call the model requested in that call (if any). The counter is incremented
+ after each step completes, including the final step that hits an exit condition or `max_agent_steps`.
+- "token_usage": Aggregated token usage from every LLM call in the run, summed from each LLM message's
+ `meta["usage"]`.
+- "tool_call_counts": Mapping of tool name to the number of times that tool was invoked.
- Any additional keys defined in the `state_schema`.
-**Raises:**
-
-- BreakpointException – If an agent breakpoint is triggered.
-
#### run_async
```python
@@ -275,13 +353,8 @@ run_async(
streaming_callback: StreamingCallbackT | None = None,
*,
generation_kwargs: dict[str, Any] | None = None,
- break_point: AgentBreakpoint | None = None,
- snapshot: AgentSnapshot | None = None,
- system_prompt: str | None = None,
- user_prompt: str | None = None,
tools: ToolsType | list[str] | None = None,
- snapshot_callback: SnapshotCallback | None = None,
- confirmation_strategy_context: dict[str, Any] | None = None,
+ hook_context: dict[str, Any] | None = None,
**kwargs: Any
) -> dict[str, Any]
```
@@ -299,21 +372,11 @@ if available.
LLM. The same callback can be configured to emit tool results when a tool is called.
- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for LLM. These parameters will
override the parameters passed during component initialization.
-- **break_point** (AgentBreakpoint | None) – An AgentBreakpoint, can be a Breakpoint for the "chat_generator" or a ToolBreakpoint
- for "tool_invoker".
-- **snapshot** (AgentSnapshot | None) – An `AgentSnapshot` object containing the state of a previously saved agent execution,
- used to restart the agent from where it left off.
-- **system_prompt** (str | None) – System prompt for the agent. If provided, it overrides the default system prompt.
-- **user_prompt** (str | None) – User prompt for the agent. If provided, it overrides the default user prompt and is
- appended to the messages provided at runtime.
- **tools** (ToolsType | list\[str\] | None) – Optional list of Tool objects, a Toolset, or list of tool names to use for this run.
-- **snapshot_callback** (SnapshotCallback | None) – Optional callback function that is invoked when a pipeline snapshot is created.
- The callback receives a `PipelineSnapshot` object and can return an optional string.
- If provided, the callback is used instead of the default file-saving behavior.
-- **confirmation_strategy_context** (dict\[str, Any\] | None) – Optional dictionary for passing request-scoped resources
- to confirmation strategies. Useful in web/server environments to provide per-request
- objects (e.g., WebSocket connections, async queues, Redis pub/sub clients) that strategies
- can use for non-blocking user interaction.
+- **hook_context** (dict\[str, Any\] | None) – Optional dictionary of request-scoped resources made available to hooks via
+ `state.data.get("hook_context")`. Useful in web/server environments to provide per-request objects
+ (e.g., WebSocket connections, async queues, Redis pub/sub clients) that a hook can use, for
+ example a ConfirmationHook driving non-blocking user interaction.
- **kwargs** (Any) – Additional data to pass to the State schema used by the Agent.
The keys must match the schema defined in the Agent's `state_schema`.
@@ -322,12 +385,14 @@ if available.
- dict\[str, Any\] – A dictionary with the following keys:
- "messages": List of all messages exchanged during the agent's run.
- "last_message": The last message exchanged during the agent's run.
+- "step_count": The number of steps the agent ran. A step is one chat-generator call plus the
+ execution of every tool call the model requested in that call (if any). The counter is incremented
+ after each step completes, including the final step that hits an exit condition or `max_agent_steps`.
+- "token_usage": Aggregated token usage from every LLM call in the run, summed from each LLM message's
+ `meta["usage"]`.
+- "tool_call_counts": Mapping of tool name to the number of times that tool was invoked.
- Any additional keys defined in the `state_schema`.
-**Raises:**
-
-- BreakpointException – If an agent breakpoint is triggered.
-
## state/state
### State
diff --git a/docs-website/reference/haystack-api/audio_api.md b/docs-website/reference/haystack-api/audio_api.md
deleted file mode 100644
index 394c7877bbe..00000000000
--- a/docs-website/reference/haystack-api/audio_api.md
+++ /dev/null
@@ -1,245 +0,0 @@
----
-title: "Audio"
-id: audio-api
-description: "Transcribes audio files."
-slug: "/audio-api"
----
-
-
-## whisper_local
-
-### LocalWhisperTranscriber
-
-Transcribes audio files using OpenAI's Whisper model on your local machine.
-
-For the supported audio formats, languages, and other parameters, see the
-[Whisper API documentation](https://platform.openai.com/docs/guides/speech-to-text) and the official Whisper
-[GitHub repository](https://github.com/openai/whisper).
-
-### Usage example
-
-```python
-from haystack.components.audio import LocalWhisperTranscriber
-
-whisper = LocalWhisperTranscriber(model="small")
-transcription = whisper.run(sources=["test/test_files/audio/answer.wav"])
-print(transcription)
-
-# >> {'documents': [Document(id=dae7051417caaf19304a4ef2ec845e981abe1efd4c8e6ee7ffb25867f165c411,
-# >> content: ' Answer.', meta: {'audio_file': PosixPath('test/test_files/audio/answer.wav'), 'language': 'en'})]}
-```
-
-#### __init__
-
-```python
-__init__(
- model: WhisperLocalModel = "large",
- device: ComponentDevice | None = None,
- whisper_params: dict[str, Any] | None = None,
-) -> None
-```
-
-Creates an instance of the LocalWhisperTranscriber component.
-
-**Parameters:**
-
-- **model** (WhisperLocalModel) – The name of the model to use. Set to one of the following models:
- "tiny", "base", "small", "medium", "large" (default).
- For details on the models and their modifications, see the
- [Whisper documentation](https://github.com/openai/whisper?tab=readme-ov-file#available-models-and-languages).
-- **device** (ComponentDevice | None) – The device for loading the model. If `None`, automatically selects the default device.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Loads the model in memory.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> LocalWhisperTranscriber
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- LocalWhisperTranscriber – The deserialized component.
-
-#### run
-
-```python
-run(
- sources: list[str | Path | ByteStream],
- whisper_params: dict[str, Any] | None = None,
-) -> dict[str, Any]
-```
-
-Transcribes a list of audio files into a list of documents.
-
-**Parameters:**
-
-- **sources** (list\[str | Path | ByteStream\]) – A list of paths or binary streams to transcribe.
-- **whisper_params** (dict\[str, Any\] | None) – For the supported audio formats, languages, and other parameters, see the
- [Whisper API documentation](https://platform.openai.com/docs/guides/speech-to-text) and the official Whisper
- [GitHup repo](https://github.com/openai/whisper).
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following keys:
-- `documents`: A list of documents where each document is a transcribed audio file. The content of
- the document is the transcription text, and the document's metadata contains the values returned by
- the Whisper model, such as the alignment data and the path to the audio file used
- for the transcription.
-
-#### transcribe
-
-```python
-transcribe(
- sources: list[str | Path | ByteStream], **kwargs: Any
-) -> list[Document]
-```
-
-Transcribes the audio files into a list of Documents, one for each input file.
-
-For the supported audio formats, languages, and other parameters, see the
-[Whisper API documentation](https://platform.openai.com/docs/guides/speech-to-text) and the official Whisper
-[github repo](https://github.com/openai/whisper).
-
-**Parameters:**
-
-- **sources** (list\[str | Path | ByteStream\]) – A list of paths or binary streams to transcribe.
-
-**Returns:**
-
-- list\[Document\] – A list of Documents, one for each file.
-
-## whisper_remote
-
-### RemoteWhisperTranscriber
-
-Transcribes audio files using the OpenAI's Whisper API.
-
-The component requires an OpenAI API key, see the
-[OpenAI documentation](https://platform.openai.com/docs/api-reference/authentication) for more details.
-For the supported audio formats, languages, and other parameters, see the
-[Whisper API documentation](https://platform.openai.com/docs/guides/speech-to-text).
-
-### Usage example
-
-```python
-from haystack.components.audio import RemoteWhisperTranscriber
-
-whisper = RemoteWhisperTranscriber(model="whisper-1")
-transcription = whisper.run(sources=["test/test_files/audio/answer.wav"])
-```
-
-#### __init__
-
-```python
-__init__(
- api_key: Secret = Secret.from_env_var("OPENAI_API_KEY"),
- model: str = "whisper-1",
- api_base_url: str | None = None,
- organization: str | None = None,
- http_client_kwargs: dict[str, Any] | None = None,
- **kwargs: Any
-) -> None
-```
-
-Creates an instance of the RemoteWhisperTranscriber component.
-
-**Parameters:**
-
-- **api_key** (Secret) – OpenAI API key.
- You can set it with an environment variable `OPENAI_API_KEY`, or pass with this parameter
- during initialization.
-- **model** (str) – Name of the model to use. Currently accepts only `whisper-1`.
-- **organization** (str | None) – Your OpenAI organization ID. See OpenAI's documentation on
- [Setting Up Your Organization](https://platform.openai.com/docs/guides/production-best-practices/setting-up-your-organization).
-- **api_base_url** (str | None) – An optional URL to use as the API base. For details, see the
- OpenAI [documentation](https://platform.openai.com/docs/api-reference/audio).
-- **http_client_kwargs** (dict\[str, Any\] | None) – A dictionary of keyword arguments to configure a custom `httpx.Client`or `httpx.AsyncClient`.
- For more information, see the [HTTPX documentation](https://www.python-httpx.org/api/#client).
-- **kwargs** (Any) – Other optional parameters for the model. These are sent directly to the OpenAI
- endpoint. See OpenAI [documentation](https://platform.openai.com/docs/api-reference/audio) for more details.
- Some of the supported parameters are:
-- `language`: The language of the input audio.
- Provide the input language in ISO-639-1 format
- to improve transcription accuracy and latency.
-- `prompt`: An optional text to guide the model's
- style or continue a previous audio segment.
- The prompt should match the audio language.
-- `response_format`: The format of the transcript
- output. This component only supports `json`.
-- `temperature`: The sampling temperature, between 0
- and 1. Higher values like 0.8 make the output more
- random, while lower values like 0.2 make it more
- focused and deterministic. If set to 0, the model
- uses log probability to automatically increase the
- temperature until certain thresholds are hit.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> RemoteWhisperTranscriber
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- RemoteWhisperTranscriber – The deserialized component.
-
-#### run
-
-```python
-run(sources: list[str | Path | ByteStream]) -> dict[str, Any]
-```
-
-Transcribes the list of audio files into a list of documents.
-
-**Parameters:**
-
-- **sources** (list\[str | Path | ByteStream\]) – A list of file paths or `ByteStream` objects containing the audio files to transcribe.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following keys:
-- `documents`: A list of documents, one document for each file.
- The content of each document is the transcribed text.
diff --git a/docs-website/reference/haystack-api/builders_api.md b/docs-website/reference/haystack-api/builders_api.md
index 6ab572365bb..077c7e428d0 100644
--- a/docs-website/reference/haystack-api/builders_api.md
+++ b/docs-website/reference/haystack-api/builders_api.md
@@ -163,9 +163,10 @@ A template can be a list of `ChatMessage` objects, or a special string, as shown
It constructs prompts using static or dynamic templates, which you can update for each pipeline run.
-Template variables in the template are optional unless specified otherwise.
-If an optional variable isn't provided, it defaults to an empty string. Use `variable` and `required_variables`
-to define input types and required variables.
+Template variables in the template are required by default. To make any subset of variables optional,
+set `required_variables` to an explicit list of the variables that should remain required; any variable
+not listed becomes optional and defaults to an empty string when missing.
+Set `required_variables` to `None` to mark every variable as optional.
### Usage examples
@@ -266,7 +267,7 @@ builder.run(user_name="John", images=images)
```python
__init__(
template: list[ChatMessage] | str | None = None,
- required_variables: list[str] | Literal["*"] | None = None,
+ required_variables: list[str] | Literal["*"] | None = "*",
variables: list[str] | None = None,
) -> None
```
@@ -279,8 +280,10 @@ Constructs a ChatPromptBuilder component.
renders the prompt with the provided variables. Provide the template in either
the `init` method`or the`run\` method.
- **required_variables** (list\[str\] | Literal['\*'] | None) – List variables that must be provided as input to ChatPromptBuilder.
- If a variable listed as required is not provided, an exception is raised.
- If set to `"*"`, all variables found in the prompt are required. Optional.
+ Defaults to `"*"`, which marks every variable found in the prompt as required.
+ Pass an explicit list to only require a subset of the variables; any variable not listed becomes
+ optional and is replaced with an empty string in the rendered prompt when missing.
+ Set to `None` to mark every variable as optional.
- **variables** (list\[str\] | None) – List input variables to use in prompt templates instead of the ones inferred from the
`template` parameter. For example, to use more variables during prompt engineering than the ones present
in the default template, you can provide them here.
@@ -353,8 +356,9 @@ Deserialize this component from a dictionary.
Renders a prompt filling in any variables so that it can send it to a Generator.
The prompt uses Jinja2 template syntax.
-The variables in the default template are used as PromptBuilder's input and are all optional.
-If they're not provided, they're replaced with an empty string in the rendered prompt.
+The variables in the default template are used as PromptBuilder's input and are all required by default.
+To make any subset of variables optional, set `required_variables` to an explicit list of the variables that
+should remain required. Optional variables are replaced with an empty string in the rendered prompt.
To try out different prompts, you can replace the prompt template at runtime by
providing a template for each pipeline run invocation.
@@ -377,12 +381,12 @@ builder.run(target_language="spanish", snippet="I can't speak spanish.")
#### In a Pipeline
This is an example of a RAG pipeline where PromptBuilder renders a custom prompt template and fills it
-with the contents of the retrieved documents and a query. The rendered prompt is then sent to a Generator.
+with the contents of the retrieved documents and a query. The rendered prompt is then sent to a ChatGenerator.
```python
from haystack import Pipeline, Document
from haystack.utils import Secret
-from haystack.components.generators import OpenAIGenerator
+from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.builders.prompt_builder import PromptBuilder
# in a real world use case documents could come from a retriever, web, or any other source
@@ -399,7 +403,7 @@ prompt_template = """
"""
p = Pipeline()
p.add_component(instance=PromptBuilder(template=prompt_template), name="prompt_builder")
-p.add_component(instance=OpenAIGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY")), name="llm")
+p.add_component(instance=OpenAIChatGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY")), name="llm")
p.connect("prompt_builder", "llm")
question = "Where does Joe live?"
@@ -480,7 +484,7 @@ Use `template_variables` to overwrite pipeline variables (such as documents) as
```python
__init__(
template: str,
- required_variables: list[str] | Literal["*"] | None = None,
+ required_variables: list[str] | Literal["*"] | None = "*",
variables: list[str] | None = None,
) -> None
```
@@ -492,12 +496,12 @@ Constructs a PromptBuilder component.
- **template** (str) – A prompt template that uses Jinja2 syntax to add variables. For example:
`"Summarize this document: {{ documents[0].content }}\nSummary:"`
It's used to render the prompt.
- The variables in the default template are input for PromptBuilder and are all optional,
- unless explicitly specified.
- If an optional variable is not provided, it's replaced with an empty string in the rendered prompt.
+ The variables in the default template are input for PromptBuilder and are all required by default.
- **required_variables** (list\[str\] | Literal['\*'] | None) – List variables that must be provided as input to PromptBuilder.
- If a variable listed as required is not provided, an exception is raised.
- If set to `"*"`, all variables found in the prompt are required. Optional.
+ Defaults to `"*"`, which marks every variable found in the prompt as required.
+ Pass an explicit list to only require a subset of the variables; any variable not listed becomes
+ optional and is replaced with an empty string in the rendered prompt when missing.
+ Set to `None` to mark every variable as optional.
- **variables** (list\[str\] | None) – List input variables to use in prompt templates instead of the ones inferred from the
`template` parameter. For example, to use more variables during prompt engineering than the ones present
in the default template, you can provide them here.
diff --git a/docs-website/reference/haystack-api/classifiers_api.md b/docs-website/reference/haystack-api/classifiers_api.md
deleted file mode 100644
index 5785ad31d6a..00000000000
--- a/docs-website/reference/haystack-api/classifiers_api.md
+++ /dev/null
@@ -1,247 +0,0 @@
----
-title: "Classifiers"
-id: classifiers-api
-description: "Classify documents based on the provided labels."
-slug: "/classifiers-api"
----
-
-
-## document_language_classifier
-
-### DocumentLanguageClassifier
-
-Classifies the language of each document and adds it to its metadata.
-
-Provide a list of languages during initialization. If the document's text doesn't match any of the
-specified languages, the metadata value is set to "unmatched".
-To route documents based on their language, use the MetadataRouter component after DocumentLanguageClassifier.
-For routing plain text, use the TextLanguageRouter component instead.
-
-### Usage example
-
-```python
-from haystack import Document, Pipeline
-from haystack.document_stores.in_memory import InMemoryDocumentStore
-from haystack.components.classifiers import DocumentLanguageClassifier
-from haystack.components.routers import MetadataRouter
-from haystack.components.writers import DocumentWriter
-
-docs = [Document(id="1", content="This is an English document"),
- Document(id="2", content="Este es un documento en español")]
-
-document_store = InMemoryDocumentStore()
-
-p = Pipeline()
-p.add_component(instance=DocumentLanguageClassifier(languages=["en"]), name="language_classifier")
-p.add_component(
-instance=MetadataRouter(rules={
- "en": {
- "field": "meta.language",
- "operator": "==",
- "value": "en"
- }
-}),
-name="router")
-p.add_component(instance=DocumentWriter(document_store=document_store), name="writer")
-p.connect("language_classifier.documents", "router.documents")
-p.connect("router.en", "writer.documents")
-
-p.run({"language_classifier": {"documents": docs}})
-
-written_docs = document_store.filter_documents()
-assert len(written_docs) == 1
-assert written_docs[0] == Document(id="1", content="This is an English document", meta={"language": "en"})
-```
-
-#### __init__
-
-```python
-__init__(languages: list[str] | None = None) -> None
-```
-
-Initializes the DocumentLanguageClassifier component.
-
-**Parameters:**
-
-- **languages** (list\[str\] | None) – A list of ISO language codes.
- See the supported languages in [`langdetect` documentation](https://github.com/Mimino666/langdetect#languages).
- If not specified, defaults to ["en"].
-
-#### run
-
-```python
-run(documents: list[Document]) -> dict[str, list[Document]]
-```
-
-Classifies the language of each document and adds it to its metadata.
-
-If the document's text doesn't match any of the languages specified at initialization,
-sets the metadata value to "unmatched".
-
-**Parameters:**
-
-- **documents** (list\[Document\]) – A list of documents for language classification.
-
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following key:
-- `documents`: A list of documents with an added `language` metadata field.
-
-**Raises:**
-
-- TypeError – if the input is not a list of Documents.
-
-## zero_shot_document_classifier
-
-### TransformersZeroShotDocumentClassifier
-
-Performs zero-shot classification of documents based on given labels and adds the predicted label to their metadata.
-
-The component uses a Hugging Face pipeline for zero-shot classification.
-Provide the model and the set of labels to be used for categorization during initialization.
-Additionally, you can configure the component to allow multiple labels to be true.
-
-Classification is run on the document's content field by default. If you want it to run on another field, set the
-`classification_field` to one of the document's metadata fields.
-
-Available models for the task of zero-shot-classification include:
-\- `valhalla/distilbart-mnli-12-3`
-\- `cross-encoder/nli-distilroberta-base`
-\- `cross-encoder/nli-deberta-v3-xsmall`
-
-### Usage example
-
-The following is a pipeline that classifies documents based on predefined classification labels
-retrieved from a search pipeline:
-
-```python
-from haystack import Document
-from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
-from haystack.document_stores.in_memory import InMemoryDocumentStore
-from haystack.core.pipeline import Pipeline
-from haystack.components.classifiers import TransformersZeroShotDocumentClassifier
-
-documents = [Document(id="0", content="Today was a nice day!"),
- Document(id="1", content="Yesterday was a bad day!")]
-
-document_store = InMemoryDocumentStore()
-retriever = InMemoryBM25Retriever(document_store=document_store)
-document_classifier = TransformersZeroShotDocumentClassifier(
- model="cross-encoder/nli-deberta-v3-xsmall",
- labels=["positive", "negative"],
-)
-
-document_store.write_documents(documents)
-
-pipeline = Pipeline()
-pipeline.add_component(instance=retriever, name="retriever")
-pipeline.add_component(instance=document_classifier, name="document_classifier")
-pipeline.connect("retriever", "document_classifier")
-
-queries = ["How was your day today?", "How was your day yesterday?"]
-expected_predictions = ["positive", "negative"]
-
-for idx, query in enumerate(queries):
- result = pipeline.run({"retriever": {"query": query, "top_k": 1}})
- assert result["document_classifier"]["documents"][0].to_dict()["id"] == str(idx)
- assert (result["document_classifier"]["documents"][0].to_dict()["classification"]["label"]
- == expected_predictions[idx])
-```
-
-#### __init__
-
-```python
-__init__(
- model: str,
- labels: list[str],
- multi_label: bool = False,
- classification_field: str | None = None,
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- huggingface_pipeline_kwargs: dict[str, Any] | None = None,
-) -> None
-```
-
-Initializes the TransformersZeroShotDocumentClassifier.
-
-See the Hugging Face [website](https://huggingface.co/models?pipeline_tag=zero-shot-classification&sort=downloads&search=nli)
-for the full list of zero-shot classification models (NLI) models.
-
-**Parameters:**
-
-- **model** (str) – The name or path of a Hugging Face model for zero shot document classification.
-- **labels** (list\[str\]) – The set of possible class labels to classify each document into, for example,
- ["positive", "negative"]. The labels depend on the selected model.
-- **multi_label** (bool) – Whether or not multiple candidate labels can be true.
- If `False`, the scores are normalized such that
- the sum of the label likelihoods for each sequence is 1. If `True`, the labels are considered
- independent and probabilities are normalized for each candidate by doing a softmax of the entailment
- score vs. the contradiction score.
-- **classification_field** (str | None) – Name of document's meta field to be used for classification.
- If not set, `Document.content` is used by default.
-- **device** (ComponentDevice | None) – The device on which the model is loaded. If `None`, the default device is automatically
- selected. If a device/device map is specified in `huggingface_pipeline_kwargs`, it overrides this parameter.
-- **token** (Secret | None) – The Hugging Face token to use as HTTP bearer authorization.
- Check your HF token in your [account settings](https://huggingface.co/settings/tokens).
-- **huggingface_pipeline_kwargs** (dict\[str, Any\] | None) – Dictionary containing keyword arguments used to initialize the
- Hugging Face pipeline for text classification.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> TransformersZeroShotDocumentClassifier
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- TransformersZeroShotDocumentClassifier – Deserialized component.
-
-#### run
-
-```python
-run(documents: list[Document], batch_size: int = 1) -> dict[str, Any]
-```
-
-Classifies the documents based on the provided labels and adds them to their metadata.
-
-The classification results are stored in the `classification` dict within
-each document's metadata. If `multi_label` is set to `True`, the scores for each label are available under
-the `details` key within the `classification` dictionary.
-
-**Parameters:**
-
-- **documents** (list\[Document\]) – Documents to process.
-- **batch_size** (int) – Batch size used for processing the content in each document.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following key:
-- `documents`: A list of documents with an added metadata field called `classification`.
diff --git a/docs-website/reference/haystack-api/connectors_api.md b/docs-website/reference/haystack-api/connectors_api.md
deleted file mode 100644
index 25449841228..00000000000
--- a/docs-website/reference/haystack-api/connectors_api.md
+++ /dev/null
@@ -1,275 +0,0 @@
----
-title: "Connectors"
-id: connectors-api
-description: "Various connectors to integrate with external services."
-slug: "/connectors-api"
----
-
-
-## openapi
-
-### OpenAPIConnector
-
-OpenAPIConnector enables direct invocation of REST endpoints defined in an OpenAPI specification.
-
-The OpenAPIConnector serves as a bridge between Haystack pipelines and any REST API that follows
-the OpenAPI(formerly Swagger) specification. It dynamically interprets the API specification and
-provides an interface for executing API operations. It is usually invoked by passing input
-arguments to it from a Haystack pipeline run method or by other components in a pipeline that
-pass input arguments to this component.
-
-Example:
-
-
-
-```python
-from haystack.utils import Secret
-from haystack.components.connectors.openapi import OpenAPIConnector
-
-serper_dev_token = Secret.from_env_var("SERPERDEV_API_KEY")
-
-def my_custom_config_factory():
- # Create and return a custom configuration for the OpenAPIClient
- pass
-
-connector = OpenAPIConnector(
- openapi_spec="https://bit.ly/serperdev_openapi",
- credentials=serper_dev_token,
- service_kwargs={"config_factory": my_custom_config_factory()}
-)
-response = connector.run(
- operation_id="search",
- arguments={"q": "Who was Nikola Tesla?"}
-)
-```
-
-Note:
-
-- The `service_kwargs` argument is optional, it can be used to pass additional options to the OpenAPIClient.
-
-#### __init__
-
-```python
-__init__(
- openapi_spec: str,
- credentials: Secret | None = None,
- service_kwargs: dict[str, Any] | None = None,
-) -> None
-```
-
-Initialize the OpenAPIConnector with a specification and optional credentials.
-
-**Parameters:**
-
-- **openapi_spec** (str) – URL, file path, or raw string of the OpenAPI specification
-- **credentials** (Secret | None) – Optional API key or credentials for the service wrapped in a Secret
-- **service_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments passed to OpenAPIClient.from_spec()
- For example, you can pass a custom config_factory or other configuration options.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serialize this component to a dictionary.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> OpenAPIConnector
-```
-
-Deserialize this component from a dictionary.
-
-#### run
-
-```python
-run(
- operation_id: str, arguments: dict[str, Any] | None = None
-) -> dict[str, Any]
-```
-
-Invokes a REST endpoint specified in the OpenAPI specification.
-
-**Parameters:**
-
-- **operation_id** (str) – The operationId from the OpenAPI spec to invoke
-- **arguments** (dict\[str, Any\] | None) – Optional parameters for the endpoint (query, path, or body parameters)
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary containing the service response
-
-## openapi_service
-
-### patch_request
-
-```python
-patch_request(
- self: Operation,
- base_url: str,
- *,
- data: Any | None = None,
- parameters: dict[str, Any] | None = None,
- raw_response: bool = False,
- security: dict[str, str] | None = None,
- session: Any | None = None,
- verify: bool | str = True
-) -> Any | None
-```
-
-Sends an HTTP request as described by this path.
-
-**Parameters:**
-
-- **base_url** (str) – The URL to append this operation's path to when making
- the call.
-- **data** (Any | None) – The request body to send.
-- **parameters** (dict\[str, Any\] | None) – The parameters used to create the path.
-- **raw_response** (bool) – If true, return the raw response instead of validating
- and extrapolating it.
-- **security** (dict\[str, str\] | None) – The security scheme to use, and the values it needs to
- process successfully.
-- **session** (Any | None) – A persistent request session.
-- **verify** (bool | str) – If we should do an SSL verification on the request or not.
- In case str was provided, will use that as the CA.
-
-**Returns:**
-
-- Any | None – The response data, either raw or processed depending on raw_response flag.
-
-### OpenAPIServiceConnector
-
-A component which connects the Haystack framework to OpenAPI services.
-
-The `OpenAPIServiceConnector` component connects the Haystack framework to OpenAPI services, enabling it to call
-operations as defined in the OpenAPI specification of the service.
-
-It integrates with `ChatMessage` dataclass, where the `ToolCall` entries in messages are used to determine the
-method to be called and the parameters to be passed. The method name and parameters are then used to invoke the
-method on the OpenAPI service. The response from the service is returned as a `ChatMessage`.
-
-Before using this component, users usually resolve service endpoint parameters with a help of
-`OpenAPIServiceToFunctions` component.
-
-The example below demonstrates how to use the `OpenAPIServiceConnector` to invoke a method on a https://serper.dev/
-service specified via OpenAPI specification.
-
-Note, however, that `OpenAPIServiceConnector` is usually not meant to be used directly, but rather as part of a
-pipeline that includes the `OpenAPIServiceToFunctions` component and a Chat Generator component using an LLM
-with tool calling capabilities. In the example below we use the tool call payload directly, but in a
-real-world scenario, the tool calls would usually be generated by the Chat Generator component.
-
-You need to define the `serper_token` variable with your Serper.dev API token for the example to work.
-Can be through the `SERPERDEV_API_KEY` environment variable or by directly assigning the token string to the
-variable in the code.
-
-Usage example:
-
-
-
-```python
-import json
-import httpx
-
-from haystack.components.connectors import OpenAPIServiceConnector
-from haystack.dataclasses import ChatMessage, ToolCall
-from haystack.utils import Secret
-
-tool_call = ToolCall(
- tool_name="search",
- arguments={"q": "Why was Sam Altman ousted from OpenAI?"},
-)
-message = ChatMessage.from_assistant(tool_calls=[tool_call])
-
-serper_token = Secret.from_env_var("SERPERDEV_API_KEY").resolve_value()
-serperdev_openapi_spec = json.loads(httpx.get("https://bit.ly/serper_dev_spec", follow_redirects=True).text)
-service_connector = OpenAPIServiceConnector()
-result = service_connector.run(
- messages=[message],
- service_openapi_spec=serperdev_openapi_spec,
- service_credentials=serper_token,
-)
-print(result)
-
-# {'service_response': ChatMessage(_role=, _content=[TextContent(text=
-# '{"searchParameters": {"q": "Why was Sam Altman ousted from OpenAI?",
-# "type": "search", "engine": "google"}, "answerBox": {"snippet": "Concerns over AI safety and OpenAI's role
-# in protecting were at the center of Altman's brief ouster from the company."...
-```
-
-#### __init__
-
-```python
-__init__(ssl_verify: bool | str | None = None) -> None
-```
-
-Initializes the OpenAPIServiceConnector instance
-
-**Parameters:**
-
-- **ssl_verify** ([bool | str | None) – Decide if to use SSL verification to the requests or not,
- in case a string is passed, will be used as the CA.
-
-#### run
-
-```python
-run(
- messages: list[ChatMessage],
- service_openapi_spec: dict[str, Any],
- service_credentials: dict | str | None = None,
-) -> dict[str, list[ChatMessage]]
-```
-
-Processes a list of chat messages to invoke a method on an OpenAPI service.
-
-It parses the last message in the list, expecting it to contain tool calls.
-
-**Parameters:**
-
-- **messages** (list\[ChatMessage\]) – A list of `ChatMessage` objects containing the messages to be processed. The last message
- should contain the tool calls.
-- **service_openapi_spec** (dict\[str, Any\]) – The OpenAPI JSON specification object of the service to be invoked. All the refs
- should already be resolved.
-- **service_credentials** (dict | str | None) – The credentials to be used for authentication with the service.
- Currently, only the http and apiKey OpenAPI security schemes are supported.
-
-**Returns:**
-
-- dict\[str, list\[ChatMessage\]\] – A dictionary with the following keys:
-- `service_response`: a list of `ChatMessage` objects, each containing the response from the service. The
- response is in JSON format, and the `content` attribute of the `ChatMessage` contains
- the JSON string.
-
-**Raises:**
-
-- ValueError – If the last message is not from the assistant or if it does not contain tool calls.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> OpenAPIServiceConnector
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- OpenAPIServiceConnector – The deserialized component.
diff --git a/docs-website/reference/haystack-api/converters_api.md b/docs-website/reference/haystack-api/converters_api.md
index 2ea0c90456a..543ebb54f68 100644
--- a/docs-website/reference/haystack-api/converters_api.md
+++ b/docs-website/reference/haystack-api/converters_api.md
@@ -6,135 +6,6 @@ slug: "/converters-api"
---
-## azure
-
-### AzureOCRDocumentConverter
-
-Converts files to documents using Azure's Document Intelligence service.
-
-Supported file formats are: PDF, JPEG, PNG, BMP, TIFF, DOCX, XLSX, PPTX, and HTML.
-
-To use this component, you need an active Azure account
-and a Document Intelligence or Cognitive Services resource. For help with setting up your resource, see
-[Azure documentation](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/quickstarts/get-started-sdks-rest-api).
-
-### Usage example
-
-
-
-```python
-import os
-from datetime import datetime
-from haystack.components.converters import AzureOCRDocumentConverter
-from haystack.utils import Secret
-
-converter = AzureOCRDocumentConverter(
- endpoint=os.environ["CORE_AZURE_CS_ENDPOINT"],
- api_key=Secret.from_env_var("CORE_AZURE_CS_API_KEY"),
-)
-results = converter.run(
- sources=["test/test_files/pdf/react_paper.pdf"],
- meta={"date_added": datetime.now().isoformat()},
-)
-documents = results["documents"]
-print(documents[0].content)
-# 'This is a text from the PDF file.'
-```
-
-#### __init__
-
-```python
-__init__(
- endpoint: str,
- api_key: Secret = Secret.from_env_var("AZURE_AI_API_KEY"),
- model_id: str = "prebuilt-read",
- preceding_context_len: int = 3,
- following_context_len: int = 3,
- merge_multiple_column_headers: bool = True,
- page_layout: Literal["natural", "single_column"] = "natural",
- threshold_y: float | None = 0.05,
- store_full_path: bool = False,
-) -> None
-```
-
-Creates an AzureOCRDocumentConverter component.
-
-**Parameters:**
-
-- **endpoint** (str) – The endpoint of your Azure resource.
-- **api_key** (Secret) – The API key of your Azure resource.
-- **model_id** (str) – The ID of the model you want to use. For a list of available models, see [Azure documentation]
- (https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/choose-model-feature).
-- **preceding_context_len** (int) – Number of lines before a table to include as preceding context
- (this will be added to the metadata).
-- **following_context_len** (int) – Number of lines after a table to include as subsequent context (
- this will be added to the metadata).
-- **merge_multiple_column_headers** (bool) – If `True`, merges multiple column header rows into a single row.
-- **page_layout** (Literal['natural', 'single_column']) – The type reading order to follow. Possible options:
-- `natural`: Uses the natural reading order determined by Azure.
-- `single_column`: Groups all lines with the same height on the page based on a threshold
- determined by `threshold_y`.
-- **threshold_y** (float | None) – Only relevant if `single_column` is set to `page_layout`.
- The threshold, in inches, to determine if two recognized PDF elements are grouped into a
- single line. This is crucial for section headers or numbers which may be spatially separated
- from the remaining text on the horizontal axis.
-- **store_full_path** (bool) – If True, the full path of the file is stored in the metadata of the document.
- If False, only the file name is stored.
-
-#### run
-
-```python
-run(
- sources: list[str | Path | ByteStream],
- meta: dict[str, Any] | list[dict[str, Any]] | None = None,
-) -> dict[str, Any]
-```
-
-Convert a list of files to Documents using Azure's Document Intelligence service.
-
-**Parameters:**
-
-- **sources** (list\[str | Path | ByteStream\]) – List of file paths or ByteStream objects.
-- **meta** (dict\[str, Any\] | list\[dict\[str, Any\]\] | None) – Optional metadata to attach to the Documents.
- This value can be either a list of dictionaries or a single dictionary.
- If it's a single dictionary, its content is added to the metadata of all produced Documents.
- If it's a list, the length of the list must match the number of sources, because the two lists will be
- zipped. If `sources` contains ByteStream objects, their `meta` will be added to the output Documents.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following keys:
-- `documents`: List of created Documents
-- `raw_azure_response`: List of raw Azure responses used to create the Documents
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> AzureOCRDocumentConverter
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- AzureOCRDocumentConverter – The deserialized component.
-
## csv
### CSVToDocument
@@ -626,7 +497,8 @@ into ImageContent objects.
Converts image file references into empty Document objects with associated metadata.
This component is useful in pipelines where image file paths need to be wrapped in `Document` objects to be
-processed by downstream components such as the `SentenceTransformersImageDocumentEmbedder`.
+processed by downstream components such as the `LLMDocumentContentExtractor` or the
+`SentenceTransformersDocumentImageEmbedder` (available in the `sentence-transformers-haystack` integration).
It does **not** extract any content from the image files, instead it creates `Document` objects with `None` as
their content and attaches metadata such as file path and any user-provided values.
@@ -1211,67 +1083,6 @@ Initialize the MultiFileConverter.
- **encoding** (str) – The encoding to use when reading files.
- **json_content_key** (str) – The key to use in a content field in a document when converting JSON files.
-## openapi_functions
-
-### OpenAPIServiceToFunctions
-
-Converts OpenAPI service definitions to a format suitable for OpenAI function calling.
-
-The definition must respect OpenAPI specification 3.0.0 or higher.
-It can be specified in JSON or YAML format.
-Each function must have:
-\- unique operationId
-\- description
-\- requestBody and/or parameters
-\- schema for the requestBody and/or parameters
-For more details on OpenAPI specification see the [official documentation](https://github.com/OAI/OpenAPI-Specification).
-For more details on OpenAI function calling see the [official documentation](https://platform.openai.com/docs/guides/function-calling).
-
-Usage example:
-
-```python
-from haystack.components.converters import OpenAPIServiceToFunctions
-from haystack.dataclasses.byte_stream import ByteStream
-
-converter = OpenAPIServiceToFunctions()
-spec = ByteStream.from_string(
- '{"openapi":"3.0.0","info":{"title":"API","version":"1.0.0"},"paths":{"/search":{"get":{"operationId":"search","summary":"Search","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}}]}}}}'
-)
-result = converter.run(sources=[spec])
-assert result["functions"]
-```
-
-#### __init__
-
-```python
-__init__() -> None
-```
-
-Create an OpenAPIServiceToFunctions component.
-
-#### run
-
-```python
-run(sources: list[str | Path | ByteStream]) -> dict[str, Any]
-```
-
-Converts OpenAPI definitions in OpenAI function calling format.
-
-**Parameters:**
-
-- **sources** (list\[str | Path | ByteStream\]) – File paths or ByteStream objects of OpenAPI definitions (in JSON or YAML format).
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following keys:
-- functions: Function definitions in JSON object format
-- openapi_specs: OpenAPI specs in JSON/YAML object format with resolved references
-
-**Raises:**
-
-- RuntimeError – If the OpenAPI definitions cannot be downloaded or processed.
-- ValueError – If the source type is not recognized or no functions are found in the OpenAPI definitions.
-
## output_adapter
### OutputAdaptationException
@@ -1705,108 +1516,6 @@ Converts PDF files to documents.
- dict\[str, list\[Document\]\] – A dictionary with the following keys:
- `documents`: A list of converted documents.
-## tika
-
-### XHTMLParser
-
-Bases: HTMLParser
-
-Custom parser to extract pages from Tika XHTML content.
-
-#### handle_starttag
-
-```python
-handle_starttag(tag: str, attrs: list[tuple[str, str | None]]) -> None
-```
-
-Identify the start of a page div.
-
-#### handle_endtag
-
-```python
-handle_endtag(tag: str) -> None
-```
-
-Identify the end of a page div.
-
-#### handle_data
-
-```python
-handle_data(data: str) -> None
-```
-
-Populate the page content.
-
-### TikaDocumentConverter
-
-Converts files of different types to Documents.
-
-This component uses [Apache Tika](https://tika.apache.org/) for parsing the files and, therefore,
-requires a running Tika server.
-For more options on running Tika,
-see the [official documentation](https://github.com/apache/tika-docker/blob/main/README.md#usage).
-
-Usage example:
-
-
-
-```python
-from haystack.components.converters.tika import TikaDocumentConverter
-from datetime import datetime
-
-converter = TikaDocumentConverter()
-results = converter.run(
- sources=["sample.docx", "my_document.rtf", "archive.zip"],
- meta={"date_added": datetime.now().isoformat()}
-)
-documents = results["documents"]
-
-print(documents[0].content)
-# >> 'This is a text from the docx file.'
-```
-
-#### __init__
-
-```python
-__init__(
- tika_url: str = "http://localhost:9998/tika", store_full_path: bool = False
-) -> None
-```
-
-Create a TikaDocumentConverter component.
-
-**Parameters:**
-
-- **tika_url** (str) – Tika server URL.
-- **store_full_path** (bool) – If True, the full path of the file is stored in the metadata of the document.
- If False, only the file name is stored.
-
-#### run
-
-```python
-run(
- sources: list[str | Path | ByteStream],
- meta: dict[str, Any] | list[dict[str, Any]] | None = None,
-) -> dict[str, list[Document]]
-```
-
-Converts files to Documents.
-
-**Parameters:**
-
-- **sources** (list\[str | Path | ByteStream\]) – List of HTML file paths or ByteStream objects.
-- **meta** (dict\[str, Any\] | list\[dict\[str, Any\]\] | None) – Optional metadata to attach to the Documents.
- This value can be either a list of dictionaries or a single dictionary.
- If it's a single dictionary, its content is added to the metadata of all produced Documents.
- If it's a list, the length of the list must match the number of sources, because the two lists will
- be zipped.
- If `sources` contains ByteStream objects, their `meta` will be added to the output Documents.
-
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
-- `documents`: Created Documents
-
## txt
### TextFileToDocument
diff --git a/docs-website/reference/haystack-api/data_classes_api.md b/docs-website/reference/haystack-api/data_classes_api.md
index 3b7b14dd5cd..9c99a7413ba 100644
--- a/docs-website/reference/haystack-api/data_classes_api.md
+++ b/docs-website/reference/haystack-api/data_classes_api.md
@@ -114,97 +114,6 @@ Populate the Breakpoint from a dictionary representation.
- Breakpoint – An instance of Breakpoint.
-### ToolBreakpoint
-
-Bases: Breakpoint
-
-A dataclass representing a breakpoint specific to tools used within an Agent component.
-
-Inherits from Breakpoint and adds the ability to target individual tools. If `tool_name` is None,
-the breakpoint applies to all tools within the Agent component.
-
-**Parameters:**
-
-- **tool_name** (str | None) – The name of the tool to target within the Agent component. If None, applies to all tools.
-
-### AgentBreakpoint
-
-A dataclass representing a breakpoint tied to an Agent’s execution.
-
-This allows for debugging either a specific component (e.g., the chat generator) or a tool used by the agent.
-It enforces constraints on which component names are valid for each breakpoint type.
-
-**Parameters:**
-
-- **agent_name** (str) – The name of the agent component in a pipeline where the breakpoint is set.
-- **break_point** (Breakpoint | ToolBreakpoint) – An instance of Breakpoint or ToolBreakpoint indicating where to break execution.
-
-**Raises:**
-
-- ValueError – If the component_name is invalid for the given breakpoint type:
-- Breakpoint must have component_name='chat_generator'.
-- ToolBreakpoint must have component_name='tool_invoker'.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Convert the AgentBreakpoint to a dictionary representation.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary containing the agent name and the breakpoint details.
-
-#### from_dict
-
-```python
-from_dict(data: dict) -> AgentBreakpoint
-```
-
-Populate the AgentBreakpoint from a dictionary representation.
-
-**Parameters:**
-
-- **data** (dict) – A dictionary containing the agent name and the breakpoint details.
-
-**Returns:**
-
-- AgentBreakpoint – An instance of AgentBreakpoint.
-
-### AgentSnapshot
-
-Snapshot of an Agent's state at a breakpoint (component inputs, visit counts, and breakpoint).
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Convert the AgentSnapshot to a dictionary representation.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary containing the agent state, timestamp, and breakpoint.
-
-#### from_dict
-
-```python
-from_dict(data: dict) -> AgentSnapshot
-```
-
-Populate the AgentSnapshot from a dictionary representation.
-
-**Parameters:**
-
-- **data** (dict) – A dictionary containing the agent state, timestamp, and breakpoint.
-
-**Returns:**
-
-- AgentSnapshot – An instance of AgentSnapshot.
-
### PipelineState
A dataclass to hold the state of the pipeline at a specific point in time.
@@ -254,8 +163,7 @@ A dataclass to hold a snapshot of the pipeline at a specific point in time.
- **original_input_data** (dict\[str, Any\]) – The original input data provided to the pipeline.
- **ordered_component_names** (list\[str\]) – A list of component names in the order they were visited.
- **pipeline_state** (PipelineState) – The state of the pipeline at the time of the snapshot.
-- **break_point** (AgentBreakpoint | Breakpoint) – The breakpoint that triggered the snapshot.
-- **agent_snapshot** (AgentSnapshot | None) – Optional agent snapshot if the breakpoint is an agent breakpoint.
+- **break_point** (Breakpoint) – The breakpoint that triggered the snapshot.
- **timestamp** (datetime | None) – A timestamp indicating when the snapshot was taken.
- **include_outputs_from** (set\[str\]) – Set of component names whose outputs should be included in the pipeline results.
@@ -1138,6 +1046,20 @@ For PDF to ImageContent conversion, use the `PDFToImageContent` component.
- ValueError – If the URL does not point to an image or if it points to a PDF file.
+## skill_info
+
+### SkillInfo
+
+Lightweight metadata describing a skill.
+
+This is what a `SkillStore` returns when listing its skills, keeping the catalog cheap; the full skill
+content (the instructions body and bundled files) is fetched on demand.
+
+**Parameters:**
+
+- **name** (str) – The skill's name, used to look it up.
+- **description** (str) – A short description of when to use the skill. Shown to the agent up front.
+
## sparse_embedding
### SparseEmbedding
@@ -1338,11 +1260,15 @@ Picks the correct streaming callback given an optional initial and runtime callb
The runtime callback takes precedence over the initial callback.
+In an async context (`requires_async=True`), a sync callback is accepted but emits a warning: it will run inline on
+the event loop and may block it. In a sync context (`requires_async=False`), an async callback is rejected because
+there is no way to await it.
+
**Parameters:**
- **init_callback** (StreamingCallbackT | None) – The initial callback.
- **runtime_callback** (StreamingCallbackT | None) – The runtime callback.
-- **requires_async** (bool) – Whether the selected callback must be async compatible.
+- **requires_async** (bool) – Whether the selected callback will be invoked from an async context.
**Returns:**
diff --git a/docs-website/reference/haystack-api/document_stores_api.md b/docs-website/reference/haystack-api/document_stores_api.md
index 635ffe2a63b..107347db73d 100644
--- a/docs-website/reference/haystack-api/document_stores_api.md
+++ b/docs-website/reference/haystack-api/document_stores_api.md
@@ -32,6 +32,7 @@ __init__(
"dot_product", "cosine"
] = "dot_product",
index: str | None = None,
+ shared: bool = True,
async_executor: ThreadPoolExecutor | None = None,
return_embedding: bool = True,
) -> None
@@ -50,7 +51,11 @@ Initializes the DocumentStore.
One of "dot_product" (default) or "cosine". To choose the most appropriate function, look for information
about your embedding model.
- **index** (str | None) – A specific index to store the documents. If not specified, a random UUID is used.
- Using the same index allows you to store documents across multiple InMemoryDocumentStore instances.
+ When `shared` is True, instances using the same index share the same documents.
+- **shared** (bool) – Whether the documents live in process-global storage shared across instances using the same
+ index (True, the default), or are kept instance-local and freed when this instance is garbage collected
+ (False). Shared storage persists for the lifetime of the process, so prefer `shared=False` for stores
+ that are created frequently (for example per request) to avoid unbounded memory growth.
- **async_executor** (ThreadPoolExecutor | None) – Optional ThreadPoolExecutor to use for async calls. If not provided, a single-threaded
executor will be initialized and used.
- **return_embedding** (bool) – Whether to return the embedding of the retrieved Documents. Default is True.
diff --git a/docs-website/reference/haystack-api/embedders_api.md b/docs-website/reference/haystack-api/embedders_api.md
index 9638aca1d08..f2dcee126ee 100644
--- a/docs-website/reference/haystack-api/embedders_api.md
+++ b/docs-website/reference/haystack-api/embedders_api.md
@@ -101,6 +101,38 @@ Creates an AzureOpenAIDocumentEmbedder component.
- **raise_on_failure** (bool) – Whether to raise an exception if the embedding request fails. If `False`, the component will log the error
and continue processing the remaining documents. If `True`, it will raise an exception on failure.
+#### warm_up
+
+```python
+warm_up() -> None
+```
+
+Initializes the synchronous AzureOpenAI client.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Initializes the asynchronous AzureOpenAI client on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Releases the synchronous AzureOpenAI client.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Releases the asynchronous AzureOpenAI client.
+
#### to_dict
```python
@@ -213,157 +245,141 @@ Creates an AzureOpenAITextEmbedder component.
- **http_client_kwargs** (dict\[str, Any\] | None) – A dictionary of keyword arguments to configure a custom `httpx.Client`or `httpx.AsyncClient`.
For more information, see the [HTTPX documentation](https://www.python-httpx.org/api/#client).
-#### to_dict
+#### warm_up
```python
-to_dict() -> dict[str, Any]
+warm_up() -> None
```
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
+Initializes the synchronous Azure OpenAI client.
-#### from_dict
+#### warm_up_async
```python
-from_dict(data: dict[str, Any]) -> AzureOpenAITextEmbedder
+warm_up_async() -> None
```
-Deserializes the component from a dictionary.
+Initializes the asynchronous Azure OpenAI client on the serving event loop.
-**Parameters:**
+#### close
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
+```python
+close() -> None
+```
-**Returns:**
+Releases the synchronous Azure OpenAI client.
-- AzureOpenAITextEmbedder – Deserialized component.
+#### close_async
-## hugging_face_api_document_embedder
+```python
+close_async() -> None
+```
-### HuggingFaceAPIDocumentEmbedder
+Releases the asynchronous Azure OpenAI client.
-Embeds documents using Hugging Face APIs.
+#### to_dict
-Use it with the following Hugging Face APIs:
+```python
+to_dict() -> dict[str, Any]
+```
-- [Free Serverless Inference API](https://huggingface.co/inference-api)
-- [Paid Inference Endpoints](https://huggingface.co/inference-endpoints)
-- [Self-hosted Text Embeddings Inference](https://github.com/huggingface/text-embeddings-inference)
+Serializes the component to a dictionary.
-### Usage examples
+**Returns:**
-#### With free serverless inference API
+- dict\[str, Any\] – Dictionary with serialized data.
-
+#### from_dict
```python
-from haystack.components.embedders import HuggingFaceAPIDocumentEmbedder
-from haystack.utils import Secret
-from haystack.dataclasses import Document
+from_dict(data: dict[str, Any]) -> AzureOpenAITextEmbedder
+```
-doc = Document(content="I love pizza!")
+Deserializes the component from a dictionary.
-doc_embedder = HuggingFaceAPIDocumentEmbedder(api_type="serverless_inference_api",
- api_params={"model": "BAAI/bge-small-en-v1.5"},
- token=Secret.from_token(""))
+**Parameters:**
-result = document_embedder.run([doc])
-print(result["documents"][0].embedding)
+- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-# [0.017020374536514282, -0.023255806416273117, ...]
-```
+**Returns:**
-#### With paid inference endpoints
+- AzureOpenAITextEmbedder – Deserialized component.
-
+## mock_document_embedder
-```python
-from haystack.components.embedders import HuggingFaceAPIDocumentEmbedder
-from haystack.utils import Secret
-from haystack.dataclasses import Document
+### MockDocumentEmbedder
-doc = Document(content="I love pizza!")
+A Document Embedder that returns deterministic embeddings without calling any API.
-doc_embedder = HuggingFaceAPIDocumentEmbedder(api_type="inference_endpoints",
- api_params={"url": ""},
- token=Secret.from_token(""))
+It is a drop-in replacement for real Document Embedders (such as `OpenAIDocumentEmbedder`) in tests, smoke tests,
+and quick prototypes. It implements the same interface (`run`, `run_async`, serialization) but never contacts an
+external service, so it is fully deterministic and free to run.
-result = document_embedder.run([doc])
-print(result["documents"][0].embedding)
+The embedding is selected based on how the component is configured:
-# [0.017020374536514282, -0.023255806416273117, ...]
-```
+- **Deterministic (default)**: with no configuration, each document's embedding is derived from a hash of its
+ (prepared) text. The same text always yields the same embedding, and different texts yield different
+ embeddings, so the mock works in retrieval pipelines and is reproducible across runs and processes.
+- **Fixed embedding**: pass an `embedding` vector. The same vector is assigned to every document.
+- **Dynamic embedding**: pass an `embedding_fn` callable that receives the (prepared) text of a document and
+ returns the embedding. This is useful when the embedding should depend on the input in a custom way.
-#### With self-hosted text embeddings inference
+Like real Document Embedders, the metadata fields listed in `meta_fields_to_embed` are concatenated with the
+document content before embedding, so the deterministic embedding reflects the embedded metadata.
-
+### Usage example
```python
-from haystack.components.embedders import HuggingFaceAPIDocumentEmbedder
-from haystack.dataclasses import Document
-
-doc = Document(content="I love pizza!")
-
-doc_embedder = HuggingFaceAPIDocumentEmbedder(api_type="text_embeddings_inference",
- api_params={"url": "http://localhost:8080"})
-
-result = document_embedder.run([doc])
-print(result["documents"][0].embedding)
+from haystack import Document
+from haystack.components.embedders import MockDocumentEmbedder
-# [0.017020374536514282, -0.023255806416273117, ...]
+embedder = MockDocumentEmbedder(dimension=8)
+result = embedder.run([Document(content="I love pizza!")])
+print(result["documents"][0].embedding) # a deterministic list of 8 floats
```
#### __init__
```python
__init__(
- api_type: HFEmbeddingAPIType | str,
- api_params: dict[str, str],
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
+ embedding: list[float] | None = None,
+ *,
+ embedding_fn: EmbeddingFn | None = None,
+ dimension: int = 768,
+ model: str = "mock-model",
+ meta: dict[str, Any] | None = None,
prefix: str = "",
suffix: str = "",
- truncate: bool | None = True,
- normalize: bool | None = False,
- batch_size: int = 32,
- progress_bar: bool = True,
meta_fields_to_embed: list[str] | None = None,
embedding_separator: str = "\n",
- concurrency_limit: int = 4,
+ progress_bar: bool = False
) -> None
```
-Creates a HuggingFaceAPIDocumentEmbedder component.
+Creates an instance of MockDocumentEmbedder.
**Parameters:**
-- **api_type** (HFEmbeddingAPIType | str) – The type of Hugging Face API to use.
-- **api_params** (dict\[str, str\]) – A dictionary with the following keys:
-- `model`: Hugging Face model ID. Required when `api_type` is `SERVERLESS_INFERENCE_API`.
-- `url`: URL of the inference endpoint. Required when `api_type` is `INFERENCE_ENDPOINTS` or
- `TEXT_EMBEDDINGS_INFERENCE`.
-- **token** (Secret | None) – The Hugging Face token to use as HTTP bearer authorization.
- Check your HF token in your [account settings](https://huggingface.co/settings/tokens).
-- **prefix** (str) – A string to add at the beginning of each text.
-- **suffix** (str) – A string to add at the end of each text.
-- **truncate** (bool | None) – Truncates the input text to the maximum length supported by the model.
- Applicable when `api_type` is `TEXT_EMBEDDINGS_INFERENCE`, or `INFERENCE_ENDPOINTS`
- if the backend uses Text Embeddings Inference.
- If `api_type` is `SERVERLESS_INFERENCE_API`, this parameter is ignored.
-- **normalize** (bool | None) – Normalizes the embeddings to unit length.
- Applicable when `api_type` is `TEXT_EMBEDDINGS_INFERENCE`, or `INFERENCE_ENDPOINTS`
- if the backend uses Text Embeddings Inference.
- If `api_type` is `SERVERLESS_INFERENCE_API`, this parameter is ignored.
-- **batch_size** (int) – Number of documents to process at once.
-- **progress_bar** (bool) – If `True`, shows a progress bar when running.
+- **embedding** (list\[float\] | None) – An optional fixed embedding assigned to every document. Mutually exclusive with
+ `embedding_fn`. If neither is provided, a deterministic embedding is derived from each document's text.
+- **embedding_fn** (EmbeddingFn | None) – An optional callable that receives the prepared text of a document and returns the
+ embedding as a list of floats. Mutually exclusive with `embedding`. To support serialization, pass a
+ named function (lambdas and nested functions cannot be serialized).
+- **dimension** (int) – The number of dimensions of the deterministic embedding. Ignored when `embedding` or
+ `embedding_fn` is provided, since their length is determined by the value or callable.
+- **model** (str) – The model name reported in the metadata. Purely cosmetic; no model is loaded.
+- **meta** (dict\[str, Any\] | None) – Additional metadata merged into the output `meta`.
+- **prefix** (str) – A string to add at the beginning of each text before embedding.
+- **suffix** (str) – A string to add at the end of each text before embedding.
- **meta_fields_to_embed** (list\[str\] | None) – List of metadata fields to embed along with the document text.
- **embedding_separator** (str) – Separator used to concatenate the metadata fields to the document text.
-- **concurrency_limit** (int) – The maximum number of requests that should be allowed to run concurrently.
- This parameter is only used in the `run_async` method.
+- **progress_bar** (bool) – Accepted for interface compatibility with real Document Embedders and ignored.
+
+**Raises:**
+
+- ValueError – If both `embedding` and `embedding_fn` are provided, if `dimension` is not positive, or
+ if `embedding` is an empty list.
+- TypeError – If `embedding` is not a sequence of numbers.
#### to_dict
@@ -371,162 +387,133 @@ Creates a HuggingFaceAPIDocumentEmbedder component.
to_dict() -> dict[str, Any]
```
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
+Serialize the component to a dictionary.
#### from_dict
```python
-from_dict(data: dict[str, Any]) -> HuggingFaceAPIDocumentEmbedder
+from_dict(data: dict[str, Any]) -> MockDocumentEmbedder
```
-Deserializes the component from a dictionary.
-
-**Parameters:**
+Deserialize the component from a dictionary.
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
+#### warm_up
-**Returns:**
+```python
+warm_up() -> None
+```
-- HuggingFaceAPIDocumentEmbedder – Deserialized component.
+No-op warm up, provided for interface compatibility with real Embedders.
#### run
```python
-run(documents: list[Document]) -> dict[str, list[Document]]
+run(documents: list[Document]) -> dict[str, Any]
```
-Embeds a list of documents.
+Return the input documents with deterministic embeddings added, without calling any API.
**Parameters:**
-- **documents** (list\[Document\]) – Documents to embed.
+- **documents** (list\[Document\]) – A list of documents to embed.
**Returns:**
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
+- dict\[str, Any\] – A dictionary with the following keys:
- `documents`: A list of documents with embeddings.
+- `meta`: Metadata about the (mock) model.
+
+**Raises:**
+
+- TypeError – If `documents` is not a list of `Document` objects.
#### run_async
```python
-run_async(documents: list[Document]) -> dict[str, list[Document]]
+run_async(documents: list[Document]) -> dict[str, Any]
```
-Embeds a list of documents asynchronously.
+Asynchronously return the input documents with deterministic embeddings added, without calling any API.
**Parameters:**
-- **documents** (list\[Document\]) – Documents to embed.
+- **documents** (list\[Document\]) – A list of documents to embed.
**Returns:**
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
+- dict\[str, Any\] – A dictionary with the following keys:
- `documents`: A list of documents with embeddings.
+- `meta`: Metadata about the (mock) model.
-## hugging_face_api_text_embedder
-
-### HuggingFaceAPITextEmbedder
-
-Embeds strings using Hugging Face APIs.
+**Raises:**
-Use it with the following Hugging Face APIs:
+- TypeError – If `documents` is not a list of `Document` objects.
-- [Free Serverless Inference API](https://huggingface.co/inference-api)
-- [Paid Inference Endpoints](https://huggingface.co/inference-endpoints)
-- [Self-hosted Text Embeddings Inference](https://github.com/huggingface/text-embeddings-inference)
+## mock_text_embedder
-### Usage examples
+### MockTextEmbedder
-#### With free serverless inference API
+A Text Embedder that returns deterministic embeddings without calling any API.
-
-
-```python
-from haystack.components.embedders import HuggingFaceAPITextEmbedder
-from haystack.utils import Secret
-
-text_embedder = HuggingFaceAPITextEmbedder(api_type="serverless_inference_api",
- api_params={"model": "BAAI/bge-small-en-v1.5"},
- token=Secret.from_token(""))
-
-print(text_embedder.run("I love pizza!"))
-
-# {'embedding': [0.017020374536514282, -0.023255806416273117, ...],
-```
+It is a drop-in replacement for real Text Embedders (such as `OpenAITextEmbedder`) in tests, smoke tests, and
+quick prototypes. It implements the same interface (`run`, `run_async`, serialization) but never contacts an
+external service, so it is fully deterministic and free to run.
-#### With paid inference endpoints
-
-
-
-```python
-from haystack.components.embedders import HuggingFaceAPITextEmbedder
-from haystack.utils import Secret
-text_embedder = HuggingFaceAPITextEmbedder(api_type="inference_endpoints",
- api_params={"model": "BAAI/bge-small-en-v1.5"},
- token=Secret.from_token(""))
-
-print(text_embedder.run("I love pizza!"))
-
-# {'embedding': [0.017020374536514282, -0.023255806416273117, ...],
-```
+The embedding is selected based on how the component is configured:
-#### With self-hosted text embeddings inference
+- **Deterministic (default)**: with no configuration, the embedding is derived from a hash of the input text.
+ The same text always yields the same embedding, and different texts yield different embeddings, so the mock
+ works in retrieval pipelines and is reproducible across runs and processes.
+- **Fixed embedding**: pass an `embedding` vector. The same vector is returned for every input.
+- **Dynamic embedding**: pass an `embedding_fn` callable that receives the (prepared) text and returns the
+ embedding. This is useful when the embedding should depend on the input in a custom way.
-
+### Usage example
```python
-from haystack.components.embedders import HuggingFaceAPITextEmbedder
-from haystack.utils import Secret
-
-text_embedder = HuggingFaceAPITextEmbedder(api_type="text_embeddings_inference",
- api_params={"url": "http://localhost:8080"})
-
-print(text_embedder.run("I love pizza!"))
+from haystack.components.embedders import MockTextEmbedder
-# {'embedding': [0.017020374536514282, -0.023255806416273117, ...],
+embedder = MockTextEmbedder(dimension=8)
+result = embedder.run("I love pizza!")
+print(result["embedding"]) # a deterministic list of 8 floats
```
#### __init__
```python
__init__(
- api_type: HFEmbeddingAPIType | str,
- api_params: dict[str, str],
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
+ embedding: list[float] | None = None,
+ *,
+ embedding_fn: EmbeddingFn | None = None,
+ dimension: int = 768,
+ model: str = "mock-model",
+ meta: dict[str, Any] | None = None,
prefix: str = "",
- suffix: str = "",
- truncate: bool | None = True,
- normalize: bool | None = False,
+ suffix: str = ""
) -> None
```
-Creates a HuggingFaceAPITextEmbedder component.
+Creates an instance of MockTextEmbedder.
**Parameters:**
-- **api_type** (HFEmbeddingAPIType | str) – The type of Hugging Face API to use.
-- **api_params** (dict\[str, str\]) – A dictionary with the following keys:
-- `model`: Hugging Face model ID. Required when `api_type` is `SERVERLESS_INFERENCE_API`.
-- `url`: URL of the inference endpoint. Required when `api_type` is `INFERENCE_ENDPOINTS` or
- `TEXT_EMBEDDINGS_INFERENCE`.
-- **token** (Secret | None) – The Hugging Face token to use as HTTP bearer authorization.
- Check your HF token in your [account settings](https://huggingface.co/settings/tokens).
-- **prefix** (str) – A string to add at the beginning of each text.
-- **suffix** (str) – A string to add at the end of each text.
-- **truncate** (bool | None) – Truncates the input text to the maximum length supported by the model.
- Applicable when `api_type` is `TEXT_EMBEDDINGS_INFERENCE`, or `INFERENCE_ENDPOINTS`
- if the backend uses Text Embeddings Inference.
- If `api_type` is `SERVERLESS_INFERENCE_API`, this parameter is ignored.
-- **normalize** (bool | None) – Normalizes the embeddings to unit length.
- Applicable when `api_type` is `TEXT_EMBEDDINGS_INFERENCE`, or `INFERENCE_ENDPOINTS`
- if the backend uses Text Embeddings Inference.
- If `api_type` is `SERVERLESS_INFERENCE_API`, this parameter is ignored.
+- **embedding** (list\[float\] | None) – An optional fixed embedding returned for every input. Mutually exclusive with
+ `embedding_fn`. If neither is provided, a deterministic embedding is derived from the input text.
+- **embedding_fn** (EmbeddingFn | None) – An optional callable that receives the prepared text (after `prefix`/`suffix` are
+ applied) and returns the embedding as a list of floats. Mutually exclusive with `embedding`. To support
+ serialization, pass a named function (lambdas and nested functions cannot be serialized).
+- **dimension** (int) – The number of dimensions of the deterministic embedding. Ignored when `embedding` or
+ `embedding_fn` is provided, since their length is determined by the value or callable.
+- **model** (str) – The model name reported in the metadata. Purely cosmetic; no model is loaded.
+- **meta** (dict\[str, Any\] | None) – Additional metadata merged into the output `meta`.
+- **prefix** (str) – A string to add at the beginning of the text before embedding.
+- **suffix** (str) – A string to add at the end of the text before embedding.
+
+**Raises:**
+
+- ValueError – If both `embedding` and `embedding_fn` are provided, if `dimension` is not positive, or
+ if `embedding` is an empty list.
+- TypeError – If `embedding` is not a sequence of numbers.
#### to_dict
@@ -534,27 +521,23 @@ Creates a HuggingFaceAPITextEmbedder component.
to_dict() -> dict[str, Any]
```
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
+Serialize the component to a dictionary.
#### from_dict
```python
-from_dict(data: dict[str, Any]) -> HuggingFaceAPITextEmbedder
+from_dict(data: dict[str, Any]) -> MockTextEmbedder
```
-Deserializes the component from a dictionary.
-
-**Parameters:**
+Deserialize the component from a dictionary.
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
+#### warm_up
-**Returns:**
+```python
+warm_up() -> None
+```
-- HuggingFaceAPITextEmbedder – Deserialized component.
+No-op warm up, provided for interface compatibility with real Embedders.
#### run
@@ -562,16 +545,21 @@ Deserializes the component from a dictionary.
run(text: str) -> dict[str, Any]
```
-Embeds a single string.
+Return a deterministic embedding for the input text without calling any API.
**Parameters:**
-- **text** (str) – Text to embed.
+- **text** (str) – The text to embed.
**Returns:**
- dict\[str, Any\] – A dictionary with the following keys:
- `embedding`: The embedding of the input text.
+- `meta`: Metadata about the (mock) model.
+
+**Raises:**
+
+- TypeError – If `text` is not a string.
#### run_async
@@ -579,174 +567,21 @@ Embeds a single string.
run_async(text: str) -> dict[str, Any]
```
-Embeds a single string asynchronously.
+Asynchronously return a deterministic embedding for the input text without calling any API.
**Parameters:**
-- **text** (str) – Text to embed.
+- **text** (str) – The text to embed.
**Returns:**
- dict\[str, Any\] – A dictionary with the following keys:
- `embedding`: The embedding of the input text.
+- `meta`: Metadata about the (mock) model.
-## image/sentence_transformers_doc_image_embedder
-
-### SentenceTransformersDocumentImageEmbedder
-
-A component for computing Document embeddings based on images using Sentence Transformers models.
-
-The embedding of each Document is stored in the `embedding` field of the Document.
-
-### Usage example
-
-
-
-```python
-from haystack import Document
-from haystack.components.embedders.image import SentenceTransformersDocumentImageEmbedder
-
-embedder = SentenceTransformersDocumentImageEmbedder(model="sentence-transformers/clip-ViT-B-32")
-
-documents = [
- Document(content="A photo of a cat", meta={"file_path": "cat.jpg"}),
- Document(content="A photo of a dog", meta={"file_path": "dog.jpg"}),
-]
-
-result = embedder.run(documents=documents)
-documents_with_embeddings = result["documents"]
-print(documents_with_embeddings)
-
-# [Document(id=...,
-# content='A photo of a cat',
-# meta={'file_path': 'cat.jpg',
-# 'embedding_source': {'type': 'image', 'file_path_meta_field': 'file_path'}},
-# embedding=vector of size 512),
-# ...]
-```
-
-#### __init__
-
-```python
-__init__(
- *,
- file_path_meta_field: str = "file_path",
- root_path: str | None = None,
- model: str = "sentence-transformers/clip-ViT-B-32",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- batch_size: int = 32,
- progress_bar: bool = True,
- normalize_embeddings: bool = False,
- trust_remote_code: bool = False,
- local_files_only: bool = False,
- model_kwargs: dict[str, Any] | None = None,
- tokenizer_kwargs: dict[str, Any] | None = None,
- config_kwargs: dict[str, Any] | None = None,
- precision: Literal[
- "float32", "int8", "uint8", "binary", "ubinary"
- ] = "float32",
- encode_kwargs: dict[str, Any] | None = None,
- backend: Literal["torch", "onnx", "openvino"] = "torch"
-) -> None
-```
-
-Creates a SentenceTransformersDocumentEmbedder component.
-
-**Parameters:**
-
-- **file_path_meta_field** (str) – The metadata field in the Document that contains the file path to the image or PDF.
-- **root_path** (str | None) – The root directory path where document files are located. If provided, file paths in
- document metadata will be resolved relative to this path. If None, file paths are treated as absolute paths.
-- **model** (str) – The Sentence Transformers model to use for calculating embeddings. Pass a local path or ID of the model on
- Hugging Face. To be used with this component, the model must be able to embed images and text into the same
- vector space. Compatible models include:
-- "sentence-transformers/clip-ViT-B-32"
-- "sentence-transformers/clip-ViT-L-14"
-- "sentence-transformers/clip-ViT-B-16"
-- "sentence-transformers/clip-ViT-B-32-multilingual-v1"
-- "jinaai/jina-embeddings-v4"
-- "jinaai/jina-clip-v1"
-- "jinaai/jina-clip-v2".
-- **device** (ComponentDevice | None) – The device to use for loading the model.
- Overrides the default device.
-- **token** (Secret | None) – The API token to download private models from Hugging Face.
-- **batch_size** (int) – Number of documents to embed at once.
-- **progress_bar** (bool) – If `True`, shows a progress bar when embedding documents.
-- **normalize_embeddings** (bool) – If `True`, the embeddings are normalized using L2 normalization, so that each embedding has a norm of 1.
-- **trust_remote_code** (bool) – If `False`, allows only Hugging Face verified model architectures.
- If `True`, allows custom models and scripts.
-- **local_files_only** (bool) – If `True`, does not attempt to download the model from Hugging Face Hub and only looks at local files.
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoModelForSequenceClassification.from_pretrained`
- when loading the model. Refer to specific model documentation for available kwargs.
-- **tokenizer_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoTokenizer.from_pretrained` when loading the tokenizer.
- Refer to specific model documentation for available kwargs.
-- **config_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoConfig.from_pretrained` when loading the model configuration.
-- **precision** (Literal['float32', 'int8', 'uint8', 'binary', 'ubinary']) – The precision to use for the embeddings.
- All non-float32 precisions are quantized embeddings.
- Quantized embeddings are smaller and faster to compute, but may have a lower accuracy.
- They are useful for reducing the size of the embeddings of a corpus for semantic search, among other tasks.
-- **encode_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `SentenceTransformer.encode` when embedding documents.
- This parameter is provided for fine customization. Be careful not to clash with already set parameters and
- avoid passing parameters that change the output type.
-- **backend** (Literal['torch', 'onnx', 'openvino']) – The backend to use for the Sentence Transformers model. Choose from "torch", "onnx", or "openvino".
- Refer to the [Sentence Transformers documentation](https://sbert.net/docs/sentence_transformer/usage/efficiency.html)
- for more information on acceleration and quantization options.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> SentenceTransformersDocumentImageEmbedder
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- SentenceTransformersDocumentImageEmbedder – Deserialized component.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### run
-
-```python
-run(documents: list[Document]) -> dict[str, list[Document]]
-```
-
-Embed a list of documents.
-
-**Parameters:**
-
-- **documents** (list\[Document\]) – Documents to embed.
+**Raises:**
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
-- `documents`: Documents with embeddings.
+- TypeError – If `text` is not a string.
## openai_document_embedder
@@ -828,6 +663,38 @@ in the OpenAI client.
- **raise_on_failure** (bool) – Whether to raise an exception if the embedding request fails. If `False`, the component will log the error
and continue processing the remaining documents. If `True`, it will raise an exception on failure.
+#### warm_up
+
+```python
+warm_up() -> None
+```
+
+Initializes the synchronous OpenAI client.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Initializes the asynchronous OpenAI client on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Releases the synchronous OpenAI client.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Releases the asynchronous OpenAI client.
+
#### to_dict
```python
@@ -962,431 +829,37 @@ in the OpenAI client.
- **http_client_kwargs** (dict\[str, Any\] | None) – A dictionary of keyword arguments to configure a custom `httpx.Client`or `httpx.AsyncClient`.
For more information, see the [HTTPX documentation](https://www.python-httpx.org/api/#client).
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> OpenAITextEmbedder
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- OpenAITextEmbedder – Deserialized component.
-
-#### run
-
-```python
-run(text: str) -> dict[str, Any]
-```
-
-Embeds a single string.
-
-**Parameters:**
-
-- **text** (str) – Text to embed.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following keys:
-- `embedding`: The embedding of the input text.
-- `meta`: Information about the usage of the model.
-
-#### run_async
-
-```python
-run_async(text: str) -> dict[str, Any]
-```
-
-Asynchronously embed a single string.
-
-This is the asynchronous version of the `run` method. It has the same parameters and return values
-but can be used with `await` in async code.
-
-**Parameters:**
-
-- **text** (str) – Text to embed.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following keys:
-- `embedding`: The embedding of the input text.
-- `meta`: Information about the usage of the model.
-
-## sentence_transformers_document_embedder
-
-### SentenceTransformersDocumentEmbedder
-
-Calculates document embeddings using Sentence Transformers models.
-
-It stores the embeddings in the `embedding` metadata field of each document.
-You can also embed documents' metadata.
-Use this component in indexing pipelines to embed input documents
-and send them to DocumentWriter to write into a Document Store.
-
-### Usage example:
-
-
-
-```python
-from haystack import Document
-from haystack.components.embedders import SentenceTransformersDocumentEmbedder
-doc = Document(content="I love pizza!")
-doc_embedder = SentenceTransformersDocumentEmbedder()
-
-result = doc_embedder.run([doc])
-print(result['documents'][0].embedding)
-
-# [-0.07804739475250244, 0.1498992145061493, ...]
-```
-
-#### __init__
-
-```python
-__init__(
- model: str = "sentence-transformers/all-mpnet-base-v2",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- prefix: str = "",
- suffix: str = "",
- batch_size: int = 32,
- progress_bar: bool = True,
- normalize_embeddings: bool = False,
- meta_fields_to_embed: list[str] | None = None,
- embedding_separator: str = "\n",
- trust_remote_code: bool = False,
- local_files_only: bool = False,
- truncate_dim: int | None = None,
- model_kwargs: dict[str, Any] | None = None,
- tokenizer_kwargs: dict[str, Any] | None = None,
- config_kwargs: dict[str, Any] | None = None,
- precision: Literal[
- "float32", "int8", "uint8", "binary", "ubinary"
- ] = "float32",
- encode_kwargs: dict[str, Any] | None = None,
- backend: Literal["torch", "onnx", "openvino"] = "torch",
- revision: str | None = None,
-) -> None
-```
-
-Creates a SentenceTransformersDocumentEmbedder component.
-
-**Parameters:**
-
-- **model** (str) – The model to use for calculating embeddings.
- Pass a local path or ID of the model on Hugging Face.
-- **device** (ComponentDevice | None) – The device to use for loading the model.
- Overrides the default device.
-- **token** (Secret | None) – The API token to download private models from Hugging Face.
-- **prefix** (str) – A string to add at the beginning of each document text.
- Can be used to prepend the text with an instruction, as required by some embedding models,
- such as E5 and bge.
-- **suffix** (str) – A string to add at the end of each document text.
-- **batch_size** (int) – Number of documents to embed at once.
-- **progress_bar** (bool) – If `True`, shows a progress bar when embedding documents.
-- **normalize_embeddings** (bool) – If `True`, the embeddings are normalized using L2 normalization, so that each embedding has a norm of 1.
-- **meta_fields_to_embed** (list\[str\] | None) – List of metadata fields to embed along with the document text.
-- **embedding_separator** (str) – Separator used to concatenate the metadata fields to the document text.
-- **trust_remote_code** (bool) – If `False`, allows only Hugging Face verified model architectures.
- If `True`, allows custom models and scripts.
-- **local_files_only** (bool) – If `True`, does not attempt to download the model from Hugging Face Hub and only looks at local files.
-- **truncate_dim** (int | None) – The dimension to truncate sentence embeddings to. `None` does no truncation.
- If the model wasn't trained with Matryoshka Representation Learning,
- truncating embeddings can significantly affect performance.
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoModelForSequenceClassification.from_pretrained`
- when loading the model. Refer to specific model documentation for available kwargs.
-- **tokenizer_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoTokenizer.from_pretrained` when loading the tokenizer.
- Refer to specific model documentation for available kwargs.
-- **config_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoConfig.from_pretrained` when loading the model configuration.
-- **precision** (Literal['float32', 'int8', 'uint8', 'binary', 'ubinary']) – The precision to use for the embeddings.
- All non-float32 precisions are quantized embeddings.
- Quantized embeddings are smaller and faster to compute, but may have a lower accuracy.
- They are useful for reducing the size of the embeddings of a corpus for semantic search, among other tasks.
-- **encode_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `SentenceTransformer.encode` when embedding documents.
- This parameter is provided for fine customization. Be careful not to clash with already set parameters and
- avoid passing parameters that change the output type.
-- **backend** (Literal['torch', 'onnx', 'openvino']) – The backend to use for the Sentence Transformers model. Choose from "torch", "onnx", or "openvino".
- Refer to the [Sentence Transformers documentation](https://sbert.net/docs/sentence_transformer/usage/efficiency.html)
- for more information on acceleration and quantization options.
-- **revision** (str | None) – The specific model version to use. It can be a branch name, a tag name, or a commit id,
- for a stored model on Hugging Face.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> SentenceTransformersDocumentEmbedder
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- SentenceTransformersDocumentEmbedder – Deserialized component.
-
#### warm_up
```python
warm_up() -> None
```
-Initializes the component.
+Initializes the synchronous OpenAI client.
-#### run
+#### warm_up_async
```python
-run(documents: list[Document]) -> dict[str, list[Document]]
+warm_up_async() -> None
```
-Embed a list of documents.
-
-**Parameters:**
-
-- **documents** (list\[Document\]) – Documents to embed.
-
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
-- `documents`: Documents with embeddings.
-
-## sentence_transformers_sparse_document_embedder
-
-### SentenceTransformersSparseDocumentEmbedder
-
-Calculates document sparse embeddings using sparse embedding models from Sentence Transformers.
-
-It stores the sparse embeddings in the `sparse_embedding` metadata field of each document.
-You can also embed documents' metadata.
-Use this component in indexing pipelines to embed input documents
-and send them to DocumentWriter to write a into a Document Store.
-
-### Usage example:
-
-
-
-```python
-from haystack import Document
-from haystack.components.embedders import SentenceTransformersSparseDocumentEmbedder
-
-doc = Document(content="I love pizza!")
-doc_embedder = SentenceTransformersSparseDocumentEmbedder()
-
-result = doc_embedder.run([doc])
-print(result['documents'][0].sparse_embedding)
+Initializes the asynchronous OpenAI client on the serving event loop.
-# SparseEmbedding(indices=[999, 1045, ...], values=[0.918, 0.867, ...])
-```
-
-#### __init__
+#### close
```python
-__init__(
- *,
- model: str = "prithivida/Splade_PP_en_v2",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- prefix: str = "",
- suffix: str = "",
- batch_size: int = 32,
- progress_bar: bool = True,
- meta_fields_to_embed: list[str] | None = None,
- embedding_separator: str = "\n",
- trust_remote_code: bool = False,
- local_files_only: bool = False,
- model_kwargs: dict[str, Any] | None = None,
- tokenizer_kwargs: dict[str, Any] | None = None,
- config_kwargs: dict[str, Any] | None = None,
- backend: Literal["torch", "onnx", "openvino"] = "torch",
- revision: str | None = None
-) -> None
+close() -> None
```
-Creates a SentenceTransformersSparseDocumentEmbedder component.
+Releases the synchronous OpenAI client.
-**Parameters:**
-
-- **model** (str) – The model to use for calculating sparse embeddings.
- Pass a local path or ID of the model on Hugging Face.
-- **device** (ComponentDevice | None) – The device to use for loading the model.
- Overrides the default device.
-- **token** (Secret | None) – The API token to download private models from Hugging Face.
-- **prefix** (str) – A string to add at the beginning of each document text.
-- **suffix** (str) – A string to add at the end of each document text.
-- **batch_size** (int) – Number of documents to embed at once.
-- **progress_bar** (bool) – If `True`, shows a progress bar when embedding documents.
-- **meta_fields_to_embed** (list\[str\] | None) – List of metadata fields to embed along with the document text.
-- **embedding_separator** (str) – Separator used to concatenate the metadata fields to the document text.
-- **trust_remote_code** (bool) – If `False`, allows only Hugging Face verified model architectures.
- If `True`, allows custom models and scripts.
-- **local_files_only** (bool) – If `True`, does not attempt to download the model from Hugging Face Hub and only looks at local files.
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoModelForSequenceClassification.from_pretrained`
- when loading the model. Refer to specific model documentation for available kwargs.
-- **tokenizer_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoTokenizer.from_pretrained` when loading the tokenizer.
- Refer to specific model documentation for available kwargs.
-- **config_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoConfig.from_pretrained` when loading the model configuration.
-- **backend** (Literal['torch', 'onnx', 'openvino']) – The backend to use for the Sentence Transformers model. Choose from "torch", "onnx", or "openvino".
- Refer to the [Sentence Transformers documentation](https://sbert.net/docs/sentence_transformer/usage/efficiency.html)
- for more information on acceleration and quantization options.
-- **revision** (str | None) – The specific model version to use. It can be a branch name, a tag name, or a commit id,
- for a stored model on Hugging Face.
-
-#### to_dict
+#### close_async
```python
-to_dict() -> dict[str, Any]
+close_async() -> None
```
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> SentenceTransformersSparseDocumentEmbedder
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- SentenceTransformersSparseDocumentEmbedder – Deserialized component.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### run
-
-```python
-run(documents: list[Document]) -> dict[str, list[Document]]
-```
-
-Embed a list of documents.
-
-**Parameters:**
-
-- **documents** (list\[Document\]) – Documents to embed.
-
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
-- `documents`: Documents with sparse embeddings under the `sparse_embedding` field.
-
-## sentence_transformers_sparse_text_embedder
-
-### SentenceTransformersSparseTextEmbedder
-
-Embeds strings using sparse embedding models from Sentence Transformers.
-
-You can use it to embed user query and send it to a sparse embedding retriever.
-
-Usage example:
-
-
-
-```python
-from haystack.components.embedders import SentenceTransformersSparseTextEmbedder
-
-text_to_embed = "I love pizza!"
-
-text_embedder = SentenceTransformersSparseTextEmbedder()
-
-print(text_embedder.run(text_to_embed))
-
-# {'sparse_embedding': SparseEmbedding(indices=[999, 1045, ...], values=[0.918, 0.867, ...])}
-```
-
-#### __init__
-
-```python
-__init__(
- *,
- model: str = "prithivida/Splade_PP_en_v2",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- prefix: str = "",
- suffix: str = "",
- trust_remote_code: bool = False,
- local_files_only: bool = False,
- model_kwargs: dict[str, Any] | None = None,
- tokenizer_kwargs: dict[str, Any] | None = None,
- config_kwargs: dict[str, Any] | None = None,
- backend: Literal["torch", "onnx", "openvino"] = "torch",
- revision: str | None = None
-) -> None
-```
-
-Create a SentenceTransformersSparseTextEmbedder component.
-
-**Parameters:**
-
-- **model** (str) – The model to use for calculating sparse embeddings.
- Specify the path to a local model or the ID of the model on Hugging Face.
-- **device** (ComponentDevice | None) – Overrides the default device used to load the model.
-- **token** (Secret | None) – An API token to use private models from Hugging Face.
-- **prefix** (str) – A string to add at the beginning of each text to be embedded.
-- **suffix** (str) – A string to add at the end of each text to embed.
-- **trust_remote_code** (bool) – If `False`, permits only Hugging Face verified model architectures.
- If `True`, permits custom models and scripts.
-- **local_files_only** (bool) – If `True`, does not attempt to download the model from Hugging Face Hub and only looks at local files.
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoModelForSequenceClassification.from_pretrained`
- when loading the model. Refer to specific model documentation for available kwargs.
-- **tokenizer_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoTokenizer.from_pretrained` when loading the tokenizer.
- Refer to specific model documentation for available kwargs.
-- **config_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoConfig.from_pretrained` when loading the model configuration.
-- **backend** (Literal['torch', 'onnx', 'openvino']) – The backend to use for the Sentence Transformers model. Choose from "torch", "onnx", or "openvino".
- Refer to the [Sentence Transformers documentation](https://sbert.net/docs/sentence_transformer/usage/efficiency.html)
- for more information on acceleration and quantization options.
-- **revision** (str | None) – The specific model version to use. It can be a branch name, a tag name, or a commit id,
- for a stored model on Hugging Face.
+Releases the asynchronous OpenAI client.
#### to_dict
@@ -1403,7 +876,7 @@ Serializes the component to a dictionary.
#### from_dict
```python
-from_dict(data: dict[str, Any]) -> SentenceTransformersSparseTextEmbedder
+from_dict(data: dict[str, Any]) -> OpenAITextEmbedder
```
Deserializes the component from a dictionary.
@@ -1414,15 +887,7 @@ Deserializes the component from a dictionary.
**Returns:**
-- SentenceTransformersSparseTextEmbedder – Deserialized component.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
+- OpenAITextEmbedder – Deserialized component.
#### run
@@ -1430,7 +895,7 @@ Initializes the component.
run(text: str) -> dict[str, Any]
```
-Embed a single string.
+Embeds a single string.
**Parameters:**
@@ -1439,144 +904,19 @@ Embed a single string.
**Returns:**
- dict\[str, Any\] – A dictionary with the following keys:
-- `sparse_embedding`: The sparse embedding of the input text.
-
-## sentence_transformers_text_embedder
-
-### SentenceTransformersTextEmbedder
-
-Embeds strings using Sentence Transformers models.
-
-You can use it to embed user query and send it to an embedding retriever.
-
-Usage example:
-
-
-
-```python
-from haystack.components.embedders import SentenceTransformersTextEmbedder
-
-text_to_embed = "I love pizza!"
-
-text_embedder = SentenceTransformersTextEmbedder()
-
-print(text_embedder.run(text_to_embed))
-
-# {'embedding': [-0.07804739475250244, 0.1498992145061493,, ...]}
-```
-
-#### __init__
-
-```python
-__init__(
- model: str = "sentence-transformers/all-mpnet-base-v2",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- prefix: str = "",
- suffix: str = "",
- batch_size: int = 32,
- progress_bar: bool = True,
- normalize_embeddings: bool = False,
- trust_remote_code: bool = False,
- local_files_only: bool = False,
- truncate_dim: int | None = None,
- model_kwargs: dict[str, Any] | None = None,
- tokenizer_kwargs: dict[str, Any] | None = None,
- config_kwargs: dict[str, Any] | None = None,
- precision: Literal[
- "float32", "int8", "uint8", "binary", "ubinary"
- ] = "float32",
- encode_kwargs: dict[str, Any] | None = None,
- backend: Literal["torch", "onnx", "openvino"] = "torch",
- revision: str | None = None,
-) -> None
-```
-
-Create a SentenceTransformersTextEmbedder component.
-
-**Parameters:**
-
-- **model** (str) – The model to use for calculating embeddings.
- Specify the path to a local model or the ID of the model on Hugging Face.
-- **device** (ComponentDevice | None) – Overrides the default device used to load the model.
-- **token** (Secret | None) – An API token to use private models from Hugging Face.
-- **prefix** (str) – A string to add at the beginning of each text to be embedded.
- You can use it to prepend the text with an instruction, as required by some embedding models,
- such as E5 and bge.
-- **suffix** (str) – A string to add at the end of each text to embed.
-- **batch_size** (int) – Number of texts to embed at once.
-- **progress_bar** (bool) – If `True`, shows a progress bar for calculating embeddings.
- If `False`, disables the progress bar.
-- **normalize_embeddings** (bool) – If `True`, the embeddings are normalized using L2 normalization, so that the embeddings have a norm of 1.
-- **trust_remote_code** (bool) – If `False`, permits only Hugging Face verified model architectures.
- If `True`, permits custom models and scripts.
-- **local_files_only** (bool) – If `True`, does not attempt to download the model from Hugging Face Hub and only looks at local files.
-- **truncate_dim** (int | None) – The dimension to truncate sentence embeddings to. `None` does no truncation.
- If the model has not been trained with Matryoshka Representation Learning,
- truncation of embeddings can significantly affect performance.
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoModelForSequenceClassification.from_pretrained`
- when loading the model. Refer to specific model documentation for available kwargs.
-- **tokenizer_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoTokenizer.from_pretrained` when loading the tokenizer.
- Refer to specific model documentation for available kwargs.
-- **config_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoConfig.from_pretrained` when loading the model configuration.
-- **precision** (Literal['float32', 'int8', 'uint8', 'binary', 'ubinary']) – The precision to use for the embeddings.
- All non-float32 precisions are quantized embeddings.
- Quantized embeddings are smaller in size and faster to compute, but may have a lower accuracy.
- They are useful for reducing the size of the embeddings of a corpus for semantic search, among other tasks.
-- **encode_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `SentenceTransformer.encode` when embedding texts.
- This parameter is provided for fine customization. Be careful not to clash with already set parameters and
- avoid passing parameters that change the output type.
-- **backend** (Literal['torch', 'onnx', 'openvino']) – The backend to use for the Sentence Transformers model. Choose from "torch", "onnx", or "openvino".
- Refer to the [Sentence Transformers documentation](https://sbert.net/docs/sentence_transformer/usage/efficiency.html)
- for more information on acceleration and quantization options.
-- **revision** (str | None) – The specific model version to use. It can be a branch name, a tag name, or a commit id,
- for a stored model on Hugging Face.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> SentenceTransformersTextEmbedder
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- SentenceTransformersTextEmbedder – Deserialized component.
+- `embedding`: The embedding of the input text.
+- `meta`: Information about the usage of the model.
-#### warm_up
+#### run_async
```python
-warm_up() -> None
+run_async(text: str) -> dict[str, Any]
```
-Initializes the component.
-
-#### run
-
-```python
-run(text: str) -> dict[str, Any]
-```
+Asynchronously embed a single string.
-Embed a single string.
+This is the asynchronous version of the `run` method. It has the same parameters and return values
+but can be used with `await` in async code.
**Parameters:**
@@ -1586,3 +926,4 @@ Embed a single string.
- dict\[str, Any\] – A dictionary with the following keys:
- `embedding`: The embedding of the input text.
+- `meta`: Information about the usage of the model.
diff --git a/docs-website/reference/haystack-api/evaluators_api.md b/docs-website/reference/haystack-api/evaluators_api.md
index a076299d769..f00bdea0ab9 100644
--- a/docs-website/reference/haystack-api/evaluators_api.md
+++ b/docs-website/reference/haystack-api/evaluators_api.md
@@ -880,7 +880,31 @@ If no LLM is specified using the `chat_generator` parameter, the component will
warm_up() -> None
```
-Warm up the component by warming up the underlying chat generator.
+Warm up the underlying chat generator.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the underlying chat generator on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the underlying chat generator's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the underlying chat generator's async resources.
#### validate_init_parameters
diff --git a/docs-website/reference/haystack-api/extractors_api.md b/docs-website/reference/haystack-api/extractors_api.md
index 5196eefb777..b6cc0f29731 100644
--- a/docs-website/reference/haystack-api/extractors_api.md
+++ b/docs-website/reference/haystack-api/extractors_api.md
@@ -116,7 +116,31 @@ Initialize the LLMDocumentContentExtractor component.
warm_up() -> None
```
-Warm up the ChatGenerator if it has a warm_up method.
+Warm up the underlying chat generator.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the underlying chat generator on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the underlying chat generator's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the underlying chat generator's async resources.
#### to_dict
@@ -162,6 +186,27 @@ Run extraction on image-based documents. One LLM call per document.
- dict\[str, list\[Document\]\] – A dictionary with "documents" (successfully processed) and "failed_documents" (with failure metadata).
+#### run_async
+
+```python
+run_async(documents: list[Document]) -> dict[str, list[Document]]
+```
+
+Asynchronously run extraction on image-based documents. One LLM call per document.
+
+This is the asynchronous version of the `run` method. It has the same parameters and return values
+but can be used with `await` in an async code. LLM calls are made concurrently, bounded by `max_workers`.
+If the chat generator only implements a synchronous `run` method, it is executed in a thread to avoid
+blocking the event loop.
+
+**Parameters:**
+
+- **documents** (list\[Document\]) – A list of image-based documents to process. Each must have a valid file path in its metadata.
+
+**Returns:**
+
+- dict\[str, list\[Document\]\] – A dictionary with "documents" (successfully processed) and "failed_documents" (with failure metadata).
+
## llm_metadata_extractor
### LLMMetadataExtractor
@@ -328,7 +373,31 @@ Initializes the LLMMetadataExtractor.
warm_up() -> None
```
-Warm up the LLM provider component.
+Warm up the underlying chat generator and splitter.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the underlying chat generator and splitter on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the underlying chat generator's and splitter's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the underlying chat generator's and splitter's async resources.
#### to_dict
@@ -429,182 +498,6 @@ and return values but can be used with `await` in an async code.
"metadata_extraction_error" and "metadata_extraction_response" in their metadata. These documents can be
re-run with the extractor to extract metadata.
-## named_entity_extractor
-
-### NamedEntityExtractorBackend
-
-Bases: Enum
-
-NLP backend to use for Named Entity Recognition.
-
-#### from_str
-
-```python
-from_str(string: str) -> NamedEntityExtractorBackend
-```
-
-Convert a string to a NamedEntityExtractorBackend enum.
-
-### NamedEntityAnnotation
-
-Describes a single NER annotation.
-
-**Parameters:**
-
-- **entity** (str) – Entity label.
-- **start** (int) – Start index of the entity in the document.
-- **end** (int) – End index of the entity in the document.
-- **score** (float | None) – Score calculated by the model.
-
-### NamedEntityExtractor
-
-Annotates named entities in a collection of documents.
-
-The component supports two backends: Hugging Face and spaCy. The
-former can be used with any sequence classification model from the
-[Hugging Face model hub](https://huggingface.co/models), while the
-latter can be used with any [spaCy model](https://spacy.io/models)
-that contains an NER component. Annotations are stored as metadata
-in the documents.
-
-Usage example:
-
-```python
-from haystack import Document
-from haystack.components.extractors.named_entity_extractor import NamedEntityExtractor
-
-documents = [
- Document(content="I'm Merlin, the happy pig!"),
- Document(content="My name is Clara and I live in Berkeley, California."),
-]
-extractor = NamedEntityExtractor(backend="hugging_face", model="dslim/bert-base-NER")
-results = extractor.run(documents=documents)["documents"]
-annotations = [NamedEntityExtractor.get_stored_annotations(doc) for doc in results]
-print(annotations)
-# >> [[NamedEntityAnnotation(entity='PER', start=4, end=10, score=np.float32(0.99054915))],
-# >> [NamedEntityAnnotation(entity='PER', start=11, end=16, score=np.float32(0.99641764)),
-# >> NamedEntityAnnotation(entity='LOC', start=31, end=39, score=np.float32(0.996198)),
-# >> NamedEntityAnnotation(entity='LOC', start=41, end=51, score=np.float32(0.9990196))]]
-```
-
-#### __init__
-
-```python
-__init__(
- *,
- backend: str | NamedEntityExtractorBackend,
- model: str,
- pipeline_kwargs: dict[str, Any] | None = None,
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- )
-) -> None
-```
-
-Create a Named Entity extractor component.
-
-**Parameters:**
-
-- **backend** (str | NamedEntityExtractorBackend) – Backend to use for NER.
-- **model** (str) – Name of the model or a path to the model on
- the local disk. Dependent on the backend.
-- **pipeline_kwargs** (dict\[str, Any\] | None) – Keyword arguments passed to the pipeline. The
- pipeline can override these arguments. Dependent on the backend.
-- **device** (ComponentDevice | None) – The device on which the model is loaded. If `None`,
- the default device is automatically selected. If a
- device/device map is specified in `pipeline_kwargs`,
- it overrides this parameter (only applicable to the
- HuggingFace backend).
-- **token** (Secret | None) – The API token to download private models from Hugging Face.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initialize the component.
-
-**Raises:**
-
-- ComponentError – If the backend fails to initialize successfully.
-
-#### run
-
-```python
-run(documents: list[Document], batch_size: int = 1) -> dict[str, Any]
-```
-
-Annotate named entities in each document and store the annotations in the document's metadata.
-
-**Parameters:**
-
-- **documents** (list\[Document\]) – Documents to process.
-- **batch_size** (int) – Batch size used for processing the documents.
-
-**Returns:**
-
-- dict\[str, Any\] – Processed documents.
-
-**Raises:**
-
-- ComponentError – If the backend fails to process a document.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> NamedEntityExtractor
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- NamedEntityExtractor – Deserialized component.
-
-#### initialized
-
-```python
-initialized: bool
-```
-
-Returns if the extractor is ready to annotate text.
-
-#### get_stored_annotations
-
-```python
-get_stored_annotations(
- document: Document,
-) -> list[NamedEntityAnnotation] | None
-```
-
-Returns the document's named entity annotations stored in its metadata, if any.
-
-**Parameters:**
-
-- **document** (Document) – Document whose annotations are to be fetched.
-
-**Returns:**
-
-- list\[NamedEntityAnnotation\] | None – The stored annotations.
-
## regex_text_extractor
### RegexTextExtractor
diff --git a/docs-website/reference/haystack-api/fetchers_api.md b/docs-website/reference/haystack-api/fetchers_api.md
index 7bdc3154422..f47c9117a55 100644
--- a/docs-website/reference/haystack-api/fetchers_api.md
+++ b/docs-website/reference/haystack-api/fetchers_api.md
@@ -74,6 +74,38 @@ Initializes the component.
- **client_kwargs** (dict | None) – Additional keyword arguments to pass to the httpx client.
If `None`, default values are used.
+#### warm_up
+
+```python
+warm_up() -> None
+```
+
+Initializes the synchronous httpx client.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Initializes the asynchronous httpx client on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Releases the synchronous httpx client.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Releases the asynchronous httpx client.
+
#### run
```python
diff --git a/docs-website/reference/haystack-api/generators_api.md b/docs-website/reference/haystack-api/generators_api.md
index 140195f5fbe..0692611cdb8 100644
--- a/docs-website/reference/haystack-api/generators_api.md
+++ b/docs-website/reference/haystack-api/generators_api.md
@@ -6,148 +6,6 @@ slug: "/generators-api"
---
-## azure
-
-### AzureOpenAIGenerator
-
-Bases: OpenAIGenerator
-
-Generates text using OpenAI's large language models (LLMs).
-
-It works with the gpt-4 - type models and supports streaming responses
-from OpenAI API.
-
-You can customize how the text is generated by passing parameters to the
-OpenAI API. Use the `**generation_kwargs` argument when you initialize
-the component or when you run it. Any parameter that works with
-`openai.ChatCompletion.create` will work here too.
-
-For details on OpenAI API parameters, see
-[OpenAI documentation](https://platform.openai.com/docs/api-reference/chat).
-
-### Usage example
-
-
-
-```python
-from haystack.components.generators import AzureOpenAIGenerator
-from haystack.utils import Secret
-
-client = AzureOpenAIGenerator(
- azure_endpoint=Secret.from_env_var("AZURE_OPENAI_ENDPOINT").resolve_value(),
- api_key=Secret.from_env_var("AZURE_OPENAI_API_KEY"),
- azure_deployment="gpt-4.1-mini")
-
-response = client.run("What's Natural Language Processing? Be brief.")
-
-print(response)
-# >> {'replies': ['Natural Language Processing (NLP) is a branch of artificial intelligence that focuses on
-# >> the interaction between computers and human language. It involves enabling computers to understand, interpret,
-# >> and respond to natural human language in a way that is both meaningful and useful.'], 'meta': [{'model':
-# >> 'gpt-4.1-mini', 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 16,
-# >> 'completion_tokens': 49, 'total_tokens': 65}}]}
-```
-
-#### __init__
-
-```python
-__init__(
- azure_endpoint: str | None = None,
- api_version: str | None = "2024-12-01-preview",
- azure_deployment: str | None = "gpt-4.1-mini",
- api_key: Secret | None = Secret.from_env_var(
- "AZURE_OPENAI_API_KEY", strict=False
- ),
- azure_ad_token: Secret | None = Secret.from_env_var(
- "AZURE_OPENAI_AD_TOKEN", strict=False
- ),
- organization: str | None = None,
- streaming_callback: StreamingCallbackT | None = None,
- system_prompt: str | None = None,
- timeout: float | None = None,
- max_retries: int | None = None,
- http_client_kwargs: dict[str, Any] | None = None,
- generation_kwargs: dict[str, Any] | None = None,
- default_headers: dict[str, str] | None = None,
- *,
- azure_ad_token_provider: AzureADTokenProvider | None = None
-) -> None
-```
-
-Initialize the Azure OpenAI Generator.
-
-**Parameters:**
-
-- **azure_endpoint** (str | None) – The endpoint of the deployed model, for example `https://example-resource.azure.openai.com/`.
-- **api_version** (str | None) – The version of the API to use. Defaults to 2024-12-01-preview.
-- **azure_deployment** (str | None) – The deployment of the model, usually the model name.
-- **api_key** (Secret | None) – The API key to use for authentication.
-- **azure_ad_token** (Secret | None) – [Azure Active Directory token](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id).
-- **organization** (str | None) – Your organization ID, defaults to `None`. For help, see
- [Setting up your organization](https://platform.openai.com/docs/guides/production-best-practices/setting-up-your-organization).
-- **streaming_callback** (StreamingCallbackT | None) – A callback function called when a new token is received from the stream.
- It accepts [StreamingChunk](https://docs.haystack.deepset.ai/docs/data-classes#streamingchunk)
- as an argument.
-- **system_prompt** (str | None) – The system prompt to use for text generation. If not provided, the Generator
- omits the system prompt and uses the default system prompt.
-- **timeout** (float | None) – Timeout for AzureOpenAI client. If not set, it is inferred from the
- `OPENAI_TIMEOUT` environment variable or set to 30.
-- **max_retries** (int | None) – Maximum retries to establish contact with AzureOpenAI if it returns an internal error.
- If not set, it is inferred from the `OPENAI_MAX_RETRIES` environment variable or set to 5.
-- **http_client_kwargs** (dict\[str, Any\] | None) – A dictionary of keyword arguments to configure a custom `httpx.Client`or `httpx.AsyncClient`.
- For more information, see the [HTTPX documentation](https://www.python-httpx.org/api/#client).
-- **generation_kwargs** (dict\[str, Any\] | None) – Other parameters to use for the model, sent directly to
- the OpenAI endpoint. See [OpenAI documentation](https://platform.openai.com/docs/api-reference/chat) for
- more details.
- Some of the supported parameters:
-- `max_completion_tokens`: An upper bound for the number of tokens that can be generated for a completion,
- including visible output tokens and reasoning tokens.
-- `temperature`: The sampling temperature to use. Higher values mean the model takes more risks.
- Try 0.9 for more creative applications and 0 (argmax sampling) for ones with a well-defined answer.
-- `top_p`: An alternative to sampling with temperature, called nucleus sampling, where the model
- considers the results of the tokens with top_p probability mass. For example, 0.1 means only the tokens
- comprising the top 10% probability mass are considered.
-- `n`: The number of completions to generate for each prompt. For example, with 3 prompts and n=2,
- the LLM will generate two completions per prompt, resulting in 6 completions total.
-- `stop`: One or more sequences after which the LLM should stop generating tokens.
-- `presence_penalty`: The penalty applied if a token is already present.
- Higher values make the model less likely to repeat the token.
-- `frequency_penalty`: Penalty applied if a token has already been generated.
- Higher values make the model less likely to repeat the token.
-- `logit_bias`: Adds a logit bias to specific tokens. The keys of the dictionary are tokens, and the
- values are the bias to add to that token.
-- **default_headers** (dict\[str, str\] | None) – Default headers to use for the AzureOpenAI client.
-- **azure_ad_token_provider** (AzureADTokenProvider | None) – A function that returns an Azure Active Directory token, will be invoked on
- every request.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serialize this component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – The serialized component as a dictionary.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> AzureOpenAIGenerator
-```
-
-Deserialize this component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary representation of this component.
-
-**Returns:**
-
-- AzureOpenAIGenerator – The deserialized component instance.
-
## chat/azure
### AzureOpenAIChatGenerator
@@ -340,10 +198,31 @@ Initialize the Azure OpenAI Chat Generator component.
warm_up() -> None
```
-Warm up the Azure OpenAI chat generator.
+Warm up the tools and initialize the synchronous Azure OpenAI client.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the tools and initialize the asynchronous Azure OpenAI client on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Releases the synchronous Azure OpenAI client.
-This will warm up the tools registered in the chat generator.
-This method is idempotent and will only warm up the tools once.
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Releases the asynchronous Azure OpenAI client.
#### to_dict
@@ -627,7 +506,29 @@ warm_up() -> None
Warm up all underlying chat generators.
-This method calls warm_up() on each underlying generator that supports it.
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up all underlying chat generators on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the underlying chat generators' resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the underlying chat generators' async resources.
#### run
@@ -691,170 +592,66 @@ Asynchronously execute chat generators sequentially until one succeeds.
- RuntimeError – If all chat generators fail.
-## chat/hugging_face_api
+## chat/llm
-### HuggingFaceAPIChatGenerator
+### LLM
-Completes chats using Hugging Face APIs.
+Bases: Agent
-HuggingFaceAPIChatGenerator uses the [ChatMessage](https://docs.haystack.deepset.ai/docs/chatmessage)
-format for input and output. Use it to generate text with Hugging Face APIs:
+A text generation component powered by a large language model.
-- [Serverless Inference API (Inference Providers)](https://huggingface.co/docs/inference-providers)
-- [Paid Inference Endpoints](https://huggingface.co/inference-endpoints)
-- [Self-hosted Text Generation Inference](https://github.com/huggingface/text-generation-inference)
+The LLM component is a simplified version of the Agent that focuses solely on text generation
+without tool usage. It processes messages and returns a single response from the language model.
### Usage examples
-#### With the serverless inference API (Inference Providers) - free tier available
-
-```python
-from haystack.components.generators.chat import HuggingFaceAPIChatGenerator
-from haystack.dataclasses import ChatMessage
-from haystack.utils import Secret
-from haystack.utils.hf import HFGenerationAPIType
-
-messages = [ChatMessage.from_system("\nYou are a helpful, respectful and honest assistant"),
- ChatMessage.from_user("What's Natural Language Processing? Please be succinct")]
-
-# the api_type can be expressed using the HFGenerationAPIType enum or as a string
-api_type = HFGenerationAPIType.SERVERLESS_INFERENCE_API
-api_type = "serverless_inference_api" # this is equivalent to the above
-
-generator = HuggingFaceAPIChatGenerator(
- api_type=api_type,
- api_params={"model": "Qwen/Qwen2.5-7B-Instruct", "provider": "together"},
- token=Secret.from_env_var("HF_API_TOKEN")
-)
-
-result = generator.run(messages)
-print(result)
-# >> {'replies': [ChatMessage(_role=,
-# >> _content=[TextContent(text='Natural Language Processing (NLP) is a field of AI that focuses on the interaction
-# >> between humans and computers using natural language. It enables machines to understand, interpret, and
-# >> generate human language.')], _name=None, _meta={'model': 'Qwen/Qwen2.5-7B-Instruct', 'finish_reason':
-# >> 'tool_calls', 'index': 0, 'usage': {'prompt_tokens': 33, 'completion_tokens': 39}})]}
-```
-
-#### With the serverless inference API (Inference Providers) and text+image input
-
-
-
```python
-from haystack.components.generators.chat import HuggingFaceAPIChatGenerator
-from haystack.dataclasses import ChatMessage, ImageContent
-from haystack.utils import Secret
-from haystack.utils.hf import HFGenerationAPIType
-
-# Create an image from file path, URL, or base64
-image = ImageContent.from_file_path("test/test_files/images/apple.jpg")
-
-# Create a multimodal message with both text and image
-messages = [ChatMessage.from_user(content_parts=["Describe this image in detail", image])]
+from haystack.components.generators.chat import LLM
+from haystack.components.generators.chat import OpenAIChatGenerator
-generator = HuggingFaceAPIChatGenerator(
- api_type=HFGenerationAPIType.SERVERLESS_INFERENCE_API,
- api_params={
- "model": "Qwen/Qwen3.5-9B", "provider": "together" # Vision Language Model
- },
- token=Secret.from_env_var("HF_API_TOKEN")
+llm = LLM(
+ chat_generator=OpenAIChatGenerator(),
+ system_prompt="You are a helpful translation assistant.",
+ user_prompt="Summarize the following document: {{ document }}",
+ required_variables=["document"],
)
-result = generator.run(messages)
-print(result)
-```
-
-#### With paid inference endpoints
-
-
-
-```python
-from haystack.components.generators.chat import HuggingFaceAPIChatGenerator
-from haystack.dataclasses import ChatMessage
-from haystack.utils import Secret
-
-messages = [ChatMessage.from_system("\nYou are a helpful, respectful and honest assistant"),
- ChatMessage.from_user("What's Natural Language Processing?")]
-
-generator = HuggingFaceAPIChatGenerator(api_type="inference_endpoints",
- api_params={"url": ""},
- token=Secret.from_token(""))
-
-result = generator.run(messages)
-print(result)
-```
-
-#### With self-hosted text generation inference
-
-
-
-```python
-from haystack.components.generators.chat import HuggingFaceAPIChatGenerator
-from haystack.dataclasses import ChatMessage
-
-messages = [ChatMessage.from_system("\nYou are a helpful, respectful and honest assistant"),
- ChatMessage.from_user("What's Natural Language Processing?")]
-
-generator = HuggingFaceAPIChatGenerator(api_type="text_generation_inference",
- api_params={"url": "http://localhost:8080"})
-
-result = generator.run(messages)
-print(result)
+result = llm.run(document="The weather is lovely today and the sun is shining. ")
+print(result["last_message"].text)
```
#### __init__
```python
__init__(
- api_type: HFGenerationAPIType | str,
- api_params: dict[str, str],
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- generation_kwargs: dict[str, Any] | None = None,
- stop_words: list[str] | None = None,
- streaming_callback: StreamingCallbackT | None = None,
- tools: ToolsType | None = None,
+ *,
+ chat_generator: ChatGenerator,
+ system_prompt: str | None = None,
+ user_prompt: str | None = None,
+ required_variables: list[str] | Literal["*"] = "*",
+ streaming_callback: StreamingCallbackT | None = None
) -> None
```
-Initialize the HuggingFaceAPIChatGenerator instance.
+Initialize the LLM component.
**Parameters:**
-- **api_type** (HFGenerationAPIType | str) – The type of Hugging Face API to use. Available types:
-- `text_generation_inference`: See [TGI](https://github.com/huggingface/text-generation-inference).
-- `inference_endpoints`: See [Inference Endpoints](https://huggingface.co/inference-endpoints).
-- `serverless_inference_api`: See
- [Serverless Inference API - Inference Providers](https://huggingface.co/docs/inference-providers).
-- **api_params** (dict\[str, str\]) – A dictionary with the following keys:
-- `model`: Hugging Face model ID. Required when `api_type` is `SERVERLESS_INFERENCE_API`.
-- `provider`: Provider name. Recommended when `api_type` is `SERVERLESS_INFERENCE_API`.
-- `url`: URL of the inference endpoint. Required when `api_type` is `INFERENCE_ENDPOINTS` or
- `TEXT_GENERATION_INFERENCE`.
-- Other parameters specific to the chosen API type, such as `timeout`, `headers`, etc.
-- **token** (Secret | None) – The Hugging Face token to use as HTTP bearer authorization.
- Check your HF token in your [account settings](https://huggingface.co/settings/tokens).
-- **generation_kwargs** (dict\[str, Any\] | None) – A dictionary with keyword arguments to customize text generation.
- Some examples: `max_tokens`, `temperature`, `top_p`.
- For details, see [Hugging Face chat_completion documentation](https://huggingface.co/docs/huggingface_hub/package_reference/inference_client#huggingface_hub.InferenceClient.chat_completion).
-- **stop_words** (list\[str\] | None) – An optional list of strings representing the stop words.
-- **streaming_callback** (StreamingCallbackT | None) – An optional callable for handling streaming responses.
-- **tools** (ToolsType | None) – A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
- The chosen model should support tool/function calling, according to the model card.
- Support for tools in the Hugging Face API and TGI is not yet fully refined and you may experience
- unexpected behavior.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
+- **chat_generator** (ChatGenerator) – An instance of the chat generator that the LLM should use.
+- **system_prompt** (str | None) – System prompt for the LLM. Can be a plain string template or a Jinja2 message template.
+- **user_prompt** (str | None) – User prompt for the LLM. This prompt is appended to the messages provided at
+ runtime. Can be a plain string template or a Jinja2 message template. If it contains template variables
+ (e.g., `{{ variable_name }}`), they become inputs to the component. If omitted or if there are no
+ template variables, `messages` must be provided at runtime instead.
+- **required_variables** (list\[str\] | Literal['\*']) – Variables that must be provided as input to `user_prompt` or `system_prompt`.
+ If a variable listed as required is not provided, an exception is raised.
+ If set to `"*"`, all variables found in the prompt are required. Defaults to `"*"`.
+ Only relevant when `user_prompt` or `system_prompt` contains template variables.
+- **streaming_callback** (StreamingCallbackT | None) – A callback that will be invoked when a response is streamed from the LLM.
-Warm up the Hugging Face API chat generator.
+**Raises:**
-This will warm up the tools registered in the chat generator.
-This method is idempotent and will only warm up the tools once.
+- ValueError – If user_prompt contains template variables but required_variables is an empty list.
#### to_dict
@@ -862,227 +659,173 @@ This method is idempotent and will only warm up the tools once.
to_dict() -> dict[str, Any]
```
-Serialize this component to a dictionary.
+Serialize the LLM component to a dictionary.
**Returns:**
-- dict\[str, Any\] – A dictionary containing the serialized component.
+- dict\[str, Any\] – Dictionary with serialized data.
#### from_dict
```python
-from_dict(data: dict[str, Any]) -> HuggingFaceAPIChatGenerator
+from_dict(data: dict[str, Any]) -> LLM
```
-Deserialize this component from a dictionary.
+Deserialize the LLM from a dictionary.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
+
+**Returns:**
+
+- LLM – Deserialized LLM instance.
#### run
```python
run(
- messages: list[ChatMessage] | str,
- generation_kwargs: dict[str, Any] | None = None,
- tools: ToolsType | None = None,
+ *,
streaming_callback: StreamingCallbackT | None = None,
-) -> dict[str, list[ChatMessage]]
+ generation_kwargs: dict[str, Any] | None = None,
+ **kwargs: Any
+) -> dict[str, Any]
```
-Invoke the text generation inference based on the provided messages and generation parameters.
+Process messages and generate a response from the language model.
**Parameters:**
-- **messages** (list\[ChatMessage\] | str) – A list of ChatMessage objects representing the input messages. If a string is provided, it is converted
- to a list containing a ChatMessage with user role.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation.
-- **tools** (ToolsType | None) – A list of tools or a Toolset for which the model can prepare calls. If set, it will override
- the `tools` parameter set during component initialization. This parameter can accept either a
- list of `Tool` objects or a `Toolset` instance.
-- **streaming_callback** (StreamingCallbackT | None) – An optional callable for handling streaming responses. If set, it will override the `streaming_callback`
- parameter set during component initialization.
+- **messages** – Optional list of ChatMessage objects to prepend to the conversation. Whether this is
+ required or optional depends on the `user_prompt` configuration: if `user_prompt` has no template
+ variables, `messages` must be provided. Passed via `**kwargs`.
+- **streaming_callback** (StreamingCallbackT | None) – A callback that will be invoked when a response is streamed from the LLM.
+- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for the underlying chat generator. These parameters
+ will override the parameters passed during component initialization.
+- **kwargs** (Any) – Additional keyword arguments. These are used to fill template variables in `user_prompt` or
+ `system_prompt` (the keys must match template variable names).
**Returns:**
-- dict\[str, list\[ChatMessage\]\] – A dictionary with the following keys:
-- `replies`: A list containing the generated responses as ChatMessage objects.
+- dict\[str, Any\] – A dictionary with the following keys:
+- "messages": List of all messages exchanged during the LLM's run.
+- "last_message": The last message exchanged during the LLM's run.
+- "token_usage": Token usage from the LLM call (e.g. prompt_tokens, completion_tokens). Empty if the
+ chat generator did not return usage data.
#### run_async
```python
run_async(
- messages: list[ChatMessage] | str,
- generation_kwargs: dict[str, Any] | None = None,
- tools: ToolsType | None = None,
+ *,
streaming_callback: StreamingCallbackT | None = None,
-) -> dict[str, list[ChatMessage]]
+ generation_kwargs: dict[str, Any] | None = None,
+ **kwargs: Any
+) -> dict[str, Any]
```
-Asynchronously invokes the text generation inference based on the provided messages and generation parameters.
-
-This is the asynchronous version of the `run` method. It has the same parameters
-and return values but can be used with `await` in an async code.
+Asynchronously process messages and generate a response from the language model.
**Parameters:**
-- **messages** (list\[ChatMessage\] | str) – A list of ChatMessage objects representing the input messages. If a string is provided, it is converted
- to a list containing a ChatMessage with user role.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation.
-- **tools** (ToolsType | None) – A list of tools or a Toolset for which the model can prepare calls. If set, it will override the `tools`
- parameter set during component initialization. This parameter can accept either a list of `Tool` objects
- or a `Toolset` instance.
-- **streaming_callback** (StreamingCallbackT | None) – An optional callable for handling streaming responses. If set, it will override the `streaming_callback`
- parameter set during component initialization.
+- **messages** – Optional list of ChatMessage objects to prepend to the conversation. Whether this is
+ required or optional depends on the `user_prompt` configuration: if `user_prompt` has no template
+ variables, `messages` must be provided. Passed via `**kwargs`.
+- **streaming_callback** (StreamingCallbackT | None) – An asynchronous callback that will be invoked when a response is streamed
+ from the LLM.
+- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for the underlying chat generator. These parameters
+ will override the parameters passed during component initialization.
+- **kwargs** (Any) – Additional keyword arguments. These are used to fill template variables in `user_prompt` or
+ `system_prompt` (the keys must match template variable names).
**Returns:**
-- dict\[str, list\[ChatMessage\]\] – A dictionary with the following keys:
-- `replies`: A list containing the generated responses as ChatMessage objects.
-
-## chat/hugging_face_local
-
-### default_tool_parser
-
-```python
-default_tool_parser(text: str) -> list[ToolCall] | None
-```
-
-Default implementation for parsing tool calls from model output text.
-
-Uses DEFAULT_TOOL_PATTERN to extract tool calls.
+- dict\[str, Any\] – A dictionary with the following keys:
+- "messages": List of all messages exchanged during the LLM's run.
+- "last_message": The last message exchanged during the LLM's run.
+- "token_usage": Token usage from the LLM call (e.g. prompt_tokens, completion_tokens). Empty if the
+ chat generator did not return usage data.
-**Parameters:**
+## chat/mock
-- **text** (str) – The text to parse for tool calls.
+### MockChatGenerator
-**Returns:**
+A Chat Generator that returns predefined responses without calling any API.
-- list\[ToolCall\] | None – A list containing a single ToolCall if a valid tool call is found, None otherwise.
+It is a drop-in replacement for real Chat Generators (such as `OpenAIChatGenerator`) in tests, smoke tests, and
+quick prototypes. It implements the same interface (`run`, `run_async`, streaming, serialization) but never
+contacts an external service, so it is fully deterministic and free to run.
-### HuggingFaceLocalChatGenerator
+The response is selected based on how the component is configured:
-Generates chat responses using models from Hugging Face that run locally.
+- **Fixed response**: pass a single string or `ChatMessage`. The same reply is returned on every call.
+ Any `ChatMessage` passed as a response must have the `assistant` role.
+- **Cycling responses**: pass a list of strings and/or `ChatMessage` objects. Each call returns the next item,
+ wrapping around to the start once the list is exhausted. This is useful to drive multi-step flows such as
+ Agents, where the first call returns a tool call and a later call returns the final answer.
+- **Dynamic response**: pass a `response_fn` callable that receives the input messages and returns the reply.
+ This is useful when the reply should depend on the input, for example to echo back part of the prompt.
+- **Echo (default)**: with no configuration, the component echoes back the text of the last message that has
+ text content. This makes it usable out of the box for quick prototyping.
-Use this component with chat-based models,
-such as `Qwen/Qwen3-0.6B` or `meta-llama/Llama-2-7b-chat-hf`.
-LLMs running locally may need powerful hardware.
+Pass `ChatMessage` objects (rather than plain strings) to return tool calls or reasoning content, which is handy
+for exercising tool-calling pipelines without a real model.
### Usage example
-
-
```python
-from haystack.components.generators.chat import HuggingFaceLocalChatGenerator
-from haystack.dataclasses import ChatMessage
+from haystack.components.generators.chat import MockChatGenerator
+from haystack.dataclasses import ChatMessage, ToolCall
-generator = HuggingFaceLocalChatGenerator(model="Qwen/Qwen3-0.6B")
-messages = [ChatMessage.from_user("What's Natural Language Processing? Be brief.")]
-print(generator.run(messages))
-```
+# Fixed response
+generator = MockChatGenerator(responses="Hello, this is a mock response.")
+result = generator.run([ChatMessage.from_user("Hi!")])
+print(result["replies"][0].text) # "Hello, this is a mock response."
-```
-{'replies':
- [ChatMessage(_role=, _content=[TextContent(text=
- "Natural Language Processing (NLP) is a subfield of artificial intelligence that deals
- with the interaction between computers and human language. It enables computers to understand, interpret, and
- generate human language in a valuable way. NLP involves various techniques such as speech recognition, text
- analysis, sentiment analysis, and machine translation. The ultimate goal is to make it easier for computers to
- process and derive meaning from human language, improving communication between humans and machines.")],
- _name=None,
- _meta={'finish_reason': 'stop', 'index': 0, 'model':
- 'mistralai/Mistral-7B-Instruct-v0.2',
- 'usage': {'completion_tokens': 90, 'prompt_tokens': 19, 'total_tokens': 109}})
- ]
-}
+# Cycling responses to drive an Agent-like loop
+generator = MockChatGenerator(
+ responses=[
+ ChatMessage.from_assistant(tool_calls=[ToolCall(tool_name="search", arguments={"query": "Haystack"})]),
+ "Here is the final answer.",
+ ]
+)
```
#### __init__
```python
__init__(
- model: str = "Qwen/Qwen3-0.6B",
- task: (
- Literal["text-generation", "text2text-generation", "image-text-to-text"]
- | None
- ) = None,
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- chat_template: str | None = None,
- generation_kwargs: dict[str, Any] | None = None,
- huggingface_pipeline_kwargs: dict[str, Any] | None = None,
- stop_words: list[str] | None = None,
- streaming_callback: StreamingCallbackT | None = None,
- tools: ToolsType | None = None,
- tool_parsing_function: Callable[[str], list[ToolCall] | None] | None = None,
- async_executor: ThreadPoolExecutor | None = None,
+ responses: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
*,
- enable_thinking: bool = False
+ response_fn: ResponseFn | None = None,
+ model: str = "mock-model",
+ meta: dict[str, Any] | None = None,
+ streaming_callback: StreamingCallbackT | None = None
) -> None
```
-Initializes the HuggingFaceLocalChatGenerator component.
+Creates an instance of MockChatGenerator.
**Parameters:**
-- **model** (str) – The Hugging Face text generation model name or path,
- for example, `mistralai/Mistral-7B-Instruct-v0.2` or `TheBloke/OpenHermes-2.5-Mistral-7B-16k-AWQ`.
- The model must be a chat model supporting the ChatML messaging
- format.
- If the model is specified in `huggingface_pipeline_kwargs`, this parameter is ignored.
-- **task** (Literal['text-generation', 'text2text-generation', 'image-text-to-text'] | None) – The task for the Hugging Face pipeline. Possible options:
-- `text-generation`: Supported by decoder models, like GPT.
-- `text2text-generation`: Deprecated as of Transformers v5; use `text-generation` instead.
- Previously supported by encoder–decoder models such as T5.
-- `image-text-to-text`: Supported by vision-language models.
- If the task is specified in `huggingface_pipeline_kwargs`, this parameter is ignored.
- If not specified, the component calls the Hugging Face API to infer the task from the model name.
-- **device** (ComponentDevice | None) – The device for loading the model. If `None`, automatically selects the default device.
- If a device or device map is specified in `huggingface_pipeline_kwargs`, it overrides this parameter.
-- **token** (Secret | None) – The token to use as HTTP bearer authorization for remote files.
- If the token is specified in `huggingface_pipeline_kwargs`, this parameter is ignored.
-- **chat_template** (str | None) – Specifies an optional Jinja template for formatting chat
- messages. Most high-quality chat models have their own templates, but for models without this
- feature or if you prefer a custom template, use this parameter.
-- **generation_kwargs** (dict\[str, Any\] | None) – A dictionary with keyword arguments to customize text generation.
- Some examples: `max_length`, `max_new_tokens`, `temperature`, `top_k`, `top_p`.
- See Hugging Face's documentation for more information:
-- - [customize-text-generation](https://huggingface.co/docs/transformers/main/en/generation_strategies#customize-text-generation)
-- - [GenerationConfig](https://huggingface.co/docs/transformers/main/en/main_classes/text_generation#transformers.GenerationConfig)
- The only `generation_kwargs` set by default is `max_new_tokens`, which is set to 512 tokens.
-- **huggingface_pipeline_kwargs** (dict\[str, Any\] | None) – Dictionary with keyword arguments to initialize the
- Hugging Face pipeline for text generation.
- These keyword arguments provide fine-grained control over the Hugging Face pipeline.
- In case of duplication, these kwargs override `model`, `task`, `device`, and `token` init parameters.
- For kwargs, see [Hugging Face documentation](https://huggingface.co/docs/transformers/en/main_classes/pipelines#transformers.pipeline.task).
- In this dictionary, you can also include `model_kwargs` to specify the kwargs for [model initialization](https://huggingface.co/docs/transformers/en/main_classes/model#transformers.PreTrainedModel.from_pretrained)
-- **stop_words** (list\[str\] | None) – A list of stop words. If the model generates a stop word, the generation stops.
- If you provide this parameter, don't specify the `stopping_criteria` in `generation_kwargs`.
- For some chat models, the output includes both the new text and the original prompt.
- In these cases, make sure your prompt has no stop words.
-- **streaming_callback** (StreamingCallbackT | None) – An optional callable for handling streaming responses.
-- **tools** (ToolsType | None) – A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
-- **tool_parsing_function** (Callable\\[[str\], list\[ToolCall\] | None\] | None) – A callable that takes a string and returns a list of ToolCall objects or None.
- If None, the default_tool_parser will be used which extracts tool calls using a predefined pattern.
-- **async_executor** (ThreadPoolExecutor | None) – Optional ThreadPoolExecutor to use for async calls. If not provided, a single-threaded executor will be
- initialized and used
-- **enable_thinking** (bool) – Whether to enable thinking mode in the chat template for thinking-capable models.
- When enabled, the model generates intermediate reasoning before the final response. Defaults to False.
-
-#### shutdown
+- **responses** (str | ChatMessage | Sequence\[str | ChatMessage\] | None) – The predefined response(s) to return. Accepts a single string or `ChatMessage` (returned on
+ every call), or a non-empty list of strings and/or `ChatMessage` objects that are returned in order,
+ cycling back to the start once exhausted. Strings are wrapped into assistant `ChatMessage` objects, and any
+ `ChatMessage` passed must have the `assistant` role. Mutually exclusive with `response_fn`. If neither is
+ provided, the component echoes the last message with text content.
+- **response_fn** (ResponseFn | None) – An optional callable that receives the input messages and returns the reply as a string or
+ an assistant `ChatMessage`. Use this for input-dependent responses. Mutually exclusive with `responses`. To
+ support serialization, pass a named function (lambdas and nested functions cannot be serialized).
+- **model** (str) – The model name reported in the response metadata. Purely cosmetic; no model is loaded.
+- **meta** (dict\[str, Any\] | None) – Additional metadata merged into the `meta` of every returned `ChatMessage`. A per-response
+ `ChatMessage`'s own metadata takes precedence over this value.
+- **streaming_callback** (StreamingCallbackT | None) – An optional callback invoked with `StreamingChunk` objects reconstructed from the
+ predefined response. It lets the mock exercise streaming code paths without a real model.
-```python
-shutdown() -> None
-```
-
-Explicitly shutdown the executor if we own it.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
+**Raises:**
-Initializes the component and warms up tools if provided.
+- ValueError – If both `responses` and `response_fn` are provided, if `responses` is an empty list, or if
+ a `ChatMessage` response does not have the `assistant` role.
#### to_dict
@@ -1090,274 +833,86 @@ Initializes the component and warms up tools if provided.
to_dict() -> dict[str, Any]
```
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
+Serialize the component to a dictionary.
#### from_dict
```python
-from_dict(data: dict[str, Any]) -> HuggingFaceLocalChatGenerator
+from_dict(data: dict[str, Any]) -> MockChatGenerator
```
-Deserializes the component from a dictionary.
-
-**Parameters:**
+Deserialize the component from a dictionary.
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
+#### warm_up
-**Returns:**
+```python
+warm_up() -> None
+```
-- HuggingFaceLocalChatGenerator – The deserialized component.
+No-op warm up, provided for interface compatibility with real Chat Generators.
#### run
```python
run(
messages: list[ChatMessage] | str,
- generation_kwargs: dict[str, Any] | None = None,
streaming_callback: StreamingCallbackT | None = None,
+ generation_kwargs: dict[str, Any] | None = None,
+ *,
tools: ToolsType | None = None,
+ tools_strict: bool | None = None
) -> dict[str, list[ChatMessage]]
```
-Invoke text generation inference based on the provided messages and generation parameters.
-
-**Parameters:**
-
-- **messages** (list\[ChatMessage\] | str) – A list of ChatMessage objects representing the input messages. If a string is provided,
- it is converted to a list containing a ChatMessage with user role.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation.
-- **streaming_callback** (StreamingCallbackT | None) – An optional callable for handling streaming responses.
-- **tools** (ToolsType | None) – A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
- If set, it will override the `tools` parameter provided during initialization.
-
-**Returns:**
-
-- dict\[str, list\[ChatMessage\]\] – A dictionary with the following keys:
-- `replies`: A list containing the generated responses as ChatMessage instances.
-
-#### create_message
-
-```python
-create_message(
- text: str,
- index: int,
- tokenizer: Union[PreTrainedTokenizer, PreTrainedTokenizerFast],
- prompt: str,
- generation_kwargs: dict[str, Any],
- parse_tool_calls: bool = False,
-) -> ChatMessage
-```
+Return a predefined reply for the given messages without calling any API.
-Create a ChatMessage instance from the provided text, populated with metadata.
+The signature mirrors `OpenAIChatGenerator.run` so the mock can be used as a positional drop-in replacement.
**Parameters:**
-- **text** (str) – The generated text.
-- **index** (int) – The index of the generated text.
-- **tokenizer** (Union\[PreTrainedTokenizer, PreTrainedTokenizerFast\]) – The tokenizer used for generation.
-- **prompt** (str) – The prompt used for generation.
-- **generation_kwargs** (dict\[str, Any\]) – The generation parameters.
-- **parse_tool_calls** (bool) – Whether to attempt parsing tool calls from the text.
+- **messages** (list\[ChatMessage\] | str) – The conversation history as a list of `ChatMessage` instances or a single string.
+- **streaming_callback** (StreamingCallbackT | None) – An optional callback invoked with reconstructed `StreamingChunk` objects. Overrides
+ the callback set at initialization.
+- **generation_kwargs** (dict\[str, Any\] | None) – Accepted for interface compatibility and ignored.
+- **tools** (ToolsType | None) – Accepted for interface compatibility and ignored.
+- **tools_strict** (bool | None) – Accepted for interface compatibility and ignored.
**Returns:**
-- ChatMessage – A ChatMessage instance.
+- dict\[str, list\[ChatMessage\]\] – A dictionary with a single key `replies` containing the predefined reply as a list of one
+ `ChatMessage` (empty in echo mode when there is no message to echo).
#### run_async
```python
run_async(
messages: list[ChatMessage] | str,
- generation_kwargs: dict[str, Any] | None = None,
streaming_callback: StreamingCallbackT | None = None,
+ generation_kwargs: dict[str, Any] | None = None,
+ *,
tools: ToolsType | None = None,
+ tools_strict: bool | None = None
) -> dict[str, list[ChatMessage]]
```
-Asynchronously invokes text generation inference based on the provided messages and generation parameters.
-
-This is the asynchronous version of the `run` method. It has the same parameters
-and return values but can be used with `await` in an async code.
-
-**Parameters:**
-
-- **messages** (list\[ChatMessage\] | str) – A list of ChatMessage objects representing the input messages.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation.
-- **streaming_callback** (StreamingCallbackT | None) – An optional callable for handling streaming responses.
-- **tools** (ToolsType | None) – A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
- If set, it will override the `tools` parameter provided during initialization.
-
-**Returns:**
-
-- dict\[str, list\[ChatMessage\]\] – A dictionary with the following keys:
-- `replies`: A list containing the generated responses as ChatMessage instances.
-
-## chat/llm
-
-### LLM
-
-Bases: Agent
-
-A text generation component powered by a large language model.
-
-The LLM component is a simplified version of the Agent that focuses solely on text generation
-without tool usage. It processes messages and returns a single response from the language model.
-
-### Usage examples
-
-```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)
-```
-
-#### __init__
-
-```python
-__init__(
- *,
- chat_generator: ChatGenerator,
- system_prompt: str | None = None,
- user_prompt: str | None = None,
- required_variables: list[str] | Literal["*"] = "*",
- streaming_callback: StreamingCallbackT | None = None
-) -> None
-```
-
-Initialize the LLM component.
-
-**Parameters:**
-
-- **chat_generator** (ChatGenerator) – An instance of the chat generator that the LLM should use.
-- **system_prompt** (str | None) – System prompt for the LLM.
-- **user_prompt** (str | None) – User prompt for the LLM. This prompt is appended to the messages provided at
- runtime. If it contains Jinja2 template variables (e.g., `{{ variable_name }}`), they become
- inputs to the component. If omitted or if there are no template variables, `messages` must be
- provided at runtime instead.
-- **required_variables** (list\[str\] | Literal['\*']) – Variables that must be provided as input to user_prompt.
- If a variable listed as required is not provided, an exception is raised.
- If set to `"*"`, all variables found in the prompt are required. Defaults to `"*"`.
- Only relevant when `user_prompt` contains template variables.
-- **streaming_callback** (StreamingCallbackT | None) – A callback that will be invoked when a response is streamed from the LLM.
-
-**Raises:**
-
-- ValueError – If user_prompt contains template variables but required_variables is an empty list.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serialize the LLM component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> LLM
-```
-
-Deserialize the LLM from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- LLM – Deserialized LLM instance.
-
-#### run
-
-```python
-run(
- *,
- streaming_callback: StreamingCallbackT | None = None,
- generation_kwargs: dict[str, Any] | None = None,
- system_prompt: str | None = None,
- user_prompt: str | None = None,
- **kwargs: Any
-) -> dict[str, Any]
-```
-
-Process messages and generate a response from the language model.
-
-**Parameters:**
-
-- **messages** – Optional list of ChatMessage objects to prepend to the conversation. Whether this is
- required or optional depends on the `user_prompt` configuration: if `user_prompt` has no template
- variables, `messages` must be provided. Passed via `**kwargs`.
-- **streaming_callback** (StreamingCallbackT | None) – A callback that will be invoked when a response is streamed from the LLM.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for the underlying chat generator. These parameters
- will override the parameters passed during component initialization.
-- **system_prompt** (str | None) – System prompt for the LLM. If provided, it overrides the default system prompt.
-- **user_prompt** (str | None) – User prompt for the LLM. If provided, it overrides the default user prompt and is
- appended to the messages provided at runtime.
-- **kwargs** (Any) – Additional keyword arguments. These are used to fill template variables in the `user_prompt`
- (the keys must match template variable names).
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following keys:
-- "messages": List of all messages exchanged during the LLM's run.
-- "last_message": The last message exchanged during the LLM's run.
-
-#### run_async
+Asynchronously return a predefined reply for the given messages without calling any API.
-```python
-run_async(
- *,
- streaming_callback: StreamingCallbackT | None = None,
- generation_kwargs: dict[str, Any] | None = None,
- system_prompt: str | None = None,
- user_prompt: str | None = None,
- **kwargs: Any
-) -> dict[str, Any]
-```
-
-Asynchronously process messages and generate a response from the language model.
+The signature mirrors `OpenAIChatGenerator.run_async` so the mock can be used as a positional drop-in
+replacement.
**Parameters:**
-- **messages** – Optional list of ChatMessage objects to prepend to the conversation. Whether this is
- required or optional depends on the `user_prompt` configuration: if `user_prompt` has no template
- variables, `messages` must be provided. Passed via `**kwargs`.
-- **streaming_callback** (StreamingCallbackT | None) – An asynchronous callback that will be invoked when a response is streamed
- from the LLM.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for the underlying chat generator. These parameters
- will override the parameters passed during component initialization.
-- **system_prompt** (str | None) – System prompt for the LLM. If provided, it overrides the default system prompt.
-- **user_prompt** (str | None) – User prompt for the LLM. If provided, it overrides the default user prompt and is
- appended to the messages provided at runtime.
-- **kwargs** (Any) – Additional keyword arguments. These are used to fill template variables in the `user_prompt`
- (the keys must match template variable names).
+- **messages** (list\[ChatMessage\] | str) – The conversation history as a list of `ChatMessage` instances or a single string.
+- **streaming_callback** (StreamingCallbackT | None) – An optional callback invoked with reconstructed `StreamingChunk` objects. Overrides
+ the callback set at initialization.
+- **generation_kwargs** (dict\[str, Any\] | None) – Accepted for interface compatibility and ignored.
+- **tools** (ToolsType | None) – Accepted for interface compatibility and ignored.
+- **tools_strict** (bool | None) – Accepted for interface compatibility and ignored.
**Returns:**
-- dict\[str, Any\] – A dictionary with the following keys:
-- "messages": List of all messages exchanged during the LLM's run.
-- "last_message": The last message exchanged during the LLM's run.
+- dict\[str, list\[ChatMessage\]\] – A dictionary with a single key `replies` containing the predefined reply as a list of one
+ `ChatMessage` (empty in echo mode when there is no message to echo).
## chat/openai
@@ -1514,10 +1069,31 @@ in the OpenAI client.
warm_up() -> None
```
-Warm up the OpenAI chat generator.
+Warm up the tools and initialize the synchronous OpenAI client.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the tools and initialize the asynchronous OpenAI client on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Releases the synchronous OpenAI client.
-This will warm up the tools registered in the chat generator.
-This method is idempotent and will only warm up the tools once.
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Releases the asynchronous OpenAI client.
#### to_dict
@@ -1603,8 +1179,8 @@ but can be used with `await` in async code.
- **messages** (list\[ChatMessage\] | str) – A list of ChatMessage instances representing the input messages. If a string is provided, it is converted
to a list containing a ChatMessage with user role.
-- **streaming_callback** (StreamingCallbackT | None) – A callback function that is called when a new token is received from the stream.
- Must be a coroutine.
+- **streaming_callback** (StreamingCallbackT | None) – A callback function that is called when a new token is received from the stream. Async callbacks are
+ preferred; a sync callback is accepted but will run synchronously on the event loop and may block it.
- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation. These parameters will
override the parameters passed during component initialization.
For details on OpenAI API parameters, see [OpenAI documentation](https://platform.openai.com/docs/api-reference/chat/create).
@@ -1770,27 +1346,48 @@ in the OpenAI client.
warm_up() -> None
```
-Warm up the OpenAI responses chat generator.
-
-This will warm up the tools registered in the chat generator.
-This method is idempotent and will only warm up the tools once.
+Warm up the tools and initialize the synchronous OpenAI client.
-#### to_dict
+#### warm_up_async
```python
-to_dict() -> dict[str, Any]
+warm_up_async() -> None
```
-Serialize this component to a dictionary.
+Warm up the tools and initialize the asynchronous OpenAI client on the serving event loop.
-**Returns:**
+#### close
-- dict\[str, Any\] – The serialized component as a dictionary.
+```python
+close() -> None
+```
-#### from_dict
+Releases the synchronous OpenAI client.
+
+#### close_async
```python
-from_dict(data: dict[str, Any]) -> OpenAIResponsesChatGenerator
+close_async() -> None
+```
+
+Releases the asynchronous OpenAI client.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize this component to a dictionary.
+
+**Returns:**
+
+- dict\[str, Any\] – The serialized component as a dictionary.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> OpenAIResponsesChatGenerator
```
Deserialize this component from a dictionary.
@@ -1862,8 +1459,8 @@ but can be used with `await` in async code.
**Parameters:**
- **messages** (list\[ChatMessage\] | str) – A list of ChatMessage instances representing the input messages.
-- **streaming_callback** (StreamingCallbackT | None) – A callback function that is called when a new token is received from the stream.
- Must be a coroutine.
+- **streaming_callback** (StreamingCallbackT | None) – A callback function that is called when a new token is received from the stream. Async callbacks are
+ preferred; a sync callback is accepted but will run synchronously on the event loop and may block it.
- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation. These parameters will
override the parameters passed during component initialization.
For details on OpenAI API parameters, see [OpenAI documentation](https://platform.openai.com/docs/api-reference/responses/create).
@@ -1881,503 +1478,124 @@ but can be used with `await` in async code.
- dict\[str, list\[ChatMessage\]\] – A dictionary with the following key:
- `replies`: A list containing the generated responses as ChatMessage instances.
-## hugging_face_api
-
-### HuggingFaceAPIGenerator
-
-Generates text using Hugging Face APIs.
-
-Use it with the following Hugging Face APIs:
-
-- [Paid Inference Endpoints](https://huggingface.co/inference-endpoints)
-- [Self-hosted Text Generation Inference](https://github.com/huggingface/text-generation-inference)
-
-**Note:** As of July 2025, the Hugging Face Inference API no longer offers generative models through the
-`text_generation` endpoint. Generative models are now only available through providers supporting the
-`chat_completion` endpoint. As a result, this component might no longer work with the Hugging Face Inference API.
-Use the `HuggingFaceAPIChatGenerator` component, which supports the `chat_completion` endpoint.
-
-### Usage examples
-
-#### With Hugging Face Inference Endpoints
-
-
-
-```python
-from haystack.components.generators import HuggingFaceAPIGenerator
-from haystack.utils import Secret
-
-generator = HuggingFaceAPIGenerator(api_type="inference_endpoints",
- api_params={"url": ""},
- token=Secret.from_token(""))
-
-result = generator.run(prompt="What's Natural Language Processing?")
-print(result)
-```
-
-#### With self-hosted text generation inference
-
-
-
-```python
-from haystack.components.generators import HuggingFaceAPIGenerator
-
-generator = HuggingFaceAPIGenerator(api_type="text_generation_inference",
- api_params={"url": "http://localhost:8080"})
+## openai_image_generator
-result = generator.run(prompt="What's Natural Language Processing?")
-print(result)
-```
-
-#### With the free serverless inference API
-
-Be aware that this example might not work as the Hugging Face Inference API no longer offer models that support the
-`text_generation` endpoint. Use the `HuggingFaceAPIChatGenerator` for generative models through the
-`chat_completion` endpoint.
-
-
-
-```python
-from haystack.components.generators import HuggingFaceAPIGenerator
-from haystack.utils import Secret
-
-generator = HuggingFaceAPIGenerator(api_type="serverless_inference_api",
- api_params={"model": "HuggingFaceH4/zephyr-7b-beta"},
- token=Secret.from_token(""))
-
-result = generator.run(prompt="What's Natural Language Processing?")
-print(result)
-```
-
-#### __init__
-
-```python
-__init__(
- api_type: HFGenerationAPIType | str,
- api_params: dict[str, str],
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- generation_kwargs: dict[str, Any] | None = None,
- stop_words: list[str] | None = None,
- streaming_callback: StreamingCallbackT | None = None,
-) -> None
-```
-
-Initialize the HuggingFaceAPIGenerator instance.
-
-**Parameters:**
-
-- **api_type** (HFGenerationAPIType | str) – The type of Hugging Face API to use. Available types:
-- `text_generation_inference`: See [TGI](https://github.com/huggingface/text-generation-inference).
-- `inference_endpoints`: See [Inference Endpoints](https://huggingface.co/inference-endpoints).
-- `serverless_inference_api`: See [Serverless Inference API](https://huggingface.co/inference-api).
- This might no longer work due to changes in the models offered in the Hugging Face Inference API.
- Please use the `HuggingFaceAPIChatGenerator` component instead.
-- **api_params** (dict\[str, str\]) – A dictionary with the following keys:
-- `model`: Hugging Face model ID. Required when `api_type` is `SERVERLESS_INFERENCE_API`.
-- `url`: URL of the inference endpoint. Required when `api_type` is `INFERENCE_ENDPOINTS` or
- `TEXT_GENERATION_INFERENCE`.
-- Other parameters specific to the chosen API type, such as `timeout`, `headers`, `provider` etc.
-- **token** (Secret | None) – The Hugging Face token to use as HTTP bearer authorization.
- Check your HF token in your [account settings](https://huggingface.co/settings/tokens).
-- **generation_kwargs** (dict\[str, Any\] | None) – A dictionary with keyword arguments to customize text generation. Some examples: `max_new_tokens`,
- `temperature`, `top_k`, `top_p`.
- For details, see [Hugging Face documentation](https://huggingface.co/docs/huggingface_hub/en/package_reference/inference_client#huggingface_hub.InferenceClient.text_generation)
- for more information.
-- **stop_words** (list\[str\] | None) – An optional list of strings representing the stop words.
-- **streaming_callback** (StreamingCallbackT | None) – An optional callable for handling streaming responses.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serialize this component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary containing the serialized component.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> HuggingFaceAPIGenerator
-```
+### OpenAIImageGenerator
-Deserialize this component from a dictionary.
-
-#### run
-
-```python
-run(
- prompt: str,
- streaming_callback: StreamingCallbackT | None = None,
- generation_kwargs: dict[str, Any] | None = None,
-) -> dict[str, Any]
-```
-
-Invoke the text generation inference for the given prompt and generation parameters.
-
-**Parameters:**
-
-- **prompt** (str) – A string representing the prompt.
-- **streaming_callback** (StreamingCallbackT | None) – A callback function that is called when a new token is received from the stream.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the generated replies and metadata. Both are lists of length n.
-- replies: A list of strings representing the generated replies.
-
-## hugging_face_local
-
-### HuggingFaceLocalGenerator
-
-Generates text using models from Hugging Face that run locally.
-
-LLMs running locally may need powerful hardware.
-
-### Usage example
-
-```python
-from haystack.components.generators import HuggingFaceLocalGenerator
-
-generator = HuggingFaceLocalGenerator(
- model="Qwen/Qwen3-0.6B",
- task="text-generation",
- generation_kwargs={"max_new_tokens": 100, "temperature": 0.9}
-)
-
-print(generator.run("Who is the best American actor?"))
-# >> {'replies': ['John Cusack']}
-```
-
-#### __init__
-
-```python
-__init__(
- model: str = "Qwen/Qwen3-0.6B",
- task: Literal["text-generation", "text2text-generation"] | None = None,
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- generation_kwargs: dict[str, Any] | None = None,
- huggingface_pipeline_kwargs: dict[str, Any] | None = None,
- stop_words: list[str] | None = None,
- streaming_callback: StreamingCallbackT | None = None,
-) -> None
-```
-
-Creates an instance of a HuggingFaceLocalGenerator.
-
-**Parameters:**
-
-- **model** (str) – The Hugging Face text generation model name or path.
-- **task** (Literal['text-generation', 'text2text-generation'] | None) – The task for the Hugging Face pipeline. Possible options:
-- `text-generation`: Supported by decoder models, like GPT.
-- `text2text-generation`: Deprecated as of Transformers v5; use `text-generation` instead.
- Previously supported by encoder–decoder models such as T5.
- If the task is specified in `huggingface_pipeline_kwargs`, this parameter is ignored.
- If not specified, the component calls the Hugging Face API to infer the task from the model name.
-- **device** (ComponentDevice | None) – The device for loading the model. If `None`, automatically selects the default device.
- If a device or device map is specified in `huggingface_pipeline_kwargs`, it overrides this parameter.
-- **token** (Secret | None) – The token to use as HTTP bearer authorization for remote files.
- If the token is specified in `huggingface_pipeline_kwargs`, this parameter is ignored.
-- **generation_kwargs** (dict\[str, Any\] | None) – A dictionary with keyword arguments to customize text generation.
- Some examples: `max_length`, `max_new_tokens`, `temperature`, `top_k`, `top_p`.
- See Hugging Face's documentation for more information:
-- [customize-text-generation](https://huggingface.co/docs/transformers/main/en/generation_strategies#customize-text-generation)
-- [transformers.GenerationConfig](https://huggingface.co/docs/transformers/main/en/main_classes/text_generation#transformers.GenerationConfig)
-- **huggingface_pipeline_kwargs** (dict\[str, Any\] | None) – Dictionary with keyword arguments to initialize the
- Hugging Face pipeline for text generation.
- These keyword arguments provide fine-grained control over the Hugging Face pipeline.
- In case of duplication, these kwargs override `model`, `task`, `device`, and `token` init parameters.
- For available kwargs, see [Hugging Face documentation](https://huggingface.co/docs/transformers/en/main_classes/pipelines#transformers.pipeline.task).
- In this dictionary, you can also include `model_kwargs` to specify the kwargs for model initialization:
- [transformers.PreTrainedModel.from_pretrained](https://huggingface.co/docs/transformers/en/main_classes/model#transformers.PreTrainedModel.from_pretrained)
-- **stop_words** (list\[str\] | None) – If the model generates a stop word, the generation stops.
- If you provide this parameter, don't specify the `stopping_criteria` in `generation_kwargs`.
- For some chat models, the output includes both the new text and the original prompt.
- In these cases, make sure your prompt has no stop words.
-- **streaming_callback** (StreamingCallbackT | None) – An optional callable for handling streaming responses.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> HuggingFaceLocalGenerator
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- HuggingFaceLocalGenerator – The deserialized component.
-
-#### run
-
-```python
-run(
- prompt: str,
- streaming_callback: StreamingCallbackT | None = None,
- generation_kwargs: dict[str, Any] | None = None,
-) -> dict[str, Any]
-```
-
-Run the text generation model on the given prompt.
-
-**Parameters:**
-
-- **prompt** (str) – A string representing the prompt.
-- **streaming_callback** (StreamingCallbackT | None) – A callback function that is called when a new token is received from the stream.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary containing the generated replies.
-- replies: A list of strings representing the generated replies.
-
-## openai
-
-### OpenAIGenerator
-
-Generates text using OpenAI's large language models (LLMs).
-
-It works with the gpt-4 and gpt-5 series models and supports streaming responses
-from OpenAI API. It uses strings as input and output.
-
-You can customize how the text is generated by passing parameters to the
-OpenAI API. Use the `**generation_kwargs` argument when you initialize
-the component or when you run it. Any parameter that works with
-`openai.ChatCompletion.create` will work here too.
+Generates images using OpenAI's image generation models such as `gpt-image-2`.
For details on OpenAI API parameters, see
-[OpenAI documentation](https://platform.openai.com/docs/api-reference/chat).
+[OpenAI documentation](https://developers.openai.com/api/reference/resources/images/methods/generate).
### Usage example
```python
-from haystack.components.generators import OpenAIGenerator
-client = OpenAIGenerator()
-response = client.run("What's Natural Language Processing? Be brief.")
+from haystack.components.generators import OpenAIImageGenerator
+image_generator = OpenAIImageGenerator()
+response = image_generator.run("Show me a picture of a black cat.")
print(response)
-
-# >> {'replies': ['Natural Language Processing (NLP) is a branch of artificial intelligence that focuses on
-# >> the interaction between computers and human language. It involves enabling computers to understand, interpret,
-# >> and respond to natural human language in a way that is both meaningful and useful.'], 'meta': [{'model':
-# >> 'gpt-5-mini', 'index': 0, 'finish_reason': 'stop', 'usage': {'prompt_tokens': 16,
-# >> 'completion_tokens': 49, 'total_tokens': 65}}]}
```
#### __init__
```python
__init__(
+ model: str = "gpt-image-2",
+ quality: Literal["auto", "high", "medium", "low"] = "auto",
+ size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] = "1024x1024",
+ response_format: Literal["b64_json"] = "b64_json",
api_key: Secret = Secret.from_env_var("OPENAI_API_KEY"),
- model: str = "gpt-5-mini",
- streaming_callback: StreamingCallbackT | None = None,
api_base_url: str | None = None,
organization: str | None = None,
- system_prompt: str | None = None,
- generation_kwargs: dict[str, Any] | None = None,
timeout: float | None = None,
max_retries: int | None = None,
http_client_kwargs: dict[str, Any] | None = None,
) -> None
```
-Creates an instance of OpenAIGenerator. Unless specified otherwise in `model`, uses OpenAI's gpt-5-mini
-
-By setting the 'OPENAI_TIMEOUT' and 'OPENAI_MAX_RETRIES' you can change the timeout and max_retries parameters
-in the OpenAI client.
+Creates an instance of OpenAIImageGenerator. Unless specified otherwise in `model`, uses OpenAI's gpt-image-2.
**Parameters:**
+- **model** (str) – The model to use for image generation. Model names can be found in the
+ [OpenAI documentation](https://developers.openai.com/api/docs/models/all).
+- **quality** (Literal['auto', 'high', 'medium', 'low']) – The quality of the generated image. Can be "auto", "high", "medium", or "low".
+- **size** (Literal['1024x1024', '1024x1536', '1536x1024', 'auto']) – The size of the generated images. One of 1024x1024, 1024x1536, 1536x1024, or "auto".
+ `gpt-image-2` also supports arbitrary sizes. You can find more information about supported sizes in
+ the [OpenAI documentation](https://developers.openai.com/api/reference/resources/images/methods/generate).
+- **response_format** (Literal['b64_json']) – This parameter is ignored and only kept for backward compatibility.
- **api_key** (Secret) – The OpenAI API key to connect to OpenAI.
-- **model** (str) – The name of the model to use.
-- **streaming_callback** (StreamingCallbackT | None) – A callback function that is called when a new token is received from the stream.
- The callback function accepts StreamingChunk as an argument.
- **api_base_url** (str | None) – An optional base URL.
- **organization** (str | None) – The Organization ID, defaults to `None`.
-- **system_prompt** (str | None) – The system prompt to use for text generation. If not provided, the system prompt is
- omitted, and the default system prompt of the model is used.
-- **generation_kwargs** (dict\[str, Any\] | None) – Other parameters to use for the model. These parameters are all sent directly to
- the OpenAI endpoint. See OpenAI [documentation](https://platform.openai.com/docs/api-reference/chat) for
- more details.
- Some of the supported parameters:
-- `max_completion_tokens`: An upper bound for the number of tokens that can be generated for a completion,
- including visible output tokens and reasoning tokens.
-- `temperature`: What sampling temperature to use. Higher values mean the model will take more risks.
- Try 0.9 for more creative applications and 0 (argmax sampling) for ones with a well-defined answer.
-- `top_p`: An alternative to sampling with temperature, called nucleus sampling, where the model
- considers the results of the tokens with top_p probability mass. So, 0.1 means only the tokens
- comprising the top 10% probability mass are considered.
-- `n`: How many completions to generate for each prompt. For example, if the LLM gets 3 prompts and n is 2,
- it will generate two completions for each of the three prompts, ending up with 6 completions in total.
-- `stop`: One or more sequences after which the LLM should stop generating tokens.
-- `presence_penalty`: What penalty to apply if a token is already present at all. Bigger values mean
- the model will be less likely to repeat the same token in the text.
-- `frequency_penalty`: What penalty to apply if a token has already been generated in the text.
- Bigger values mean the model will be less likely to repeat the same token in the text.
-- `logit_bias`: Add a logit bias to specific tokens. The keys of the dictionary are tokens, and the
- values are the bias to add to that token.
-- **timeout** (float | None) – Timeout for OpenAI Client calls, if not set it is inferred from the `OPENAI_TIMEOUT` environment variable
+- **timeout** (float | None) – Timeout for OpenAI Client calls. If not set, it is inferred from the `OPENAI_TIMEOUT` environment variable
or set to 30.
-- **max_retries** (int | None) – Maximum retries to establish contact with OpenAI if it returns an internal error, if not set it is inferred
+- **max_retries** (int | None) – Maximum retries to establish contact with OpenAI if it returns an internal error. If not set, it is inferred
from the `OPENAI_MAX_RETRIES` environment variable or set to 5.
- **http_client_kwargs** (dict\[str, Any\] | None) – A dictionary of keyword arguments to configure a custom `httpx.Client`or `httpx.AsyncClient`.
For more information, see the [HTTPX documentation](https://www.python-httpx.org/api/#client).
-#### to_dict
+#### warm_up
```python
-to_dict() -> dict[str, Any]
+warm_up() -> None
```
-Serialize this component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – The serialized component as a dictionary.
+Initializes the synchronous OpenAI client.
-#### from_dict
+#### warm_up_async
```python
-from_dict(data: dict[str, Any]) -> OpenAIGenerator
+warm_up_async() -> None
```
-Deserialize this component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary representation of this component.
-
-**Returns:**
-
-- OpenAIGenerator – The deserialized component instance.
+Initializes the asynchronous OpenAI client on the serving event loop.
-#### run
+#### close
```python
-run(
- prompt: str,
- system_prompt: str | None = None,
- streaming_callback: StreamingCallbackT | None = None,
- generation_kwargs: dict[str, Any] | None = None,
-) -> dict[str, list[str] | list[dict[str, Any]]]
+close() -> None
```
-Invoke the text generation inference based on the provided messages and generation parameters.
+Releases the synchronous OpenAI client.
-**Parameters:**
-
-- **prompt** (str) – The string prompt to use for text generation.
-- **system_prompt** (str | None) – The system prompt to use for text generation. If this run time system prompt is omitted, the system
- prompt, if defined at initialisation time, is used.
-- **streaming_callback** (StreamingCallbackT | None) – A callback function that is called when a new token is received from the stream.
-- **generation_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for text generation. These parameters will potentially override the parameters
- passed in the `__init__` method. For more details on the parameters supported by the OpenAI API, refer to
- the OpenAI [documentation](https://platform.openai.com/docs/api-reference/chat/create).
-
-**Returns:**
-
-- dict\[str, list\[str\] | list\[dict\[str, Any\]\]\] – A list of strings containing the generated responses and a list of dictionaries containing the metadata
- for each response.
-
-## openai_dalle
-
-### DALLEImageGenerator
-
-Generates images using OpenAI's image generation models such as `gpt-image-2`.
-
-For details on OpenAI API parameters, see
-[OpenAI documentation](https://developers.openai.com/api/reference/resources/images/methods/generate).
-
-### Usage example
+#### close_async
```python
-from haystack.components.generators import DALLEImageGenerator
-image_generator = DALLEImageGenerator()
-response = image_generator.run("Show me a picture of a black cat.")
-print(response)
+close_async() -> None
```
-#### __init__
+Releases the asynchronous OpenAI client.
+
+#### run
```python
-__init__(
- model: str = "gpt-image-2",
- quality: Literal["auto", "high", "medium", "low"] = "auto",
- size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] = "1024x1024",
- response_format: Literal["b64_json"] = "b64_json",
- api_key: Secret = Secret.from_env_var("OPENAI_API_KEY"),
- api_base_url: str | None = None,
- organization: str | None = None,
- timeout: float | None = None,
- max_retries: int | None = None,
- http_client_kwargs: dict[str, Any] | None = None,
-) -> None
+run(
+ prompt: str,
+ size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] | None = None,
+ quality: Literal["auto", "high", "medium", "low"] | None = None,
+ response_format: Literal["b64_json"] | None = None,
+) -> dict[str, Any]
```
-Creates an instance of DALLEImageGenerator. Unless specified otherwise in `model`, uses OpenAI's gpt-image-2.
+Invokes the image generation inference based on the provided prompt and generation parameters.
**Parameters:**
-- **model** (str) – The model to use for image generation. Model names can be found in the
- [OpenAI documentation](https://developers.openai.com/api/docs/models/all).
-- **quality** (Literal['auto', 'high', 'medium', 'low']) – The quality of the generated image. Can be "auto", "high", "medium", or "low".
-- **size** (Literal['1024x1024', '1024x1536', '1536x1024', 'auto']) – The size of the generated images. One of 1024x1024, 1024x1536, 1536x1024, or "auto".
- `gpt-image-2` also supports arbitrary sizes. You can find more information about supported sizes in
- the [OpenAI documentation](https://developers.openai.com/api/reference/resources/images/methods/generate).
-- **response_format** (Literal['b64_json']) – This parameter is ignored and only kept for backward compatibility.
-- **api_key** (Secret) – The OpenAI API key to connect to OpenAI.
-- **api_base_url** (str | None) – An optional base URL.
-- **organization** (str | None) – The Organization ID, defaults to `None`.
-- **timeout** (float | None) – Timeout for OpenAI Client calls. If not set, it is inferred from the `OPENAI_TIMEOUT` environment variable
- or set to 30.
-- **max_retries** (int | None) – Maximum retries to establish contact with OpenAI if it returns an internal error. If not set, it is inferred
- from the `OPENAI_MAX_RETRIES` environment variable or set to 5.
-- **http_client_kwargs** (dict\[str, Any\] | None) – A dictionary of keyword arguments to configure a custom `httpx.Client`or `httpx.AsyncClient`.
- For more information, see the [HTTPX documentation](https://www.python-httpx.org/api/#client).
-
-#### warm_up
+- **prompt** (str) – The prompt to generate the image.
+- **size** (Literal['1024x1024', '1024x1536', '1536x1024', 'auto'] | None) – If provided, overrides the size provided during initialization.
+- **quality** (Literal['auto', 'high', 'medium', 'low'] | None) – If provided, overrides the quality provided during initialization.
+- **response_format** (Literal['b64_json'] | None) – This parameter is ignored and only kept for backward compatibility.
-```python
-warm_up() -> None
-```
+**Returns:**
-Warm up the OpenAI client.
+- dict\[str, Any\] – A dictionary containing the generated list of images as base64 encoded JSON strings and the revised prompt.
+ The revised prompt is the prompt that was used to generate the image, if there was any revision
+ to the prompt made by OpenAI.
-#### run
+#### run_async
```python
-run(
+run_async(
prompt: str,
size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] | None = None,
quality: Literal["auto", "high", "medium", "low"] | None = None,
@@ -2385,7 +1603,10 @@ run(
) -> dict[str, Any]
```
-Invokes the image generation inference based on the provided prompt and generation parameters.
+Asynchronously invokes the image generation inference based on the provided prompt and generation parameters.
+
+This is the asynchronous version of the `run` method. It has the same parameters and return values
+but can be used with `await` in an async code.
**Parameters:**
@@ -2415,7 +1636,7 @@ Serialize this component to a dictionary.
#### from_dict
```python
-from_dict(data: dict[str, Any]) -> DALLEImageGenerator
+from_dict(data: dict[str, Any]) -> OpenAIImageGenerator
```
Deserialize this component from a dictionary.
@@ -2426,7 +1647,7 @@ Deserialize this component from a dictionary.
**Returns:**
-- DALLEImageGenerator – The deserialized component instance.
+- OpenAIImageGenerator – The deserialized component instance.
## utils
diff --git a/docs-website/reference/haystack-api/hooks_api.md b/docs-website/reference/haystack-api/hooks_api.md
new file mode 100644
index 00000000000..f281f7c969d
--- /dev/null
+++ b/docs-website/reference/haystack-api/hooks_api.md
@@ -0,0 +1,609 @@
+---
+title: "Hooks"
+id: hooks-api
+description: "Hooks that run at points in the Agent's run loop and influence it by mutating State, including built-in tool result offloading."
+slug: "/hooks-api"
+---
+
+
+## from_function
+
+### FunctionHook
+
+Wraps a function (or a sync/async pair) into a serializable `Hook`.
+
+Produced by the `@hook` decorator for the single-function case. To give a hook both an optimized sync and async
+path, construct it directly with both `function` and `async_function` set.
+
+#### __init__
+
+```python
+__init__(
+ function: Callable[[State], None] | None = None,
+ async_function: Callable[[State], Awaitable[None]] | None = None,
+) -> None
+```
+
+Initialize the hook with a synchronous function, an async function, or both.
+
+**Parameters:**
+
+- **function** (Callable\\[[State\], None\] | None) – The synchronous function invoked by `run`. Must be a regular function — coroutine functions
+ should be passed to `async_function` instead. Either `function` or `async_function` (or both) must be set.
+- **async_function** (Callable\\[[State\], Awaitable[None]\] | None) – Optional coroutine function awaited by `run_async`. When only `async_function` is set,
+ `run` raises a `RuntimeError`. When only `function` is set, `run_async` calls `function`.
+
+**Raises:**
+
+- ValueError – If neither is set, if `function` is a coroutine function, if `async_function` is not, or
+ if a provided function does not declare a `State`-typed parameter.
+
+#### run
+
+```python
+run(state: State) -> None
+```
+
+Run the synchronous function against the live `State`.
+
+**Parameters:**
+
+- **state** (State) – The Agent's live `State`, mutated in place by the wrapped function.
+
+**Raises:**
+
+- RuntimeError – If the hook only has an `async_function`; use the Agent's async run methods instead.
+
+#### run_async
+
+```python
+run_async(state: State) -> None
+```
+
+Await the async function if set, otherwise call the synchronous function.
+
+**Parameters:**
+
+- **state** (State) – The Agent's live `State`, mutated in place by the wrapped function.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the hook, storing each wrapped function as an importable reference.
+
+**Returns:**
+
+- dict\[str, Any\] – A dictionary with the hook's type and the import paths of its sync/async functions.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> FunctionHook
+```
+
+Deserialize the hook, resolving each function from its importable reference.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – The serialized hook dictionary produced by `to_dict`.
+
+**Returns:**
+
+- FunctionHook – The reconstructed `FunctionHook`.
+
+### hook
+
+```python
+hook(function: Callable[[State], None | Awaitable[None]]) -> FunctionHook
+```
+
+Wrap a function into a `Hook` the Agent can invoke during its run loop.
+
+The decorated function receives the Agent's `State` and influences the run by mutating it in place. A coroutine
+function is wrapped as the hook's async path; a regular function as its sync path. To give a single hook both
+paths, construct a `FunctionHook` directly with both `function` and `async_function`.
+
+### Usage example
+
+```python
+from haystack.components.agents import Agent
+from haystack.hooks import hook
+from haystack.components.agents.state import State
+from haystack.dataclasses import ChatMessage
+
+@hook
+def require_save(state: State) -> None:
+ if state.get("tool_call_counts", {}).get("save", 0) == 0:
+ state.set("messages", [ChatMessage.from_system("You must call `save` before finishing.")])
+ state.set("continue_run", True)
+
+agent = Agent(chat_generator=..., tools=[...], hooks={"on_exit": [require_save]})
+```
+
+**Parameters:**
+
+- **function** (Callable\\[[State\], None | Awaitable[None]\]) – A callable taking the Agent's `State` and returning `None` (sync or async).
+
+**Returns:**
+
+- FunctionHook – A `FunctionHook` wrapping the function.
+
+## protocol
+
+### Hook
+
+Bases: Protocol
+
+A callable the Agent invokes at a point in its run loop, receiving the live `State`.
+
+A hook influences the run only by mutating `State` in place. At least `messages` (the conversation),
+`step_count`, `token_usage` and `tool_call_counts` are available; any additional keys defined in the Agent's
+`state_schema` are available too. The same hook object can be registered under multiple hook points.
+
+Implement this protocol directly for stateful hooks (e.g. one wrapping a component), or use the `@hook` decorator to
+wrap a plain `(State) -> None` function.
+
+A hook may additionally define `async def run_async(self, state: State) -> None` for true async behavior; when
+absent, the Agent calls `run` during async runs. It is left off this protocol on purpose so sync-only hooks
+don't have to implement it.
+
+A hook may also implement the optional lifecycle methods `warm_up` / `warm_up_async` and `close` / `close_async`.
+The Agent calls them from its own `warm_up` / `warm_up_async` and `close` / `close_async`, so a hook can defer
+opening clients or reading credentials until warm-up and release them on close.
+
+#### run
+
+```python
+run(state: State) -> None
+```
+
+Run the hook against the live `State`, mutating it in place.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the hook to a dictionary.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> Hook
+```
+
+Deserialize the hook from a dictionary.
+
+## tool_result_offloading/hooks
+
+### ToolResultOffloadHook
+
+Offload tool results to a `ToolResultStore`, replacing them in the conversation with a compact pointer.
+
+This `after_tool` Agent hook writes the full result to the store so the next LLM call sees a reference instead of
+the full result. Register it on an `Agent` under the `after_tool` hook point. Which tools offload, and under what
+condition, is controlled per tool by `offload_strategies`:
+
+```python
+from haystack.components.agents import Agent
+from haystack.components.generators.chat import OpenAIChatGenerator
+from haystack.hooks.tool_result_offloading import (
+ AlwaysOffload,
+ FileSystemToolResultStore,
+ NeverOffload,
+ OffloadOverChars,
+ ToolResultOffloadHook,
+)
+
+hook = ToolResultOffloadHook(
+ store=FileSystemToolResultStore(root="tool_results"),
+ offload_strategies={
+ "web_search": AlwaysOffload(), # force offload
+ "get_time": NeverOffload(), # opt out
+ ("read_file", "list_dir"): OffloadOverChars(4000), # tuple key: shared policy
+ "*": OffloadOverChars(8000), # wildcard default for any unlisted tool
+ },
+)
+agent = Agent(
+ chat_generator=OpenAIChatGenerator(model="gpt-5.4-nano"),
+ tools=[web_search, get_time, read_file, list_dir],
+ hooks={"after_tool": [hook]},
+)
+```
+
+A key may be a single tool name, a tuple of tool names sharing one policy, or the wildcard `"*"` which applies to
+any tool without a more specific entry. More specific keys win. A tool with no matching key (and no `"*"`) is not
+offloaded.
+
+Only successful, text tool output is offloaded. Error results (including `before_tool` human-in-the-loop
+rejections) are always left in context. Non-text results (image or file content) are also left in context, and a
+warning is logged when such a result has a matching offload policy; supporting only text is a deliberate choice
+for now. Each result is offloaded at most once, even though the hook runs on every tool step.
+
+The hook keeps no mutable state, so a single instance can be shared across concurrent runs. The constructor
+`store`, however, is shared by every run that does not override it — fine for single-user or local use, but in a
+multi-user server give each run its own isolated store (a per-session directory or sandbox) via `hook_context`
+under the key `RESULT_STORE_CONTEXT_KEY`
+(`agent.run(messages=[...], hook_context={RESULT_STORE_CONTEXT_KEY: per_request_store})`); it overrides the
+constructor store for that run. Isolating the store per run keeps concurrent users from colliding on store keys or
+reading each other's offloaded results — important especially when a bash/read tool is scoped to the store.
+
+#### __init__
+
+```python
+__init__(
+ store: ToolResultStore,
+ offload_strategies: dict[str | tuple[str, ...], OffloadPolicy],
+ *,
+ preview_chars: int = 200
+) -> None
+```
+
+Initialize the hook with a store and per-tool offload strategies.
+
+**Parameters:**
+
+- **store** (ToolResultStore) – Where offloaded results are written. Can be overridden per run via `hook_context`.
+- **offload_strategies** (dict\[str | tuple\[str, ...\], OffloadPolicy\]) – Mapping of tool name (or a tuple of tool names, or the wildcard `"*"`) to the
+ `OffloadPolicy` that decides whether that tool's results are offloaded.
+- **preview_chars** (int) – Number of leading characters of the original result to include in the pointer left in
+ the conversation, so the model knows roughly what was offloaded.
+
+#### run
+
+```python
+run(state: State) -> None
+```
+
+Offload the freshly produced tool results in `state.data["messages"]` according to `offload_strategies`.
+
+Considers only the trailing block of tool-result messages (the current step's results); earlier history is
+left untouched. Offloads each of those messages its policy opts in for, and writes the rewritten conversation
+back to `messages` only if at least one message changed.
+
+Results are written to the store this run resolves to: a per-run store passed in `state`'s `hook_context`
+under `RESULT_STORE_CONTEXT_KEY` if present, otherwise the store the hook was constructed with. Supply the
+per-run store when calling the Agent, e.g.
+`agent.run(messages=[...], hook_context={RESULT_STORE_CONTEXT_KEY: per_request_store})`. In a multi-user
+server, pass an isolated store per run this way so concurrent users write to separate locations and never
+read each other's results.
+
+The hook keeps no mutable state, so a single instance is safe to share across concurrent runs; isolation
+comes entirely from giving each run its own store via `hook_context`.
+
+**Parameters:**
+
+- **state** (State) – The Agent's live `State`. Reads the per-run store from `hook_context` and rewrites the offloaded
+ tool-result messages back into `messages`.
+
+**Returns:**
+
+- None – None. The hook mutates `state` in place.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the hook, including its store and per-tool offload strategies.
+
+**Returns:**
+
+- dict\[str, Any\] – A dictionary representation of the hook.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> ToolResultOffloadHook
+```
+
+Deserialize the hook, reconstructing its store and offload strategies.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – A dictionary representation produced by `to_dict`.
+
+**Returns:**
+
+- ToolResultOffloadHook – The deserialized `ToolResultOffloadHook`.
+
+## tool_result_offloading/policies
+
+### AlwaysOffload
+
+Bases: OffloadPolicy
+
+Offload every result of the tool it is assigned to.
+
+#### should_offload
+
+```python
+should_offload(tool_name: str, result: str, state: State) -> bool
+```
+
+Decide whether to offload the given tool result.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool that produced the result (unused; this policy always offloads).
+- **result** (str) – The tool result string (unused; this policy always offloads).
+- **state** (State) – The Agent's live `State` (unused; this policy always offloads).
+
+**Returns:**
+
+- bool – Always True.
+
+### NeverOffload
+
+Bases: OffloadPolicy
+
+Never offload; keep the tool's full result in context. Use to opt a tool out of a wildcard default.
+
+#### should_offload
+
+```python
+should_offload(tool_name: str, result: str, state: State) -> bool
+```
+
+Decide whether to offload the given tool result.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool that produced the result (unused; this policy never offloads).
+- **result** (str) – The tool result string (unused; this policy never offloads).
+- **state** (State) – The Agent's live `State` (unused; this policy never offloads).
+
+**Returns:**
+
+- bool – Always False.
+
+### OffloadOverChars
+
+Bases: OffloadPolicy
+
+Offload a result only when its string length exceeds `threshold` characters.
+
+#### __init__
+
+```python
+__init__(threshold: int) -> None
+```
+
+Initialize the policy with its character threshold.
+
+**Parameters:**
+
+- **threshold** (int) – Offload the result when its length in characters is strictly greater than this value.
+
+#### should_offload
+
+```python
+should_offload(tool_name: str, result: str, state: State) -> bool
+```
+
+Decide whether to offload the given tool result based on its length.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool that produced the result (unused; only length is considered).
+- **result** (str) – The tool result string whose length is compared against the threshold.
+- **state** (State) – The Agent's live `State` (unused; only length is considered).
+
+**Returns:**
+
+- bool – True when `result` is longer than `threshold` characters, otherwise False.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the policy, including its threshold.
+
+**Returns:**
+
+- dict\[str, Any\] – A dictionary representation of the policy.
+
+## tool_result_offloading/stores
+
+### FileSystemToolResultStore
+
+Bases: ToolResultStore
+
+A `ToolResultStore` that writes offloaded tool results to files under a root directory on the local file system.
+
+```python
+from haystack.hooks.tool_result_offloading import FileSystemToolResultStore
+
+store = FileSystemToolResultStore(root="tool_results")
+reference = store.write(key="search_1.txt", content="...")
+store.read(reference)
+```
+
+#### __init__
+
+```python
+__init__(root: str | Path) -> None
+```
+
+Initialize the store with the root directory results are written under.
+
+**Parameters:**
+
+- **root** (str | Path) – Directory under which result files are written. Created on first write if it does not exist.
+
+#### write
+
+```python
+write(*, key: str, content: str) -> str
+```
+
+Write `content` to `/`, creating parent directories, and return the file path.
+
+The resolved target must stay within the root directory: a `key` that escapes it (e.g. containing `../` or an
+absolute path) is rejected, so a tool-provided key cannot write outside the store.
+
+**Parameters:**
+
+- **key** (str) – Relative file name for the result within the store root.
+- **content** (str) – The tool result to persist.
+
+**Returns:**
+
+- str – The absolute path the content was written to, as a string, for use with `read`.
+
+**Raises:**
+
+- ValueError – If `key` resolves to a location outside the store root.
+
+#### read
+
+```python
+read(reference: str) -> str
+```
+
+Read back the content previously written to `reference`.
+
+**Parameters:**
+
+- **reference** (str) – A path returned by `write`.
+
+**Returns:**
+
+- str – The stored content.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the store, storing its root directory as a string.
+
+**Returns:**
+
+- dict\[str, Any\] – A dictionary representation of the store.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> FileSystemToolResultStore
+```
+
+Deserialize the store from a dictionary.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – A dictionary representation produced by `to_dict`.
+
+**Returns:**
+
+- FileSystemToolResultStore – The deserialized `FileSystemToolResultStore`.
+
+## tool_result_offloading/types/protocol
+
+### ToolResultStore
+
+Bases: Protocol
+
+A place a `ToolResultOffloadHook` writes offloaded tool results to, and reads them back from.
+
+Implementations decide where and how the content lives (local disk, an isolated sandbox filesystem, object
+storage, ...). `write` returns an opaque reference string that the Agent puts in the conversation in place of the
+full result; `read` resolves that reference back to the original content.
+
+Implement both `to_dict` and `from_dict` to make a custom store serializable; the default implementations below
+cover stores whose constructor takes no arguments.
+
+#### write
+
+```python
+write(*, key: str, content: str) -> str
+```
+
+Persist `content` under `key` and return an opaque reference to it.
+
+**Parameters:**
+
+- **key** (str) – A stable, per-result identifier the hook derives from the tool call (e.g. a file name).
+- **content** (str) – The tool result to persist.
+
+**Returns:**
+
+- str – A reference string (e.g. a path or URI) that `read` can later resolve.
+
+#### read
+
+```python
+read(reference: str) -> str
+```
+
+Return the content previously stored under `reference`.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the store to a dictionary.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> ToolResultStore
+```
+
+Deserialize the store from a dictionary.
+
+### OffloadPolicy
+
+Bases: Protocol
+
+Decides, per tool result, whether the `ToolResultOffloadHook` offloads it to the store or leaves it in context.
+
+A `ToolResultOffloadHook` maps tool names to policies, so different tools can offload under different conditions
+(always, never, or a custom rule such as a size threshold).
+
+Implement both `to_dict` and `from_dict` to make a custom policy serializable; the default implementations below
+cover policies whose constructor takes no arguments.
+
+#### should_offload
+
+```python
+should_offload(tool_name: str, result: str, state: State) -> bool
+```
+
+Return whether the given tool result should be offloaded.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool that produced the result.
+- **result** (str) – The tool result as a string (the content that would otherwise stay in the conversation).
+- **state** (State) – The Agent's live `State`, for policies that decide based on run context.
+
+**Returns:**
+
+- bool – True to offload the result to the store, False to leave it in context.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the policy to a dictionary.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> OffloadPolicy
+```
+
+Deserialize the policy from a dictionary.
diff --git a/docs-website/reference/haystack-api/human_in_the_loop_api.md b/docs-website/reference/haystack-api/human_in_the_loop_api.md
index 0dfddd4adb5..97b39925a47 100644
--- a/docs-website/reference/haystack-api/human_in_the_loop_api.md
+++ b/docs-website/reference/haystack-api/human_in_the_loop_api.md
@@ -64,6 +64,115 @@ Populate the ToolExecutionDecision from a dictionary representation.
- ToolExecutionDecision – An instance of ToolExecutionDecision.
+## hooks
+
+### ConfirmationHook
+
+A `before_tool` Agent hook that applies Human-in-the-Loop confirmation strategies to pending tool calls.
+
+Register it on an `Agent` to confirm, modify, or reject tool calls before they run:
+
+```python
+from haystack.components.agents import Agent
+from haystack.human_in_the_loop import (
+ AlwaysAskPolicy,
+ BlockingConfirmationStrategy,
+ ConfirmationHook,
+ NeverAskPolicy,
+ RichConsoleUI,
+ SimpleConsoleUI,
+)
+
+hook = ConfirmationHook(
+ confirmation_strategies={
+ "my_tool": BlockingConfirmationStrategy(
+ confirmation_policy=NeverAskPolicy(), confirmation_ui=SimpleConsoleUI()
+ )
+ }
+)
+agent = Agent(chat_generator=..., tools=[...], hooks={"before_tool": [hook]})
+```
+
+A key may be a single tool name, a tuple of tool names sharing one strategy, or the wildcard `"*"` which applies
+to any tool without a more specific entry. More specific keys win, so you can set a default for all tools and
+override individual ones:
+
+```python
+hook = ConfirmationHook(
+ confirmation_strategies={
+ "delete_file": BlockingConfirmationStrategy(
+ confirmation_policy=AlwaysAskPolicy(), confirmation_ui=RichConsoleUI()
+ ),
+ "*": BlockingConfirmationStrategy(
+ confirmation_policy=NeverAskPolicy(), confirmation_ui=SimpleConsoleUI()
+ ),
+ }
+)
+```
+
+Request-scoped resources for the strategies (e.g. a WebSocket or queue) are passed per run via the Agent's
+`hook_context` argument (`agent.run(messages=[...], hook_context={...})`) and read by the hook with
+`state.data.get("hook_context")`.
+
+This hook only makes sense at the `before_tool` hook point, where the pending tool calls exist (between the model
+requesting tools and those tools running); the Agent enforces this and raises if it is registered elsewhere. Use a
+single ConfirmationHook with one entry per tool (or per tuple of tools) in `confirmation_strategies` rather than
+registering several hooks.
+
+#### __init__
+
+```python
+__init__(
+ confirmation_strategies: dict[str | tuple[str, ...], ConfirmationStrategy],
+) -> None
+```
+
+Initialize the hook with its per-tool confirmation strategies.
+
+**Parameters:**
+
+- **confirmation_strategies** (dict\[str | tuple\[str, ...\], ConfirmationStrategy\]) – Mapping of tool name (or a tuple of tool names) to its `ConfirmationStrategy`.
+ The wildcard key `"*"` applies to any tool without a more specific entry.
+
+#### run
+
+```python
+run(state: State) -> None
+```
+
+Confirm the pending tool calls, rewriting the `messages` in `state` to reflect modifications and rejections.
+
+**Parameters:**
+
+- **state** (State) – The Agent's live `State`. Reads the available tools (`state.data.get("tools")`) and the per-run
+ context (`state.data.get("hook_context")`), and the pending tool calls from the last message; writes the
+ updated conversation back to `messages`. Reads go through `state.data` rather than `state.get`, which
+ deep-copies and would break non-copyable resources (e.g. a WebSocket or client) in `hook_context`.
+
+#### run_async
+
+```python
+run_async(state: State) -> None
+```
+
+Async version of `run`.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the hook, including its confirmation strategies (tuple keys become JSON-array strings).
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> ConfirmationHook
+```
+
+Deserialize the hook, reconstructing its confirmation strategies.
+
## policies
### AlwaysAskPolicy
diff --git a/docs-website/reference/haystack-api/image_converters_api.md b/docs-website/reference/haystack-api/image_converters_api.md
index 11d61480767..472bdf7149c 100644
--- a/docs-website/reference/haystack-api/image_converters_api.md
+++ b/docs-website/reference/haystack-api/image_converters_api.md
@@ -114,7 +114,8 @@ into ImageContent objects.
Converts image file references into empty Document objects with associated metadata.
This component is useful in pipelines where image file paths need to be wrapped in `Document` objects to be
-processed by downstream components such as the `SentenceTransformersImageDocumentEmbedder`.
+processed by downstream components such as the `LLMDocumentContentExtractor` or the
+`SentenceTransformersDocumentImageEmbedder` (available in the `sentence-transformers-haystack` integration).
It does **not** extract any content from the image files, instead it creates `Document` objects with `None` as
their content and attaches metadata such as file path and any user-provided values.
diff --git a/docs-website/reference/haystack-api/joiners_api.md b/docs-website/reference/haystack-api/joiners_api.md
index 62e33cc716d..b0517e2cec7 100644
--- a/docs-website/reference/haystack-api/joiners_api.md
+++ b/docs-website/reference/haystack-api/joiners_api.md
@@ -299,9 +299,7 @@ It supports different join modes:
```python
from haystack import Pipeline, Document
-# Requires: pip install sentence-transformers-haystack
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersTextEmbedder
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersDocumentEmbedder
+from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder
from haystack.components.joiners import DocumentJoiner
from haystack.components.retrievers import InMemoryBM25Retriever
from haystack.components.retrievers import InMemoryEmbeddingRetriever
@@ -309,14 +307,14 @@ from haystack.document_stores.in_memory import InMemoryDocumentStore
document_store = InMemoryDocumentStore()
docs = [Document(content="Paris"), Document(content="Berlin"), Document(content="London")]
-embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
+embedder = OpenAIDocumentEmbedder()
docs_embeddings = embedder.run(docs)
document_store.write_documents(docs_embeddings['documents'])
p = Pipeline()
p.add_component(instance=InMemoryBM25Retriever(document_store=document_store), name="bm25_retriever")
p.add_component(
- instance=SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"),
+ instance=OpenAITextEmbedder(),
name="text_embedder",
)
p.add_component(instance=InMemoryEmbeddingRetriever(document_store=document_store), name="embedding_retriever")
diff --git a/docs-website/reference/haystack-api/pipeline_api.md b/docs-website/reference/haystack-api/pipeline_api.md
index 51bc892464f..cdf31b06e9f 100644
--- a/docs-website/reference/haystack-api/pipeline_api.md
+++ b/docs-website/reference/haystack-api/pipeline_api.md
@@ -6,42 +6,77 @@ slug: "/pipeline-api"
---
-## async_pipeline
+## pipeline
+
+### PipelineStreamHandle
+
+Handle returned by `Pipeline.stream()`.
+
+Async-iterable over `StreamingChunk`s produced by streaming components in the pipeline. After iteration ends,
+`result` holds the final pipeline output dict.
+
+By default, iteration cleans up automatically: if the consumer abandons iteration, the underlying pipeline task is
+cancelled. `aclose()` is also available for explicit cleanup.
+
+#### result
+
+```python
+result: dict[str, Any]
+```
+
+Final pipeline output dict, available only after a successful, complete run.
-### AsyncPipeline
+Raises a `RuntimeError` if the pipeline has not finished or was cancelled. If the pipeline failed, re-raises the
+original exception.
+
+#### aclose
+
+```python
+aclose() -> None
+```
+
+Cancel the underlying pipeline task.
+
+Bounded by `_CLEANUP_TIMEOUT_SECONDS` so that components cannot block cleanup indefinitely.
+
+### Pipeline
Bases: PipelineBase
-Asynchronous version of the Pipeline orchestration engine.
+Orchestration engine that runs components according to the execution graph.
-Manages components in a pipeline allowing for concurrent processing when the pipeline's execution graph permits.
-This enables efficient processing of components by minimizing idle time and maximizing resource utilization.
+Supports both a synchronous run path (`run`) and an asynchronous run path
+(`run_async`, `run_async_generator`, `stream`).
-#### run_async_generator
+#### run
```python
-run_async_generator(
+run(
data: dict[str, Any],
include_outputs_from: set[str] | None = None,
- concurrency_limit: int = 4,
-) -> AsyncIterator[dict[str, Any]]
+ *,
+ break_point: Breakpoint | None = None,
+ pipeline_snapshot: PipelineSnapshot | None = None,
+ snapshot_callback: SnapshotCallback | None = None
+) -> dict[str, Any]
```
-Executes the pipeline step by step asynchronously, yielding partial outputs when any component finishes.
+Runs the Pipeline with given input data.
+
+`run` executes synchronously and blocks the calling thread until the run completes. In an async context,
+use `run_async` instead.
Usage:
```python
-from haystack import Document
-from haystack.components.builders import ChatPromptBuilder
+from haystack import Pipeline, Document
+from haystack.components.builders.answer_builder import AnswerBuilder
+from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder
+from haystack.components.generators.chat import OpenAIChatGenerator
+from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
from haystack.dataclasses import ChatMessage
-from haystack.utils import Secret
from haystack.document_stores.in_memory import InMemoryDocumentStore
-from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
-from haystack.components.generators.chat import OpenAIChatGenerator
-from haystack.components.builders.prompt_builder import PromptBuilder
-from haystack import AsyncPipeline
-import asyncio
+from haystack.utils import Secret
# Write documents to InMemoryDocumentStore
document_store = InMemoryDocumentStore()
@@ -51,103 +86,122 @@ document_store.write_documents([
Document(content="My name is Giorgio and I live in Rome.")
])
-prompt_template = [
- ChatMessage.from_user(
- '''
- Given these documents, answer the question.
- Documents:
- {% for doc in documents %}
- {{ doc.content }}
- {% endfor %}
- Question: {{question}}
- Answer:
- ''')
-]
-
-# Create and connect pipeline components
retriever = InMemoryBM25Retriever(document_store=document_store)
-prompt_builder = ChatPromptBuilder(template=prompt_template)
-llm = OpenAIChatGenerator()
-rag_pipeline = AsyncPipeline()
+prompt_template = """
+Given these documents, answer the question.
+Documents:
+{% for doc in documents %}
+ {{ doc.content }}
+{% endfor %}
+Question: {{question}}
+Answer:
+"""
+
+template = [ChatMessage.from_user(prompt_template)]
+prompt_builder = ChatPromptBuilder(
+ template=template,
+ required_variables=["question", "documents"],
+ variables=["question", "documents"]
+)
+
+llm = OpenAIChatGenerator()
+rag_pipeline = Pipeline()
rag_pipeline.add_component("retriever", retriever)
rag_pipeline.add_component("prompt_builder", prompt_builder)
rag_pipeline.add_component("llm", llm)
rag_pipeline.connect("retriever", "prompt_builder.documents")
rag_pipeline.connect("prompt_builder", "llm")
-# Prepare input data
question = "Who lives in Paris?"
-data = {
- "retriever": {"query": question},
- "prompt_builder": {"question": question},
-}
+results = rag_pipeline.run(
+ {
+ "retriever": {"query": question},
+ "prompt_builder": {"question": question},
+ }
+)
+print(results["llm"]["replies"][0].text)
+# Jean lives in Paris
+```
-# Process results as they become available
-async def process_results():
- async for partial_output in rag_pipeline.run_async_generator(
- data=data,
- include_outputs_from={"retriever", "llm"}
- ):
- # Each partial_output contains the results from a completed component
- if "retriever" in partial_output:
- print("Retrieved documents:", len(partial_output["retriever"]["documents"]))
- if "llm" in partial_output:
- print("Generated answer:", partial_output["llm"]["replies"][0])
+**Parameters:**
+- **data** (dict\[str, Any\]) – A dictionary of inputs for the pipeline's components. Each key is a component name
+ and its value is a dictionary of that component's input parameters:
-asyncio.run(process_results())
+```
+data = {
+ "comp1": {"input1": 1, "input2": 2},
+}
```
-**Parameters:**
+For convenience, this format is also supported when input names are unique:
+
+```
+data = {
+ "input1": 1, "input2": 2,
+}
+```
-- **data** (dict\[str, Any\]) – Initial input data to the pipeline.
-- **concurrency_limit** (int) – The maximum number of components that are allowed to run concurrently.
- **include_outputs_from** (set\[str\] | None) – Set of component names whose individual outputs are to be
included in the pipeline's output. For components that are
invoked multiple times (in a loop), only the last-produced
output is included.
+- **break_point** (Breakpoint | None) – A breakpoint that pauses execution before the specified component runs by raising a
+ `BreakpointException` carrying a `PipelineSnapshot` of the current pipeline state.
+- **pipeline_snapshot** (PipelineSnapshot | None) – A snapshot of a previously interrupted pipeline execution to resume from. Can be combined with
+ `break_point` to step through a pipeline: resume from the snapshot and pause again at the next
+ breakpoint. The `break_point` must target a different component or visit count than the one the
+ snapshot was created at, otherwise it would trigger again before any progress is made.
+- **snapshot_callback** (SnapshotCallback | None) – Optional callback function that is invoked when a pipeline snapshot is created.
+ The callback receives a `PipelineSnapshot` object and can return an optional string
+ (e.g., a file path or identifier).
+ If provided, the callback is used instead of the default file-saving behavior,
+ allowing custom handling of snapshots (e.g., saving to a database, sending to a remote service).
+ If not provided, the default behavior saves snapshots to a JSON file.
**Returns:**
-- AsyncIterator\[dict\[str, Any\]\] – An async iterator containing partial (and final) outputs.
+- dict\[str, Any\] – A dictionary where each entry corresponds to a component name
+ and its output. If `include_outputs_from` is `None`, this dictionary
+ will only contain the outputs of leaf components, i.e., components
+ without outgoing connections.
**Raises:**
- ValueError – If invalid inputs are provided to the pipeline.
-- PipelineMaxComponentRuns – If a component exceeds the maximum number of allowed executions within the pipeline.
- PipelineRuntimeError – If the Pipeline contains cycles with unsupported connections that would cause
it to get stuck and fail running.
Or if a Component fails or returns output in an unsupported type.
+- PipelineMaxComponentRuns – If a Component reaches the maximum number of times it can be run in this Pipeline.
+- PipelineBreakpointException – When a pipeline_breakpoint is triggered. Contains the component name, state, and partial results.
-#### run_async
+#### run_async_generator
```python
-run_async(
+run_async_generator(
data: dict[str, Any],
include_outputs_from: set[str] | None = None,
concurrency_limit: int = 4,
-) -> dict[str, Any]
+) -> AsyncGenerator[dict[str, Any], None]
```
-Provides an asynchronous interface to run the pipeline with provided input data.
-
-This method allows the pipeline to be integrated into an asynchronous workflow, enabling non-blocking
-execution of pipeline components.
+Executes the pipeline step by step asynchronously, yielding partial outputs when any component finishes.
Usage:
```python
-import asyncio
-
from haystack import Document
from haystack.components.builders import ChatPromptBuilder
-from haystack.components.generators.chat import OpenAIChatGenerator
-from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
-from haystack.core.pipeline import AsyncPipeline
from haystack.dataclasses import ChatMessage
+from haystack.utils import Secret
from haystack.document_stores.in_memory import InMemoryDocumentStore
+from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
+from haystack.components.generators.chat import OpenAIChatGenerator
+from haystack.components.builders.prompt_builder import PromptBuilder
+from haystack import Pipeline
+import asyncio
# Write documents to InMemoryDocumentStore
document_store = InMemoryDocumentStore()
@@ -170,104 +224,88 @@ prompt_template = [
''')
]
+# Create and connect pipeline components
retriever = InMemoryBM25Retriever(document_store=document_store)
prompt_builder = ChatPromptBuilder(template=prompt_template)
llm = OpenAIChatGenerator()
-rag_pipeline = AsyncPipeline()
+rag_pipeline = Pipeline()
rag_pipeline.add_component("retriever", retriever)
rag_pipeline.add_component("prompt_builder", prompt_builder)
rag_pipeline.add_component("llm", llm)
rag_pipeline.connect("retriever", "prompt_builder.documents")
rag_pipeline.connect("prompt_builder", "llm")
-# Ask a question
+# Prepare input data
question = "Who lives in Paris?"
-
-async def run_inner(data, include_outputs_from):
- return await rag_pipeline.run_async(data=data, include_outputs_from=include_outputs_from)
-
data = {
"retriever": {"query": question},
"prompt_builder": {"question": question},
}
-results = asyncio.run(run_inner(data, include_outputs_from={"retriever", "llm"}))
-
-print(results["llm"]["replies"])
-# [ChatMessage(_role=, _content=[TextContent(text='Jean lives in Paris.')],
-# _name=None, _meta={'model': 'gpt-5-mini', 'index': 0, 'finish_reason': 'stop', 'usage':
-# {'completion_tokens': 6, 'prompt_tokens': 69, 'total_tokens': 75,
-# 'completion_tokens_details': CompletionTokensDetails(accepted_prediction_tokens=0,
-# audio_tokens=0, reasoning_tokens=0, rejected_prediction_tokens=0), 'prompt_tokens_details':
-# PromptTokensDetails(audio_tokens=0, cached_tokens=0)}})]
-```
-**Parameters:**
+# Process results as they become available
+async def process_results():
+ async for partial_output in rag_pipeline.run_async_generator(
+ data=data,
+ include_outputs_from={"retriever", "llm"}
+ ):
+ # Each partial_output contains the results from a completed component
+ if "retriever" in partial_output:
+ print("Retrieved documents:", len(partial_output["retriever"]["documents"]))
+ if "llm" in partial_output:
+ print("Generated answer:", partial_output["llm"]["replies"][0])
-- **data** (dict\[str, Any\]) – A dictionary of inputs for the pipeline's components. Each key is a component name
- and its value is a dictionary of that component's input parameters:
-```
-data = {
- "comp1": {"input1": 1, "input2": 2},
-}
+asyncio.run(process_results())
```
-For convenience, this format is also supported when input names are unique:
-
-```
-data = {
- "input1": 1, "input2": 2,
-}
-```
+**Parameters:**
+- **data** (dict\[str, Any\]) – Initial input data to the pipeline.
+- **concurrency_limit** (int) – The maximum number of components that are allowed to run concurrently.
- **include_outputs_from** (set\[str\] | None) – Set of component names whose individual outputs are to be
included in the pipeline's output. For components that are
invoked multiple times (in a loop), only the last-produced
output is included.
-- **concurrency_limit** (int) – The maximum number of components that should be allowed to run concurrently.
**Returns:**
-- dict\[str, Any\] – A dictionary where each entry corresponds to a component name
- and its output. If `include_outputs_from` is `None`, this dictionary
- will only contain the outputs of leaf components, i.e., components
- without outgoing connections.
+- AsyncGenerator\[dict\[str, Any\], None\] – An async iterator containing partial (and final) outputs.
**Raises:**
-- ValueError – If invalid inputs are provided to the pipeline.
+- ValueError – If invalid inputs are provided to the pipeline, or if `concurrency_limit` is less than 1.
+- PipelineMaxComponentRuns – If a component exceeds the maximum number of allowed executions within the pipeline.
- PipelineRuntimeError – If the Pipeline contains cycles with unsupported connections that would cause
it to get stuck and fail running.
Or if a Component fails or returns output in an unsupported type.
-- PipelineMaxComponentRuns – If a Component reaches the maximum number of times it can be run in this Pipeline.
-#### run
+#### run_async
```python
-run(
+run_async(
data: dict[str, Any],
include_outputs_from: set[str] | None = None,
concurrency_limit: int = 4,
) -> dict[str, Any]
```
-Provides a synchronous interface to run the pipeline with given input data.
-
-Internally, the pipeline components are executed asynchronously, but the method itself
-will block until the entire pipeline execution is complete.
+Provides an asynchronous interface to run the pipeline with provided input data.
-In case you need asynchronous methods, consider using `run_async` or `run_async_generator`.
+This method allows the pipeline to be integrated into an asynchronous workflow, enabling non-blocking
+execution of pipeline components.
Usage:
```python
+import asyncio
+
from haystack import Document
from haystack.components.builders import ChatPromptBuilder
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
-from haystack.core.pipeline import AsyncPipeline
+from haystack import Pipeline
from haystack.dataclasses import ChatMessage
from haystack.document_stores.in_memory import InMemoryDocumentStore
@@ -292,12 +330,11 @@ prompt_template = [
''')
]
-
retriever = InMemoryBM25Retriever(document_store=document_store)
prompt_builder = ChatPromptBuilder(template=prompt_template)
llm = OpenAIChatGenerator()
-rag_pipeline = AsyncPipeline()
+rag_pipeline = Pipeline()
rag_pipeline.add_component("retriever", retriever)
rag_pipeline.add_component("prompt_builder", prompt_builder)
rag_pipeline.add_component("llm", llm)
@@ -307,20 +344,23 @@ rag_pipeline.connect("prompt_builder", "llm")
# Ask a question
question = "Who lives in Paris?"
+async def run_inner(data, include_outputs_from):
+ return await rag_pipeline.run_async(data=data, include_outputs_from=include_outputs_from)
+
data = {
"retriever": {"query": question},
"prompt_builder": {"question": question},
}
-results = rag_pipeline.run(data)
+results = asyncio.run(run_inner(data, include_outputs_from={"retriever", "llm"}))
print(results["llm"]["replies"])
# [ChatMessage(_role=, _content=[TextContent(text='Jean lives in Paris.')],
# _name=None, _meta={'model': 'gpt-5-mini', 'index': 0, 'finish_reason': 'stop', 'usage':
-# {'completion_tokens': 6, 'prompt_tokens': 69, 'total_tokens': 75, 'completion_tokens_details':
-# CompletionTokensDetails(accepted_prediction_tokens=0, audio_tokens=0, reasoning_tokens=0,
-# rejected_prediction_tokens=0), 'prompt_tokens_details': PromptTokensDetails(audio_tokens=0,
-# cached_tokens=0)}})]
+# {'completion_tokens': 6, 'prompt_tokens': 69, 'total_tokens': 75,
+# 'completion_tokens_details': CompletionTokensDetails(accepted_prediction_tokens=0,
+# audio_tokens=0, reasoning_tokens=0, rejected_prediction_tokens=0), 'prompt_tokens_details':
+# PromptTokensDetails(audio_tokens=0, cached_tokens=0)}})]
```
**Parameters:**
@@ -357,95 +397,63 @@ data = {
**Raises:**
-- ValueError – If invalid inputs are provided to the pipeline.
+- ValueError – If invalid inputs are provided to the pipeline, or if `concurrency_limit` is less than 1.
- PipelineRuntimeError – If the Pipeline contains cycles with unsupported connections that would cause
it to get stuck and fail running.
Or if a Component fails or returns output in an unsupported type.
- PipelineMaxComponentRuns – If a Component reaches the maximum number of times it can be run in this Pipeline.
-- RuntimeError – If called from within an async context. Use `run_async` instead.
-
-## pipeline
-
-### Pipeline
-
-Bases: PipelineBase
-
-Synchronous version of the orchestration engine.
-
-Orchestrates component execution according to the execution graph, one after the other.
-#### run
+#### stream
```python
-run(
+stream(
data: dict[str, Any],
- include_outputs_from: set[str] | None = None,
*,
- break_point: Breakpoint | AgentBreakpoint | None = None,
- pipeline_snapshot: PipelineSnapshot | None = None,
- snapshot_callback: SnapshotCallback | None = None
-) -> dict[str, Any]
+ streaming_components: list[str] | None = None,
+ include_outputs_from: set[str] | None = None,
+ concurrency_limit: int = 4,
+ cancel_on_abandon: bool = True
+) -> PipelineStreamHandle
```
-Runs the Pipeline with given input data.
+Run the pipeline and return a handle that streams `StreamingChunk`s as they arrive.
+
+Iterate the handle with `async for` to consume chunks; after iteration ends, `handle.result` holds the final
+pipeline output dict (same as `run_async`). By default, if iteration is abandoned, the underlying pipeline task
+is cancelled automatically. Pass `cancel_on_abandon=False` to instead let the pipeline run to completion.
+
+For every async-capable component that exposes a `streaming_callback` input socket, a forwarder is injected at
+runtime that pushes chunks onto the handle's queue. If a `streaming_callback` is provided at component init or
+at runtime (inside `data`, e.g. `data={"llm": {"streaming_callback": cb}}`), it is also invoked for each chunk.
+Async callbacks are preferred; a sync callback is accepted but will run synchronously on the event loop and
+may block it.
Usage:
```python
-from haystack import Pipeline, Document
-from haystack.components.builders.answer_builder import AnswerBuilder
-from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder
+import asyncio
+
+from haystack.components.builders import ChatPromptBuilder
from haystack.components.generators.chat import OpenAIChatGenerator
-from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
+from haystack import Pipeline
from haystack.dataclasses import ChatMessage
-from haystack.document_stores.in_memory import InMemoryDocumentStore
-from haystack.utils import Secret
-
-# Write documents to InMemoryDocumentStore
-document_store = InMemoryDocumentStore()
-document_store.write_documents([
- Document(content="My name is Jean and I live in Paris."),
- Document(content="My name is Mark and I live in Berlin."),
- Document(content="My name is Giorgio and I live in Rome.")
-])
-
-retriever = InMemoryBM25Retriever(document_store=document_store)
-
-prompt_template = """
-Given these documents, answer the question.
-Documents:
-{% for doc in documents %}
- {{ doc.content }}
-{% endfor %}
-Question: {{question}}
-Answer:
-"""
-template = [ChatMessage.from_user(prompt_template)]
-prompt_builder = ChatPromptBuilder(
- template=template,
- required_variables=["question", "documents"],
- variables=["question", "documents"]
+pipe = Pipeline()
+pipe.add_component(
+ "prompt_builder",
+ ChatPromptBuilder(template=[ChatMessage.from_user("Tell me about {{topic}}")]),
)
+pipe.add_component("llm", OpenAIChatGenerator())
+pipe.connect("prompt_builder.prompt", "llm.messages")
-llm = OpenAIChatGenerator()
-rag_pipeline = Pipeline()
-rag_pipeline.add_component("retriever", retriever)
-rag_pipeline.add_component("prompt_builder", prompt_builder)
-rag_pipeline.add_component("llm", llm)
-rag_pipeline.connect("retriever", "prompt_builder.documents")
-rag_pipeline.connect("prompt_builder", "llm")
-
-question = "Who lives in Paris?"
-results = rag_pipeline.run(
- {
- "retriever": {"query": question},
- "prompt_builder": {"question": question},
- }
-)
+async def main():
+ handle = pipe.stream(data={"prompt_builder": {"topic": "Italy"}})
+ async for chunk in handle:
+ print(chunk.content, end="", flush=True)
+ return handle.result
-print(results["llm"]["replies"][0].text)
-# Jean lives in Paris
+result = asyncio.run(main())
+print(result["llm"]["replies"])
```
**Parameters:**
@@ -467,31 +475,27 @@ data = {
}
```
+- **streaming_components** (list\[str\] | None) – Names of components to stream from. If `None` (default), every streaming-capable
+ component is forwarded. If a list, only the listed components are forwarded; unknown names or names of
+ components that do not support streaming raise `ValueError`.
- **include_outputs_from** (set\[str\] | None) – Set of component names whose individual outputs are to be
included in the pipeline's output. For components that are
invoked multiple times (in a loop), only the last-produced
output is included.
-- **break_point** (Breakpoint | AgentBreakpoint | None) – A set of breakpoints that can be used to debug the pipeline execution.
-- **pipeline_snapshot** (PipelineSnapshot | None) – A dictionary containing a snapshot of a previously saved pipeline execution.
-- **snapshot_callback** (SnapshotCallback | None) – Optional callback function that is invoked when a pipeline snapshot is created.
- The callback receives a `PipelineSnapshot` object and can return an optional string
- (e.g., a file path or identifier).
- If provided, the callback is used instead of the default file-saving behavior,
- allowing custom handling of snapshots (e.g., saving to a database, sending to a remote service).
- If not provided, the default behavior saves snapshots to a JSON file.
+- **concurrency_limit** (int) – The maximum number of components that should be allowed to run concurrently.
+- **cancel_on_abandon** (bool) – If `True` (default), the underlying pipeline task is cancelled when iteration is
+ abandoned. If `False`, the pipeline runs to completion even when the consumer stops reading.
**Returns:**
-- dict\[str, Any\] – A dictionary where each entry corresponds to a component name
- and its output. If `include_outputs_from` is `None`, this dictionary
- will only contain the outputs of leaf components, i.e., components
- without outgoing connections.
+- PipelineStreamHandle – A `PipelineStreamHandle` that is async-iterable over `StreamingChunk`s. After iteration ends,
+ `handle.result` holds the final pipeline output dict (same shape as `run_async`).
**Raises:**
-- ValueError – If invalid inputs are provided to the pipeline.
-- PipelineRuntimeError – If the Pipeline contains cycles with unsupported connections that would cause
- it to get stuck and fail running.
- Or if a Component fails or returns output in an unsupported type.
-- PipelineMaxComponentRuns – If a Component reaches the maximum number of times it can be run in this Pipeline.
-- PipelineBreakpointException – When a pipeline_breakpoint is triggered. Contains the component name, state, and partial results.
+- ValueError – If `streaming_components` contains unknown component names or components that do not support streaming,
+ or if invalid inputs are provided to the pipeline, or if `concurrency_limit` is less than 1.
+- PipelineRuntimeError – Surfaced during iteration. If the Pipeline contains cycles with unsupported connections that would cause
+ it to get stuck and fail running, or if a Component fails or returns output in an unsupported type.
+- PipelineMaxComponentRuns – Surfaced during iteration. If a Component reaches the maximum number of times it can be run in this
+ Pipeline.
diff --git a/docs-website/reference/haystack-api/preprocessors_api.md b/docs-website/reference/haystack-api/preprocessors_api.md
index 7df1a3ad652..d1bff4fc0a5 100644
--- a/docs-website/reference/haystack-api/preprocessors_api.md
+++ b/docs-website/reference/haystack-api/preprocessors_api.md
@@ -488,8 +488,7 @@ This component is inspired by [5 Levels of Text Splitting](https://github.com/Fu
```python
from haystack import Document
-# Requires: pip install sentence-transformers-haystack
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersDocumentEmbedder
+from haystack.components.embedders import OpenAIDocumentEmbedder
from haystack.components.preprocessors import EmbeddingBasedDocumentSplitter
# Create a document with content that has a clear topic shift
@@ -499,7 +498,7 @@ doc = Document(
)
# Initialize the embedder to calculate semantic similarities
-embedder = SentenceTransformersDocumentEmbedder()
+embedder = OpenAIDocumentEmbedder()
# Configure the splitter with parameters that control splitting behavior
splitter = EmbeddingBasedDocumentSplitter(
@@ -557,7 +556,34 @@ Initialize EmbeddingBasedDocumentSplitter.
warm_up() -> None
```
-Warm up the component by initializing the sentence splitter.
+Warm up the component by initializing the sentence splitter and the document embedder.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the component on the serving event loop.
+
+Initializes the sentence splitter and warms up the document embedder using its async warm-up path when
+available, falling back to the synchronous one otherwise.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the document embedder's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the document embedder's async resources.
#### run
diff --git a/docs-website/reference/haystack-api/query_api.md b/docs-website/reference/haystack-api/query_api.md
index 8021c22cd0c..f7c68ce1647 100644
--- a/docs-website/reference/haystack-api/query_api.md
+++ b/docs-website/reference/haystack-api/query_api.md
@@ -108,7 +108,37 @@ The language of the original query is preserved in the expanded queries.
- **query** (str) – The original query to expand.
- **n_expansions** (int | None) – Number of additional queries to generate (not including the original).
- If None, uses the value from initialization. Can be 0 to generate no additional queries.
+ If None, uses the value from initialization. Must be a positive integer.
+
+**Returns:**
+
+- dict\[str, list\[str\]\] – Dictionary with "queries" key containing the list of expanded queries.
+ If include_original_query=True, the original query will be included in addition
+ to the n_expansions alternative queries.
+
+**Raises:**
+
+- ValueError – If n_expansions is not positive (less than or equal to 0).
+
+#### run_async
+
+```python
+run_async(query: str, n_expansions: int | None = None) -> dict[str, list[str]]
+```
+
+Asynchronously expand the input query into multiple semantically similar queries.
+
+The language of the original query is preserved in the expanded queries.
+
+This is the asynchronous version of the `run` method. It has the same parameters and return values
+but can be used with `await` in an async code. If the chat generator only implements a synchronous
+`run` method, it is executed in a thread to avoid blocking the event loop.
+
+**Parameters:**
+
+- **query** (str) – The original query to expand.
+- **n_expansions** (int | None) – Number of additional queries to generate (not including the original).
+ If None, uses the value from initialization. Must be a positive integer.
**Returns:**
@@ -126,4 +156,28 @@ The language of the original query is preserved in the expanded queries.
warm_up() -> None
```
-Warm up the LLM provider component.
+Warm up the underlying chat generator.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the underlying chat generator on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the underlying chat generator's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the underlying chat generator's async resources.
diff --git a/docs-website/reference/haystack-api/rankers_api.md b/docs-website/reference/haystack-api/rankers_api.md
index f656899d2f0..983cee7eac8 100644
--- a/docs-website/reference/haystack-api/rankers_api.md
+++ b/docs-website/reference/haystack-api/rankers_api.md
@@ -6,181 +6,6 @@ slug: "/rankers-api"
---
-## hugging_face_tei
-
-### TruncationDirection
-
-Bases: str, Enum
-
-Defines the direction to truncate text when input length exceeds the model's limit.
-
-Attributes:
-LEFT: Truncate text from the left side (start of text).
-RIGHT: Truncate text from the right side (end of text).
-
-### HuggingFaceTEIRanker
-
-Ranks documents based on their semantic similarity to the query.
-
-It can be used with a Text Embeddings Inference (TEI) API endpoint:
-
-- [Self-hosted Text Embeddings Inference](https://github.com/huggingface/text-embeddings-inference)
-- [Hugging Face Inference Endpoints](https://huggingface.co/inference-endpoints)
-
-Usage example:
-
-
-
-```python
-from haystack import Document
-from haystack.components.rankers import HuggingFaceTEIRanker
-from haystack.utils import Secret
-
-reranker = HuggingFaceTEIRanker(
- url="http://localhost:8080",
- top_k=5,
- timeout=30,
- token=Secret.from_token("my_api_token")
-)
-
-docs = [Document(content="The capital of France is Paris"), Document(content="The capital of Germany is Berlin")]
-
-result = reranker.run(query="What is the capital of France?", documents=docs)
-
-ranked_docs = result["documents"]
-print(ranked_docs)
-# >> {'documents': [Document(id=..., content: 'the capital of France is Paris', score: 0.9979767),
-# >> Document(id=..., content: 'the capital of Germany is Berlin', score: 0.13982213)]}
-```
-
-#### __init__
-
-```python
-__init__(
- *,
- url: str,
- top_k: int = 10,
- raw_scores: bool = False,
- timeout: int | None = 30,
- max_retries: int = 3,
- retry_status_codes: list[int] | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- )
-) -> None
-```
-
-Initializes the TEI reranker component.
-
-**Parameters:**
-
-- **url** (str) – Base URL of the TEI reranking service (for example, "https://api.example.com").
-- **top_k** (int) – Maximum number of top documents to return.
-- **raw_scores** (bool) – If True, include raw relevance scores in the API payload.
-- **timeout** (int | None) – Request timeout in seconds.
-- **max_retries** (int) – Maximum number of retry attempts for failed requests.
-- **retry_status_codes** (list\[int\] | None) – List of HTTP status codes that will trigger a retry.
- When None, HTTP 408, 418, 429 and 503 will be retried (default: None).
-- **token** (Secret | None) – The Hugging Face token to use as HTTP bearer authorization. Not always required
- depending on your TEI server configuration.
- Check your HF token in your [account settings](https://huggingface.co/settings/tokens).
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> HuggingFaceTEIRanker
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- HuggingFaceTEIRanker – Deserialized component.
-
-#### run
-
-```python
-run(
- query: str,
- documents: list[Document],
- top_k: int | None = None,
- truncation_direction: TruncationDirection | None = None,
-) -> dict[str, list[Document]]
-```
-
-Reranks the provided documents by relevance to the query using the TEI API.
-
-Before ranking, documents are deduplicated by their id, retaining only the document with the highest score
-if a score is present.
-
-**Parameters:**
-
-- **query** (str) – The user query string to guide reranking.
-- **documents** (list\[Document\]) – List of `Document` objects to rerank.
-- **top_k** (int | None) – Optional override for the maximum number of documents to return.
-- **truncation_direction** (TruncationDirection | None) – If set, enables text truncation in the specified direction.
-
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
-- `documents`: A list of reranked documents.
-
-**Raises:**
-
-- RuntimeError – - If the API request fails.
-- RuntimeError – - If the API returns an error response.
-- TypeError – - If the API response is not in the expected list format.
-
-#### run_async
-
-```python
-run_async(
- query: str,
- documents: list[Document],
- top_k: int | None = None,
- truncation_direction: TruncationDirection | None = None,
-) -> dict[str, list[Document]]
-```
-
-Asynchronously reranks the provided documents by relevance to the query using the TEI API.
-
-Before ranking, documents are deduplicated by their id, retaining only the document with the highest score
-if a score is present.
-
-**Parameters:**
-
-- **query** (str) – The user query string to guide reranking.
-- **documents** (list\[Document\]) – List of `Document` objects to rerank.
-- **top_k** (int | None) – Optional override for the maximum number of documents to return.
-- **truncation_direction** (TruncationDirection | None) – If set, enables text truncation in the specified direction.
-
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
-- `documents`: A list of reranked documents.
-
-**Raises:**
-
-- httpx.RequestError – - If the API request fails.
-- RuntimeError – - If the API returns an error response.
-- TypeError – - If the API response is not in the expected list format.
-
## llm_ranker
### LLMRanker
@@ -268,6 +93,30 @@ warm_up() -> None
Warm up the underlying chat generator.
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the underlying chat generator on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the underlying chat generator's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the underlying chat generator's async resources.
+
#### to_dict
```python
@@ -318,6 +167,32 @@ Before ranking, duplicate documents are removed.
- dict\[str, list\[Document\]\] – A dictionary with the ranked documents under the `documents` key.
+#### run_async
+
+```python
+run_async(
+ query: str, documents: list[Document], top_k: int | None = None
+) -> dict[str, list[Document]]
+```
+
+Asynchronously rank documents for a query using an LLM.
+
+Before ranking, duplicate documents are removed.
+
+This is the asynchronous version of the `run` method. It has the same parameters and return values
+but can be used with `await` in an async code. If the chat generator only implements a synchronous
+`run` method, it is executed in a thread to avoid blocking the event loop.
+
+**Parameters:**
+
+- **query** (str) – The query used for reranking.
+- **documents** (list\[Document\]) – Candidate documents to rerank.
+- **top_k** (int | None) – The maximum number of documents to return. Overrides the instance's `top_k` if provided.
+
+**Returns:**
+
+- dict\[str, list\[Document\]\] – A dictionary with the ranked documents under the `documents` key.
+
## lost_in_the_middle
### LostInTheMiddleRanker
@@ -637,522 +512,3 @@ The output is a list of documents reordered based on how they were grouped.
- dict\[str, list\[Document\]\] – A dictionary with the following keys:
- documents: The list of documents ordered by the `group_by` and `subgroup_by` metadata values.
-
-## sentence_transformers_diversity
-
-### DiversityRankingStrategy
-
-Bases: Enum
-
-The strategy to use for diversity ranking.
-
-#### from_str
-
-```python
-from_str(string: str) -> DiversityRankingStrategy
-```
-
-Convert a string to a Strategy enum.
-
-### DiversityRankingSimilarity
-
-Bases: Enum
-
-The similarity metric to use for comparing embeddings.
-
-#### from_str
-
-```python
-from_str(string: str) -> DiversityRankingSimilarity
-```
-
-Convert a string to a Similarity enum.
-
-### SentenceTransformersDiversityRanker
-
-A Diversity Ranker based on Sentence Transformers.
-
-Applies a document ranking algorithm based on one of the two strategies:
-
-1. Greedy Diversity Order:
-
- Implements a document ranking algorithm that orders documents in a way that maximizes the overall diversity
- of the documents based on their similarity to the query.
-
- It uses a pre-trained Sentence Transformers model to embed the query and
- the documents.
-
-1. Maximum Margin Relevance:
-
- Implements a document ranking algorithm that orders documents based on their Maximum Margin Relevance (MMR)
- scores.
-
- MMR scores are calculated for each document based on their relevance to the query and diversity from already
- selected documents. The algorithm iteratively selects documents based on their MMR scores, balancing between
- relevance to the query and diversity from already selected documents. The 'lambda_threshold' controls the
- trade-off between relevance and diversity.
-
-Before ranking, documents are deduplicated by their id, retaining only the document with the highest score
-if a score is present.
-
-### Usage example
-
-```python
-from haystack import Document
-from haystack.components.rankers import SentenceTransformersDiversityRanker
-
-ranker = SentenceTransformersDiversityRanker(
- model="sentence-transformers/all-MiniLM-L6-v2", similarity="cosine", strategy="greedy_diversity_order"
-)
-
-docs = [Document(content="Paris"), Document(content="Berlin")]
-query = "What is the capital of germany?"
-output = ranker.run(query=query, documents=docs)
-docs = output["documents"]
-```
-
-#### __init__
-
-```python
-__init__(
- model: str = "sentence-transformers/all-MiniLM-L6-v2",
- top_k: int = 10,
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- similarity: str | DiversityRankingSimilarity = "cosine",
- query_prefix: str = "",
- query_suffix: str = "",
- document_prefix: str = "",
- document_suffix: str = "",
- meta_fields_to_embed: list[str] | None = None,
- embedding_separator: str = "\n",
- strategy: str | DiversityRankingStrategy = "greedy_diversity_order",
- lambda_threshold: float = 0.5,
- model_kwargs: dict[str, Any] | None = None,
- tokenizer_kwargs: dict[str, Any] | None = None,
- config_kwargs: dict[str, Any] | None = None,
- backend: Literal["torch", "onnx", "openvino"] = "torch",
-) -> None
-```
-
-Initialize a SentenceTransformersDiversityRanker.
-
-**Parameters:**
-
-- **model** (str) – Local path or name of the model in Hugging Face's model hub,
- such as `'sentence-transformers/all-MiniLM-L6-v2'`.
-- **top_k** (int) – The maximum number of Documents to return per query.
-- **device** (ComponentDevice | None) – The device on which the model is loaded. If `None`, the default device is automatically
- selected.
-- **token** (Secret | None) – The API token used to download private models from Hugging Face.
-- **similarity** (str | DiversityRankingSimilarity) – Similarity metric for comparing embeddings. Can be set to "dot_product" (default) or
- "cosine".
-- **query_prefix** (str) – A string to add to the beginning of the query text before ranking.
- Can be used to prepend the text with an instruction, as required by some embedding models,
- such as E5 and BGE.
-- **query_suffix** (str) – A string to add to the end of the query text before ranking.
-- **document_prefix** (str) – A string to add to the beginning of each Document text before ranking.
- Can be used to prepend the text with an instruction, as required by some embedding models,
- such as E5 and BGE.
-- **document_suffix** (str) – A string to add to the end of each Document text before ranking.
-- **meta_fields_to_embed** (list\[str\] | None) – List of meta fields that should be embedded along with the Document content.
-- **embedding_separator** (str) – Separator used to concatenate the meta fields to the Document content.
-- **strategy** (str | DiversityRankingStrategy) – The strategy to use for diversity ranking. Can be either "greedy_diversity_order" or
- "maximum_margin_relevance".
-- **lambda_threshold** (float) – The trade-off parameter between relevance and diversity. Only used when strategy is
- "maximum_margin_relevance".
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoModelForSequenceClassification.from_pretrained`
- when loading the model. Refer to specific model documentation for available kwargs.
-- **tokenizer_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoTokenizer.from_pretrained` when loading the tokenizer.
- Refer to specific model documentation for available kwargs.
-- **config_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoConfig.from_pretrained` when loading the model configuration.
-- **backend** (Literal['torch', 'onnx', 'openvino']) – The backend to use for the Sentence Transformers model. Choose from "torch", "onnx", or "openvino".
- Refer to the [Sentence Transformers documentation](https://sbert.net/docs/sentence_transformer/usage/efficiency.html)
- for more information on acceleration and quantization options.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> SentenceTransformersDiversityRanker
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- SentenceTransformersDiversityRanker – The deserialized component.
-
-#### run
-
-```python
-run(
- query: str,
- documents: list[Document],
- top_k: int | None = None,
- lambda_threshold: float | None = None,
-) -> dict[str, list[Document]]
-```
-
-Rank the documents based on their diversity.
-
-**Parameters:**
-
-- **query** (str) – The search query.
-- **documents** (list\[Document\]) – List of Document objects to be ranker.
-- **top_k** (int | None) – Optional. An integer to override the top_k set during initialization.
-- **lambda_threshold** (float | None) – Override the trade-off parameter between relevance and diversity. Only used when
- strategy is "maximum_margin_relevance".
-
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following key:
-- `documents`: List of Document objects that have been selected based on the diversity ranking.
-
-**Raises:**
-
-- ValueError – If the top_k value is less than or equal to 0.
-
-## sentence_transformers_similarity
-
-### SentenceTransformersSimilarityRanker
-
-Ranks documents based on their semantic similarity to the query.
-
-It uses a pre-trained cross-encoder model from Hugging Face to embed the query and the documents.
-
-### Usage example
-
-```python
-from haystack import Document
-from haystack.components.rankers import SentenceTransformersSimilarityRanker
-
-ranker = SentenceTransformersSimilarityRanker()
-docs = [Document(content="Paris"), Document(content="Berlin")]
-query = "City in Germany"
-result = ranker.run(query=query, documents=docs)
-docs = result["documents"]
-print(docs[0].content)
-```
-
-#### __init__
-
-```python
-__init__(
- *,
- model: str | Path = "cross-encoder/ms-marco-MiniLM-L-6-v2",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- top_k: int = 10,
- query_prefix: str = "",
- query_suffix: str = "",
- document_prefix: str = "",
- document_suffix: str = "",
- meta_fields_to_embed: list[str] | None = None,
- embedding_separator: str = "\n",
- scale_score: bool = True,
- score_threshold: float | None = None,
- trust_remote_code: bool = False,
- model_kwargs: dict[str, Any] | None = None,
- tokenizer_kwargs: dict[str, Any] | None = None,
- config_kwargs: dict[str, Any] | None = None,
- backend: Literal["torch", "onnx", "openvino"] = "torch",
- batch_size: int = 16
-) -> None
-```
-
-Creates an instance of SentenceTransformersSimilarityRanker.
-
-**Parameters:**
-
-- **model** (str | Path) – The ranking model. Pass a local path or the Hugging Face model name of a cross-encoder model.
-- **device** (ComponentDevice | None) – The device on which the model is loaded. If `None`, the default device is automatically selected.
-- **token** (Secret | None) – The API token to download private models from Hugging Face.
-- **top_k** (int) – The maximum number of documents to return per query.
-- **query_prefix** (str) – A string to add at the beginning of the query text before ranking.
- Use it to prepend the text with an instruction, as required by reranking models like `bge`.
-- **query_suffix** (str) – A string to add at the end of the query text before ranking.
- Use it to append the text with an instruction, as required by reranking models like `qwen`.
-- **document_prefix** (str) – A string to add at the beginning of each document before ranking. You can use it to prepend the document
- with an instruction, as required by embedding models like `bge`.
-- **document_suffix** (str) – A string to add at the end of each document before ranking. You can use it to append the document
- with an instruction, as required by embedding models like `qwen`.
-- **meta_fields_to_embed** (list\[str\] | None) – List of metadata fields to embed with the document.
-- **embedding_separator** (str) – Separator to concatenate metadata fields to the document.
-- **scale_score** (bool) – If `True`, scales the raw logit predictions using a Sigmoid activation function.
- If `False`, disables scaling of the raw logit predictions.
-- **score_threshold** (float | None) – Use it to return documents with a score above this threshold only.
-- **trust_remote_code** (bool) – If `False`, allows only Hugging Face verified model architectures.
- If `True`, allows custom models and scripts.
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoModelForSequenceClassification.from_pretrained`
- when loading the model. Refer to specific model documentation for available kwargs.
-- **tokenizer_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoTokenizer.from_pretrained` when loading the tokenizer.
- Refer to specific model documentation for available kwargs.
-- **config_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoConfig.from_pretrained` when loading the model configuration.
-- **backend** (Literal['torch', 'onnx', 'openvino']) – The backend to use for the Sentence Transformers model. Choose from "torch", "onnx", or "openvino".
- Refer to the [Sentence Transformers documentation](https://sbert.net/docs/sentence_transformer/usage/efficiency.html)
- for more information on acceleration and quantization options.
-- **batch_size** (int) – The batch size to use for inference. The higher the batch size, the more memory is required.
- If you run into memory issues, reduce the batch size.
-
-**Raises:**
-
-- ValueError – If `top_k` is not > 0.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> SentenceTransformersSimilarityRanker
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- SentenceTransformersSimilarityRanker – Deserialized component.
-
-#### run
-
-```python
-run(
- *,
- query: str,
- documents: list[Document],
- top_k: int | None = None,
- scale_score: bool | None = None,
- score_threshold: float | None = None
-) -> dict[str, list[Document]]
-```
-
-Returns a list of documents ranked by their similarity to the given query.
-
-Before ranking, documents are deduplicated by their id, retaining only the document with the highest score
-if a score is present.
-
-**Parameters:**
-
-- **query** (str) – The input query to compare the documents to.
-- **documents** (list\[Document\]) – A list of documents to be ranked.
-- **top_k** (int | None) – The maximum number of documents to return.
-- **scale_score** (bool | None) – If `True`, scales the raw logit predictions using a Sigmoid activation function.
- If `False`, disables scaling of the raw logit predictions.
- If set, overrides the value set at initialization.
-- **score_threshold** (float | None) – Use it to return documents only with a score above this threshold.
- If set, overrides the value set at initialization.
-
-**Returns:**
-
-- dict\[str, list\[Document\]\] – A dictionary with the following keys:
-- `documents`: A list of documents closest to the query, sorted from most similar to least similar.
-
-**Raises:**
-
-- ValueError – If `top_k` is not > 0.
-
-## transformers_similarity
-
-### TransformersSimilarityRanker
-
-Ranks documents based on their semantic similarity to the query.
-
-It uses a pre-trained cross-encoder model from Hugging Face to embed the query and the documents.
-
-Note:
-This component is considered legacy and will no longer receive updates. It may be deprecated in a future release,
-with removal following after a deprecation period.
-Consider using SentenceTransformersSimilarityRanker instead, which provides the same functionality along with
-additional features.
-
-### Usage example
-
-```python
-from haystack import Document
-from haystack.components.rankers import TransformersSimilarityRanker
-
-ranker = TransformersSimilarityRanker()
-docs = [Document(content="Paris"), Document(content="Berlin")]
-query = "City in Germany"
-result = ranker.run(query=query, documents=docs)
-docs = result["documents"]
-print(docs[0].content)
-```
-
-#### __init__
-
-```python
-__init__(
- model: str | Path = "cross-encoder/ms-marco-MiniLM-L-6-v2",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- top_k: int = 10,
- query_prefix: str = "",
- document_prefix: str = "",
- meta_fields_to_embed: list[str] | None = None,
- embedding_separator: str = "\n",
- scale_score: bool = True,
- calibration_factor: float | None = 1.0,
- score_threshold: float | None = None,
- model_kwargs: dict[str, Any] | None = None,
- tokenizer_kwargs: dict[str, Any] | None = None,
- batch_size: int = 16,
-) -> None
-```
-
-Creates an instance of TransformersSimilarityRanker.
-
-**Parameters:**
-
-- **model** (str | Path) – The ranking model. Pass a local path or the Hugging Face model name of a cross-encoder model.
-- **device** (ComponentDevice | None) – The device on which the model is loaded. If `None`, overrides the default device.
-- **token** (Secret | None) – The API token to download private models from Hugging Face.
-- **top_k** (int) – The maximum number of documents to return per query.
-- **query_prefix** (str) – A string to add at the beginning of the query text before ranking.
- Use it to prepend the text with an instruction, as required by reranking models like `bge`.
-- **document_prefix** (str) – A string to add at the beginning of each document before ranking. You can use it to prepend the document
- with an instruction, as required by embedding models like `bge`.
-- **meta_fields_to_embed** (list\[str\] | None) – List of metadata fields to embed with the document.
-- **embedding_separator** (str) – Separator to concatenate metadata fields to the document.
-- **scale_score** (bool) – If `True`, scales the raw logit predictions using a Sigmoid activation function.
- If `False`, disables scaling of the raw logit predictions.
-- **calibration_factor** (float | None) – Use this factor to calibrate probabilities with `sigmoid(logits * calibration_factor)`.
- Used only if `scale_score` is `True`.
-- **score_threshold** (float | None) – Use it to return documents with a score above this threshold only.
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoModelForSequenceClassification.from_pretrained`
- when loading the model. Refer to specific model documentation for available kwargs.
-- **tokenizer_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments for `AutoTokenizer.from_pretrained` when loading the tokenizer.
- Refer to specific model documentation for available kwargs.
-- **batch_size** (int) – The batch size to use for inference. The higher the batch size, the more memory is required.
- If you run into memory issues, reduce the batch size.
-
-**Raises:**
-
-- ValueError – If `top_k` is not > 0.
- If `scale_score` is True and `calibration_factor` is not provided.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> TransformersSimilarityRanker
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- TransformersSimilarityRanker – Deserialized component.
-
-#### run
-
-```python
-run(
- query: str,
- documents: list[Document],
- top_k: int | None = None,
- scale_score: bool | None = None,
- calibration_factor: float | None = None,
- score_threshold: float | None = None,
-) -> dict[str, Any]
-```
-
-Returns a list of documents ranked by their similarity to the given query.
-
-Before ranking, documents are deduplicated by their id, retaining only the document with the highest score
-if a score is present.
-
-**Parameters:**
-
-- **query** (str) – The input query to compare the documents to.
-- **documents** (list\[Document\]) – A list of documents to be ranked.
-- **top_k** (int | None) – The maximum number of documents to return.
-- **scale_score** (bool | None) – If `True`, scales the raw logit predictions using a Sigmoid activation function.
- If `False`, disables scaling of the raw logit predictions.
-- **calibration_factor** (float | None) – Use this factor to calibrate probabilities with `sigmoid(logits * calibration_factor)`.
- Used only if `scale_score` is `True`.
-- **score_threshold** (float | None) – Use it to return documents only with a score above this threshold.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the following keys:
-- `documents`: A list of documents closest to the query, sorted from most similar to least similar.
-
-**Raises:**
-
-- ValueError – If `top_k` is not > 0.
- If `scale_score` is True and `calibration_factor` is not provided.
diff --git a/docs-website/reference/haystack-api/readers_api.md b/docs-website/reference/haystack-api/readers_api.md
deleted file mode 100644
index 16e7c1a94b8..00000000000
--- a/docs-website/reference/haystack-api/readers_api.md
+++ /dev/null
@@ -1,193 +0,0 @@
----
-title: "Readers"
-id: readers-api
-description: "Takes a query and a set of Documents as input and returns ExtractedAnswers by selecting a text span within the Documents."
-slug: "/readers-api"
----
-
-
-## extractive
-
-### ExtractiveReader
-
-Locates and extracts answers to a given query from Documents.
-
-The ExtractiveReader component performs extractive question answering.
-It assigns a score to every possible answer span independently of other answer spans.
-This fixes a common issue of other implementations which make comparisons across documents harder by normalizing
-each document's answers independently.
-
-Example usage:
-
-```python
-from haystack import Document
-from haystack.components.readers import ExtractiveReader
-
-docs = [
- Document(content="Python is a popular programming language"),
- Document(content="python ist eine beliebte Programmiersprache"),
-]
-
-reader = ExtractiveReader()
-
-question = "What is a popular programming language?"
-result = reader.run(query=question, documents=docs)
-assert "Python" in result["answers"][0].data
-```
-
-#### __init__
-
-```python
-__init__(
- model: Path | str = "deepset/roberta-base-squad2-distilled",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- top_k: int = 20,
- score_threshold: float | None = None,
- max_seq_length: int = 384,
- stride: int = 128,
- max_batch_size: int | None = None,
- answers_per_seq: int | None = None,
- no_answer: bool = True,
- calibration_factor: float = 0.1,
- overlap_threshold: float | None = 0.01,
- model_kwargs: dict[str, Any] | None = None,
-) -> None
-```
-
-Creates an instance of ExtractiveReader.
-
-**Parameters:**
-
-- **model** (Path | str) – A Hugging Face transformers question answering model.
- Can either be a path to a folder containing the model files or an identifier for the Hugging Face hub.
-- **device** (ComponentDevice | None) – The device on which the model is loaded. If `None`, the default device is automatically selected.
-- **token** (Secret | None) – The API token used to download private models from Hugging Face.
-- **top_k** (int) – Number of answers to return per query. It is required even if score_threshold is set.
- An additional answer with no text is returned if no_answer is set to True (default).
-- **score_threshold** (float | None) – Returns only answers with the probability score above this threshold.
-- **max_seq_length** (int) – Maximum number of tokens. If a sequence exceeds it, the sequence is split.
-- **stride** (int) – Number of tokens that overlap when sequence is split because it exceeds max_seq_length.
-- **max_batch_size** (int | None) – Maximum number of samples that are fed through the model at the same time.
-- **answers_per_seq** (int | None) – Number of answer candidates to consider per sequence.
- This is relevant when a Document was split into multiple sequences because of max_seq_length.
-- **no_answer** (bool) – Whether to return an additional `no answer` with an empty text and a score representing the
- probability that the other top_k answers are incorrect.
-- **calibration_factor** (float) – Factor used for calibrating probabilities.
-- **overlap_threshold** (float | None) – If set this will remove duplicate answers if they have an overlap larger than the
- supplied threshold. For example, for the answers "in the river in Maine" and "the river" we would remove
- one of these answers since the second answer has a 100% (1.0) overlap with the first answer.
- However, for the answers "the river in" and "in Maine" there is only a max overlap percentage of 25% so
- both of these answers could be kept if this variable is set to 0.24 or lower.
- If None is provided then all answers are kept.
-- **model_kwargs** (dict\[str, Any\] | None) – Additional keyword arguments passed to `AutoModelForQuestionAnswering.from_pretrained`
- when loading the model specified in `model`. For details on what kwargs you can pass,
- see the model's documentation.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> ExtractiveReader
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- ExtractiveReader – Deserialized component.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### deduplicate_by_overlap
-
-```python
-deduplicate_by_overlap(
- answers: list[ExtractedAnswer], overlap_threshold: float | None
-) -> list[ExtractedAnswer]
-```
-
-De-duplicates overlapping Extractive Answers.
-
-De-duplicates overlapping Extractive Answers from the same document based on how much the spans of the
-answers overlap.
-
-**Parameters:**
-
-- **answers** (list\[ExtractedAnswer\]) – List of answers to be deduplicated.
-- **overlap_threshold** (float | None) – If set this will remove duplicate answers if they have an overlap larger than the
- supplied threshold. For example, for the answers "in the river in Maine" and "the river" we would remove
- one of these answers since the second answer has a 100% (1.0) overlap with the first answer.
- However, for the answers "the river in" and "in Maine" there is only a max overlap percentage of 25% so
- both of these answers could be kept if this variable is set to 0.24 or lower.
- If None is provided then all answers are kept.
-
-**Returns:**
-
-- list\[ExtractedAnswer\] – List of deduplicated answers.
-
-#### run
-
-```python
-run(
- query: str,
- documents: list[Document],
- top_k: int | None = None,
- score_threshold: float | None = None,
- max_seq_length: int | None = None,
- stride: int | None = None,
- max_batch_size: int | None = None,
- answers_per_seq: int | None = None,
- no_answer: bool | None = None,
- overlap_threshold: float | None = None,
-) -> dict[str, Any]
-```
-
-Locates and extracts answers from the given Documents using the given query.
-
-**Parameters:**
-
-- **query** (str) – Query string.
-- **documents** (list\[Document\]) – List of Documents in which you want to search for an answer to the query.
-- **top_k** (int | None) – The maximum number of answers to return.
- An additional answer is returned if no_answer is set to True (default).
-- **score_threshold** (float | None) – Returns only answers with the score above this threshold.
-- **max_seq_length** (int | None) – Maximum number of tokens. If a sequence exceeds it, the sequence is split.
-- **stride** (int | None) – Number of tokens that overlap when sequence is split because it exceeds max_seq_length.
-- **max_batch_size** (int | None) – Maximum number of samples that are fed through the model at the same time.
-- **answers_per_seq** (int | None) – Number of answer candidates to consider per sequence.
- This is relevant when a Document was split into multiple sequences because of max_seq_length.
-- **no_answer** (bool | None) – Whether to return no answer scores.
-- **overlap_threshold** (float | None) – If set this will remove duplicate answers if they have an overlap larger than the
- supplied threshold. For example, for the answers "in the river in Maine" and "the river" we would remove
- one of these answers since the second answer has a 100% (1.0) overlap with the first answer.
- However, for the answers "the river in" and "in Maine" there is only a max overlap percentage of 25% so
- both of these answers could be kept if this variable is set to 0.24 or lower.
- If None is provided then all answers are kept.
-
-**Returns:**
-
-- dict\[str, Any\] – List of answers sorted by (desc.) answer score.
diff --git a/docs-website/reference/haystack-api/retrievers_api.md b/docs-website/reference/haystack-api/retrievers_api.md
index b953c50692b..fb61f3d10ac 100644
--- a/docs-website/reference/haystack-api/retrievers_api.md
+++ b/docs-website/reference/haystack-api/retrievers_api.md
@@ -408,9 +408,7 @@ In query pipelines, use a TextEmbedder to embed queries and send them to the ret
```python
from haystack import Document
-# Requires: pip install sentence-transformers-haystack
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersDocumentEmbedder
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersTextEmbedder
+from haystack.components.embedders import OpenAIDocumentEmbedder, OpenAITextEmbedder
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
from haystack.document_stores.in_memory import InMemoryDocumentStore
@@ -418,7 +416,7 @@ docs = [
Document(content="Python is a popular programming language"),
Document(content="python ist eine beliebte Programmiersprache"),
]
-doc_embedder = SentenceTransformersDocumentEmbedder()
+doc_embedder = OpenAIDocumentEmbedder()
docs_with_embeddings = doc_embedder.run(docs)["documents"]
doc_store = InMemoryDocumentStore()
@@ -426,7 +424,7 @@ doc_store.write_documents(docs_with_embeddings)
retriever = InMemoryEmbeddingRetriever(doc_store)
query="Programmiersprache"
-text_embedder = SentenceTransformersTextEmbedder()
+text_embedder = OpenAITextEmbedder()
query_embedding = text_embedder.run(query)["embedding"]
result = retriever.run(query_embedding=query_embedding)
@@ -577,9 +575,8 @@ The results are combined and sorted by relevance score.
from haystack import Document
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.document_stores.types import DuplicatePolicy
-# Requires: pip install sentence-transformers-haystack
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersTextEmbedder
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersDocumentEmbedder
+from haystack.components.embedders import OpenAITextEmbedder
+from haystack.components.embedders import OpenAIDocumentEmbedder
from haystack.components.retrievers import InMemoryEmbeddingRetriever
from haystack.components.writers import DocumentWriter
from haystack.components.retrievers import MultiQueryEmbeddingRetriever
@@ -595,14 +592,14 @@ documents = [
# Populate the document store
doc_store = InMemoryDocumentStore()
-doc_embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
+doc_embedder = OpenAIDocumentEmbedder()
doc_writer = DocumentWriter(document_store=doc_store, policy=DuplicatePolicy.SKIP)
documents = doc_embedder.run(documents)["documents"]
doc_writer.run(documents=documents)
# Run the multi-query retriever
in_memory_retriever = InMemoryEmbeddingRetriever(document_store=doc_store, top_k=1)
-query_embedder = SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
+query_embedder = OpenAITextEmbedder()
multi_query_retriever = MultiQueryEmbeddingRetriever(
retriever=in_memory_retriever,
@@ -647,7 +644,31 @@ Initialize MultiQueryEmbeddingRetriever.
warm_up() -> None
```
-Warm up the query embedder and the retriever if any has a warm_up method.
+Warm up the query embedder and the retriever.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the query embedder and the retriever on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the query embedder's and the retriever's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the query embedder's and the retriever's async resources.
#### run
@@ -785,7 +806,31 @@ Initialize MultiQueryTextRetriever.
warm_up() -> None
```
-Warm up the retriever if it has a warm_up method.
+Warm up the retriever.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the retriever on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the retriever's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the retriever's async resources.
#### run
@@ -881,9 +926,7 @@ from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.document_stores.types import DuplicatePolicy
from haystack.components.retrievers import InMemoryBM25Retriever, InMemoryEmbeddingRetriever
from haystack.components.retrievers import TextEmbeddingRetriever, MultiRetriever
-# Requires: pip install sentence-transformers-haystack
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersTextEmbedder
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersDocumentEmbedder
+from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder
from haystack.components.writers import DocumentWriter
documents = [
@@ -894,7 +937,7 @@ documents = [
# Populate the document store
doc_store = InMemoryDocumentStore()
-doc_embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
+doc_embedder = OpenAIDocumentEmbedder()
doc_writer = DocumentWriter(document_store=doc_store, policy=DuplicatePolicy.SKIP)
doc_writer.run(documents=doc_embedder.run(documents)["documents"])
@@ -904,7 +947,7 @@ retriever = MultiRetriever(
"bm25": InMemoryBM25Retriever(document_store=doc_store),
"embedding": TextEmbeddingRetriever(
retriever=InMemoryEmbeddingRetriever(document_store=doc_store),
- text_embedder=SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"),
+ text_embedder=OpenAITextEmbedder(),
),
},
top_k=3,
@@ -960,7 +1003,31 @@ Create the MultiRetriever component.
warm_up() -> None
```
-Warm up the retrievers if any has a warm_up method.
+Warm up the retrievers.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the retrievers on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the retrievers' resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the retrievers' async resources.
#### run
@@ -1274,9 +1341,7 @@ The results are sorted by relevance score.
from haystack import Document
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.document_stores.types import DuplicatePolicy
-# Requires: pip install sentence-transformers-haystack
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersTextEmbedder
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersDocumentEmbedder
+from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder
from haystack.components.retrievers import InMemoryEmbeddingRetriever, TextEmbeddingRetriever
from haystack.components.writers import DocumentWriter
@@ -1291,14 +1356,14 @@ documents = [
# Populate the document store
doc_store = InMemoryDocumentStore()
-doc_embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
+doc_embedder = OpenAIDocumentEmbedder()
doc_writer = DocumentWriter(document_store=doc_store, policy=DuplicatePolicy.SKIP)
documents = doc_embedder.run(documents)["documents"]
doc_writer.run(documents=documents)
# Run the retriever
in_memory_retriever = InMemoryEmbeddingRetriever(document_store=doc_store, top_k=1)
-text_embedder = SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
+text_embedder = OpenAITextEmbedder()
retriever = TextEmbeddingRetriever(retriever=in_memory_retriever, text_embedder=text_embedder)
result = retriever.run(query="Geothermal energy")
@@ -1326,7 +1391,31 @@ Initialize TextEmbeddingRetriever.
warm_up() -> None
```
-Warm up the text embedder and the retriever if any has a warm_up method.
+Warm up the text embedder and the retriever.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the text embedder and the retriever on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the text embedder's and the retriever's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the text embedder's and the retriever's async resources.
#### run
diff --git a/docs-website/reference/haystack-api/routers_api.md b/docs-website/reference/haystack-api/routers_api.md
index 57490d4ec07..b42fcb668b1 100644
--- a/docs-website/reference/haystack-api/routers_api.md
+++ b/docs-website/reference/haystack-api/routers_api.md
@@ -657,7 +657,31 @@ Initialize the LLMMessagesRouter component.
warm_up() -> None
```
-Warm up the underlying LLM.
+Warm up the underlying chat generator.
+
+#### warm_up_async
+
+```python
+warm_up_async() -> None
+```
+
+Warm up the underlying chat generator on the serving event loop.
+
+#### close
+
+```python
+close() -> None
+```
+
+Release the underlying chat generator's resources.
+
+#### close_async
+
+```python
+close_async() -> None
+```
+
+Release the underlying chat generator's async resources.
#### run
@@ -682,6 +706,33 @@ Classify the messages based on LLM output and route them to the appropriate outp
- ValueError – If messages is an empty list or contains messages with unsupported roles.
+#### run_async
+
+```python
+run_async(messages: list[ChatMessage]) -> dict[str, str | list[ChatMessage]]
+```
+
+Asynchronously classify the messages based on LLM output and route them to the appropriate output connection.
+
+This is the asynchronous version of the `run` method. It has the same parameters and return values
+but can be used with `await` in an async code. If the chat generator only implements a synchronous
+`run` method, it is executed in a thread to avoid blocking the event loop.
+
+**Parameters:**
+
+- **messages** (list\[ChatMessage\]) – A list of ChatMessages to be routed. Only user and assistant messages are supported.
+
+**Returns:**
+
+- dict\[str, str | list\[ChatMessage\]\] – A dictionary with the following keys:
+- "chat_generator_text": The text output of the LLM, useful for debugging.
+- "output_names": Each contains the list of messages that matched the corresponding pattern.
+- "unmatched": The messages that did not match any of the output patterns.
+
+**Raises:**
+
+- ValueError – If messages is an empty list or contains messages with unsupported roles.
+
#### to_dict
```python
@@ -855,374 +906,3 @@ Deserialize this component from a dictionary.
**Returns:**
- MetadataRouter – The deserialized component instance.
-
-## text_language_router
-
-### TextLanguageRouter
-
-Routes text strings to different output connections based on their language.
-
-Provide a list of languages during initialization. If the document's text doesn't match any of the
-specified languages, the metadata value is set to "unmatched".
-For routing documents based on their language, use the DocumentLanguageClassifier component,
-followed by the MetaDataRouter.
-
-### Usage example
-
-```python
-from haystack import Pipeline, Document
-from haystack.components.routers import TextLanguageRouter
-from haystack.document_stores.in_memory import InMemoryDocumentStore
-from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
-
-document_store = InMemoryDocumentStore()
-document_store.write_documents([Document(content="Elvis Presley was an American singer and actor.")])
-
-p = Pipeline()
-p.add_component(instance=TextLanguageRouter(languages=["en"]), name="text_language_router")
-p.add_component(instance=InMemoryBM25Retriever(document_store=document_store), name="retriever")
-p.connect("text_language_router.en", "retriever.query")
-
-result = p.run({"text_language_router": {"text": "Who was Elvis Presley?"}})
-assert result["retriever"]["documents"][0].content == "Elvis Presley was an American singer and actor."
-
-result = p.run({"text_language_router": {"text": "ένα ελληνικό κείμενο"}})
-assert result["text_language_router"]["unmatched"] == "ένα ελληνικό κείμενο"
-```
-
-#### __init__
-
-```python
-__init__(languages: list[str] | None = None) -> None
-```
-
-Initialize the TextLanguageRouter component.
-
-**Parameters:**
-
-- **languages** (list\[str\] | None) – A list of ISO language codes.
- See the supported languages in [`langdetect` documentation](https://github.com/Mimino666/langdetect#languages).
- If not specified, defaults to ["en"].
-
-#### run
-
-```python
-run(text: str) -> dict[str, str]
-```
-
-Routes the text strings to different output connections based on their language.
-
-If the document's text doesn't match any of the specified languages, the metadata value is set to "unmatched".
-
-**Parameters:**
-
-- **text** (str) – A text string to route.
-
-**Returns:**
-
-- dict\[str, str\] – A dictionary in which the key is the language (or `"unmatched"`),
- and the value is the text.
-
-**Raises:**
-
-- TypeError – If the input is not a string.
-
-## transformers_text_router
-
-### TransformersTextRouter
-
-Routes the text strings to different connections based on a category label.
-
-The labels are specific to each model and can be found it its description on Hugging Face.
-
-### Usage example
-
-
-
-```python
-from haystack.core.pipeline import Pipeline
-from haystack.components.routers import TransformersTextRouter
-from haystack.components.builders import PromptBuilder
-from haystack.components.generators import HuggingFaceLocalGenerator
-
-p = Pipeline()
-p.add_component(
- instance=TransformersTextRouter(model="papluca/xlm-roberta-base-language-detection"),
- name="text_router"
-)
-p.add_component(
- instance=PromptBuilder(template="Answer the question: {{query}}\nAnswer:"),
- name="english_prompt_builder"
-)
-p.add_component(
- instance=PromptBuilder(template="Beantworte die Frage: {{query}}\nAntwort:"),
- name="german_prompt_builder"
-)
-
-p.add_component(
- instance=HuggingFaceLocalGenerator(model="DiscoResearch/Llama3-DiscoLeo-Instruct-8B-v0.1"),
- name="german_llm"
-)
-p.add_component(
- instance=HuggingFaceLocalGenerator(model="microsoft/Phi-3-mini-4k-instruct"),
- name="english_llm"
-)
-
-p.connect("text_router.en", "english_prompt_builder.query")
-p.connect("text_router.de", "german_prompt_builder.query")
-p.connect("english_prompt_builder.prompt", "english_llm.prompt")
-p.connect("german_prompt_builder.prompt", "german_llm.prompt")
-
-# English Example
-print(p.run({"text_router": {"text": "What is the capital of Germany?"}}))
-
-# German Example
-print(p.run({"text_router": {"text": "Was ist die Hauptstadt von Deutschland?"}}))
-```
-
-#### __init__
-
-```python
-__init__(
- model: str,
- labels: list[str] | None = None,
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- huggingface_pipeline_kwargs: dict[str, Any] | None = None,
-) -> None
-```
-
-Initializes the TransformersTextRouter component.
-
-**Parameters:**
-
-- **model** (str) – The name or path of a Hugging Face model for text classification.
-- **labels** (list\[str\] | None) – The list of labels. If not provided, the component fetches the labels
- from the model configuration file hosted on the Hugging Face Hub using
- `transformers.AutoConfig.from_pretrained`.
-- **device** (ComponentDevice | None) – The device for loading the model. If `None`, automatically selects the default device.
- If a device or device map is specified in `huggingface_pipeline_kwargs`, it overrides this parameter.
-- **token** (Secret | None) – The API token used to download private models from Hugging Face.
- If `True`, uses either `HF_API_TOKEN` or `HF_TOKEN` environment variables.
- To generate these tokens, run `transformers-cli login`.
-- **huggingface_pipeline_kwargs** (dict\[str, Any\] | None) – A dictionary of keyword arguments for initializing the Hugging Face
- text classification pipeline.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> TransformersTextRouter
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- TransformersTextRouter – Deserialized component.
-
-#### run
-
-```python
-run(text: str) -> dict[str, str]
-```
-
-Routes the text strings to different connections based on a category label.
-
-**Parameters:**
-
-- **text** (str) – A string of text to route.
-
-**Returns:**
-
-- dict\[str, str\] – A dictionary with the label as key and the text as value.
-
-**Raises:**
-
-- TypeError – If the input is not a str.
-
-## zero_shot_text_router
-
-### TransformersZeroShotTextRouter
-
-Routes the text strings to different connections based on a category label.
-
-Specify the set of labels for categorization when initializing the component.
-
-### Usage example
-
-```python
-from haystack import Document
-from haystack.document_stores.in_memory import InMemoryDocumentStore
-from haystack.core.pipeline import Pipeline
-from haystack.components.routers import TransformersZeroShotTextRouter
-from haystack.components.embedders import SentenceTransformersTextEmbedder, SentenceTransformersDocumentEmbedder
-from haystack.components.retrievers import InMemoryEmbeddingRetriever
-
-document_store = InMemoryDocumentStore()
-doc_embedder = SentenceTransformersDocumentEmbedder(model="intfloat/e5-base-v2")
-docs = [
- Document(
- content="Germany, officially the Federal Republic of Germany, is a country in the western region of "
- "Central Europe. The nation's capital and most populous city is Berlin and its main financial centre "
- "is Frankfurt; the largest urban area is the Ruhr."
- ),
- Document(
- content="France, officially the French Republic, is a country located primarily in Western Europe. "
- "France is a unitary semi-presidential republic with its capital in Paris, the country's largest city "
- "and main cultural and commercial centre; other major urban areas include Marseille, Lyon, Toulouse, "
- "Lille, Bordeaux, Strasbourg, Nantes and Nice."
- )
-]
-docs_with_embeddings = doc_embedder.run(docs)
-document_store.write_documents(docs_with_embeddings["documents"])
-
-p = Pipeline()
-p.add_component(instance=TransformersZeroShotTextRouter(labels=["passage", "query"]), name="text_router")
-p.add_component(
- instance=SentenceTransformersTextEmbedder(model="intfloat/e5-base-v2", prefix="passage: "),
- name="passage_embedder"
-)
-p.add_component(
- instance=SentenceTransformersTextEmbedder(model="intfloat/e5-base-v2", prefix="query: "),
- name="query_embedder"
-)
-p.add_component(
- instance=InMemoryEmbeddingRetriever(document_store=document_store),
- name="query_retriever"
-)
-p.add_component(
- instance=InMemoryEmbeddingRetriever(document_store=document_store),
- name="passage_retriever"
-)
-
-p.connect("text_router.passage", "passage_embedder.text")
-p.connect("passage_embedder.embedding", "passage_retriever.query_embedding")
-p.connect("text_router.query", "query_embedder.text")
-p.connect("query_embedder.embedding", "query_retriever.query_embedding")
-
-# Query Example
-p.run({"text_router": {"text": "What is the capital of Germany?"}})
-
-# Passage Example
-p.run({
- "text_router":{
- "text": "The United Kingdom of Great Britain and Northern Ireland, commonly known as the " "United Kingdom (UK) or Britain, is a country in Northwestern Europe, off the north-western coast of " "the continental mainland."
- }
-})
-```
-
-#### __init__
-
-```python
-__init__(
- labels: list[str],
- multi_label: bool = False,
- model: str = "MoritzLaurer/deberta-v3-base-zeroshot-v1.1-all-33",
- device: ComponentDevice | None = None,
- token: Secret | None = Secret.from_env_var(
- ["HF_API_TOKEN", "HF_TOKEN"], strict=False
- ),
- huggingface_pipeline_kwargs: dict[str, Any] | None = None,
-) -> None
-```
-
-Initializes the TransformersZeroShotTextRouter component.
-
-**Parameters:**
-
-- **labels** (list\[str\]) – The set of labels to use for classification. Can be a single label,
- a string of comma-separated labels, or a list of labels.
-- **multi_label** (bool) – Indicates if multiple labels can be true.
- If `False`, label scores are normalized so their sum equals 1 for each sequence.
- If `True`, the labels are considered independent and probabilities are normalized for each candidate by
- doing a softmax of the entailment score vs. the contradiction score.
-- **model** (str) – The name or path of a Hugging Face model for zero-shot text classification.
-- **device** (ComponentDevice | None) – The device for loading the model. If `None`, automatically selects the default device.
- If a device or device map is specified in `huggingface_pipeline_kwargs`, it overrides this parameter.
-- **token** (Secret | None) – The API token used to download private models from Hugging Face.
- If `True`, uses either `HF_API_TOKEN` or `HF_TOKEN` environment variables.
- To generate these tokens, run `transformers-cli login`.
-- **huggingface_pipeline_kwargs** (dict\[str, Any\] | None) – A dictionary of keyword arguments for initializing the Hugging Face
- zero shot text classification.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Initializes the component.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> TransformersZeroShotTextRouter
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
-
-**Returns:**
-
-- TransformersZeroShotTextRouter – Deserialized component.
-
-#### run
-
-```python
-run(text: str) -> dict[str, str]
-```
-
-Routes the text strings to different connections based on a category label.
-
-**Parameters:**
-
-- **text** (str) – A string of text to route.
-
-**Returns:**
-
-- dict\[str, str\] – A dictionary with the label as key and the text as value.
-
-**Raises:**
-
-- TypeError – If the input is not a str.
diff --git a/docs-website/reference/haystack-api/skill_stores_api.md b/docs-website/reference/haystack-api/skill_stores_api.md
new file mode 100644
index 00000000000..ef0d2a86c55
--- /dev/null
+++ b/docs-website/reference/haystack-api/skill_stores_api.md
@@ -0,0 +1,254 @@
+---
+title: "Skill Stores"
+id: skill-stores-api
+description: "Storage layers that discover skills and serve their content on demand."
+slug: "/skill-stores-api"
+---
+
+
+## file_system/skill_store
+
+### FileSystemSkillStore
+
+SkillStore backed by a directory of skill sub-directories on the local filesystem.
+
+Expected layout:
+
+```
+skills/
+ pdf-forms/
+ SKILL.md # frontmatter (name, description) + markdown instructions
+ reference/forms.md # optional bundled file
+```
+
+The skill catalog is built by reading the frontmatter of each `SKILL.md` on `warm_up`; bodies and bundled files
+are read lazily when the agent calls the corresponding tool.
+
+#### __init__
+
+```python
+__init__(skills_dir: str | Path) -> None
+```
+
+Initialize the store with the root directory to scan.
+
+No filesystem access happens here; the directory is scanned lazily on first use (see `warm_up`), so the store
+can be constructed cheaply.
+
+**Parameters:**
+
+- **skills_dir** (str | Path) – Root directory that contains one sub-directory per skill.
+
+#### warm_up
+
+```python
+warm_up() -> None
+```
+
+Scan `skills_dir` and build the skill catalog by reading each skill's `SKILL.md` frontmatter.
+
+Only the frontmatter is read here; bodies and bundled files are read lazily when the corresponding method is
+called. Idempotent: repeated calls after the first are no-ops.
+
+**Raises:**
+
+- ValueError – If `skills_dir` does not exist, is not a directory, a skill's frontmatter is missing,
+ malformed, or missing a required field, or two skills share the same name.
+
+#### list_skills
+
+```python
+list_skills() -> dict[str, SkillInfo]
+```
+
+Return all skills discovered on disk, warming up the store first if needed.
+
+**Returns:**
+
+- dict\[str, SkillInfo\] – Mapping of skill name to its metadata.
+
+**Raises:**
+
+- ValueError – If the skills directory is invalid or a skill's frontmatter is malformed.
+
+#### load_skill
+
+```python
+load_skill(name: str) -> tuple[str, list[str]]
+```
+
+Read the named skill's instruction body and the manifest of its bundled files.
+
+**Parameters:**
+
+- **name** (str) – Skill name as returned by `list_skills`.
+
+**Returns:**
+
+- tuple\[str, list\[str\]\] – A tuple of (markdown body of the skill's `SKILL.md` with frontmatter stripped, sorted list of
+ POSIX-style paths relative to the skill directory for any bundled files). The file list is empty when
+ the skill bundles no extras.
+
+**Raises:**
+
+- KeyError – If no skill with `name` exists.
+
+#### read_skill_file
+
+```python
+read_skill_file(name: str, path: str) -> str | ImageContent | FileContent
+```
+
+Read a file bundled with the named skill, preventing path traversal outside the skill directory.
+
+The return type depends on the file: text files are returned as a `str`, image files (PNG, JPEG, ...) as an
+`ImageContent`, and PDFs as a `FileContent`, so a multimodal agent can pass them straight to the model.
+
+**Parameters:**
+
+- **name** (str) – Skill name as returned by `list_skills`.
+- **path** (str) – Path of the file relative to the skill directory (e.g. `"reference/forms.md"`).
+
+**Returns:**
+
+- str | ImageContent | FileContent – The file's text content (`str`), an `ImageContent` for images, or a `FileContent` for PDFs.
+
+**Raises:**
+
+- KeyError – If no skill with `name` exists.
+- PermissionError – If `path` resolves outside the skill's directory (path-traversal attempt). The
+ message lists the readable files so the caller can retry with a valid path.
+- FileNotFoundError – If the file does not exist within the skill. The message lists the readable
+ files so the caller can retry with a valid path.
+- ValueError – If the file is binary but not a supported image or PDF (i.e. not UTF-8 text either).
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize this store to a dictionary for use with `from_dict`.
+
+**Returns:**
+
+- dict\[str, Any\] – Dictionary representation of the store.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> FileSystemSkillStore
+```
+
+Deserialize a `FileSystemSkillStore` from its dictionary representation.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – Dictionary representation of the store, as produced by `to_dict`.
+
+**Returns:**
+
+- FileSystemSkillStore – A new `FileSystemSkillStore` instance.
+
+## types/protocol
+
+### SkillStore
+
+Bases: Protocol
+
+Protocol for a skill storage layer.
+
+A `SkillStore` is responsible for discovering available skills and providing their content on demand. Implement
+this protocol to back a `haystack.tools.SkillToolset` with any storage system — a local directory, a database,
+a remote API, or an in-memory fixture.
+
+Skills are identified by their `name`, which must be unique within a store. The `name` is the lookup key for every
+method below; implementations resolve it to their own internal locator (a directory, a row id, an object key, ...).
+
+Implementations may defer all I/O (filesystem reads, database connections, ...) until a method is actually called,
+so a store can be constructed cheaply and only touch its backend on first use.
+
+Skill content is text: instruction bodies and bundled files are returned as strings. Binary assets (images,
+fonts, ...) are not supported.
+
+#### list_skills
+
+```python
+list_skills() -> dict[str, SkillInfo]
+```
+
+Discover and return all available skills.
+
+**Returns:**
+
+- dict\[str, SkillInfo\] – Mapping of skill name to its metadata.
+
+#### load_skill
+
+```python
+load_skill(name: str) -> tuple[str, list[str]]
+```
+
+Return the named skill's instruction body and the manifest of its bundled files.
+
+**Parameters:**
+
+- **name** (str) – Skill name as returned by `list_skills`.
+
+**Returns:**
+
+- tuple\[str, list\[str\]\] – A tuple of (markdown body with frontmatter stripped, sorted list of POSIX-style paths relative
+ to the skill root for any bundled files). The file list is empty when the skill bundles no extras.
+
+**Raises:**
+
+- KeyError – If no skill with `name` exists.
+
+#### read_skill_file
+
+```python
+read_skill_file(name: str, path: str) -> str | ImageContent | FileContent
+```
+
+Read a file bundled with the named skill.
+
+Implementations should return text files as a `str`, image files as an `ImageContent`, and PDFs as a
+`FileContent`, so a multimodal agent can pass binary assets straight to the model.
+
+**Parameters:**
+
+- **name** (str) – Skill name as returned by `list_skills`.
+- **path** (str) – Path of the file relative to the skill root (e.g. `"reference/forms.md"`).
+
+**Returns:**
+
+- str | ImageContent | FileContent – The file's text content (`str`), an `ImageContent` for images, or a `FileContent` for PDFs.
+
+**Raises:**
+
+- KeyError – If no skill with `name` exists.
+- FileNotFoundError – If the file does not exist within the skill.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize this store to a dictionary for use with `from_dict`.
+
+Implement both this method and `from_dict` to make your custom store serializable.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> SkillStore
+```
+
+Deserialize a store from a dictionary produced by `to_dict`.
+
+Implement both this method and `to_dict` to make your custom store serializable.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – Dictionary as produced by `to_dict`.
diff --git a/docs-website/reference/haystack-api/tool_components_api.md b/docs-website/reference/haystack-api/tool_components_api.md
deleted file mode 100644
index 59c97798835..00000000000
--- a/docs-website/reference/haystack-api/tool_components_api.md
+++ /dev/null
@@ -1,314 +0,0 @@
----
-title: "Tool Components"
-id: tool-components-api
-description: "Components related to Tool Calling."
-slug: "/tool-components-api"
----
-
-
-## tool_invoker
-
-### ToolInvokerError
-
-Bases: Exception
-
-Base exception class for ToolInvoker errors.
-
-### ToolNotFoundException
-
-Bases: ToolInvokerError
-
-Exception raised when a tool is not found in the list of available tools.
-
-### StringConversionError
-
-Bases: ToolInvokerError
-
-Exception raised when the conversion of a tool result to a string fails.
-
-### ResultConversionError
-
-Bases: ToolInvokerError
-
-Exception raised when the conversion of a tool output to a result fails.
-
-### ToolOutputMergeError
-
-Bases: ToolInvokerError
-
-Exception raised when merging tool outputs into state fails.
-
-#### from_exception
-
-```python
-from_exception(tool_name: str, error: Exception) -> ToolOutputMergeError
-```
-
-Create a ToolOutputMergeError from an exception.
-
-### ToolInvoker
-
-Invokes tools based on prepared tool calls and returns the results as a list of ChatMessage objects.
-
-Also handles reading/writing from a shared `State`.
-At initialization, the ToolInvoker component is provided with a list of available tools.
-At runtime, the component processes a list of ChatMessage object containing tool calls
-and invokes the corresponding tools.
-The results of the tool invocations are returned as a list of ChatMessage objects with tool role.
-
-Usage example:
-
-```python
-from haystack.dataclasses import ChatMessage, ToolCall
-from haystack.tools import Tool
-from haystack.components.tools import ToolInvoker
-
-# Tool definition
-def dummy_weather_function(city: str):
- return f"The weather in {city} is 20 degrees."
-
-parameters = {"type": "object",
- "properties": {"city": {"type": "string"}},
- "required": ["city"]}
-
-tool = Tool(name="weather_tool",
- description="A tool to get the weather",
- function=dummy_weather_function,
- parameters=parameters)
-
-# Usually, the ChatMessage with tool_calls is generated by a Language Model
-# Here, we create it manually for demonstration purposes
-tool_call = ToolCall(
- tool_name="weather_tool",
- arguments={"city": "Berlin"}
-)
-message = ChatMessage.from_assistant(tool_calls=[tool_call])
-
-# ToolInvoker initialization and run
-invoker = ToolInvoker(tools=[tool])
-result = invoker.run(messages=[message])
-
-print(result)
-```
-
-```
-# >> {
-# >> 'tool_messages': [
-# >> ChatMessage(
-# >> _role=,
-# >> _content=[
-# >> ToolCallResult(
-# >> result='"The weather in Berlin is 20 degrees."',
-# >> origin=ToolCall(
-# >> tool_name='weather_tool',
-# >> arguments={'city': 'Berlin'},
-# >> id=None
-# >> )
-# >> )
-# >> ],
-# >> _meta={}
-# >> )
-# >> ]
-# >> }
-```
-
-Usage example with a Toolset:
-
-````python
-from haystack.dataclasses import ChatMessage, ToolCall
-from haystack.tools import Tool, Toolset
-from haystack.components.tools import ToolInvoker
-
-# Tool definition
-def dummy_weather_function(city: str):
- return f"The weather in {city} is 20 degrees."
-
-parameters = {"type": "object",
- "properties": {"city": {"type": "string"}},
- "required": ["city"]}
-
-tool = Tool(name="weather_tool",
- description="A tool to get the weather",
- function=dummy_weather_function,
- parameters=parameters)
-
-# Create a Toolset
-toolset = Toolset([tool])
-
-# Usually, the ChatMessage with tool_calls is generated by a Language Model
-# Here, we create it manually for demonstration purposes
-tool_call = ToolCall(
- tool_name="weather_tool",
- arguments={"city": "Berlin"}
-)
-message = ChatMessage.from_assistant(tool_calls=[tool_call])
-
-# ToolInvoker initialization and run with Toolset
-invoker = ToolInvoker(tools=toolset)
-result = invoker.run(messages=[message])
-
-print(result)
-
-#### __init__
-
-```python
-__init__(
- tools: ToolsType,
- raise_on_failure: bool = True,
- convert_result_to_json_string: bool = False,
- streaming_callback: StreamingCallbackT | None = None,
- *,
- enable_streaming_callback_passthrough: bool = False,
- max_workers: int = 4
-) -> None
-````
-
-Initialize the ToolInvoker component.
-
-**Parameters:**
-
-- **tools** (ToolsType) – A list of Tool and/or Toolset objects, or a Toolset instance that can resolve tools.
-- **raise_on_failure** (bool) – If True, the component will raise an exception in case of errors
- (tool not found, tool invocation errors, tool result conversion errors).
- If False, the component will return a ChatMessage object with `error=True`
- and a description of the error in `result`.
-- **convert_result_to_json_string** (bool) – If True, the tool invocation result will be converted to a string using `json.dumps`.
- If False, the tool invocation result will be converted to a string using `str`.
-- **streaming_callback** (StreamingCallbackT | None) – A callback function that will be called to emit tool results.
- Note that the result is only emitted once it becomes available — it is not
- streamed incrementally in real time.
-- **enable_streaming_callback_passthrough** (bool) – If True, the `streaming_callback` will be passed to the tool invocation if the tool supports it.
- This allows tools to stream their results back to the client.
- Note that this requires the tool to have a `streaming_callback` parameter in its `invoke` method signature.
- If False, the `streaming_callback` will not be passed to the tool invocation.
-- **max_workers** (int) – The maximum number of workers to use in the thread pool executor.
- This also decides the maximum number of concurrent tool invocations.
-
-**Raises:**
-
-- ValueError – If no tools are provided or if duplicate tool names are found.
-
-#### warm_up
-
-```python
-warm_up() -> None
-```
-
-Warm up the tool invoker.
-
-This will warm up the tools registered in the tool invoker.
-This method is idempotent and will only warm up the tools once.
-
-#### run
-
-```python
-run(
- messages: list[ChatMessage],
- state: State | None = None,
- streaming_callback: StreamingCallbackT | None = None,
- *,
- enable_streaming_callback_passthrough: bool | None = None,
- tools: ToolsType | None = None
-) -> dict[str, Any]
-```
-
-Processes ChatMessage objects containing tool calls and invokes the corresponding tools, if available.
-
-**Parameters:**
-
-- **messages** (list\[ChatMessage\]) – A list of ChatMessage objects.
-- **state** (State | None) – The runtime state that should be used by the tools.
-- **streaming_callback** (StreamingCallbackT | None) – A callback function that will be called to emit tool results.
- Note that the result is only emitted once it becomes available — it is not
- streamed incrementally in real time.
-- **enable_streaming_callback_passthrough** (bool | None) – If True, the `streaming_callback` will be passed to the tool invocation if the tool supports it.
- This allows tools to stream their results back to the client.
- Note that this requires the tool to have a `streaming_callback` parameter in its `invoke` method signature.
- If False, the `streaming_callback` will not be passed to the tool invocation.
- If None, the value from the constructor will be used.
-- **tools** (ToolsType | None) – A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
- If set, it will override the `tools` parameter provided during initialization.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the key `tool_messages` containing a list of ChatMessage objects with tool role.
- Each ChatMessage objects wraps the result of a tool invocation.
-
-**Raises:**
-
-- ToolNotFoundException – If the tool is not found in the list of available tools and `raise_on_failure` is True.
-- ToolInvocationError – If the tool invocation fails and `raise_on_failure` is True.
-- StringConversionError – If the conversion of the tool result to a string fails and `raise_on_failure` is True.
-- ToolOutputMergeError – If merging tool outputs into state fails and `raise_on_failure` is True.
-
-#### run_async
-
-```python
-run_async(
- messages: list[ChatMessage],
- state: State | None = None,
- streaming_callback: StreamingCallbackT | None = None,
- *,
- enable_streaming_callback_passthrough: bool | None = None,
- tools: ToolsType | None = None
-) -> dict[str, Any]
-```
-
-Asynchronously processes ChatMessage objects containing tool calls.
-
-Multiple tool calls are performed concurrently.
-
-**Parameters:**
-
-- **messages** (list\[ChatMessage\]) – A list of ChatMessage objects.
-- **state** (State | None) – The runtime state that should be used by the tools.
-- **streaming_callback** (StreamingCallbackT | None) – An asynchronous callback function that will be called to emit tool results.
- Note that the result is only emitted once it becomes available — it is not
- streamed incrementally in real time.
-- **enable_streaming_callback_passthrough** (bool | None) – If True, the `streaming_callback` will be passed to the tool invocation if the tool supports it.
- This allows tools to stream their results back to the client.
- Note that this requires the tool to have a `streaming_callback` parameter in its `invoke` method signature.
- If False, the `streaming_callback` will not be passed to the tool invocation.
- If None, the value from the constructor will be used.
-- **tools** (ToolsType | None) – A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
- If set, it will override the `tools` parameter provided during initialization.
-
-**Returns:**
-
-- dict\[str, Any\] – A dictionary with the key `tool_messages` containing a list of ChatMessage objects with tool role.
- Each ChatMessage objects wraps the result of a tool invocation.
-
-**Raises:**
-
-- ToolNotFoundException – If the tool is not found in the list of available tools and `raise_on_failure` is True.
-- ToolInvocationError – If the tool invocation fails and `raise_on_failure` is True.
-- StringConversionError – If the conversion of the tool result to a string fails and `raise_on_failure` is True.
-- ToolOutputMergeError – If merging tool outputs into state fails and `raise_on_failure` is True.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> ToolInvoker
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- ToolInvoker – The deserialized component.
diff --git a/docs-website/reference/haystack-api/tools_api.md b/docs-website/reference/haystack-api/tools_api.md
index b6f6ab0aaf4..0ebd08b67ff 100644
--- a/docs-website/reference/haystack-api/tools_api.md
+++ b/docs-website/reference/haystack-api/tools_api.md
@@ -31,20 +31,21 @@ Key features:
To use ComponentTool, you first need a Haystack component - either an existing one or a new one you create.
You can create a ComponentTool from the component by passing the component to the ComponentTool constructor.
-Below is an example of creating a ComponentTool from an existing SerperDevWebSearch component.
+Below is an example of creating a ComponentTool from an existing SerperDevWebSearch component
+from the `serperdev-haystack` integration package (`pip install serperdev-haystack`).
## Usage Example:
```python
-from haystack import component, Pipeline
+from haystack import component
from haystack.tools import ComponentTool
-from haystack.components.websearch import SerperDevWebSearch
from haystack.utils import Secret
-from haystack.components.tools.tool_invoker import ToolInvoker
+from haystack.components.agents import Agent
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
+from haystack_integrations.components.websearch.serperdev import SerperDevWebSearch
# Create a SerperDev search component
search = SerperDevWebSearch(api_key=Secret.from_env_var("SERPERDEV_API_KEY"), top_k=3)
@@ -56,18 +57,13 @@ tool = ComponentTool(
description="Search the web for current information on any topic" # Optional: defaults to component docstring
)
-# Create pipeline with OpenAIChatGenerator and ToolInvoker
-pipeline = Pipeline()
-pipeline.add_component("llm", OpenAIChatGenerator(tools=[tool]))
-pipeline.add_component("tool_invoker", ToolInvoker(tools=[tool]))
-
-# Connect components
-pipeline.connect("llm.replies", "tool_invoker.messages")
+# Create an Agent with an OpenAIChatGenerator and the tool
+agent = Agent(chat_generator=OpenAIChatGenerator(), tools=[tool])
message = ChatMessage.from_user("Use the web search tool to find information about Nikola Tesla")
-# Run pipeline
-result = pipeline.run({"llm": {"messages": [message]}})
+# Run the Agent
+result = agent.run(messages=[message])
print(result)
```
@@ -232,7 +228,9 @@ print(tool)
**Parameters:**
-- **function** (Callable) – The function to be converted into a Tool.
+- **function** (Callable) – The function to be converted into a Tool. May be either a regular function (assigned to the
+ resulting Tool's `function` field) or a coroutine function defined with `async def` (assigned
+ to `async_function`).
The function must include type hints for all parameters.
The function is expected to have basic python input types (str, int, float, bool, list, dict, tuple).
Other input types may work but are not guaranteed.
@@ -446,9 +444,7 @@ Below is an example of creating a PipelineTool
from haystack import Document, Pipeline
from haystack.dataclasses import ChatMessage
from haystack.document_stores.in_memory import InMemoryDocumentStore
-# Requires: pip install sentence-transformers-haystack
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersTextEmbedder
-from haystack_integrations.components.embedders.sentence_transformers import SentenceTransformersDocumentEmbedder
+from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.retrievers import InMemoryEmbeddingRetriever
from haystack.components.agents import Agent
@@ -456,7 +452,7 @@ from haystack.tools import PipelineTool
# Initialize a document store and add some documents
document_store = InMemoryDocumentStore()
-document_embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
+document_embedder = OpenAIDocumentEmbedder()
documents = [
Document(content="Nikola Tesla was a Serbian-American inventor and electrical engineer."),
Document(
@@ -469,9 +465,7 @@ document_store.write_documents(docs_with_embeddings)
# Build a simple retrieval pipeline
retrieval_pipeline = Pipeline()
-retrieval_pipeline.add_component(
- "embedder", SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
-)
+retrieval_pipeline.add_component("embedder", OpenAITextEmbedder())
retrieval_pipeline.add_component("retriever", InMemoryEmbeddingRetriever(document_store=document_store))
retrieval_pipeline.connect("embedder.embedding", "retriever.query_embedding")
@@ -508,7 +502,7 @@ print(result["messages"][-1].text)
```python
__init__(
- pipeline: Pipeline | AsyncPipeline,
+ pipeline: Pipeline,
*,
name: str,
description: str,
@@ -525,7 +519,7 @@ Create a Tool instance from a Haystack pipeline.
**Parameters:**
-- **pipeline** (Pipeline | AsyncPipeline) – The Haystack pipeline to wrap as a tool.
+- **pipeline** (Pipeline) – The Haystack pipeline to wrap as a tool.
- **name** (str) – Name of the tool.
- **description** (str) – Description of the tool.
- **input_mapping** (dict\[str, list\[str\]\] | None) – A dictionary mapping component input names to pipeline input socket paths.
@@ -645,36 +639,50 @@ Bases: Toolset
Dynamic tool discovery from large catalogs using BM25 search.
-This Toolset enables LLMs to discover and use tools from large catalogs through
-BM25-based search. Instead of exposing all tools at once (which can overwhelm the
-LLM context), it provides a `search_tools` bootstrap tool that allows the LLM to
-find and load specific tools as needed.
+This Toolset enables LLMs to discover and use tools from large catalogs through BM25-based search.
+Instead of exposing all tools at once (which can overwhelm the LLM context), it provides a `search_tools` bootstrap
+tool that allows the LLM to find and load specific tools as needed.
-For very small catalogs (below `search_threshold`), acts as a simple passthrough
-exposing all tools directly without any discovery mechanism.
+For very small catalogs (below `search_threshold`), acts as a simple passthrough exposing all tools directly
+without any discovery mechanism.
### Usage Example
```python
+from typing import Annotated
+
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",
- parameters={}, function=lambda: None),
- Tool(name="search_web", description="Search the web",
- parameters={}, function=lambda: None),
- # ... 100s more tools
-]
-toolset = SearchableToolset(catalog=catalog)
+from haystack.tools import SearchableToolset, tool
+
+@tool
+def get_weather(city: Annotated[str, "The city to get the weather for"]) -> str:
+ '''Get the current weather for a city.'''
+ return f"The weather in {city} is 22°C and sunny."
+
+@tool
+def search_web(query: Annotated[str, "The query to search the web for"]) -> str:
+ '''Search the web for a query.'''
+ return f"Top result for '{query}': ..."
+
+@tool
+def convert_currency(
+ amount: Annotated[float, "The amount to convert"],
+ to_currency: Annotated[str, "The currency to convert to, e.g. 'EUR'"],
+) -> str:
+ '''Convert an amount in USD to another currency.'''
+ return f"{amount} USD is {amount * 0.9} {to_currency}"
+
+# search_threshold=2 means a catalog of 2+ tools activates discovery: the agent only sees the
+# `search_tools` tool and must search to load the others (set it higher for larger catalogs).
+toolset = SearchableToolset(catalog=[get_weather, search_web, convert_currency], search_threshold=2)
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?")])
+print(result["last_message"].text)
```
#### __init__
@@ -697,12 +705,11 @@ Initialize the SearchableToolset.
- **catalog** (ToolsType) – Source of tools - a list of Tools, list of Toolsets, or a single Toolset.
- **top_k** (int) – Default number of results for search_tools.
-- **search_threshold** (int) – Minimum catalog size to activate search.
- If catalog has fewer tools, acts as passthrough (all tools visible).
- Default is 8.
+- **search_threshold** (int) – Minimum catalog size to activate search. If catalog has fewer tools, acts as
+ passthrough (all tools visible). Default is 8.
- **search_tool_name** (str) – Custom name for the bootstrap search tool. Default is "search_tools".
-- **search_tool_description** (str | None) – Custom description for the bootstrap search tool.
- If not provided, uses a default description.
+- **search_tool_description** (str | None) – Custom description for the bootstrap search tool. If not provided, uses a
+ default description.
- **search_tool_parameters_description** (dict\[str, str\] | None) – Custom descriptions for the bootstrap search tool's parameters.
Keys must be a subset of `{"tool_keywords", "k"}`.
Example: `{"tool_keywords": "Keywords to find tools, e.g. 'email send'"}`
@@ -723,10 +730,29 @@ warm_up() -> None
Prepare the toolset for use.
-Warms up child toolsets first (so lazy toolsets like MCPToolset can connect),
-then flattens the catalog, indexes it, and creates the search_tools bootstrap tool.
-In passthrough mode, it warms up all catalog tools directly.
-Must be called before using the toolset with an Agent.
+Warms up the catalog (so lazy toolsets like MCPToolset can connect) and flattens it. Above the passthrough
+threshold, it also indexes the catalog and creates the search_tools bootstrap tool.
+
+This method is idempotent: it only warms up the toolset the first time it is called.
+
+**Raises:**
+
+- ValueError – If the flattened catalog contains tools with duplicate names.
+
+#### get_selectable_tools
+
+```python
+get_selectable_tools() -> list[Tool]
+```
+
+Return the full catalog of tools that can be selected by name.
+
+Iteration only exposes the search tool plus already-discovered tools, but name-based selection can target
+any tool in the catalog, so this returns the entire flattened catalog (warming up first if needed).
+
+**Returns:**
+
+- list\[Tool\] – The flattened catalog of tools.
#### clear
@@ -736,9 +762,24 @@ clear() -> None
Clear all discovered tools.
-This method allows resetting the toolset's discovered tools between agent runs
-when the same toolset instance is reused. This can be useful for long-running
-applications to control memory usage or to start fresh searches.
+This method allows resetting the toolset's discovered tools between agent runs when the same toolset instance
+is reused. This can be useful for long-running applications to control memory usage or to start fresh searches.
+
+#### spawn
+
+```python
+spawn() -> SearchableToolset
+```
+
+Return an isolated copy for a single run.
+
+The copy shares the read-only catalog and BM25 index but gets fresh discovered tools and name selection,
+plus a bootstrap search tool bound to the copy. This way concurrent runs sharing the same configured
+SearchableToolset don't share discovered tools or collide on the active selection.
+
+**Returns:**
+
+- SearchableToolset – A run-scoped copy of this SearchableToolset.
#### to_dict
@@ -768,6 +809,130 @@ Deserialize a toolset from a dictionary.
- SearchableToolset – New SearchableToolset instance.
+**Raises:**
+
+- TypeError – If a serialized catalog entry is not a subclass of Tool or Toolset.
+
+## skills/skill_toolset
+
+### SkillToolset
+
+Bases: Toolset
+
+A Toolset that lets an Agent discover and read skills via progressive disclosure.
+
+A skill is a directory (or equivalent storage unit) containing a `SKILL.md` file with YAML frontmatter
+(`name` and `description`) and a markdown body of instructions. Skills may bundle additional files
+(reference docs, examples, templates).
+
+- On `warm_up`, the name and description of every discovered skill are baked into the `load_skill` tool
+ description so the model knows which skills exist without any system prompt injection.
+- `load_skill` returns a skill's full instructions on demand, plus a manifest of its bundled files.
+- `read_skill_file` reads a bundled file on demand.
+
+### Usage example
+
+```python
+from haystack.components.agents import Agent
+from haystack.components.generators.chat import OpenAIChatGenerator
+from haystack.dataclasses import ChatMessage
+from haystack.tools import SkillToolset
+from haystack.skill_stores.file_system import FileSystemSkillStore
+
+store = FileSystemSkillStore("skills/")
+skills_toolset = SkillToolset(store)
+agent = Agent(chat_generator=OpenAIChatGenerator(), tools=skills_toolset)
+result = agent.run(messages=[ChatMessage.from_user("Fill in this PDF form for me.")])
+```
+
+Expected filesystem layout:
+
+```
+skills/
+ pdf-forms/
+ SKILL.md # frontmatter (name, description) + markdown instructions
+ reference/forms.md
+```
+
+The tool names `load_skill` and `read_skill_file` are fixed, so an `Agent` can use at most one
+`SkillToolset`. To serve skills from multiple sources, back a single toolset with a custom store that
+merges them.
+
+#### __init__
+
+```python
+__init__(store: SkillStore) -> None
+```
+
+Initialize the SkillToolset.
+
+Constructing the toolset does not read any skills. The store is queried for the available skills on
+`warm_up()`, so stores that do I/O (reading a directory, connecting to a database) stay cheap to
+construct.
+
+The `load_skill` and `read_skill_file` tools are created right away, so the toolset can be used as a
+collection (length, membership checks, iteration) immediately.
+
+**Parameters:**
+
+- **store** (SkillStore) – A `haystack.skill_stores.types.SkillStore` instance to back this toolset.
+
+#### skills
+
+```python
+skills: dict[str, SkillInfo]
+```
+
+Mapping of skill name to its metadata. Triggers `warm_up()` on first access if not already warmed up.
+
+#### warm_up
+
+```python
+warm_up() -> None
+```
+
+Discover the available skills from the store and bake the catalog into the `load_skill` description.
+
+Only the description content is dynamic, so the (static) tools created in `__init__` are reused; this
+refreshes `load_skill`'s description once the catalog is known. Idempotent: repeated calls after the
+first are no-ops.
+
+#### add
+
+```python
+add(tool: Tool | Toolset) -> None
+```
+
+Adding tools is not supported: a SkillToolset's tools are fixed and defined by its store.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the toolset to a dictionary.
+
+**Returns:**
+
+- dict\[str, Any\] – Dictionary representation of the toolset.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> SkillToolset
+```
+
+Deserialize a toolset from a dictionary.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – Dictionary representation of the toolset, as produced by `to_dict`.
+
+**Returns:**
+
+- SkillToolset – A new SkillToolset instance.
+
## tool
### Tool
@@ -787,8 +952,11 @@ pipeline/agent setup.
- **name** (str) – Name of the Tool.
- **description** (str) – Description of the Tool.
- **parameters** (dict\[str, Any\]) – A JSON schema defining the parameters expected by the Tool.
-- **function** (Callable) – The function that will be invoked when the Tool is called.
- Must be a synchronous function; async functions are not supported.
+- **function** (Callable | None) – The synchronous function invoked by `Tool.invoke`. Must be a regular function — coroutine functions should
+ be passed to `async_function` instead. Either `function` or `async_function` (or both) must be set.
+- **async_function** (Callable | None) – Optional coroutine function awaited by `Tool.invoke_async`. When only `async_function` is set, `invoke` raises
+ a `ToolInvocationError`. When only `function` is set, `invoke_async` falls back to running `function` in a
+ worker thread via `asyncio.to_thread`.
- **outputs_to_string** (dict\[str, Any\] | None) – Optional dictionary defining how tool outputs should be converted into string(s) or results.
If not provided, the tool result is converted to a string using a default handler.
@@ -846,8 +1014,10 @@ Example:
**Raises:**
-- ValueError – If `function` is async, if `parameters` is not a valid JSON schema, or if the
- `outputs_to_state`, `outputs_to_string`, or `inputs_from_state` configurations are invalid.
+- ValueError – If neither `function` nor `async_function` is provided, if `function` is a
+ coroutine function, if `async_function` is not a coroutine function, if `parameters` is not a
+ valid JSON schema, or if the `outputs_to_state`, `outputs_to_string`, or `inputs_from_state`
+ configurations are invalid.
- TypeError – If any configuration value in `outputs_to_state`, `outputs_to_string`, or
`inputs_from_state` has the wrong type.
@@ -877,7 +1047,27 @@ as it may be called multiple times.
invoke(**kwargs: Any) -> Any
```
-Invoke the Tool with the provided keyword arguments.
+Invoke the Tool synchronously with the provided keyword arguments.
+
+**Raises:**
+
+- ToolInvocationError – If the Tool has no sync `function`, or if the underlying call
+ raises an exception.
+
+#### invoke_async
+
+```python
+invoke_async(**kwargs: Any) -> Any
+```
+
+Invoke the Tool asynchronously with the provided keyword arguments.
+
+If `async_function` is set, it is awaited directly. Otherwise the sync `function` is dispatched to a worker
+thread via `asyncio.to_thread`, which propagates the current context to the worker.
+
+**Raises:**
+
+- ToolInvocationError – If the underlying call raises an exception.
#### to_dict
@@ -922,100 +1112,62 @@ Toolset serves two main purposes:
Example:
```python
-from haystack.tools import Tool, Toolset
-from haystack.components.tools import ToolInvoker
+from typing import Annotated
+from haystack.tools import tool, Toolset
+from haystack.components.agents import Agent
+from haystack.components.generators.chat import OpenAIChatGenerator
-# Define math functions
-def add_numbers(a: int, b: int) -> int:
+# Create tools with the @tool decorator (the recommended way)
+@tool
+def add(a: Annotated[int, "first number"], b: Annotated[int, "second number"]) -> int:
+ '''Add two numbers.'''
return a + b
-def subtract_numbers(a: int, b: int) -> int:
+@tool
+def subtract(a: Annotated[int, "first number"], b: Annotated[int, "second number"]) -> int:
+ '''Subtract b from a.'''
return a - b
-# Create tools with proper schemas
-add_tool = Tool(
- name="add",
- description="Add two numbers",
- parameters={
- "type": "object",
- "properties": {
- "a": {"type": "integer"},
- "b": {"type": "integer"}
- },
- "required": ["a", "b"]
- },
- function=add_numbers
-)
-
-subtract_tool = Tool(
- name="subtract",
- description="Subtract b from a",
- parameters={
- "type": "object",
- "properties": {
- "a": {"type": "integer"},
- "b": {"type": "integer"}
- },
- "required": ["a", "b"]
- },
- function=subtract_numbers
-)
-
# Create a toolset with the math tools
-math_toolset = Toolset([add_tool, subtract_tool])
+math_toolset = Toolset([add, subtract])
-# Use the toolset with a ToolInvoker or ChatGenerator component
-invoker = ToolInvoker(tools=math_toolset)
+# Use the toolset with an Agent
+agent = Agent(chat_generator=OpenAIChatGenerator(), tools=math_toolset)
```
2. Base class for dynamic tool loading:
- By subclassing Toolset, you can create implementations that dynamically load tools
- from external sources like OpenAPI URLs, MCP servers, or other resources.
+ By subclassing Toolset, you can create implementations that dynamically load tools from external sources like
+ OpenAPI URLs, MCP servers, or other resources.
Example:
```python
+from typing import Annotated
from haystack.core.serialization import generate_qualified_class_name
-from haystack.tools import Tool, Toolset
-from haystack.components.tools import ToolInvoker
+from haystack.tools import tool, Toolset
+from haystack.components.agents import Agent
+from haystack.components.generators.chat import OpenAIChatGenerator
class CalculatorToolset(Toolset):
'''A toolset for calculator operations.'''
def __init__(self) -> None:
- tools = self._create_tools()
- super().__init__(tools)
+ super().__init__(self._create_tools())
def _create_tools(self):
- # These Tool instances are obviously defined statically and for illustration purposes only.
+ # These tools are defined statically for illustration purposes only.
# In a real-world scenario, you would dynamically load tools from an external source here.
- tools = []
- add_tool = Tool(
- name="add",
- description="Add two numbers",
- parameters={
- "type": "object",
- "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}},
- "required": ["a", "b"],
- },
- function=lambda a, b: a + b,
- )
-
- multiply_tool = Tool(
- name="multiply",
- description="Multiply two numbers",
- parameters={
- "type": "object",
- "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}},
- "required": ["a", "b"],
- },
- function=lambda a, b: a * b,
- )
-
- tools.append(add_tool)
- tools.append(multiply_tool)
-
- return tools
+ @tool
+ def add(a: Annotated[int, "first number"], b: Annotated[int, "second number"]) -> int:
+ '''Add two numbers.'''
+ return a + b
+
+ @tool
+ def multiply(a: Annotated[int, "first number"], b: Annotated[int, "second number"]) -> int:
+ '''Multiply two numbers.'''
+ return a * b
+
+ return [add, multiply]
def to_dict(self):
return {
@@ -1027,21 +1179,56 @@ class CalculatorToolset(Toolset):
def from_dict(cls, data):
return cls() # Recreate the tools dynamically during deserialization
-# Create the dynamic toolset and use it with ToolInvoker
+# Create the dynamic toolset and use it with an Agent
calculator_toolset = CalculatorToolset()
-invoker = ToolInvoker(tools=calculator_toolset)
+agent = Agent(chat_generator=OpenAIChatGenerator(), tools=calculator_toolset)
```
-Toolset implements the collection interface (__iter__, __contains__, __len__, __getitem__),
-making it behave like a list of Tools. This makes it compatible with components that expect
-iterable tools, such as ToolInvoker or Haystack chat generators.
+Toolset implements the collection interface (__iter__, __contains__, __len__, __getitem__), making it behave like
+a list of Tools. This makes it compatible with components that expect iterable tools, such as Agent or Haystack
+chat generators.
When implementing a custom Toolset subclass for dynamic tool loading:
- Perform the dynamic loading in the __init__ method
- Override to_dict() and from_dict() methods if your tools are defined dynamically
-- Serialize endpoint descriptors rather than tool instances if your tools
- are loaded from external sources
+- Serialize endpoint descriptors rather than tool instances if your tools are loaded from external sources
+
+#### get_selectable_tools
+
+```python
+get_selectable_tools() -> list[Tool]
+```
+
+Return the full set of tools that can be selected by name, ignoring any active name filter.
+
+This differs from iteration, which yields only the tools currently exposed (and respects the name filter).
+Override this when a Toolset's iteration does not surface every selectable tool, so name-based selection
+can still target the full set.
+
+Warms up the Toolset first if needed, so lazily loaded tools (those a Toolset fetches in `warm_up()`)
+are available for selection.
+
+**Returns:**
+
+- list\[Tool\] – The list of tools available for name-based selection.
+
+#### spawn
+
+```python
+spawn() -> Toolset
+```
+
+Return an isolated copy of this Toolset for a single run.
+
+The copy shares this Toolset's read-only state (its tools and any warmed-up resources) but gets fresh
+run-scoped state, so concurrent runs that share the same configured Toolset don't corrupt each other (for
+example, one run's name selection leaking into another). Warms up first if needed so the copy shares the
+warmed state. Subclasses with additional run-scoped state should override this.
+
+**Returns:**
+
+- Toolset – A run-scoped copy of this Toolset.
#### warm_up
@@ -1070,19 +1257,32 @@ class MCPToolset(Toolset):
self.mcp_connection = establish_connection(self.server_url)
```
-This method should be idempotent, as it may be called multiple times.
+This method is idempotent: it only warms up the tools the first time it is called.
+Subclasses overriding it should preserve this contract (for example by guarding on
+`self._is_warmed_up`).
#### add
```python
-add(tool: Union[Tool, Toolset]) -> None
+add(tool: Tool | Toolset) -> None
```
Add a new Tool or merge another Toolset.
+If this Toolset has already been warmed up, the newly added Tool (or the tools of the
+added Toolset) are warmed up immediately so they are ready to use without requiring a
+second `warm_up()` call on the whole Toolset.
+
+Note: adding a Toolset flattens it into its individual tools, so this is only recommended
+for Toolsets that don't manage shared resources in their `warm_up()` (or `__init__`).
+For example, combining with an `MCPToolset`, which owns a shared connection, is not
+recommended: the connection's lifecycle would no longer be managed by the original
+Toolset. In those cases combine Toolsets with `+` (which preserves each Toolset as a
+unit via `_ToolsetWrapper`) instead.
+
**Parameters:**
-- **tool** (Union\[Tool, Toolset\]) – A Tool instance or another Toolset to add
+- **tool** (Tool | Toolset) – A Tool instance or another Toolset to add
**Raises:**
diff --git a/docs-website/reference/haystack-api/utils_api.md b/docs-website/reference/haystack-api/utils_api.md
index 4b50d71ebdb..bcea35d8569 100644
--- a/docs-website/reference/haystack-api/utils_api.md
+++ b/docs-website/reference/haystack-api/utils_api.md
@@ -6,24 +6,6 @@ slug: "/utils-api"
---
-## asynchronous
-
-### is_callable_async_compatible
-
-```python
-is_callable_async_compatible(func: Callable) -> bool
-```
-
-Returns if the given callable is usable inside a component's `run_async` method.
-
-**Parameters:**
-
-- **func** (Callable) – The callable to check.
-
-**Returns:**
-
-- bool – True if the callable is compatible, False otherwise.
-
## auth
### SecretType
@@ -53,10 +35,10 @@ Encapsulates a secret used for authentication.
Usage example:
```python
-from haystack.components.generators import OpenAIGenerator
+from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.utils import Secret
-generator = OpenAIGenerator(api_key=Secret.from_token(""))
+generator = OpenAIChatGenerator(api_key=Secret.from_token(""))
```
#### from_token
@@ -281,6 +263,13 @@ deserialize_callable(callable_handle: str) -> Callable
Deserializes a callable given its full import path as a string.
+Every module path tried during resolution is checked against the
+deserialization allowlist (see `haystack.core.serialization_security`). Callables in modules
+outside the allowlist are rejected with a `DeserializationError` before any import is
+attempted. To allow a third-party module, extend the allowlist via
+`Pipeline.load(..., allowed_modules=[...])`, `allow_deserialization_module(...)`, or the
+`HAYSTACK_DESERIALIZATION_ALLOWLIST` environment variable.
+
**Parameters:**
- **callable_handle** (str) – The full path of the callable_handle
@@ -291,7 +280,8 @@ Deserializes a callable given its full import path as a string.
**Raises:**
-- DeserializationError – If the callable cannot be found
+- DeserializationError – If the module path is not on the deserialization allowlist, or if the callable cannot
+ be found.
## deserialization
@@ -800,6 +790,20 @@ Hello! I am {{user_name}}. Please describe the images.
{% endmessage %}
```
+This extension also provides an `{% insert %}` placeholder tag that evaluates an expression to a `ChatMessage`
+or a list of `ChatMessage` objects and expands it into the prompt, so a runtime conversation can be interleaved
+with literal `{% message %}` blocks:
+
+```
+{% message role="system" %}You are a helpful assistant.{% endmessage %}
+{% insert messages %}
+{% message role="user" %}{{ query }}{% endmessage %}
+```
+
+The expression can be a plain variable (`{% insert messages %}`), a slice or index
+(`{% insert messages[-1:] %}`, `{% insert messages[-1] %}`), or a combination of variables
+(`{% insert previous + current %}`).
+
### How it works
1. The `{% message %}` tag is used to define a chat message.
@@ -817,9 +821,9 @@ Hello! I am {{user_name}}. Please describe the images.
parse(parser: Any) -> nodes.Node | list[nodes.Node]
```
-Parse the message tag and its attributes in the Jinja2 template.
+Dispatch parsing based on the tag that triggered the extension.
-This method handles the parsing of role (mandatory), name (optional), meta (optional) and message body content.
+Handles both the single `{% message %}` block tag and the `{% insert %}` placeholder tag.
**Parameters:**
@@ -827,11 +831,7 @@ This method handles the parsing of role (mandatory), name (optional), meta (opti
**Returns:**
-- Node | list\[Node\] – A CallBlock node containing the parsed message configuration
-
-**Raises:**
-
-- TemplateSyntaxError – If an invalid role is provided
+- Node | list\[Node\] – A CallBlock node containing the parsed configuration
### templatize_part
@@ -1111,6 +1111,11 @@ This function will dynamically import the module if it's not already imported
and then retrieve the type object from it. It also handles nested generic types like
`list[dict[int, str]]`.
+Every module path with a `.` prefix is checked against the deserialization
+allowlist (see `haystack.core.serialization_security`) before being imported. Modules outside
+the allowlist are rejected with a `DeserializationError`. Builtin and `typing`/`collections`
+names without a module prefix bypass this check.
+
**Parameters:**
- **type_str** (str) – The string representation of the type's full import path.
@@ -1121,7 +1126,8 @@ and then retrieve the type object from it. It also handles nested generic types
**Raises:**
-- DeserializationError – If the type cannot be deserialized due to missing module or type.
+- DeserializationError – If the module is not on the deserialization allowlist, or if the type cannot be
+ deserialized due to a missing module or type.
### thread_safe_import
diff --git a/docs-website/reference/haystack-api/websearch_api.md b/docs-website/reference/haystack-api/websearch_api.md
deleted file mode 100644
index 67c85e1e40f..00000000000
--- a/docs-website/reference/haystack-api/websearch_api.md
+++ /dev/null
@@ -1,266 +0,0 @@
----
-title: "Websearch"
-id: websearch-api
-description: "Web search engine for Haystack."
-slug: "/websearch-api"
----
-
-
-## searchapi
-
-### SearchApiWebSearch
-
-Uses [SearchApi](https://www.searchapi.io/) to search the web for relevant documents.
-
-Usage example:
-
-
-
-```python
-from haystack.components.websearch import SearchApiWebSearch
-from haystack.utils import Secret
-
-websearch = SearchApiWebSearch(top_k=10, api_key=Secret.from_env_var("SEARCHAPI_API_KEY"))
-results = websearch.run(query="Who is the boyfriend of Olivia Wilde?")
-
-assert results["documents"]
-assert results["links"]
-```
-
-#### __init__
-
-```python
-__init__(
- api_key: Secret = Secret.from_env_var("SEARCHAPI_API_KEY"),
- top_k: int | None = 10,
- allowed_domains: list[str] | None = None,
- search_params: dict[str, Any] | None = None,
-) -> None
-```
-
-Initialize the SearchApiWebSearch component.
-
-**Parameters:**
-
-- **api_key** (Secret) – API key for the SearchApi API
-- **top_k** (int | None) – Number of documents to return.
-- **allowed_domains** (list\[str\] | None) – List of domains to limit the search to.
-- **search_params** (dict\[str, Any\] | None) – Additional parameters passed to the SearchApi API.
- For example, you can set 'num' to 100 to increase the number of search results.
- See the [SearchApi website](https://www.searchapi.io/) for more details.
-
-The default search engine is Google, however, users can change it by setting the `engine`
-parameter in the `search_params`.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> SearchApiWebSearch
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- SearchApiWebSearch – The deserialized component.
-
-#### run
-
-```python
-run(query: str) -> dict[str, list[Document] | list[str]]
-```
-
-Uses [SearchApi](https://www.searchapi.io/) to search the web.
-
-**Parameters:**
-
-- **query** (str) – Search query.
-
-**Returns:**
-
-- dict\[str, list\[Document\] | list\[str\]\] – A dictionary with the following keys:
-- "documents": List of documents returned by the search engine.
-- "links": List of links returned by the search engine.
-
-**Raises:**
-
-- TimeoutError – If the request to the SearchApi API times out.
-- SearchApiError – If an error occurs while querying the SearchApi API.
-
-#### run_async
-
-```python
-run_async(query: str) -> dict[str, list[Document] | list[str]]
-```
-
-Asynchronously uses [SearchApi](https://www.searchapi.io/) to search the web.
-
-This is the asynchronous version of the `run` method with the same parameters and return values.
-
-**Parameters:**
-
-- **query** (str) – Search query.
-
-**Returns:**
-
-- dict\[str, list\[Document\] | list\[str\]\] – A dictionary with the following keys:
-- "documents": List of documents returned by the search engine.
-- "links": List of links returned by the search engine.
-
-**Raises:**
-
-- TimeoutError – If the request to the SearchApi API times out.
-- SearchApiError – If an error occurs while querying the SearchApi API.
-
-## serper_dev
-
-### SerperDevWebSearch
-
-Uses [Serper](https://serper.dev/) to search the web for relevant documents.
-
-See the [Serper Dev website](https://serper.dev/) for more details.
-
-Usage example:
-
-
-
-```python
-from haystack.components.websearch import SerperDevWebSearch
-from haystack.utils import Secret
-
-serper_dev_api = Secret.from_env_var("SERPERDEV_API_KEY")
-
-websearch = SerperDevWebSearch(top_k=10, api_key=serper_dev_api)
-results = websearch.run(query="Who is the boyfriend of Olivia Wilde?")
-
-assert results["documents"]
-assert results["links"]
-
-# Example with domain filtering - exclude subdomains
-websearch_filtered = SerperDevWebSearch(
- top_k=10,
- allowed_domains=["example.com"],
- exclude_subdomains=True, # Only results from example.com, not blog.example.com
- api_key=serper_dev_api
-)
-results_filtered = websearch_filtered.run(query="search query")
-```
-
-#### __init__
-
-```python
-__init__(
- api_key: Secret = Secret.from_env_var("SERPERDEV_API_KEY"),
- top_k: int | None = 10,
- allowed_domains: list[str] | None = None,
- search_params: dict[str, Any] | None = None,
- *,
- exclude_subdomains: bool = False
-) -> None
-```
-
-Initialize the SerperDevWebSearch component.
-
-**Parameters:**
-
-- **api_key** (Secret) – API key for the Serper API.
-- **top_k** (int | None) – Number of documents to return.
-- **allowed_domains** (list\[str\] | None) – List of domains to limit the search to.
-- **exclude_subdomains** (bool) – Whether to exclude subdomains when filtering by allowed_domains.
- If True, only results from the exact domains in allowed_domains will be returned.
- If False, results from subdomains will also be included. Defaults to False.
-- **search_params** (dict\[str, Any\] | None) – Additional parameters passed to the Serper API.
- For example, you can set 'num' to 20 to increase the number of search results.
- See the [Serper website](https://serper.dev/) for more details.
-
-#### to_dict
-
-```python
-to_dict() -> dict[str, Any]
-```
-
-Serializes the component to a dictionary.
-
-**Returns:**
-
-- dict\[str, Any\] – Dictionary with serialized data.
-
-#### from_dict
-
-```python
-from_dict(data: dict[str, Any]) -> SerperDevWebSearch
-```
-
-Deserializes the component from a dictionary.
-
-**Parameters:**
-
-- **data** (dict\[str, Any\]) – The dictionary to deserialize from.
-
-**Returns:**
-
-- SerperDevWebSearch – The deserialized component.
-
-#### run
-
-```python
-run(query: str) -> dict[str, list[Document] | list[str]]
-```
-
-Use [Serper](https://serper.dev/) to search the web.
-
-**Parameters:**
-
-- **query** (str) – Search query.
-
-**Returns:**
-
-- dict\[str, list\[Document\] | list\[str\]\] – A dictionary with the following keys:
-- "documents": List of documents returned by the search engine.
-- "links": List of links returned by the search engine.
-
-**Raises:**
-
-- SerperDevError – If an error occurs while querying the SerperDev API.
-- TimeoutError – If the request to the SerperDev API times out.
-
-#### run_async
-
-```python
-run_async(query: str) -> dict[str, list[Document] | list[str]]
-```
-
-Asynchronously uses [Serper](https://serper.dev/) to search the web.
-
-This is the asynchronous version of the `run` method with the same parameters and return values.
-
-**Parameters:**
-
-- **query** (str) – Search query.
-
-**Returns:**
-
-- dict\[str, list\[Document\] | list\[str\]\] – A dictionary with the following keys:
-- "documents": List of documents returned by the search engine.
-- "links": List of links returned by the search engine.
-
-**Raises:**
-
-- SerperDevError – If an error occurs while querying the SerperDev API.
-- TimeoutError – If the request to the SerperDev API times out.