大模型结构化输出详解:从 JSON Mode 到 Structured Output,彻底解决大模型格式不稳定问题
一、什么是大模型结构化输出?
在使用大语言模型(LLM)开发 AI 应用时,我们经常会遇到这样的问题:
明明希望大模型返回一个 JSON 对象,但它却返回了一段自然语言:
好的,以下是提取结果:
{
"name": "张三",
"age": "25岁"
}
希望这些信息对你有帮助!
对于人类来说,这样的回答完全没有问题。
但是对于程序来说,可能会出现解析失败、字段缺失、数据类型不一致等问题。
例如,我们希望模型返回:
{
"name": "张三",
"age": 25,
"city": "北京"
}
但模型可能返回:
{
"name": "张三",
"age": "25",
"city": "北京",
"description": "用户来自北京"
}
这里就存在数据类型不一致和额外字段的问题。
结构化输出(Structured Output)就是让大模型按照预先定义的数据结构生成结果,而不是随意组织自然语言。
它能够让模型输出符合指定格式的数据,例如:
-
JSON 对象
-
XML 数据
-
固定字段的字典
-
符合 JSON Schema 的数据
-
Pydantic 模型对象
-
数据库可直接使用的结构化记录
简单来说:
普通输出关注模型说了什么,结构化输出关注模型按照什么数据结构返回结果。
它是大模型从聊天工具走向工程化 AI 应用的重要技术之一。
二、为什么大模型需要结构化输出?
在传统软件开发中,程序之间通常通过固定的数据格式进行通信。
例如:
user = {
"name": "张三",
"age": 25,
"city": "北京"
}
程序可以明确知道:
-
name 是字符串
-
age 是整数
-
city 是字符串
但是大模型本质上是一个基于概率预测 Token 的生成模型。
它并不天然保证每次都按照指定格式输出。
这就导致了几个常见问题。
1. 输出格式不稳定
同样的 Prompt,模型可能返回不同的格式。
第一次:
{"name": "张三", "age": 25}
第二次:
用户姓名是张三,年龄是25岁。
第三次:
```json
{"name": "张三", "age": 25}
对于需要自动化处理的程序来说,这种不确定性非常麻烦。
### 2. 字段缺失
例如,我们要求模型提取用户信息:
```json
{
"name": "",
"age": 0,
"email": ""
}
但模型可能只返回:
{
"name": "张三",
"age": 25
}
缺少 email 字段,可能导致后续程序报错。
3. 数据类型错误
例如:
{
"age": "25",
"is_student": "true"
}
这里的 age 和 is_student 都是字符串,而不是预期的整数和布尔值。
4. 无法直接对接业务系统
企业应用通常需要将大模型输出的数据传递给:
-
MySQL、PostgreSQL 等数据库
-
CRM 客户管理系统
-
ERP 企业资源管理系统
-
API 服务
-
自动化工作流
-
Agent 工具调用模块
如果输出格式不稳定,就需要额外编写大量数据清洗和解析代码。
因此,结构化输出的核心价值就是:
让大模型的输出能够被程序稳定理解、验证和使用。
三、结构化输出的核心原理
结构化输出并不是单一技术,而是一套完整的工程方案。
通常可以拆分为以下几个环节:
-
定义输出结构
-
将结构要求传递给模型
-
模型生成符合要求的内容
-
对输出结果进行格式解析
-
进行字段和类型校验
-
将数据交给下游系统
整体流程如下:
用户输入
|
v
Prompt 提示词
|
v
定义输出 Schema
|
v
大语言模型 LLM
|
v
生成结构化结果
|
v
JSON 解析
|
v
Schema 数据校验
|
+----+----+
| |
v v
校验成功 校验失败
| |
v v
业务处理 重试/修复
|
v
数据库/API/Agent
1. Schema:定义输出结构
Schema 可以理解为数据结构规范。
例如,我们希望模型提取一份简历中的基本信息:
{
"name": "string",
"age": "integer",
"education": "string",
"skills": ["string"]
}
这个结构告诉模型:
-
name 必须是字符串
-
age 必须是整数
-
education 必须是字符串
-
skills 必须是字符串数组
在实际工程中,常见的 Schema 定义方式包括:
-
JSON Schema
-
Pydantic
-
Zod
-
TypedDict
-
各类模型 API 提供的结构化输出参数
2. Constrained Decoding:约束解码

约束解码是结构化输出中的一种重要技术。
普通生成模式下,模型可以根据概率选择下一个 Token。
例如:
{
"name":
接下来模型可能生成字符串、数字、其他字段,甚至生成不符合 JSON 格式的内容。
而约束解码会根据预定义的规则,限制模型能够生成的 Token。
例如:
{
"name": "张三",
"age": 25
}
在特定位置,只允许生成符合当前语法或 Schema 约束的内容。
其基本思路可以表示为:
模型预测下一个 Token
|
v
获取候选 Token
|
v
Schema 约束检查
|
v
过滤不合法 Token
|
v
从合法 Token 中选择
|
v
继续生成
需要注意:
约束解码可以在语法或 Schema 支持的范围内保证输出形式,但不代表模型提取的信息一定真实,也不代表业务逻辑一定正确。
3. JSON Schema:结构化输出的重要规范
JSON Schema 是描述 JSON 数据结构的一种规范。
例如:
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
},
"skills": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"age",
"skills"
],
"additionalProperties": false
}
其中:
| 字段 | 含义 |
|---|---|
| type | 数据类型 |
| properties | 定义对象属性 |
| required | 必须存在的字段 |
| items | 定义数组元素类型 |
| additionalProperties | 是否允许额外字段 |
| enum | 限制字段可选值 |
| description | 描述字段含义 |
例如:
{
"type": "string",
"enum": ["男", "女", "未知"]
}
表示该字段只能取三个指定值。
JSON Schema 能够帮助开发者明确约束数据结构,也方便模型 API 和程序校验逻辑进行协作。
四、JSON Mode 和 Structured Output 有什么区别?
这是大模型开发中非常容易混淆的两个概念。
1. JSON Mode
JSON Mode 的核心目标是让模型返回合法的 JSON 格式。
例如:
{
"name": "张三",
"age": 25
}
它主要解决的是 JSON 语法问题。
但是,JSON Mode 通常不保证:
-
必须包含指定字段
-
字段类型完全符合要求
-
不会出现额外字段
-
数据满足业务规则
2. Structured Output
Structured Output 更进一步。
它不仅要求输出是 JSON,还要求输出符合预先定义的 Schema。
例如:
{
"name": "张三",
"age": 25,
"skills": [
"Python",
"机器学习"
]
}
如果 Schema 要求 age 是整数,skills 是字符串数组,那么生成结果就需要符合这些约束。
3. 两者对比

| 对比维度 | JSON Mode | Structured Output |
|---|---|---|
| 输出格式 | JSON | 指定数据结构 |
| JSON 语法合法性 | 通常保证 | 支持 |
| 字段约束 | 通常不保证 | 支持 |
| 类型约束 | 通常不保证 | 支持 |
| 必填字段 | 通常不保证 | 支持 |
| 额外字段限制 | 通常不保证 | 视 Schema 支持情况 |
| 适用场景 | 简单 JSON 返回 | 生产级 AI 应用 |
需要注意,不同模型厂商对 JSON Mode 和 Structured Output 的实现、支持范围和保证程度并不完全相同,开发时需要以对应 API 文档为准。
五、Python 实战:从零实现大模型结构化输出

下面通过一个简历信息提取案例,演示如何使用 Python 实现结构化输出。
1. 安装依赖
pip install openai pydantic
2. 定义 Pydantic 数据模型
Pydantic 可以通过 Python 类型注解定义数据结构,并自动完成数据校验。
from pydantic import BaseModel, Field
from typing import List
class ResumeInfo(BaseModel):
name: str = Field(
description="候选人姓名"
)
age: int = Field(
description="候选人年龄"
)
education: str = Field(
description="最高学历"
)
skills: List[str] = Field(
description="技术技能列表"
)
这里定义了一个 ResumeInfo 模型。
要求模型返回:
-
姓名:字符串
-
年龄:整数
-
学历:字符串
-
技能:字符串列表
3. 使用大模型 API 生成结构化结果
下面以支持 Pydantic 解析的 OpenAI Python SDK 为例:
from openai import OpenAI
from pydantic import BaseModel, Field
from typing import List
client = OpenAI()
class ResumeInfo(BaseModel):
name: str = Field(
description="候选人姓名"
)
age: int = Field(
description="候选人年龄"
)
education: str = Field(
description="最高学历"
)
skills: List[str] = Field(
description="技术技能列表"
)
response = client.responses.parse(
model="gpt-4o-2024-08-06",
input=[
{
"role": "system",
"content": "你是一个专业的简历信息提取助手。请准确提取简历中的信息。"
},
{
"role": "user",
"content": """
张三,25岁,硕士学历。
熟悉 Python、PyTorch、
机器学习和深度学习。
"""
}
],
text_format=ResumeInfo
)
result = response.output_parsed
print(result)
print(result.model_dump())
注意:这里使用的是支持 Structured Outputs 的模型和 Responses API 示例,实际使用时需要配置 API Key,并确认模型支持相应的结构化输出能力。
4. 运行结果
输出结果可以表示为:
{
"name": "张三",
"age": 25,
"education": "硕士",
"skills": [
"Python",
"PyTorch",
"机器学习",
"深度学习"
]
}
现在,大模型返回的结果已经可以被 Python 程序直接读取。
例如:
print(result.name)
print(result.age)
print(result.education)
print(result.skills)
输出:
张三
25
硕士
['Python', 'PyTorch', '机器学习', '深度学习']
这就是结构化输出的基本使用方式。
六、进阶实战:使用 JSON Schema 提取商品信息
假设我们正在开发一个电商 AI 助手,需要从用户输入中提取商品信息。
用户输入:
我想买一台预算在5000元以内的笔记本电脑,
主要用于编程,最好配备16GB以上内存。
我们希望模型返回:
{
"category": "笔记本电脑",
"budget": 5000,
"purpose": [
"编程"
],
"min_memory": 16
}
可以使用 JSON Schema 定义输出规范:
from openai import OpenAI
client = OpenAI()
schema = {
"type": "object",
"properties": {
"category": {
"type": "string"
},
"budget": {
"type": "integer"
},
"purpose": {
"type": "array",
"items": {
"type": "string"
}
},
"min_memory": {
"type": "integer"
}
},
"required": [
"category",
"budget",
"purpose",
"min_memory"
],
"additionalProperties": False
}
response = client.responses.create(
model="gpt-4o-2024-08-06",
input="我想买一台预算在5000元以内的笔记本电脑,主要用于编程,最好配备16GB以上内存。",
text={
"format": {
"type": "json_schema",
"name": "product_requirement",
"strict": True,
"schema": schema
}
}
)
print(response.output_text)
通过这种方式,我们就可以将自然语言需求转化成程序能够直接处理的结构化数据。
例如,下游系统可以根据 budget、category 和 min_memory 自动执行商品检索。
这也是 AI Agent、智能购物助手和企业自动化系统中的典型应用。
七、结构化输出在大模型应用中的典型场景
结构化输出不仅仅是为了生成 JSON,它更重要的价值在于连接大模型与真实业务系统。
1. RAG 检索增强生成
在 RAG 系统中,可以要求模型按照指定格式返回:
{
"answer": "相关问题的回答",
"sources": [
{
"document": "技术文档.pdf",
"page": 12
}
],
"confidence": 0.92
}
这样可以方便前端展示答案和参考来源。
但需要注意,confidence 字段如果由模型自行生成,并不等于经过校准的真实置信度。
2. Agent 智能体
Agent 需要根据用户任务决定调用什么工具。
例如:
{
"tool": "search_weather",
"arguments": {
"city": "北京"
}
}
Agent 可以根据结构化参数执行对应工具。
实际工具调用通常还需要工具名称校验、参数验证和权限检查,不能仅凭模型输出就执行高风险操作。
3. 信息抽取
从合同、简历、医疗文档、论文中提取信息。
例如:
{
"patient_name": "张三",
"diagnosis": "示例诊断",
"medications": [
"药物A",
"药物B"
]
}
4. 文本分类
例如,将用户反馈自动分类:
{
"category": "产品问题",
"sentiment": "负面",
"priority": "高"
}
5. 自动化工作流
例如,将客户需求自动转化成任务:
{
"task_name": "客户需求分析",
"assignee": "产品经理",
"priority": "high",
"status": "pending"
}
结构化输出能够帮助大模型与工作流系统进行数据交互。
八、结构化输出的常见问题与解决方案
问题1:模型返回的 JSON 仍然无法解析
可能原因:
-
模型输出包含额外文本
-
JSON 字符串存在转义错误
-
模型没有真正启用 JSON Mode
-
输出被截断
解决方案:
-
优先使用模型 API 原生结构化输出能力
-
检查 finish_reason 或响应状态
-
对返回结果进行 JSON 解析
-
对不完整结果进行有限重试
问题2:字段缺失怎么办?
建议:
-
使用 Schema 定义 required 字段。
-
在字段 description 中写清楚要求。
-
对确实可能缺失的信息使用 nullable 类型。
-
对输出结果进行二次校验。
例如:
from pydantic import BaseModel
class UserInfo(BaseModel):
name: str
age: int | None = None
email: str | None = None
这里 age 和 email 可以为空。
问题3:如何避免模型生成虚假数据?
结构化输出只能约束数据格式,不能保证事实准确性。
例如,用户没有提供年龄,模型可能错误推测一个年龄。
建议:
-
不允许模型随意补充未知信息。
-
对缺失字段使用 null。
-
使用原始文档或数据库进行事实核验。
-
对关键数据保留来源信息。
-
对高风险业务增加人工审核。
问题4:结构化输出会增加 Token 消耗吗?
有可能。
Schema、字段描述以及格式约束都可能增加请求开销。
此外,约束解码也可能带来额外计算成本。
建议:
-
尽量精简 Schema。
-
避免不必要的嵌套结构。
-
减少重复字段描述。
-
根据业务复杂度选择合适的结构化方案。
九、结构化输出的最佳实践
如果要在企业级大模型应用中使用结构化输出,建议遵循以下原则。
| 最佳实践 | 具体建议 |
|---|---|
| 优先使用原生能力 | 使用模型 API 支持的 Structured Output |
| 定义清晰 Schema | 明确字段名称、类型和必填规则 |
| 合理设计字段 | 不要设计过于复杂的数据结构 |
| 设置字段描述 | 告诉模型每个字段的业务含义 |
| 处理异常情况 | 处理拒绝、截断、解析失败等情况 |
| 二次校验 | 使用 Pydantic 等工具验证数据 |
| 控制权限 | 不直接执行未经校验的工具调用 |
| 保留原始数据 | 方便问题追踪与审计 |
还需要注意几个容易忽略的边界:
第一,格式正确不代表内容正确。
一个完全符合 JSON Schema 的结果,依然可能包含错误信息。
第二,Schema 校验不等于业务校验。
例如,年龄是整数并不意味着年龄一定合理。
第三,结构化输出不等于工具调用。
结构化输出负责组织数据,工具调用负责让模型或 Agent 与外部工具交互。两者可以结合,但不是同一个概念。
第四,不同模型的支持程度不同。
开发前需要确认模型是否支持 JSON Schema、严格模式、枚举、嵌套对象等能力。
十、总结
大模型结构化输出是 AI 应用工程化过程中非常重要的一项技术。
它解决的核心问题是:如何让大模型生成的数据符合程序预期,而不是只生成一段人类能够理解的自然语言。
本文介绍了:
-
结构化输出的概念与应用价值。
-
Schema、JSON Schema 和约束解码的基本原理。
-
JSON Mode 与 Structured Output 的区别。
-
使用 Python、Pydantic 实现结构化输出。
-
使用 JSON Schema 提取商品需求。
-
结构化输出在 RAG、Agent 和自动化工作流中的应用。
-
企业级结构化输出的最佳实践。
对于想要学习大模型应用开发的同学来说,建议重点掌握:
Prompt Engineering → JSON Mode → JSON Schema → Pydantic → Structured Output → Function Calling → Agent 工具调用。
掌握这套技术链路,就能将大模型从一个简单的对话工具,逐步变成能够理解业务、生成标准数据并参与真实业务流程的智能应用。
更多推荐



所有评论(0)