mirror of
https://github.com/deepset-ai/haystack.git
synced 2025-12-17 10:09:13 +00:00
308 lines
10 KiB
Markdown
308 lines
10 KiB
Markdown
|
|
---
|
||
|
|
title: Tool Components
|
||
|
|
id: tool-components-api
|
||
|
|
description: Components related to Tool Calling.
|
||
|
|
---
|
||
|
|
|
||
|
|
<a id="tool_invoker"></a>
|
||
|
|
|
||
|
|
# Module tool\_invoker
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolInvokerError"></a>
|
||
|
|
|
||
|
|
## ToolInvokerError
|
||
|
|
|
||
|
|
Base exception class for ToolInvoker errors.
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolNotFoundException"></a>
|
||
|
|
|
||
|
|
## ToolNotFoundException
|
||
|
|
|
||
|
|
Exception raised when a tool is not found in the list of available tools.
|
||
|
|
|
||
|
|
<a id="tool_invoker.StringConversionError"></a>
|
||
|
|
|
||
|
|
## StringConversionError
|
||
|
|
|
||
|
|
Exception raised when the conversion of a tool result to a string fails.
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolOutputMergeError"></a>
|
||
|
|
|
||
|
|
## ToolOutputMergeError
|
||
|
|
|
||
|
|
Exception raised when merging tool outputs into state fails.
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolOutputMergeError.from_exception"></a>
|
||
|
|
|
||
|
|
#### ToolOutputMergeError.from\_exception
|
||
|
|
|
||
|
|
```python
|
||
|
|
@classmethod
|
||
|
|
def from_exception(cls, tool_name: str,
|
||
|
|
error: Exception) -> "ToolOutputMergeError"
|
||
|
|
```
|
||
|
|
|
||
|
|
Create a ToolOutputMergeError from an exception.
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolInvoker"></a>
|
||
|
|
|
||
|
|
## 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=<ChatRole.TOOL: 'tool'>,
|
||
|
|
>> _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)
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolInvoker.__init__"></a>
|
||
|
|
|
||
|
|
#### ToolInvoker.\_\_init\_\_
|
||
|
|
|
||
|
|
```python
|
||
|
|
def __init__(tools: Union[list[Tool], Toolset],
|
||
|
|
raise_on_failure: bool = True,
|
||
|
|
convert_result_to_json_string: bool = False,
|
||
|
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
||
|
|
*,
|
||
|
|
enable_streaming_callback_passthrough: bool = False,
|
||
|
|
max_workers: int = 4)
|
||
|
|
```
|
||
|
|
|
||
|
|
Initialize the ToolInvoker component.
|
||
|
|
|
||
|
|
**Arguments**:
|
||
|
|
|
||
|
|
- `tools`: A list of tools that can be invoked or a Toolset instance that can resolve tools.
|
||
|
|
- `raise_on_failure`: 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`: 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`: 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`: 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`: 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.
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolInvoker.run"></a>
|
||
|
|
|
||
|
|
#### ToolInvoker.run
|
||
|
|
|
||
|
|
```python
|
||
|
|
@component.output_types(tool_messages=list[ChatMessage], state=State)
|
||
|
|
def run(messages: list[ChatMessage],
|
||
|
|
state: Optional[State] = None,
|
||
|
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
||
|
|
*,
|
||
|
|
enable_streaming_callback_passthrough: Optional[bool] = None,
|
||
|
|
tools: Optional[Union[list[Tool], Toolset]] = None) -> dict[str, Any]
|
||
|
|
```
|
||
|
|
|
||
|
|
Processes ChatMessage objects containing tool calls and invokes the corresponding tools, if available.
|
||
|
|
|
||
|
|
**Arguments**:
|
||
|
|
|
||
|
|
- `messages`: A list of ChatMessage objects.
|
||
|
|
- `state`: The runtime state that should be used by the tools.
|
||
|
|
- `streaming_callback`: 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`: 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`: A list of tools to use for the tool invoker. If set, overrides the tools set in the constructor.
|
||
|
|
|
||
|
|
**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.
|
||
|
|
|
||
|
|
**Returns**:
|
||
|
|
|
||
|
|
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.
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolInvoker.run_async"></a>
|
||
|
|
|
||
|
|
#### ToolInvoker.run\_async
|
||
|
|
|
||
|
|
```python
|
||
|
|
@component.output_types(tool_messages=list[ChatMessage], state=State)
|
||
|
|
async def run_async(
|
||
|
|
messages: list[ChatMessage],
|
||
|
|
state: Optional[State] = None,
|
||
|
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
||
|
|
*,
|
||
|
|
enable_streaming_callback_passthrough: Optional[bool] = None,
|
||
|
|
tools: Optional[Union[list[Tool], Toolset]] = None) -> dict[str, Any]
|
||
|
|
```
|
||
|
|
|
||
|
|
Asynchronously processes ChatMessage objects containing tool calls.
|
||
|
|
|
||
|
|
Multiple tool calls are performed concurrently.
|
||
|
|
|
||
|
|
**Arguments**:
|
||
|
|
|
||
|
|
- `messages`: A list of ChatMessage objects.
|
||
|
|
- `state`: The runtime state that should be used by the tools.
|
||
|
|
- `streaming_callback`: 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`: 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`: A list of tools to use for the tool invoker. If set, overrides the tools set in the constructor.
|
||
|
|
|
||
|
|
**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.
|
||
|
|
|
||
|
|
**Returns**:
|
||
|
|
|
||
|
|
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.
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolInvoker.to_dict"></a>
|
||
|
|
|
||
|
|
#### ToolInvoker.to\_dict
|
||
|
|
|
||
|
|
```python
|
||
|
|
def to_dict() -> dict[str, Any]
|
||
|
|
```
|
||
|
|
|
||
|
|
Serializes the component to a dictionary.
|
||
|
|
|
||
|
|
**Returns**:
|
||
|
|
|
||
|
|
Dictionary with serialized data.
|
||
|
|
|
||
|
|
<a id="tool_invoker.ToolInvoker.from_dict"></a>
|
||
|
|
|
||
|
|
#### ToolInvoker.from\_dict
|
||
|
|
|
||
|
|
```python
|
||
|
|
@classmethod
|
||
|
|
def from_dict(cls, data: dict[str, Any]) -> "ToolInvoker"
|
||
|
|
```
|
||
|
|
|
||
|
|
Deserializes the component from a dictionary.
|
||
|
|
|
||
|
|
**Arguments**:
|
||
|
|
|
||
|
|
- `data`: The dictionary to deserialize from.
|
||
|
|
|
||
|
|
**Returns**:
|
||
|
|
|
||
|
|
The deserialized component.
|