
结构化输出为何“格式正确、答案错误”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_configConfigDict(extraforbid)status:Literal[found,unknown]total:Decimal|Noneevidence:str|Nonemodel_validator(modeafter)defconsistent(self):ifself.statusunknown: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 有错它取决于输入分布。应在人工标注的可回答与不可回答样本上分别评估。自托管时还可以研究被语法保留的概率质量作为诊断信号。但它不是经过校准的正确率也没有可直接套用到所有任务的统一告警阈值。真正需要守住的是业务系统不能把“能解析”当作“可以无条件执行”。