Skip to content

OpenAI Tool Calls

请求结构

json
{
  "model": "gpt-4.1",
  "messages": [
    { "role": "user", "content": "帮我查上海天气" }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "获取指定城市天气",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {
              "type": "string",
              "description": "城市名"
            }
          },
          "required": ["city"]
        }
      }
    }
  ],
  "tool_choice": "auto"
}

响应结构

json
{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_123",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"city\":\"Shanghai\"}"
            }
          }
        ]
      }
    }
  ]
}

Python 完整闭环示例

python
from openai import OpenAI
import json

client = OpenAI()

def get_weather(city: str):
    return {"city": city, "temp": 25, "condition": "sunny"}

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "获取指定城市天气",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string"}
            },
            "required": ["city"]
        }
    }
}]

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

resp = client.chat.completions.create(
    model="gpt-4.1",
    messages=messages,
    tools=tools
)

msg = resp.choices[0].message
if msg.tool_calls:
    new_messages = list(messages)
    new_messages.append({
        "role": "assistant",
        "content": msg.content,
        "tool_calls": [tc.model_dump() for tc in msg.tool_calls]
    })

    for tc in msg.tool_calls:
        args = json.loads(tc.function.arguments)
        if tc.function.name == "get_weather":
            result = get_weather(**args)
        else:
            result = {"error": f"unknown tool {tc.function.name}"}

        new_messages.append({
            "role": "tool",
            "tool_call_id": tc.id,
            "content": json.dumps(result, ensure_ascii=False)
        })

    final_resp = client.chat.completions.create(
        model="gpt-4.1",
        messages=new_messages,
        tools=tools
    )
    print(final_resp.choices[0].message.content)

常见注意点

arguments 是字符串

function.arguments 很多时候是 JSON 字符串,不是已经解析好的对象。

tool_choice 不同模式的含义

  • auto:模型自己判断
  • none:完全不调用
  • required:至少调用一个
  • 指定函数:强制某个工具

不要相信模型一定传对参数

即使 schema 写得很好,也仍然应该在宿主侧做:

  • JSON 解析保护
  • 类型校验
  • 字段默认值处理
  • 非法值拦截

聚焦 OpenClaw、tool_calls、function calling 与 agent 实战。