Anthropic Function Calling 工具调用

FreeGuideOnline 最新 2026-07-12

json { "name": "get_weather", "description": "获取指定城市的当前天气", "input_schema": { "type": "object", "properties": { "location": { "type": "string", "description": "城市名称,例如“北京”" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位" } }, "required": ["location"] } }


### 工具调用流程
1. **发起请求**:向 Messages API 发送用户消息,并在请求中附上 `tools` 列表。
2. **模型响应**:如果模型认为需要调用工具,返回的消息会设置 `stop_reason` 为 `"tool_use"`,并在 `content` 数组中包含一个 `type` 为 `"tool_use"` 的块,内含 `id`、`name` 和 `input`(JSON 对象)。
3. **执行函数**:你的代码根据 `name` 和 `input` 执行实际函数,并获取结果。
4. **返回结果**:将执行结果作为一条新的用户消息 (`role: "user"`) 发送回 API,内容是一个 `type` 为 `"tool_result"` 的块,并带上对应的 `tool_use_id`。
5. **生成最终回复**:模型结合工具输出生成面向用户自然语言回复。

## 接入步骤

### 1. 安装与认证
使用 Anthropic Python SDK 或直接调用 API。确保已安装:
```bash
pip install anthropic

初始化客户端:

import anthropic

client = anthropic.Anthropic(api_key="your-api-key")

2. 定义工具并发送请求

将工具列表作为参数传入 messages.create

response = client.messages.create(
    model="claude-3-5-sonnet-20240620",
    max_tokens=1024,
    tools=[
        {
            "name": "get_weather",
            "description": "获取指定城市的当前天气",
            "input_schema": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市名称"
                    }
                },
                "required": ["location"]
            }
        }
    ],
    messages=[
        {"role": "user", "content": "北京今天天气如何?"}
    ]
)

3. 解析模型返回的工具调用

检查 stop_reason 是否为 "tool_use",然后提取工具调用块:

if response.stop_reason == "tool_use":
    tool_use = next(block for block in response.content if block.type == "tool_use")
    function_name = tool_use.name
    function_args = tool_use.input
    tool_use_id = tool_use.id

4. 执行函数并提交结果

模拟天气查询:

def get_weather(location):
    # 实际应用中调用真实 API
    return f"{location}当前晴天,25°C"

tool_result = get_weather(**function_args)

# 将结果封装为消息
tool_result_message = {
    "role": "user",
    "content": [
        {
            "type": "tool_result",
            "tool_use_id": tool_use_id,
            "content": tool_result
        }
    ]
}

5. 继续对话获取最终回复

将结果消息附加到历史记录中再次请求:

final_response = client.messages.create(
    model="claude-3-5-sonnet-20240620",
    max_tokens=1024,
    tools=[...], # 可以保留或移除
    messages=[
        {"role": "user", "content": "北京今天天气如何?"},
        {"role": "assistant", "content": response.content},  # 模型上一条回复
        tool_result_message
    ]
)
print(final_response.content[0].text)

高级特性

强制工具调用

通过在请求中添加 tool_choice 参数,可以强制模型必须调用某个工具,或自主决定。

tool_choice = {"type": "tool", "name": "get_weather"}

或者允许模型自行决定(默认):

tool_choice = {"type": "auto"}

并行工具调用

Claude 支持在单次响应中返回多个工具调用块。你的代码需要依次执行所有工具,并将所有结果作为一条用户消息(包含多个 tool_result 块)一次性返回。

错误处理

如果工具执行失败,可以将错误信息作为 content 返回,并可添加 is_error: true 标记:

{
  "type": "tool_result",
  "tool_use_id": "toolu_xxxx",
  "content": "Error: API timeout",
  "is_error": true
}

模型会据此调整回复,例如告知用户操作失败。

工具定义最佳实践

  • 描述需精准:描述越具体,模型越能正确选择工具。避免模糊用语。
  • 参数类型明确:使用 JSON Schema 的 type, enum, description 等关键字约束输入。
  • 减少歧义:如果两个工具功能易混淆,在描述中强调区分点。
  • 保护隐私:不要在工具描述中植入敏感数据,所有参数值由模型动态生成。

完整代码示例

import anthropic

client = anthropic.Anthropic()

def get_weather(location: str):
    # 模拟实现
    return f"{location}天气晴朗,22°C"

tools = [
    {
        "name": "get_weather",
        "description": "获取城市天气",
        "input_schema": {
            "type": "object",
            "properties": {
                "location": {"type": "string", "description": "城市名"}
            },
            "required": ["location"]
        }
    }
]

messages = [{"role": "user", "content": "上海的天气怎么样?"}]

response = client.messages.create(
    model="claude-3-5-sonnet-20240620",
    max_tokens=1024,
    tools=tools,
    messages=messages
)

while response.stop_reason == "tool_use":
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            func_name = block.name
            func_args = block.input
            tool_use_id = block.id
            result = get_weather(**func_args)
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": tool_use_id,
                "content": result
            })
    # 将 assistant 消息和工具结果都加入历史
    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": tool_results})
    
    response = client.messages.create(
        model="claude-3-5-sonnet-20240620",
        max_tokens=1024,
        tools=tools,
        messages=messages
    )

print(response.content[0].text)