news 2026/10/30 2:30:31

结构化输出为何“格式正确、答案错误”?JSON Schema 的能力边界

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
结构化输出为何“格式正确、答案错误”?JSON Schema 的能力边界

结构化输出为何“格式正确、答案错误”?JSON Schema 的能力边界

JSON 能解析、字段也都符合 Schema,业务结果仍然可能错。结构化输出约束的是可接受的形式,字段是否来自证据则是另一层问题。

一个必填下拉框没有“不知道”选项时,用户只能随便选。模型遇到类似 Schema 也可能在合法选项中给出一个缺乏依据的值。本文解释约束解码的机制,并整理 Schema 与调用端需要共同承担的检查。

1. 约束解码如何工作

模型逐步生成 Token。约束解码根据当前语法状态屏蔽不允许的候选,再对保留候选重新归一化并选择输出。

设原始分布为p(t),合法集合为A,那么一种常见的约束方式可表达为:

p'(t) = p(t) / sum(p(u) for u in A), t in A p'(t) = 0, t not in A

这解释了为什么 Schema 只能限制选项:模型原本更倾向表达“未知”,但 Schema 只接受high/medium/low,最终仍得从三者中选一个。这里的概率只是机制示意,不能解释成某个字段真实的业务置信度。

2. “总能得到合法 JSON”也有前提

原文标题使用了“总是合法”的强表述,需要补上条件。请求可能被拒绝、响应可能截断、服务可能返回错误,Schema 关键词的支持范围也因实现而异。

JSON 模式、严格 Schema 模式和普通工具调用,也不应混为一谈。调用方应检查自己实际启用的能力,并对完整响应执行本地验证。

合法 JSON 还可能包含错误金额、不存在的供应商或证据不支持的分类。结构校验通过,只能把这类问题从“解析失败”推进到“语义校验”。

3. 给未知情况设计合法分支

下面是新增的 Pydantic 2 本地校验示例。证据不足时允许空值,并通过一致性规则避免出现“unknown 但仍然有金额”的矛盾。

fromdecimalimportDecimalfromtypingimportLiteralfrompydanticimportBaseModel,ConfigDict,model_validatorclassExtraction(BaseModel):model_config=ConfigDict(extra="forbid")status:Literal["found","unknown"]total:Decimal|Noneevidence:str|None@model_validator(mode="after")defconsistent(self):ifself.status=="unknown":ifself.totalisnotNoneorself.evidenceisnotNone:raiseValueError("unknown 必须使用空值")elifself.totalisNoneornotself.evidenceornotself.evidence.strip():raiseValueError("found 必须包含金额与证据")ifself.totalisnotNoneandnotself.total.is_finite():raiseValueError("金额必须为有限值")returnself sample='{"status":"unknown","total":null,"evidence":null}'print(Extraction.model_validate_json(sample).model_dump())

金额使用 Decimal 有助于避免后续财务计算的二进制浮点误差,但数值范围、币种、精度和退款的符号仍应由具体业务定义。这里不预设所有金额都非负。

本地模型约束也不代表服务端支持同样的 JSON Schema 关键词。发送给推理服务的 Schema 应适配其支持子集,本地再执行完整业务检查。证据字符串存在,不等于证据真的支持金额,还应核对来源。

4. 调用端应分层处理失败

先处理传输错误和服务端拒绝,再检查输出是否完整,然后解析和校验结构,最后核对证据及业务规则。截断响应应进入重试或人工复核流程,不应通过补括号就当作完整结果。

对于引用 ID,确认它确实来自本次输入;对于枚举决策,验证是否满足业务条件。模型自报的confidence不能代替标注样本上的校准评测。

5. 空白循环与输出上限

JSON 语法允许字段之间存在空白。某些模型和复杂 Schema 组合可能重复生成空白,直到触发输出上限。原文据此建议限制输出长度,并为已知和未知情况提供完整示例。

自托管 vLLM 可检查disable_any_whitespace配置;核对时文档说明该选项支持 xgrammar 和 guidance 后端。它压缩字段之间的空白,不负责修复错误字段值。vLLM 结构化输出配置

原文还建议调整字段顺序、把解释写在结论前。不同解码器和模型的行为有差异,不应将字段顺序写成必然提高准确率的规律。可以记录简短证据摘要,并在自己的任务上做对照实验。

6. 评测不能只统计解析成功率

至少同时看完整响应比例、Schema 通过率、字段正确率、未知样本处理情况和可回答样本的误拒率。

unknown比例高不一定更好,比例为零也不自动证明 Schema 有错:它取决于输入分布。应在人工标注的可回答与不可回答样本上分别评估。

自托管时还可以研究被语法保留的概率质量,作为诊断信号。但它不是经过校准的正确率,也没有可直接套用到所有任务的统一告警阈值。真正需要守住的是:业务系统不能把“能解析”当作“可以无条件执行”。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/30 2:29:48

FunASR安装

在 Windows 上配置和运行 FunASR,最省事的路子是走 Docker 一键部署,或者用现成的整合包‌。下面按不同需求给出对应方案。🐳 方案一:Docker 一键部署(推荐,适合离线转写服务) 这是目前最省心的…

作者头像 李华
网站建设 2026/10/30 2:26:28

浏览器网页加载流程抓包复现

在进入实验室之前,我们已经浅浅学过计算机网络原理,大概了解了网络如何运行,了解TCP/IP四层模型和OSI七层模型,那么,数据从浏览器到服务器经历了哪些层?HTTP请求和响应长什么样?为什么输入网址后…

作者头像 李华
网站建设 2026/10/30 2:25:49

记一次 PGP 驱动残留导致的开机蓝屏修复

输对 BitLocker 48 位恢复密钥,磁盘显示已解锁,然后——蓝屏,无限循环。朋友的笔记本就这么折腾了我一整天,最后发现元凶是一个 2010 年的老软件残留驱动。这篇把从 BCD 重建到 UpperFilters 残留排查的完整过程记下来&#xff0c…

作者头像 李华