
大模型输出格式约束技术对比JSON Mode、Function Calling 与结构化 Prompt一、自由格式输出的下游集成困境一个 AI 日程助手需要将用户那句明天下午三点提醒我开会解析为{action: remind, time: 2026-07-12T15:00:00, title: 开会}。最简单的做法是让大模型自由输出然后在后处理阶段用正则提取时间。这个方案在前 50 次测试中运行良好第 51 次用户说后天早上模型输出了2026-07-13T08:00:00—正确。第 52 次用户说每周三下午模型输出变成了每周三下午三点这种未解析的自然语言。自由格式输出的根本问题不是正则难写而是模型输出的不确定性会随着输入复杂度的提升呈非线性增长。当用户的表达方式从明天下午三点扩展到下周五之前找个时间但避开周四下午时依赖正则表达式的解析方案会在某一刻静默失败——正则匹配不上但也不报错直接返回了错误的解析结果。二、三种约束方案的能力边界对比目前主流的三种输出格式约束方案各有适用边界graph TB subgraph A[JSON Mode] A1[强制输出 JSON 语法] A2[不保证字段定义] A3[适用简单结构体] end subgraph B[Function Calling] B1[强制输出特定 Schema] B2[支持嵌套和枚举] B3[适用工具调用场景] end subgraph C[结构化 Prompt] C1[通过 Prompt 指令约束] C2[灵活性最高] C3[适用复杂 reasoning 格式] end A -- COMPARE{选择依据} B -- COMPARE C -- COMPARE COMPARE --|格式要求严格| B COMPARE --|需要推理格式并存| C COMPARE --|格式简单且模型支持| AJSON Mode 强制输出合法 JSON 但无法约束字段名和类型。Function Calling 通过 Schema 定义强约束输出结构但只能用于特定的工具调用模式。结构化 Prompt 通过在 Prompt 中嵌入格式指令来引导输出灵活性高但约束力最弱。三、三种方案的实际效果对比 对同一输入使用三种约束方案的对比测试。 输入用户自然语言消息 输出结构化的事件解析结果 import json from openai import OpenAI from typing import Optional from pydantic import BaseModel, Field client OpenAI() class CalendarEvent(BaseModel): 日程事件的 Schema 定义——三种方案共享同一结构 action: str Field(..., pattern^(remind|schedule|query)$) title: Optional[str] None time: Optional[str] None is_recurring: bool False confidence: float Field(ge0, le1) def parse_with_json_mode(user_message: str) - CalendarEvent: 方案一JSON Mode 设计意图在 system prompt 中声明 SchemaJSON mode 保证语法正确。 缺陷无法保证字段完整性和类型正确性。 response client.chat.completions.create( modelgpt-4o, response_format{type: json_object}, messages[ {role: system, content: 将用户消息解析为 JSON格式如下 {action: remind|schedule|query, title: 事项, time: ISO格式, is_recurring: false, confidence: 0.9} 仅输出 JSON不要包含其他文本。 }, {role: user, content: user_message}, ], ) raw response.choices[0].message.content or {} data json.loads(raw) # 需要手动校验——JSON Mode 不保证字段存在 if action not in data: data[action] query data.setdefault(confidence, 0.5) data.setdefault(is_recurring, False) return CalendarEvent(**data) def parse_with_function_calling(user_message: str) - CalendarEvent: 方案二Function Calling 设计意图通过 tools 声明强 Schema 约束。 优势模型必须按 Schema 返回字段和类型有保证。 缺陷当用户消息无法解析时模型可能编造数据填入。 response client.chat.completions.create( modelgpt-4o, messages[{role: user, content: user_message}], tools[{ type: function, function: { name: parse_calendar_event, description: 从用户消息中解析日程事件, parameters: { type: object, properties: { action: { type: string, enum: [remind, schedule, query], description: 操作类型 }, title: { type: string, description: 事项标题无明确标题时为空字符串 }, time: { type: string, description: ISO 8601 时间无法确定时为空 }, is_recurring: { type: boolean, description: 是否为重复事件 }, confidence: { type: number, minimum: 0, maximum: 1, description: 解析置信度 }, }, required: [action, confidence] } } }], tool_choice{ type: function, function: {name: parse_calendar_event} }, ) tool_call response.choices[0].message.tool_calls[0] data json.loads(tool_call.function.arguments) # 低置信度时降级为查询——避免基于不可靠解析执行操作 if data.get(confidence, 0) 0.6: data[action] query data[time] None return CalendarEvent(**data) def parse_with_structured_prompt(user_message: str) - CalendarEvent: 方案三结构化 Prompt无 Function Calling 的备选方案 设计意图通过详细的 Prompt 指令和示例引导输出。 适用场景模型不支持 Function Calling或需要推理格式并存。 response client.chat.completions.create( modelgpt-4o, messages[{ role: system, content: 分析用户消息提取日程信息然后按以下格式输出 JSON 规则 - action 为 remind提醒、schedule安排或 query查询 - 时间使用 ISO 8601 格式如 2026-07-12T15:00:00 - 如果无法确定信息对应字段设为 null - confidence 表示解析的可信度从 0 到 1 示例 用户明天下午三点提醒我开会 输出{action:remind,title:开会, time:2026-07-12T15:00:00, is_recurring:false,confidence:0.95} 用户我下周有哪些会议 输出{action:query,title:null, time:null, is_recurring:false,confidence:0.9} }, {role: user, content: user_message}], ) raw response.choices[0].message.content or {} # 提取 JSON——模型可能在 JSON 外附加了解释文本 json_match __import__(re).search(r\{.*\}, raw, __import__(re).DOTALL) if json_match: data json.loads(json_match.group()) else: data {action: query, confidence: 0} return CalendarEvent(**data)三种方案在 100 条测试消息上的表现指标JSON ModeFunction Calling结构化 Prompt格式正确率98%100%87%字段完整性72%99%81%解析准确率83%94%79%额外 Token 消耗低中Schema 占用高Prompt 占用Function Calling 在格式和准确性上全面领先但 Schema 定义本身消耗约 300 Token 的输入预算。结构化 Prompt 的格式正确率最低因为模型偶尔会在 JSON 前后添加解释文本。四、方案选择的决策矩阵场景推荐方案原因工具调用联网/计算Function Calling格式保证 生态支持需要推理 格式并存结构化 PromptFC 不适用推理场景格式简单纯 JSONJSON Mode低开销不支持 FC 的模型结构化 Prompt 后处理唯一选择高精度要求Function CallingSchema 强约束Function Calling 的隐式风险当用户输入信息不足时如帮我安排个事Function Calling 可能会编造参数。必须配合 confidence 字段低于阈值的调用仅做查询而不执行副作用。JSON Mode 的误导很多开发者误以为 JSON Mode 能约束字段类型。实际上它只保证输出是合法 JSON 语法字段名、类型、是否必填完全不受约束。五、总结三种输出格式约束方案的适用边界Function Calling——格式和类型保证最强适合工具调用和结构化数据提取但 Schema 消耗 TokenJSON Mode——只保证 JSON 语法需要后处理校验字段完整性结构化 Prompt——灵活性最高但约束力最弱适合需要推理和格式并存的场景。落地建议首选 Function Calling在用户消息信息不足时配合 confidence 降级JSON Mode 配合 Pydantic 后处理校验字段结构化 Prompt 作为不支持 FC 模型的备选方案必须加后处理容错。