> ## Documentation Index
> Fetch the complete documentation index at: https://docs.siflow.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 工具调用（Function Calling）

> 了解算秩 Function Calling 的工具定义、tool_calls 流程、工具结果回传、参数校验和智能体应用实践。

工具调用（Function Calling）允许模型在合适的时候调用您定义的工具，并返回结构化的调用请求，说明要调用哪个工具、传入哪些参数。您的应用负责执行对应工具，并将执行结果返回给模型，模型再基于这些结果生成最终答案。

Function Calling 常用于构建智能体、检索系统，以及接入天气、数据库、内部 API 等外部系统。

该能力通过兼容 OpenAI 的调用方式提供。您可以在请求中传入 `tools` 数组，从响应中读取 `tool_calls`，再将工具执行结果以 `role: "tool"` 消息回传。

## 使用场景

* **实时数据**：查询天气、价格、库存或其他实时信息。
* **执行操作**：从自然语言创建工单、发送消息或触发工作流。
* **检索 / RAG**：让模型自行决定何时查询知识库或搜索 API。
* **智能体**：串联多次工具调用以完成多步骤任务。

## 支持的模型

平台上的大多数对话模型都支持这一能力，具体可通过 [模型广场](https://console.siflow.cn/model-inference/models) 查看。

## 工作机制

Function Calling 的完整流程通常包含两次模型调用：

1. 将用户消息和 `tools` 定义一起发送给模型。`tools` 中包含每个工具的名称、描述和参数 JSON Schema。
2. 如果模型决定调用工具，响应中会返回 `finish_reason: "tool_calls"`，并在 `message.tool_calls` 中给出调用信息。
3. 您的应用执行对应函数，再把 assistant 消息和一条带有匹配 `tool_call_id` 的 `role: "tool"` 消息追加到会话中。
4. 再次调用 API，模型会结合工具执行结果生成最终答案。

<Warning>
  模型只生成工具调用请求，不会替应用执行函数。实际函数执行、权限控制、参数校验和错误处理都需要由您的应用完成。
</Warning>

## 关键参数

* `tools`：工具定义数组，用于告诉模型有哪些工具可用。
* `tool_calls`：模型返回的工具调用请求，包含工具名称和参数。
* `tool_call_id`：工具调用 ID。回传工具结果时，需要使用该 ID 将结果与调用请求对应起来。
* `role: "tool"`：用于把工具执行结果回传给模型的消息角色。
* `tool_choice`：控制工具调用行为。可使用 `"auto"` 让模型自行决定，使用 `"none"` 禁止调用工具，也可以强制调用某个特定工具。

## 最佳实践

* **清晰描述工具**：使用明确的 `name`、`description` 和 `parameters` JSON Schema 描述每个工具。定义越清楚，模型调用越稳定。
* **校验模型生成的参数**：工具参数由模型生成。执行任何实际操作前，请先校验参数类型、取值范围和权限。
* **处理多个工具调用**：一次响应中的 `tool_calls` 可能包含多个调用项。请逐一执行，并在再次调用 API 前，为每个调用补充对应的 `role: "tool"` 消息。
* **保留调用关系**：回传工具结果时，必须使用匹配的 `tool_call_id`，否则模型无法可靠地把工具结果和调用请求对应起来。
* **预留 token 预算**：请合理设置 `max_completion_tokens`，预留足够空间。对于带推理能力的模型，思考过程本身也会消耗预算。

## 调用示例

示例使用环境变量读取 API Key，避免将密钥写入代码。

```bash theme={null}
export API_KEY="YOUR_API_KEY"
```

示例演示了 Function Calling 标准交互流程：

1. 模型在对话中自主判断并请求调用外部工具（如查询天气）。

2. 客户端在本地执行该工具并将结果返回给模型。

3. 模型最终结合工具返回的数据生成自然语言回复。

```python theme={null}
import os
import json
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["API_KEY"],
    base_url="https://api.siflow.cn/model-api",
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a city",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "City name",
                    }
                },
                "required": ["city"],
            },
        },
    }
]


def get_weather(city: str) -> dict:
    # Replace with a real API call.
    return {"city": city, "temp_c": 21, "condition": "Sunny"}


messages = [
    {"role": "user", "content": "What's the weather like in Paris today?"}
]

# 1. First call: the model decides whether to use the tool.
resp = client.chat.completions.create(
    model="Qwen/Qwen3-32B",
    messages=messages,
    tools=tools,
    tool_choice="auto",
    max_completion_tokens=1024,
)

msg = resp.choices[0].message

if msg.tool_calls:
    messages.append(msg)

    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = get_weather(**args)

        # 2. Return the tool result, linked by tool_call_id.
        messages.append(
            {
                "role": "tool",
                "tool_call_id": call.id,
                "content": json.dumps(result),
            }
        )

    # 3. Second call: the model writes the final answer.
    final = client.chat.completions.create(
        model="Qwen/Qwen3-32B",
        messages=messages,
        max_completion_tokens=1024,
    )

    print(final.choices[0].message.content)
else:
    print(msg.content)
```
