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

# 函数调用

> OpenAI Tools / Claude Tool Use / Gemini Function Calling 的统一指南

函数调用(也叫 **工具调用 / Tool Use**)允许模型在生成回复过程中要求执行外部函数,
用于查询数据库、调用 API、读写文件等动作。OpenPAI 三套协议都完整支持,且可互通。

## OpenAI 协议

```python theme={null}
from openai import OpenAI
client = OpenAI(api_key="sk-...", base_url="https://openp.ai/v1")

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

resp = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "上海天气"}],
    tools=tools,
)

call = resp.choices[0].message.tool_calls[0]
print(call.function.name, call.function.arguments)
```

执行函数后,把结果回传:

```python theme={null}
messages = [
    {"role": "user", "content": "上海天气"},
    resp.choices[0].message,            # assistant 含 tool_calls
    {"role": "tool", "tool_call_id": call.id, "content": "上海 26°C 晴"},
]
final = client.chat.completions.create(model="gpt-5.5", messages=messages)
print(final.choices[0].message.content)
```

### tool\_choice

| 值                                                 | 行为       |
| ------------------------------------------------- | -------- |
| `"auto"`(默认)                                      | 模型自主决定   |
| `"none"`                                          | 强制不调用工具  |
| `"required"`                                      | 必须调用某个工具 |
| `{"type": "function", "function": {"name": "x"}}` | 指定调用某个工具 |

### parallel\_tool\_calls

新模型默认支持并行调用多个工具,响应中 `tool_calls` 是数组,需逐个执行后一次性回传。
若需禁用并行,设置 `parallel_tool_calls: false`。

## Claude 协议

```python theme={null}
from anthropic import Anthropic
client = Anthropic(api_key="sk-...", base_url="https://openp.ai")

resp = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=[{
        "name": "get_weather",
        "description": "Get weather",
        "input_schema": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    }],
    messages=[{"role": "user", "content": "上海天气"}],
)

# 找到 tool_use block
for block in resp.content:
    if block.type == "tool_use":
        result = call_my_weather(block.input["city"])
        followup = client.messages.create(
            model="claude-opus-4-8",
            max_tokens=1024,
            messages=[
                {"role": "user", "content": "上海天气"},
                {"role": "assistant", "content": resp.content},
                {"role": "user", "content": [{
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result,
                }]},
            ],
        )
```

### tool\_choice(Claude)

```json theme={null}
{"type": "auto"}                      // 默认
{"type": "any"}                       // 必须调用某个工具
{"type": "tool", "name": "x"}         // 指定工具
{"type": "none"}                      // 禁用工具
```

## Gemini 协议

```python theme={null}
from google import genai
from google.genai import types

client = genai.Client(api_key="sk-...", http_options={"base_url": "https://openp.ai"})

weather_tool = types.Tool(function_declarations=[
    types.FunctionDeclaration(
        name="get_weather",
        description="Get weather",
        parameters={
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    )
])

resp = client.models.generate_content(
    model="gemini-3.1-pro-preview",
    contents="上海天气",
    config=types.GenerateContentConfig(tools=[weather_tool]),
)

for part in resp.candidates[0].content.parts:
    if part.function_call:
        print(part.function_call.name, part.function_call.args)
```

回传:

```python theme={null}
function_response = types.Part(function_response=types.FunctionResponse(
    name="get_weather",
    response={"city": "上海", "temp": 26}
))

followup = client.models.generate_content(
    model="gemini-3.1-pro-preview",
    contents=[
        types.Content(role="user", parts=[types.Part(text="上海天气")]),
        resp.candidates[0].content,
        types.Content(role="user", parts=[function_response]),
    ],
)
```

## 协议互通

通过 OpenPAI 的 **OpenAI 兼容端点** 调用 Claude / Gemini 模型时,
OpenPAI 会自动将 Anthropic / Google 的工具调用结构转换为 OpenAI 的 `tools` / `tool_calls`,
反向亦然。你 **无需** 关心协议差异,只需选择一套写法即可。

## 最佳实践

<CardGroup cols={2}>
  <Card title="详细 description" icon="pen">
    工具的 `description` 越具体,模型越能正确决定何时调用与传什么参数。
  </Card>

  <Card title="严格 schema" icon="shield">
    使用 `required` 与 `additionalProperties: false`,避免模型乱传字段。
  </Card>

  <Card title="错误优雅处理" icon="circle-exclamation">
    工具执行失败时,把错误信息以 `tool_result` 形式回传,模型可重试或换策略。
  </Card>

  <Card title="并行调用" icon="layer-group">
    多个相互独立的工具一次调用并行执行,降低延迟。
  </Card>
</CardGroup>
