文档API 参考📓 教程🧑‍🍳 食谱🤝 集成💜 Discord🎨 Studio
文档

ToolInvoker

该组件 旨在 执行 由 语言模型 准备的 工具 调用。它 充当 语言模型 输出 与 实际 执行 执行 特定 任务的 函数 或 工具 之间的 桥梁。

pipeline 中的最常见位置在聊天生成器之后
必需的初始化变量“tools”:一个可调用的Tools列表
强制运行变量“messages”:一个由聊天生成器生成的包含工具调用的ChatMessage对象列表
输出变量“tool_messages”:一个列表,包含ChatMessage具有工具角色的对象。每个ChatMessage对象封装了工具调用的结果。
API 参考Tools (工具)
GitHub 链接https://github.com/deepset-ai/haystack/blob/main/haystack/components/tools/tool_invoker.py

概述

一个 ToolInvoker 是一个 组件,它处理 ChatMessage 对象(包含工具调用)。它 调用 相应的 工具,并将 结果 作为 一个 包含 ChatMessage 对象的列表返回。每个 工具 都 定义了 一个 名称、描述、参数 和一个 执行 该 任务的 函数。该 ToolInvoker 负责 管理 这些 工具 并 处理 调用 过程。

您可以将多个工具传递给ToolInvoker组件,它将根据语言模型生成的工具调用自动选择正确的工具进行调用。

ToolInvoker有两个额外的有用参数:

  • convert_result_to_json_string:使用json.dumps(为 True 时)或str(为 False 时)将结果转换为字符串。
  • raise_on_failure:如果为 True,将在发生错误时引发异常。如果为 False,将返回一个ChatMessage对象,其中error=True,并在result中包含错误的描述。例如,当您想让语言模型在循环中运行并修复其错误时,可以使用此选项。

📘

ChatMessage 和 Tool 数据类

点击链接了解更多关于 ChatMessageTool 数据类的信息。

用法

单独使用

from haystack.dataclasses import ChatMessage, ToolCall
from haystack.components.tools import ToolInvoker
from haystack.tools import Tool

# 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={}
>>          )
>>      ]
>>  }

在 pipeline 中

以下代码片段展示了如何处理用户关于天气的查询。首先,我们定义一个用于获取天气数据的Tool,然后初始化一个ToolInvoker来执行此工具,同时使用一个OpenAIChatGenerator来生成响应。一个ConditionalRouter用于此管道,根据消息是否包含工具调用来路由消息。该管道连接了这些组件,处理了用户询问柏林天气状况的消息,并输出了结果。

from haystack.dataclasses import ChatMessage
from haystack.components.tools import ToolInvoker
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.routers import ConditionalRouter
from haystack.tools import Tool
from haystack import Pipeline
from typing import List  # Ensure List is imported

# Define a dummy weather tool
import random

def dummy_weather(location: str):
    return {"temp": f"{random.randint(-10, 40)} °C",
            "humidity": f"{random.randint(0, 100)}%"}

weather_tool = Tool(
    name="weather",
    description="A tool to get the weather",
    function=dummy_weather,
    parameters={
        "type": "object",
        "properties": {"location": {"type": "string"}},
        "required": ["location"],
    },
)

# Initialize the ToolInvoker with the weather tool
tool_invoker = ToolInvoker(tools=[weather_tool])

# Initialize the ChatGenerator
chat_generator = OpenAIChatGenerator(model="gpt-4o-mini", tools=[weather_tool])

# Define routing conditions
routes = [
    {
        "condition": "{{replies[0].tool_calls | length > 0}}",
        "output": "{{replies}}",
        "output_name": "there_are_tool_calls",
        "output_type": List[ChatMessage],  # Use direct type
    },
    {
        "condition": "{{replies[0].tool_calls | length == 0}}",
        "output": "{{replies}}",
        "output_name": "final_replies",
        "output_type": List[ChatMessage],  # Use direct type
    },
]

# Initialize the ConditionalRouter
router = ConditionalRouter(routes, unsafe=True)

# Create the pipeline
pipeline = Pipeline()
pipeline.add_component("generator", chat_generator)
pipeline.add_component("router", router)
pipeline.add_component("tool_invoker", tool_invoker)

# Connect components
pipeline.connect("generator.replies", "router")
pipeline.connect("router.there_are_tool_calls", "tool_invoker.messages")  # Correct connection

# Example user message
user_message = ChatMessage.from_user("What is the weather in Berlin?")

# Run the pipeline
result = pipeline.run({"messages": [user_message]})

# Print the result
print(result)
{
   "tool_invoker":{
      "tool_messages":[
         "ChatMessage(_role=<ChatRole.TOOL":"tool"">",
         "_content="[
            "ToolCallResult(result=""{'temp': '33 °C', 'humidity': '79%'}",
            "origin=ToolCall(tool_name=""weather",
            "arguments="{
               "location":"Berlin"
            },
            "id=""call_pUVl8Cycssk1dtgMWNT1T9eT"")",
            "error=False)"
         ],
         "_name=None",
         "_meta="{
            
         }")"
      ]
   }
}

其他参考资料

🧑‍🍳食谱