OpenAI 如何自定义JSON结构化输出示例

虽然提示词中可以通过json格式示例方式,指定模型的结构话输出。

然而这种方式比较容易出错,轻微的输出不规范,就会导致json解析失败。

目前使用OpenAI API进行JSON结构化输出,主要有两种推荐的方法:

1)Structured Outputs

2)Function Calling

其中,Structured Outputs是更新、更可靠的方式,能保证模型输出符合定义的JSON Schema。

这时尝试基于网络资料,给出具体的实现方法和代码示例。

1 Structured Outputs

1.1 功能描述

这是OpenAI在2024年8月推出的功能,可靠性最高。

在response_format中提供严格的JSON Schema,确保模型输出符合预期。

当然,该功能要求新一些的gpt模型,比如gpt-4o-2024-08-06。

现在已经是2026年,大部分的国内新模型应该也支持,比如本测试所用的Qwen3.5。

要求如下:

所有对象必须设置"additionalProperties": false

所有字段必须包含在required数组中,不支持可选字段。

1.2 代码示例

这里是基于OpenAI pythjon SDK的代码示例。

这里使用PyDantic,这是最简洁的方式,直接利用Pydantic模型定义数据结构。

整个过程不需要定义json结构。

复制代码
import os

model_name = "qwen3.5-xxx"
os.environ['OPENAI_API_KEY'] = gpt_api_keyxxxx
os.environ['OPENAI_BASE_URL'] = gpt_api_urlxxxxx

from openai import OpenAI
from pydantic import BaseModel
from typing import List

# 1. 定义你的数据结构(Pydantic模型)
class City(BaseModel):
    name: str
    country: str
    population: int

class CitiesData(BaseModel):
    cities: List[City]

# 2. 初始化客户端
client = OpenAI()

# 3. 调用API,将模型传入 response_format
completion = client.beta.chat.completions.parse(
    model=model_name,
    messages=[
        {"role": "system", "content": "提取文本中的城市信息。"},
        {"role": "user", "content": "柏林是德国的首都,人口约385万。巴黎是法国首都,人口216万。"}
    ],
    response_format=CitiesData,  # 关键参数
)

# 4. 获取结果
result: CitiesData = completion.choices[0].message.parsed
print(result.cities[0].name)  # 输出: 柏林
print(result.model_dump_json(indent=2))  # 输出格式化的JSON

输出示例如下所示,可见已正确结构话。

柏林

{

"cities": [

{

"name": "柏林",

"country": "德国",

"population": 385

}

]

}

1.3 原始api示例

Structured Outputs方式也支持通过在原始api请求中指定json schema的方式来结构话输出。

这里需要直接构造HTTP请求,准备一个严格的json schema。

示例如下。

复制代码
{
    "model": "qwen3.5xxx",
    "messages": [
        {"role": "system", "content": "提取城市信息。"},
        {"role": "user", "content": "柏林是德国的首都..."}
    ],
    "response_format": {
        "type": "json_schema",
        "json_schema": {
            "name": "cities_response",
            "strict": true,   // 必须为 true
            "schema": {
                "type": "object",
                "properties": {
                    "cities": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "name": {"type": "string"},
                                "country": {"type": "string"},
                                "population": {"type": "integer"}
                            },
                            "required": ["name", "country", "population"],
                            "additionalProperties": false
                        }
                    }
                },
                "required": ["cities"],
                "additionalProperties": false
            }
        }
    }
}

2 Function Calling

2.1 功能描述

Function Calling方法即工具函数调用犯法,也成为tools方法。

这是Structured Outputs推出前的标准做法,适用于需要模型同时输出文本和调用函的场景。

比如,调用函数处理复杂逻辑

Function Calling的特点是:

1)模型会决定是否调用某个函数。

2)返回的结果在tool_calls参数中。

3)相比Structured Outputs,它允许一定的灵活性,如可选字段,但可靠性略低。

2.2 代码示例

这里通过python sdk示例Function Calling方法。

复制代码
from openai import OpenAI

client = OpenAI()

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_city_info",
            "description": "获取城市信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "country": {"type": "string"},
                    "population": {"type": "integer"}
                },
                "required": ["name", "country"],
                "additionalProperties": False,
            },
            "strict": True,  # 开启严格模式
        }
    }
]

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "告诉我关于柏林的信息"}
    ],
    tools=tools,
    tool_choice="auto"  # 让模型决定是否调用
)

# 提取函数调用的参数
tool_call = response.choices[0].message.tool_calls[0]
arguments = json.loads(tool_call.function.arguments)
print(arguments)  # 输出: {'name': '柏林', 'country': '德国'}

输出如下所示

{'name': '柏林', 'country': '德国'}

3 JSON Mode

这是最早期的方法,仅保证输出是合法的JSON,不保证符合你的Schema。

使用时必须在prompt中包含"json"关键词。

复制代码
response = client.chat.completions.create(
    model="gpt-3.5-turbo",  # 仅限部分旧模型
    messages=[{"role": "user", "content": "返回JSON格式的数据。关键字:json"}],
    response_format={"type": "json_object"}  # 仅保证是JSON,不保证格式
)

4 关键注意事项

1)模型兼容性

不是所有模型都支持Structured Outputs。

如果遇到报错 `Invalid parameter: "response_format" of type "json_object" is not supported with this model`,说明当前模型不支持。

2)拒绝响应处理

当模型因安全策略拒绝回答时,返回的JSON中会包含refusal字段而不是你要的内容。

代码中需要处理这种情况。

3)成本与速度

使用`strict: true`时,第一个请求会因预计算语法树而稍慢,后续请求会恢复正常。

reference


Introducing Structured Outputs in the API

https://openai.com/index/introducing-structured-outputs-in-the-api/

Tutorial: Generating Structured Output with OpenAI

https://haystack.deepset.ai/tutorials/28_structured_output_with_openai?utm_campaign=developer-relations&utm_source=data-hour-event&utm_medium=webinar

Structured Output Example

https://pkg.go.dev/github.com/Ingenimax/agent-sdk-go@v0.2.11/examples/structured_output#section-readme

OpenAI 函数调用:上手示例大全

https://docs.kanaries.net/zh/articles/openai-function-calling

相关推荐
陆业聪2 小时前
字节跳动开源 DeerFlow 2.0 源码拆解:14层Middleware、Sub-Agent并发编排和结构化记忆是怎么做的
人工智能·langchain·aigc·agent
木心术12 小时前
卷积神经网络(CNN)与AI编程的深度整合指南
人工智能·cnn·ai编程
艾莉丝努力练剑2 小时前
【Linux信号】Linux进程信号(下):可重入函数、Volatile关键字、SIGCHLD信号
linux·运维·服务器·c++·人工智能·后端·学习
和小潘一起学AI2 小时前
AI面试问答
人工智能
智算菩萨2 小时前
GPT-5.4 进阶思考模式全面解析:从推理等级到实战提示词,代码、论文、数据处理一站通
人工智能·gpt·深度学习·机器学习·语言模型·自然语言处理·chatgpt
易知微EasyV数据可视化2 小时前
数字孪生+AI:某国家级技术科研机构:耦合仿真评估部件性能,长期运维监测承压状态
人工智能·经验分享·物联网·数字孪生·空间智能
六个点2 小时前
A2A协议入门:构建Agent之间的通信标准
人工智能
大学有意思2 小时前
广西英华国际职业学院新能源汽车技术专业2026年权威解析
人工智能·机器人
枫叶林FYL2 小时前
【自然语言处理 NLP】 大语言模型(LLM)系统工程(Large Language Model Engineering)5.1.2 ZeRO与显存优化技术
人工智能·深度学习·机器学习