Chat Completions · 工具调用

OpenAI Chat Completions 函数调用与安全接入

使用 Chat Completions 的 tools 结构,不要混用 Responses。本文说明字段布局、后续回合,以及 401 探测无法证明的能力边界。

Chat Completions 工具调用实际做了什么

模型不会替你执行代码。它只返回结构化的 tool_calls;应用需要校验参数、运行白名单函数,再回传 role: tool 消息。模型生成的参数必须按不可信输入处理。

步骤Chat Completions 字段应用职责
1. 定义tools[].type = function 与 tools[].function只暴露允许调用的函数
2. 请求choices[0].message.tool_calls[]读取 id、function.name、function.arguments
3. 执行模型不会执行外部操作鉴权、校验、执行并记录
4. 继续追加 assistant 消息 + 匹配 tool_call_id 的 role: tool请求最终回答

先验证接口、Key 和模型

请求 GET /v1/models,再使用当前 Key 返回的准确模型 ID。2026 年 8 月 4 日,对 MonkeyAI 生产环境的探测结果如下:

这些结果只能证明路由和认证可达,不能证明某个模型支持 tools、strict 或并行调用。

curl -sS https://monkeytheme.com/v1/models \
  -H "Authorization: Bearer ***"
本次复核没有使用客户 Key 完成真实工具往返。涉及写入、支付、消息或账号操作前,请用计划上线的模型和 schema 在非生产流程中测试。

发送最小 Chat Completions 工具定义

在 Chat Completions 中,函数字段位于 tools[].function 下。OpenAI OpenAPI 将该结构命名为 ChatCompletionTool。函数名最长 64 个字符,建议只使用字母、数字、下划线和短横线。

curl -sS https://monkeytheme.com/v1/chat/completions \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "MODEL_ID_FROM_LIST",
  "messages": [
    {"role": "user", "content": "What is the weather in Paris?"}
  ],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Return current weather for a city.",
      "strict": true,
      "parameters": {
        "type": "object",
        "properties": {
          "city": {"type": "string"}
        },
        "required": ["city"],
        "additionalProperties": false
      }
    }
  }],
  "tool_choice": "auto"
}'

严格模式下,每个属性都要写入 required,且每个对象设置 additionalProperties: false。OpenAI 说明:Chat Completions 默认非 strict,需要显式设置 strict: true。

解析 tool_calls 并返回工具结果

当模型选择调用工具时,assistant 消息的 content 常常为空,finish_reason 多为 tool_calls,真正的调用在 message.tool_calls。先把该 assistant 消息追加进会话,再为每个 call ID 追加一条 tool 消息。

import json
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_KEY",
    base_url="https://monkeytheme.com/v1",
)

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Return current weather for a city.",
        "strict": True,
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
            "additionalProperties": False,
        },
    },
}]

messages = [{"role": "user", "content": "What is the weather in Paris?"}]
first = client.chat.completions.create(
    model="MODEL_ID_FROM_LIST",
    messages=messages,
    tools=tools,
    tool_choice="auto",
)

assistant = first.choices[0].message
messages.append(assistant)

for call in assistant.tool_calls or []:
    args = json.loads(call.function.arguments)
    result = dispatch_approved_function(call.function.name, args)
    messages.append({
        "role": "tool",
        "tool_call_id": call.id,
        "content": json.dumps(result),
    })

final = client.chat.completions.create(
    model="MODEL_ID_FROM_LIST",
    messages=messages,
    tools=tools,
)
print(final.choices[0].message.content)

dispatch_approved_function 是应用代码,不是 SDK 自带函数。OpenAI 也提醒:function.arguments 是 JSON 字符串,可能非法或编造 schema 外字段,执行前必须校验。

tool_choice 与 parallel_tool_calls

控制项Chat Completions 取值效果
自动"tool_choice": "auto"有 tools 时的默认值:可调用零个、一个或多个
必须调用"tool_choice": "required"必须调用一个或多个工具
禁用"tool_choice": "none"不调用工具,只返回文本
指定函数{"type":"function","function":{"name":"get_weather"}}强制调用该函数
关闭并行"parallel_tool_calls": false本轮最多一个工具调用

不要把 Responses 的指定函数写法 {"type":"function","name":"..."} 直接用于 Chat Completions。Chat Completions 的名称必须嵌套在 function 下。

不要混用 Chat Completions 与 Responses 结构

项目Chat CompletionsResponses
接口/v1/chat/completions/v1/responses
函数定义tools[].function.{name,description,parameters,strict}函数字段直接位于 tools 项内
返回调用choices[0].message.tool_calls[]output[] 中类型为 function_call 的项
关联字段tool 消息使用 tool_call_idfunction_call_output 使用 call_id
结果消息{"role":"tool", ...}function_call_output 输入项

如果示例来自 Responses,先改 schema,再把 Base URL 指到 /v1/chat/completions。

给执行器加上安全边界

资料与相关教程

常见问题

模型会直接执行函数吗?

不会。模型只返回结构化 tool_calls。应用决定是否执行,并把 role: tool 结果传回模型。

收到 401 能证明工具调用可用吗?

不能。401 只能证明请求到达认证层。应使用真实 Key 和准确模型 ID 测试 tools。

Chat Completions 的函数字段写在哪里?

写在 tools[].function 下。不要像 Responses 那样把 name/description/parameters 直接放在 tools 项根级。

如何关联工具结果?

把 message.tool_calls[].id 复制到下一条 role: tool 消息的 tool_call_id。ID 缺失或不匹配会打断后续回合。

一条 assistant 消息会包含多个 tool_calls 吗?

会。除非把 parallel_tool_calls 设为 false,否则应按零个、一个或多个调用处理,并遍历每一个 call。