← 返回技术博客

OpenAI GPT 2026:Function Calling、Structured Outputs 与 JSON Schema 变了什么

OpenAI GPT 2026:Function Calling、Structured Outputs 与 JSON Schema 变了什么

2026 年维护 OpenAI Agent 的团队,最容易踩的坑不是「模型会不会说话」,而是旧代码仍把 json_object 当成结构化输出,或在 Chat Completions 上沿用非严格 Function Calling。新项目官方推荐从 gpt-5.6 起步;Function Calling 与 Structured Outputs 底层都是约束解码,但入口、默认 strict 行为和 JSON Schema 子集并不相同。

核对日期为 2026 年 8 月 18 日,字段与行为以 OpenAI Function Calling 指南Structured Outputs 指南 为准。本文不虚构延迟、价格或成功率;公开文档没写死的地方会标明「需用现网回放确认」。

如果你正在把 OpenAI 兼容后端切到其它模型,结构化输出和工具循环必须单独验收,不能只换 Base URL。可对照站内的 OpenAI API 迁移 Kimi K3 验收清单

先看结论:三件事同时变了

很多仓库还停在 2024 年的心智模型:提示词里写「请返回 JSON」、再正则抠代码块。2026 年生产链路里,这条路会被 Schema 违约、缺字段、enum 幻觉 直接打穿解析器。

真正要改的是三层,而不是再换一个更大的模型名:

交货合同
最终给用户或下游服务的对象,用 Structured Outputs(Responses 里是 text.format,Chat Completions 里是 response_format.json_schema)。
执行合同
模型要调用你的工具时,参数必须贴合工具自己的 JSON Schema;这就是 Function Calling,底层与 Structured Outputs 同一套约束解码。
兼容合同
旧的 JSON Mode(json_object)只保证「看起来像 JSON」,不保证字段、类型、enum 与 Schema 一致。官方已把它定位成 Structured Outputs 的前身,新项目不要再用它当主路径。

另外还有一条容易漏掉的产品线变化:新代码应走 Responses API。Chat Completions 仍可用,但 strict 的默认策略不同——Responses 会尽量把 Schema 规范化成严格模式,失败才回退;Chat Completions 默认仍是非严格、尽力而为。

模型与 API 主路:gpt-5.6 + Responses

Structured Outputs 从 GPT-4o 一代开始可用;官方对新项目的建议是直接用 gpt-5.6。更老的 gpt-4-turbo 及更早快照,文档仍指向 JSON Mode,而不是完整的 json_schema 严格输出。

选型时先分清两套入口

你要的结果 该用的入口 2026 年注意点
给用户/下游一个固定对象 Responses:text.format;或 Chat Completions:response_format: json_schema 打开 strict: true;SDK 可用 Pydantic / Zod + parse()
让模型调用你的函数、查库、改状态 tools 里的 function tool 工具参数 Schema 同样走 strict;并行调用、多工具循环要自己写执行器
工具面太大,不想一次塞进上下文 tool_search 延迟加载 gpt-5.4 及更新模型支持;工具定义会计入输入 token
参数不是 JSON,而是自由文本或特定文法 custom tools + 可选 CFG 适合 DSL、查询语言;不要硬套 function JSON Schema

SDK 侧更值得养成的习惯:不要手写一份容易漏 additionalProperties 的 Schema,而是用官方 helper 从类型生成。Python 走 client.responses.parse(..., text_format=YourModel);JavaScript 走 zodTextFormat。手写 Schema 时,strict: true 不满足约束会直接 请求被拒,而不是「模型随便输出再让你重试」。

和 Gemini 路线对比时,不要把「兼容 OpenAI SDK」理解成 Schema 行为也一样。Google 的能力升级路径见 Gemini 3.5 Pro 的 10 项能力升级;跨厂商拷贝同一份 JSON Schema 时,嵌套对象的 additionalProperties 规则经常是第一个炸点。

JSON Mode、Structured Outputs、Function Calling

生产事故里最常见的混淆是:日志里确实是 JSON,于是以为 Structured Outputs 已经生效。下表按官方语义拆开:

能力 保证合法 JSON 保证贴合 Schema 典型启用方式 适用模型
JSON Mode text.format.type = json_object 含部分 GPT-5 兼容档;老快照常用
Structured Outputs 是(受支持的 Schema 子集) json_schema + strict: true gpt-4o-2024-08-06 / gpt-4o-mini 及之后,新项目用 gpt-5.6
Function Calling + strict 工具参数是合法 JSON 工具参数贴合 parameters Schema tools 里 strict: true 支持 tools 的模型;推荐始终开 strict

什么时候不该用 Function Calling

如果模型不需要碰你的系统(不查库存、不改工单、不跑脚本),只是要把回答拆成卡片、步骤、评分,那就用 Structured Outputs。反过来,只要输出是「请帮我执行这个副作用」,就必须走 tools,而不是把函数参数伪装成最终回答 Schema。

拒答不再是「坏 JSON」

安全拒答时,模型不会硬塞进你的 Schema。Responses / Chat Completions 会给出独立的 refusal 字段。解析层要把拒答当成一等公民:先看 refusal,再 output_parsed,不要把空对象当成功。

Strict JSON Schema 的硬规则

开启 strict 之后,OpenAI 接受的是 JSON Schema 的子集,不是任意 Draft 2020-12 文档。请求级最常撞墙的三条:

  1. properties 里出现的每个字段,都必须出现在 required 数组。
  2. 每个 object(含嵌套)都必须 additionalProperties: false
  3. 根对象不能是 anyOf;可选语义用「必填 + 允许 null」表达,例如 ["string", "null"]

也就是说:把字段从 required 里拿掉,假装它是可选 这条旧技巧在 strict 下会直接 400。正确写法是字段仍 required,类型写成可空联合,应用层把 null 当成「未提供」。

下面这段是生产里常见的「抽取工单」对象,注意嵌套 object 也写了 additionalProperties

from openai import OpenAI
from pydantic import BaseModel

client = OpenAI()

class Ticket(BaseModel):
    title: str
    priority: str
    assignee: str | None
    tags: list[str]

response = client.responses.parse(
    model="gpt-5.6",
    input=[
        {"role": "system", "content": "从用户描述中抽取工单字段。"},
        {"role": "user", "content": "登录页 500,指派给 Noah,优先级高,标签 auth 与 api。"},
    ],
    text_format=Ticket,
)
ticket = response.output_parsed
print(ticket.title, ticket.priority, ticket.assignee)
Schema 合规 ≠ 业务正确
约束解码保证类型、必填键和 enum 取值集合;它不保证优先级真的该是 high,也不保证工号存在。下游仍要做权限、存在性和幂等校验。

调试时若请求被拒,优先看错误信息里缺的是哪条约束,而不是先降模型。Playground 生成的 Schema 默认已开 strict,把它原样拷进仓库通常比「从旧 json_object 提示词改造」更快。

跨厂商时再核对一次:同一份「每个 object 都 false」的 Schema,在部分兼容网关或其它模型上可能变成 HTTP 400。这时应做按提供商变换,而不是维护三份业务 Schema。

Function Calling 2026:strict、tool_search、custom tools

官方现在把 Function Calling 与 tool calling 当作同一件事:用 JSON Schema 描述可调用函数,再用应用侧执行器跑副作用。2026 年文档里新增或被强调的几条,会直接改你的 Agent 循环。

strict 的默认值不要靠猜

  • 建议始终显式 strict: true
  • Responses:省略 strict 时,服务端会尝试规范化 Schema;规范化失败则回退非严格,响应里的 tool 会显示 strict: false
  • Chat Completions:省略时默认非严格。
  • 微调模型若一轮调用多个函数,文档写明该轮可能关闭 strict。

工具定义会计入上下文并按输入 token 计费。描述写太长、一次挂 40 个工具,会同时打高账单和降低选工具准确率。工具很多时,用 tool_search 把低频工具延迟加载——仅 gpt-5.4 及更新模型支持,循环里还可能先出现 tool_search_call / tool_search_output,再进入真正的 function_call

custom tools:别把 DSL 塞进 JSON 对象

function tools 适合结构化参数;custom tools 适合自由文本输入输出,并可附加上下文无关文法(CFG)约束。SQL 片段、内部查询语言、需要词法终端互斥的格式,用 CFG 比「string 字段里再写一堆 prompt」稳。若 CFG 报 unexpected tokens,先查终结符是否重叠,而不是先怪模型。

tools = [{
    "type": "function",
    "name": "get_order",
    "description": "按订单号查询状态。仅在用户给出明确订单号时调用。",
    "strict": True,
    "parameters": {
        "type": "object",
        "properties": {
            "order_id": {"type": "string"},
            "locale": {"type": ["string", "null"]},
        },
        "required": ["order_id", "locale"],
        "additionalProperties": False,
    },
}]

执行循环没有变:看到 finish_reason / item type 为工具调用 → 跑本地函数 → 把结果以 tool 角色回传 → 再请求。变的是参数不再需要你用 json.loads 碰运气。仍必须保存完整 assistant 消息(含 tool_calls),否则第二轮会丢调用 ID。

并行工具调用时,顺序以调用 ID 为准

一次响应可能带多个 tool call。回传时按 call_id 对齐,不要按数组下标假设顺序。灰度日志至少记录:工具名、参数哈希、耗时、是否 strict、是否发生 schema 回退。

旧项目迁移清单

把「能跑」和「可交货」拆开验收。建议保留旧后端开关,先在独立环境回放真实流量。

  1. 模型:新链路指定 gpt-5.6(或账号已开通的同等档),不要让网关静默映射到旧快照。
  2. 输出:把 json_object 换成 json_schema + strict: true,或 Responses 的 text.format
  3. 工具:每个 function 补齐 required 与嵌套 additionalProperties: false;可选字段改可空联合。
  4. 解析:接入 parse()refusal 分支;流式场景确认增量 JSON 与最终 parsed 对象一致。
  5. 工具面:超过十几项就评估 tool_search;先缩短 description,再考虑延迟加载。
  6. 对照:用同一组固定任务对比旧 JSON Mode 与新 Schema 路径的重试率、缺字段率、人工返工。

通过标准不是「返回 200」,而是:解析器零正则兜底、工具参数类型稳定、拒答可观测、回滚开关演练过。需要长时间挂着 SDK、回放脚本和浏览器会话时,本地笔记本休眠会打断对照实验——这正是后面云端 Mac mini 的切入点。


FAQ

JSON Mode 和 Structured Outputs 可以混用吗?

不要在同一条链路上混。JSON Mode 只保证合法 JSON;Structured Outputs 才保证 Schema。混用会让监控分不清「解析失败」是模型问题还是合同问题。新代码只用 json_schema / text.format。

新项目还要写 Chat Completions 吗?

能用 Responses 就用 Responses。官方示例、parse helper 和 strict 规范化都优先走这条。存量 Chat Completions 可以继续,但必须显式设置 strict,并接受默认非严格这一差异。

为什么我的 Schema 一开 strict 就 400?

最常见是漏了 required、嵌套 object 没写 additionalProperties:false、根类型用了 anyOf,或把可选做成「不出现在 required」。把错误信息里的约束补全后再发;不要靠关闭 strict 掩盖 Schema 错误,除非你明确要非严格回退。

Function Calling 一定要 strict 吗?

官方建议始终开启。不开启时参数是尽力而为,你的执行器还得防缺字段和类型漂移。Responses 省略 strict 还可能被服务端改写,日志里要记下最终 strict 值。

tool_search 什么时候值得上?

工具定义已经明显挤占上下文、或大部分工具在单次任务里根本用不到时。需要 gpt-5.4 及以上。上线前要回放「先搜索工具再调用」的两段轨迹,旧执行器如果只认 function_call 会直接中断。

Schema 保证了,还要校验业务值吗?

要。约束解码不验证外键、权限和幂等。enum 合法不等于枚举值对你的库存有意义。把 Schema 校验和业务校验分成两层日志,故障时才分得清。

gpt-5.6 和更早的 GPT-5.x 在结构化输出上差在哪?

文档把 gpt-5.6 标为新项目默认。能力是否在你的账号、区域、批处理与微调路径上完全对齐,必须以当前模型列表和一次最小 parse 请求为准,不要用博客里的别名去猜网关映射。

和 Claude / Grok 的 JSON Schema 能共用一份吗?

合同方言接近 Draft 2020-12,但子集不同。OpenAI strict 要求每个 object 都 additionalProperties:false;有的提供商会拒绝嵌套层的该字段。保持一份业务 Schema,按提供商做变换层。

延伸阅读

在云端 Mac mini 上,Schema 验收可以 24/7 挂着跑

Function Calling 和 Structured Outputs 的回归,本质是长时间在线的对照实验:两套 SDK、固定回放集、工具沙箱、流式前端,还要避免笔记本合盖休眠。Apple Silicon 统一内存适合同时跑本地代理与浏览器调试;macOS 上 Homebrew、Docker、SSH 开箱即用;M4 Mac mini 待机功耗大约 4W,适合把验收环境挂过夜。

如果你需要一台不抢家庭带宽、能 SSH 常驻的 Mac 来跑 Agent 回放,Nuvcloud 云端 Mac mini M4 是目前把「开发机」和「对照实验机」拆开的低摩擦选项——立即了解套餐方案,让 strict Schema 的灰度不必绑在自己的笔记本上。

限时优惠 →