什么是基于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结构化输出提供了一个强大的解决方案,可确保您的大语言模型生成可靠、可预测且机器可读的回复。结构化输出有助于您在不同应用程序中保持一致的数据格式,从而更轻松地管理复杂的工作流程。