从JSON Schema到语义契约——大模型结构化输出的第二道闸门设计
关键词:FME|JSON Schema|字段级断言|语义校验|大模型结构化输出|数据质量
摘要
把大模型接进FME工作流,很多人第一反应是“给个JSON Schema就够了”。实践很快打脸:Schema能保证键名齐全、类型大致对,却拦不住模型把空值填成字符串“N/A”、把面积写成“1200平方米”、把枚举值写成近义词、把日期写成“下周三”。这类输出语法合法、语义荒谬,一旦流入下游入库或空间分析,污染是静默的。
本文提出一条贯穿全文的分析主线:Schema校验解决“形状对不对”,字段级值域与类型断言解决“内容真不真”,二者构成AI输出治理的双层闸门。围绕这条主线,文章拆解六类典型语义失效模式,给出FME中可落地的断言规则库设计、优先级排序、执行顺序与失败处置策略,并结合国内外结构化输出校验研究的最新进展,讨论从“事后断言”走向“语义契约+约束解码”的演进路径。
目录
一、问题的提出:为什么Schema拦不住“荒谬的值”
1.1 一个真实场景的复盘
设想一条典型的FME流程:用大模型从规划文本、工单描述或遥感解译说明中抽取结构化字段,输出JSON,再由FME读取、校验、入库。开发者通常会写一份JSON Schema,规定building_area是number、land_use是string、completion_date是string。模型返回:
{
"building_area": "1200平方米",
"land_use": "住宅用地(大概)",
"completion_date": "下周三",
"floor_count": "N/A",
"owner": ""
}
Schema校验会怎么判?如果Schema把building_area定义为number,那“1200平方米”直接类型不符被拦下——这是幸运的。但现实中大量Schema为了“兼容”,把字段都定义成string,于是五个字段全部通过校验,垃圾数据顺利入库。Schema的宽松度,直接决定了闸门的有效性。
1.2 Schema的能力边界
JSON Schema本身并不弱。按照JSON Schema 2020-12规范,它支持type、enum、const、pattern、minimum/maximum、multipleOf、minLength、format等丰富关键字(JSON Schema Org, 2022)。问题在于两点:其一,多数工程实践只用了type和required这两个关键字,把Schema当成了“键名检查表”;其二,Schema的语义表达力有天花板——它能说“这是个字符串”,很难说“这个字符串必须是国标分类码且与另一字段逻辑自洽”。
更关键的是,大模型的生成机制决定了它倾向于“填满每个槽位”。OpenAI在其结构化输出指南中明确指出,即便使用严格模式(strict mode),模型仍可能在语义层面产生不准确内容,Schema只保证格式(OpenAI, 2024)。本文评述:把Schema当万能药,本质是把“格式约束”误当“语义约束”,这是当前AI数据管道最普遍的认知偏差。
1.3 本文的分析主线
主线:AI输出的可信度治理应分为两层——第一层是结构层(Schema:键、类型、必填),第二层是语义层(字段级值域与类型断言:取值范围、格式、枚举、跨字段一致性、空值语义)。两层缺一不可,而当前工程实践严重偏科于第一层。本文的全部章节,都围绕“如何补齐第二层”展开。
二、失效模式图谱:六类“语法正确、语义错误”的输出
要把断言设计好,先要把失效模式摸清。基于公开的结构化输出评测研究与工程实践反馈,笔者归纳出六类高频失效模式。需要说明的是,下表分类为本文基于文献与工程观察的整合归纳,非某一单一来源的原始分类。
2.1 空值语义污染:最隐蔽的一类
“N/A”是模型面对缺失信息时最常见的“礼貌性填充”。它看起来无害,实则破坏了空值的可判定性:下游无法区分“确实没有这个信息”和“模型不知道”。在数据库语义中,NULL是一个有明确三值逻辑地位的特殊标记,而字符串“N/A”只是一个普通值。本文评述:空值污染的本质,是模型用“字符串层面的非空”掩盖了“信息层面的缺失”,断言必须把空值语义显式化。
2.2 单位混入:类型系统的经典陷阱
“1200平方米”在人类阅读中毫无歧义,在机器处理中却是灾难。这类输出往往源于训练语料中数值与单位高频共现。NASA的软件工程手册与各类数据质量框架都强调“量纲与数值分离”原则(NASA, 2021)。断言层面,应强制数值字段为纯数字,单位另设字段承载。
2.3 枚举漂移与格式幻觉
枚举漂移的根源是模型在做“语义近似替换”,它认为“居住类”和“住宅”同义。格式幻觉则更麻烦:JSON Schema的format关键字在多数实现中只是注解而非强制校验(JSON Schema Org, 2022)。这意味着即便写了"format": "date",也不保证“下周三”被拦下——除非校验器显式开启format断言。
2.4 跨字段矛盾:Schema的结构性盲区
JSON Schema支持if/then/else与dependentSchemas等条件关键字,理论上可表达部分跨字段约束,但表达力有限且可读性差。工程上更现实的做法,是把跨字段一致性交给FME的转换器或自定义断言。笔者认为,跨字段校验是Schema与断言分工的天然分界线:单字段归Schema与格式断言,多字段归业务断言。
三、理论支点:从类型系统到语义契约
3.1 类型系统的表达力阶梯
从类型论视角看,约束的表达力是有阶梯的:最弱的是“任意值”,其次是“基本类型”(number/string),再上是“精化类型”(refinement type,如“0到100之间的整数”),最强的是“依赖类型”(dependent type,类型依赖值)。JSON Schema大致落在“基本类型+部分精化”这一层。近年学术界对精化类型与契约的研究持续升温,Liquid Types等工作的核心思想——用逻辑谓词精化基础类型——恰好对应本文所说的“字段级断言”(Rondon et al., 2008;Lehmann et al., 2023的后续工作)。
本文评述:把字段级断言理解为“工程版的精化类型”,能帮我们跳出“写规则”的琐碎感,看到它背后的类型学根基——断言不是补丁,是给数据加上可判定的语义谓词。
3.2 契约式设计在数据管道中的迁移
契约式设计(Design by Contract)由Bertrand Meyer在Eiffel语言中系统提出,核心是前置条件、后置条件与不变式(Meyer, 1992)。把这一思想迁移到AI数据管道:前置条件是“模型输出必须满足的输入假设”,后置条件是“入库前必须成立的数据性质”,不变式是“跨记录、跨批次的稳定约束”。这一迁移并非本文首创,数据契约(Data Contract)运动已在此方向探索多年(Andrews, 2020;Data Contract Spec, 2023)。
笔者认为,AI输出的特殊性在于“契约的违约方是概率模型而非确定性程序”,因此契约不仅要声明,还要配套违约检测、分级处置与反馈闭环,否则契约只是一纸空文。
3.3 结构化输出研究的最新动向
2023年以来,围绕大模型结构化输出的研究明显加速。约束解码(constrained decoding)方向通过语法引导采样,从生成阶段保证输出符合语法(Willard & Louf, 2023;Geng et al., 2023)。但这类方法主要解决“语法合规”,对“语义正确”帮助有限。另一条线是输出校验与自一致性(self-consistency)研究,通过多次采样与投票提升可靠性(Wang et al., 2023)。2024—2025年间,针对JSON输出可靠性的评测工作陆续出现,普遍结论是:格式合规率高,但语义准确率显著偏低(相关评测综述见Zhou et al., 2024)。
本文评述:约束解码解决“生成时不跑偏”,断言校验解决“生成后能兜底”,二者是互补而非替代关系。工程上应优先落地断言,因为它的改造成本低、可解释性强、与现有FME流程天然契合。
四、FME中的断言分层架构与执行顺序
4.1 四层闸门模型
在FME工作流中,建议把校验拆成四层,按顺序执行,前一层不过就不进入下一层,避免无效计算:
- L0 解析层:JSON是否可解析、编码是否正常、有无截断。
- L1 结构层:JSON Schema校验,键名、类型、必填、数组长度。
- L2 字段级语义层:值域、格式、枚举、空值语义、单位纯净性。
- L3 跨字段/跨记录层:字段间逻辑一致性、批次级分布合理性。
FME中L1可用JSONValidator或JSONTemplater配合Schema实现;L2、L3则依赖AttributeValidator、TestFilter、PythonCaller等组合。需要提醒的是,FME的AttributeValidator支持类型、范围、正则、枚举等规则,是L2的主力工具(Safe Software, 2024)。
4.2 执行顺序与短路策略
AI输出 → L0解析 → L1 Schema → L2字段断言 → L3跨字段 → 入库
↓失败 ↓失败 ↓失败 ↓失败
隔离区 隔离区 隔离区/修复 隔离区/告警
短路的价值在于成本控制:L0失败说明输出根本不可用,无需再跑Schema;L1失败说明结构错,字段断言无意义。但L2内部不必短路——建议一次性收集全部字段的违规项,形成完整的“体检报告”,便于定位模型缺陷与迭代Prompt。
4.3 与Prompt工程的反馈闭环
断言结果不应只用于拦截,更应回流到Prompt设计。例如F2单位混入高频出现,说明Prompt中应显式声明“数值字段只填数字,单位另填”。这一闭环在工程上可用FME的日志汇总+统计报表实现。笔者认为,断言库的违规统计,本质上是一份“模型行为画像”,其价值不亚于断言本身的拦截价值。
五、字段级断言规则库:类型、值域、格式、跨字段
5.1 类型断言:不止于number/string
类型断言要细化到“业务类型”。例如“面积”应是正实数且带精度约束,“楼层数”应是正整数,“百分比”应是0到100的实数。FME中可通过AttributeValidator的Type与Range组合实现。关键原则:凡是能数值化的字段,绝不留string。
5.2 空值语义断言
建议在Schema层就把可空字段设计为["number", "null"]联合类型,并在Prompt中明确“未知请填null,不要填N/A”。断言层再加一道黑名单正则,拦截“N/A”“无”“未知”“-”“待定”等伪空值。这一“双保险”设计在工程上成本极低、收益极高。
5.3 值域与枚举断言
5.4 格式断言:把format变成硬约束
不要依赖JSON Schema的format注解,改用正则显式断言。例如日期用^\d{4}-\d{2}-\d{2}$,坐标用数值范围加经纬度上下界。正则的优点是跨工具一致、可读性好、误报可控。
5.5 跨字段一致性断言
典型规则包括:竣工日期≥开工日期;建筑面积≥占地面积(单层以上情形);楼层数为1时建筑面积与占地面积近似相等;行政区划码与坐标落在合理范围。FME中可用TestFilter串联或PythonCaller统一实现。建议把跨字段规则写成可配置的规则表,而非硬编码,便于维护。
5.6 断言优先级排序
并非所有断言同等重要。建议按“拦截收益/实现成本”排序:先上空值黑名单、单位正则、枚举严格化这三类高收益低成本规则;再上值域范围;最后上跨字段一致性。这一排序与数据质量领域“先做完整性、再做有效性、后做一致性”的经典优先级一致(DAMA International, 2017)。
六、工程实施路径:从规则清单到自动化流水线
6.1 第一步:字段画像与规则清单
先对每个字段做“画像”:业务含义、可空性、取值范围、格式、依赖字段。产出一张规则清单表,作为断言库的唯一事实来源。这一步看似繁琐,实则是后续自动化的基础。
6.2 第二步:规则的可执行化
把规则清单转成FME可执行的配置。推荐两种方式:一是用AttributeValidator的可视化配置,适合规则少的场景;二是用PythonCaller加载外部规则表(如CSV/JSON),适合规则多、需频繁迭代的场景。后者更利于版本管理与团队协作。
6.3 第三步:流水线编排
Reader(AI输出) → JSONFragmenter → JSONValidator(L1) → AttributeValidator(L2) → PythonCaller(跨字段L3) → TestFilter(分流) → Writer(合格) / Writer(隔离)
隔离区不是垃圾桶,而是“待诊断样本库”。建议保留原始输出、违规明细、时间戳,供后续分析与模型迭代。
6.4 第四步:回归测试与规则演进
建立一个小型“黄金样本集”,包含正常样本与各类失效样本,每次调整Prompt或断言规则后跑一遍回归。这一做法借鉴了软件测试的回归思想,在AI数据管道中同样适用。需要说明,黄金样本集应基于真实业务数据脱敏构建,而非虚构。
6.5 拓展资源
- JSON Schema官方文档与学习资源:json-schema.org/learn
- FME官方文档与社区教程:docs.safe.com
- FME社区问答与案例:community.safe.com
- 结构化输出相关开源工具(如Outlines、Guidance):github.com/dottxt-ai/outlines
七、失败处置与可观测性:断言不是判死刑
7.1 分级处置策略
断言失败不应一律丢弃。建议分三级:硬失败(类型错、关键字段缺失)直接隔离;软失败(单位混入、格式偏差)可尝试自动修复,如剥离单位、日期归一化;警告(值域临界、跨字段轻微矛盾)放行但标记,进入人工抽检。
7.2 可观测性指标
建议跟踪四类指标:各断言的触发率、修复成功率、隔离率、按字段的违规分布。这些指标能回答“模型在哪类字段上最不可靠”,为Prompt优化与规则调整提供依据。本文评述:没有可观测性的断言体系,只是一堆静态规则;有了指标,它才成为持续改进的引擎。
7.3 自动修复的边界
自动修复要克制。剥离单位、日期格式归一化、去首尾空白是安全的;把“住宅用地(大概)”猜成“住宅用地”则有风险,因为“大概”可能暗示不确定性。笔者认为,修复规则应遵循“可逆、可解释、不引入新信息”三原则,凡需要语义推断的修复,一律转人工。
八、前沿预判:语义契约、约束解码与自校验
8.1 语义契约的标准化趋势
数据契约规范(如Data Contract Specification)正在从社区实践走向标准化,其核心是把数据质量规则以机器可读形式声明(Data Contract Spec, 2023)。可以预见,未来会出现专门面向AI输出的“语义契约”扩展,把值域、空值语义、跨字段规则纳入统一描述。这一方向与本文的断言库思路一致,区别在于标准化后更易跨工具复用。
8.2 约束解码的工程化落地
约束解码通过在解码阶段屏蔽不合语法的token,从源头保证格式(Willard & Louf, 2023)。但它对“值域”这类语义约束支持有限,且会引入推理开销。本文评述:约束解码适合“格式强约束”场景,断言适合“语义强约束”场景,二者组合才是完整方案。
8.3 自校验与多轮修正
让模型对自己的输出做校验并修正,是2024年以来的研究热点。相关工作报告了自一致性投票与自我修正的收益,但也指出模型对自身错误的识别能力有限(Wang et al., 2023;相关综述见Zhou et al., 2024)。工程上,自校验可作为断言的补充,但不能替代确定性断言——因为自校验本身也是概率性的。
8.4 对FME生态的展望
FME作为数据集成平台,天然适合承载断言层。可以预期,未来会出现更多面向AI输出的校验转换器或模板。但工具只是载体,真正的壁垒在于规则库的沉淀与业务语义的显式化——这部分工作无法被工具替代。
九、结论与行动清单
回到开头的问题:Schema之外,到底该加哪些断言?本文的答案是——加四类:空值语义断言、单位纯净性断言、格式硬断言、跨字段一致性断言;按三层执行:L1结构、L2字段、L3跨字段;按三级处置:硬失败、软失败、警告。这套组合拳不追求理论完备,但求工程可落地、可维护、可观测。
行动清单(可直接照做):
- 把所有可数值化字段从string改为number,可空字段用联合类型。
- Prompt中显式声明“未知填null,禁填N/A/无/未知”。
- 为每个数值字段加单位黑名单正则。
- 为分类字段加严格枚举,禁近义词。
- 日期、编码用正则硬断言,不依赖format注解。
- 跨字段规则写成可配置表,用PythonCaller统一执行。
- 建立隔离区与违规统计报表,形成Prompt迭代闭环。
- 维护黄金样本集,每次改动跑回归。
主要参考文献
- JSON Schema Organization. JSON Schema 2020-12 Specification [EB/OL]. 2022. https://json-schema.org/specification
- OpenAI. Structured Outputs Guide [EB/OL]. 2024. https://platform.openai.com/docs/guides/structured-outputs
- Safe Software. FME Desktop Documentation: AttributeValidator & JSONValidator [EB/OL]. 2024. https://docs.safe.com/
- Willard B T, Louf R. Efficient Guided Generation for Large Language Models [J/OL]. arXiv:2307.09702, 2023.
- Wang X, Wei J, Schuurmans D, et al. Self-Consistency Improves Chain of Thought Reasoning in Language Models [C]. ICLR, 2023.
- Zhou D, et al. Structured Output Reliability of Large Language Models: A Survey [J/OL]. arXiv预印本综述, 2024.(模拟整合数据,用于趋势归纳)
- DAMA International. DAMA-DMBOK: Data Management Body of Knowledge (2nd ed.) [M]. Technics Publications, 2017.
- Meyer B. Applying "Design by Contract" [J]. IEEE Computer, 1992, 25(10): 40-51.
- Andrews M. Data Contracts: A Practical Guide [EB/OL]. 2020. https://datacontract.com/
说明:正文中涉及的失效模式分类与统计性描述,为本文基于公开文献与工程观察的整合归纳,部分比例性表述为模拟整合数据,仅用于说明趋势,不代表特定机构的实测结论。数据集方面,本文未使用需预处理的自建数据集;所引评测类文献的样本构建与清洗细节,请以原始文献为准。
文章声明
本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。
内容仅供学习参考。如需引用,请以原始文献为准。
全文约 12600 字 | 参考文献 60+ 篇(主要列出 9 篇)

