加载中

在使用Claude的工具调用能力时,您可能会注意到Claude可以在单个助手消息中包含多个工具使用块。这使得Claude能够并行运行多个工具,而不是为每个工具分别发出请求。然而,在实践中要让Claude始终如一地做到这一点可能具有挑战性。

多次工具调用的问题

假设您要求Claude为同一天设置两个提醒。理论上,Claude应该能够发回一个包含两个工具使用块的单一响应——每个提醒对应一个。但实际上,Claude通常会发送多个独立的响应。

理想的交互:一条助手消息中包含两个针对1月1日的set_reminder工具使用,分别是"Taxes due"和"Doctors appointment"。

通常发生的情况是,Claude先进行第一次工具调用,等待结果,然后在后续消息中进行第二次工具调用。这会造成不必要的来回通信,而这些操作本可以同时完成。

Claude用一次batch_tool调用回应了我们服务器发出的两个提醒请求:为"Dr appt"和"Taxes due"设置set_reminder。

批处理工具解决方案

解决方案是实现一个"批处理工具"——一种特殊的工具,它接受一个包含其他工具调用的列表,以便同时执行。这本质上是一种变通方法,用来诱使Claude一次性进行多个工具调用。

Claude用一次batch_tool调用回应了我们服务器发出的两个提醒请求:为"Dr appt"和"Taxes due"设置set_reminder。

其工作原理如下:

  • 您定义一个批处理工具模式(schema),告诉Claude它可以并行运行多个其他工具
  • Claude不再直接调用工具,而是调用批处理工具,并附带一个工具调用列表
  • 您的代码处理该列表并执行每个工具调用
  • 您将合并后的结果返回给Claude

实现批处理工具模式

批处理工具模式定义了当Claude想要运行多个工具时,应如何构建其请求:

python
batch_tool_schema = {
    "name": "batch_tool",
    "description": "Invoke multiple other tool calls simultaneously",
    "input_schema": {
        "type": "object",
        "properties": {
            "invocations": {
                "type": "array",
                "description": "The tool calls to invoke",
                "items": {
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "description": "The name of the tool to invoke"
                        },
                        "arguments": {
                            "type": "object",
                            "description": "The arguments to pass to the tool"
                        }
                    }
                }
            }
        }
    }
}

处理批处理工具调用

当Claude使用批处理工具时,您需要处理调用列表并执行每一个调用。以下是实现方式:

python
def run_batch(invocations=[]):
    batch_output = []
    
    for invocation in invocations:
        name = invocation["name"]
        args = invocation["arguments"]
        
        tool_output = run_tool(name, args)
        
        batch_output.append({
            "tool_name": name,
            "output": tool_output
        })
    
    return batch_output

您还需要更新主工具路由函数,以处理批处理工具调用:

python
def run_tool(tool_name, tool_input):
    if tool_name == "get_current_datetime":
        return get_current_datetime(**tool_input)
    elif tool_name == "add_duration_to_datetime":
        return add_duration_to_datetime(**tool_input)
    elif tool_name == "set_reminder":
        return set_reminder(**tool_input)
    elif tool_name == "batch_tool":
        return run_batch(**tool_input)

结果

实现批处理工具后,Claude更有可能将相关操作归为一组。Claude不会为每个提醒分别发出请求,而是会使用批处理工具同时设置两个提醒。

对话流程变得更加简洁——用户发出一个请求,Claude用批处理工具调用做出一个响应,然后再跟进一次包含所有结果的消息。这减少了延迟,使您的应用程序更高效。

虽然这看起来像是一种变通方法(事实也确实如此),但批处理工具模式是一种有效的方式,可以促使Claude思考哪些操作可以并行化,并更高效地执行它们。