如何保证大模型输出符合指定 JSON 格式?

未标记

询问 AI

考查重点:结构约束与解析反馈。Schema 定字段与类型,优先结构化输出/约束解码,收到后解析并校业务语义;失败给具体错误有限重试

本题目录

参考答案

核心回答

要稳定拿到指定 JSON,需要把约束放在输出协议、生成过程和接收校验三个位置,不能只在 Prompt 里写一句“请输出 JSON”。

先用 JSON Schema 明确字段名、类型、必填项、枚举、嵌套结构和未知值的表示方式。模型和接口支持时,优先使用严格的结构化输出;JSON Object 模式主要约束 JSON 语法,不能据此保证字段齐全。Prompt 再解释字段含义、提供与协议一致的例子,并要求不输出额外说明。

接收端检查请求是否正常结束,再解析完整响应、校验结构,最后检查业务规则。格式失败时,把具体错误反馈给模型,在次数和耗时预算内修复;信息不足则返回约定的未知状态或向用户补问。JSON 能解析、符合 Schema、业务内容正确是三个不同层次:即使结构合法,也不能直接把模型生成的订单号当成真实且有权访问的订单。

先把“指定格式”定义成可验证的协议

以订单意图提取为例,约定 intent 只能是 query_order 或 unknown,order 必须是对象,内部必须出现 id;提取不到订单号时,id 为 null。

{ "intent": "unknown", "order": { "id": null } }

这里有几个容易遗漏的细节:

  • 必填和非空不同。 id 可以为 null,并不意味着可以省略 id。把未知值纳入协议,能减少模型为凑字段而编造内容。
  • 列出字段不等于要求字段出现。 JSON Schema 的 properties 描述字段规则,required 才规定必填项。嵌套对象也要分别定义。
  • 多余字段需要单独约束。 若协议不允许自由扩展,在相应对象上设置 additionalProperties: false,而不只限制最外层。
  • 业务规则要另行表达。 intent=query_order 但 id=null 时,系统应补问订单号;有订单号后,还要查订单是否存在以及当前用户是否有权读取。

可以从同一份类型定义生成请求使用的 Schema,并复用它做接收校验,减少两端规则漂移。生成的 Schema 仍要适配服务端支持的子集,例如对引用、联合类型或复杂约束的限制。

生成时,原生约束和 Prompt 各做什么

支持严格 Schema 的接口可以在生成阶段限制输出结构。以 XGrammar 这类约束解码实现为例,解码器根据当前语法状态,屏蔽下一步不合法的 token,使采样继续沿合法结构前进。它比生成完再修补括号更直接,但约束的是结构,无法保证字符串里的事实正确;不同服务也不一定使用相同实现。

JSON Object 模式通常只承诺输出可解析的 JSON,对必填字段、枚举和嵌套层级的保证应另查接口约定。例如 DeepSeek 的 JSON Output 文档要求 Prompt 包含 JSON 指示并给出格式示例,同时提示空内容、输出长度等情况;阿里云百炼则区分 JSON Object 和严格 JSON Schema 模式,并规定不同的模型、模式支持条件。接入时应核对实际调用的模型和接口,而不是只看参数名称。

Function Calling 也可以把目标数据放进工具参数,由应用提取并校验。不过,是否严格遵守参数 Schema,取决于提供方及其严格模式支持;“支持工具调用”本身不等于支持所有 Schema 约束。若这里只需要结构化结果,接收工具参数也不意味着要执行一个有业务副作用的函数。

Prompt 负责讲清语义,例如:“从用户输入提取订单查询意图;只输出约定的 JSON 对象;无法提取的订单号填 null;不增加字段、Markdown 围栏或说明文字。”再附一个与 Schema 一致的合法示例。低 temperature 可以减少输出变化,但不提供格式保证。业务输入应作为待提取的数据传入,避免其中的指令覆盖输出要求。

接收端怎样校验

下面是一个接收端示例,使用 Pydantic v2;只做文本解析和结构校验,不调用模型或查询订单:

import json
from typing import Literal
from pydantic import BaseModel, ConfigDict

class OrderInfo(BaseModel):
    model_config = ConfigDict(strict=True, extra="forbid")
    id: str | None

class Extraction(BaseModel):
    model_config = ConfigDict(strict=True, extra="forbid")
    intent: Literal["query_order", "unknown"]
    order: OrderInfo

def unique_object(pairs):
    result = {}
    for key, value in pairs:
        if key in result:
            raise ValueError(f"重复字段: {key}")
        result[key] = value
    return result

def reject_constant(value):
    raise ValueError(f"非标准 JSON 数值: {value}")

def parse_output(text: str) -> Extraction:
    obj = json.loads(text, object_pairs_hook=unique_object,
                     parse_constant=reject_constant)
    return Extraction.model_validate(obj)

strict=True 避免把错误类型悄悄转换成正确类型,两个对象的 extra="forbid" 分别拒绝顶层和嵌套的多余字段。id 没有默认值,因此必须出现,但可以是 null。需要向接口传递结构定义时,可从 Extraction.model_json_schema() 获取 JSON Schema,再按接口支持范围适配。

Python 的默认 JSON 解码允许 NaN 等扩展值,并会对重复键保留最后一个值。示例拒绝非标准数值,也明确选择拒绝重复键,避免上下游对同一响应产生不同解释;重复键处理属于这里的协议策略。实际接收层还应控制响应大小与嵌套深度。

解析之前,先处理 API 错误、拒答、空内容和达到输出上限等结束状态。流式响应中的半个字符串或尚未闭合的对象,只是中间片段;需要完整对象的业务逻辑,应等响应结束并通过校验后再运行。展示增量内容与执行业务操作可以采用不同的时机。

格式失败后,怎样恢复而不过度重试

按失败原因处理,比统一“再问一次”有效:

  1. Schema 或接口配置不受支持。 修改配置或简化协议;原样重试通常不会解决问题。
  2. 语法或结构错误。 返回精确到字段路径的错误,例如 order.id 缺失或类型错误,要求按原协议重新输出。重试仍经过完整校验,并限制总次数、耗时和 token 开销。
  3. 内容被截断。 结合任务需要调整输出预算、缩小单次抽取范围,或拆分任务;补一个右括号不能恢复丢失的信息。
  4. 业务信息不足。 使用协议中的未知值、补问用户或交给约定的兜底流程,不用默认订单号或金额填平错误。

如果结果会触发写操作,修复和重试应停留在生成、校验阶段;真正执行时另做权限和幂等控制,避免一次格式修复重复创建订单。

验证效果时,分别统计首次 JSON 解析通过率、首次 Schema 通过率和业务正确率,再看修复后的最终成功率、重试次数与延迟。测试集应包含引号与转义、嵌套字段、缺失值、多余说明、截断和输入中夹带指令等情况,才能知道问题发生在哪一层。

常见追问

为什么不能用正则截取第一个大括号到最后一个大括号?

字符串本身可能包含大括号、转义引号,响应也可能包含多个对象或不完整结构。通用嵌套 JSON 应由解析器处理;若允许从包装文本提取 JSON,也要明确提取规则并继续校验,不能把“截出一段”当作正确。

严格 Schema 模式还需要接收端校验吗?

需要处理接口失败、拒答、截断与版本配置等状态,并验证业务规则。接收端的结构检查还能及时发现集成配置或协议变更问题;原生约束与接收校验承担不同位置的责任。

模型少输出一个字段,补成 null 可以吗?

只有协议明确该字段允许 null,且缺失信息的业务含义与之相符时,才能按约定处理。否则应视为结构错误;缺字段、明确为空和提取失败可能是不同状态,不能无条件合并。

对应教程

参考资料

  • 国内:JavaGuide:结构化输出与 Function Calling:参考 JSON Mode、Schema 与工具调用的约束差异及错误反馈,组织正文中协议、生成和接收校验的三层保证。
  • 国内:DeepSeek:JSON Output:依据 JSON Object 的参数、Prompt 示例和输出限制,说明正文中 DeepSeek 模式的语法保证、空内容与截断处理。
  • 国内:阿里云百炼:结构化输出:参考 JSON Object 与严格 JSON Schema 模式的区别,交代正文中百炼的字段约束与模型、调用模式支持条件。
  • 国外:LangChain:Structured output:借鉴原生输出与工具参数两条路径及校验恢复,说明正文中结构化结果的接收方式和失败修复职责。
  • 国外:JSON Schema:Object:依据 properties、required、additionalProperties 与 null 的语义,解释正文中嵌套对象必填、可空及额外字段的区别。

相关面经

5 篇

恒生电子

AI 应用开发工程师
校招秋招一面
查看原面经 →
让大模型稳定输出结构化数据,如JSON是ai应用开发常见需求,但模型有时会输出多余的解释文字或格式不合法,你会用哪些手段提升结构化输出的稳定性和可解析性。

恒生电子

AI 开发工程师
校招秋招
查看原面经 →
大模型稳定输出结构化 JSON,经常出现多余文字、格式非法,你会用哪些手段提升结构化输出稳定性与可解析性?

蚂蚁集团

面经合集
查看原面经 →
场景题(共享屏幕看代码):如何设计 Prompt,让大模型严格按照指定的 JSON 格式输出,且不包含多余的废话?
如果大模型“幻觉”或者没有严格按格式输出(比如缺失字段、格式乱掉),系统层面如何做兜底和容错处理?

去哪儿

AI 全栈开发工程师
查看原面经 →
LLM如何通过手段保证输出的内容符合规定的JSON格式?

去哪儿

AI 全栈开发工程师
秋招
查看原面经 →
生成格式化例如JSON内容,如何确保AI生成的可靠性(键的准确性,嵌套层级)

收录题集

15 份
展开剩余 10 份题集

LLMOps 与生产应用

AMIT SHEKHAR · ai-engineering-interview-questions · 1 条原题

查看题集 →

提示工程

AMIT SHEKHAR · ai-engineering-interview-questions · 1 条原题

查看题集 →

阿里巴巴问答汇编

Rocky Ding · AIGC-Interview-Book · 1 条原题

查看题集 →

百度高频面试题

Rocky Ding · AIGC-Interview-Book · 1 条原题

查看题集 →

恒生电子高频面试题

Rocky Ding · AIGC-Interview-Book · 1 条原题

查看题集 →

提示工程:应用大模型的高级方法

Rocky Ding · AIGC-Interview-Book · 1 条原题

查看题集 →

大语言模型

Datawhale · daily-interview · 1 条原题

查看题集 →

模型接口与评测问答

Guide · JavaGuide · 4 条原题

查看题集 →
展开其余 1 条原题

AI 导读问题

Guide · JavaGuide · 3 条原题

查看题集 →

大模型基础面试题

Guide · JavaGuide · 1 条原题

查看题集 →

相关题目

4 题