
什么是基于JSON Schema的结构化输出
大语言模型通常会生成无特定结构的自由格式文本,在能够有效使用之前需要进行大量的后期处理。这种不可预测性会导致错误、浪费时间并增加成本。
OpenAI推出基于JSON Schema的结构化输出以解决这一问题。结构化输出确保模型响应遵循严格的格式,减少错误,并使将大语言模型集成到需要一致的、机器可读数据的应用程序中变得更加容易,对于一致性和准确性至关重要的任务其输出更为可靠。
通常情况下,大语言模型基于概率预测逐个生成文本标记。不过,如果需要以特定格式生成文本,这种方法就不太适用了。结构化输出通过预定义的规则或模式来引导这一过程,使每个标记都符合所需的结构。
如何使用基于JSON Schema的结构化输出
并非所有的模型都支持基于JSON Schema的结构化输出。经测试,文心一言支持结构化输出。通义千问、豆包、deepseek还不支持。
下面以输出方程求解过程的结构化输出为例,阐述OpenAI Python SDK使用结构化输出的两种方法。
先准备好开发环境,以windows开发环境为例:
设置Python开发环境
安装uv。uv是一个用Rust编写的极其快速的Python包和项目管理器。
复制powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
创建python虚拟环境(假设项目目录为structured-output)
复制# Create a new directory for our project uv init structured-output cd structured-output # Create virtual environment and activate it uv venv .venv\Scripts\activate # Install dependencies uv add openai python-dotenv
设置环境变量
创建.env,.env内容如下(注意修改OPENAI_API_KEY为您的key)
复制OPENAI_API_KEY=your_api_key_here OPENAI_BASE_URL=https://qianfan.baidubce.com/v2 MODEL_NAME=ernie-3.5-128k
把.env添加到.gitignore
结构化输出方法1:手工定义Schema
通过设置chat completion的response_format打开结构化输出。response_format的格式为:
复制{
type: "json_schema",
json_schema: {
"strict": true,
"schema": ...
}
}完整例子如下:
复制import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
client = OpenAI()
chat_completion = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "你是一位数学老师。一步步引导用户完成解题过程"
},
{
"role": "user",
"content": "我该如何解7x + 6 = 41这个方程"
}
],
model=os.getenv("MODEL_NAME"),
response_format={
"type": "json_schema",
"json_schema": {
"name": "math_response",
"schema": {
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": {"type": "string"},
"output": {"type": "string"}
},
"required": ["explanation", "output"],
"additionalProperties": False
}
},
"final_answer": {"type": "string"}
},
"required": ["steps", "final_answer"],
"additionalProperties": False
},
"strict": True
}
},
)
content = chat_completion.choices[0].message.content
print(content)输出结果如下:
复制{
"final_answer":"x = 5",
"steps":[
{
"explanation":"首先,我们需要将方程中的常数项移至等式的另一边,使方程左侧只剩下未知数x的系数和x本身。",
"output":"7x = 41 - 6"
},
{
"explanation":"进行减法运算,简化方程。",
"output":"7x = 35"
},
{
"explanation":"接下来,我们需要将x的系数化为1,以求解x的值。为此,我们将方程两边同时除以7。",
"output":"x = 35 ÷ 7"
},
{
"explanation":"进行除法运算,得出x的值。",
"output":"x = 5"
}
]
}结构化输出方法2:使用自定义的pydantic模型
通过设置chat completion的response_format为自定义的pydantic模型MathReasoning
完整例子如下:
复制import os
from openai import OpenAI
from dotenv import load_dotenv
from pydantic import BaseModel
class Step(BaseModel):
explanation: str
output: str
class MathReasoning(BaseModel):
steps: list[Step]
final_answer: str
load_dotenv() # load environment variables from .env
client = OpenAI()
chat_completion = client.beta.chat.completions.parse(
messages=[
{
"role": "system",
"content": "你是一位乐于助人的数学老师。一步步引导用户完成解题过程"
},
{
"role": "user",
"content": "我该如何解7x + 6 = 41这个方程"
}
],
model=os.getenv("MODEL_NAME"),
response_format=MathReasoning,
)
math_reasoning = chat_completion.choices[0].message.parsed
print(math_reasoning.model_dump_json(indent=4))输出结果为:
复制{
"steps":[
{
"explanation":"首先,我们需要将方程中的常数项移至等式的另一边。从7x + 6 = 41开始,我们可以从两边同时减去6。",
"output":"7x + 6 - 6 = 41 - 6"
},
{
"explanation":"简化上一步的等式,得到7x = 35。",
"output":"7x = 35"
},
{
"explanation":"接下来,我们需要解出x的值。为此,我们可以将方程两边同时除以7。",
"output":"7x / 7 = 35 / 7"
},
{
"explanation":"简化上一步的等式,得到x = 5。",
"output":"x = 5"
}
],
"final_answer":"x = 5"
}JSON Schema结构化输出 VS JSON模式
JSON Schema结构化输出是JSON模式的进阶版本。JSON模式是通过设置response_format为{ "type": "json_object" }打开。使用JSON模式时,你必须始终通过对话中的某些消息(例如系统消息)指示模型生成JSON。JSON 模式不能保证输出符合任何特定的模式。
总结
JSON Schema结构化输出提供了一个强大的解决方案,可确保您的大语言模型生成可靠、可预测且机器可读的回复。结构化输出有助于您在不同应用程序中保持一致的数据格式,从而更轻松地管理复杂的工作流程。