OpenAI推出基于JSON Schema的结构化输出以解决这一问题。结构化输出确保模型响应遵循严格的格式,减少错误,并使将大语言模型集成到需要一致的、机器可读数据的应用程序中变得更加容易,对于一致性和准确性至关重要的任务其输出更为可靠。

什么是基于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"
- 1.
创建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
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
设置环境变量
创建.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
- 1.
- 2.
- 3.
把.env添加到.gitignore
结构化输出方法1:手工定义Schema
通过设置chat completion的response_format打开结构化输出。response_format的格式为:
复制
{
type: "json_schema",
json_schema: {
"strict": true,
"schema": ...
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
完整例子如下:
复制
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)
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
输出结果如下:
复制
{
"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"
}
]
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
结构化输出方法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))
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
输出结果为:
复制
{
"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"
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
JSON Schema结构化输出 VS JSON模式
JSON Schema结构化输出是JSON模式的进阶版本。JSON模式是通过设置response_format为{ "type": "json_object" }打开。使用JSON模式时,你必须始终通过对话中的某些消息(例如系统消息)指示模型生成JSON。JSON 模式不能保证输出符合任何特定的模式。
总结
JSON Schema结构化输出提供了一个强大的解决方案,可确保您的大语言模型生成可靠、可预测且机器可读的回复。结构化输出有助于您在不同应用程序中保持一致的数据格式,从而更轻松地管理复杂的工作流程。
一文读懂LLM基于JSON Schema结构化输出
1万+

被折叠的 条评论
为什么被折叠?



