实战指南

AI 数据管道 / Schema 设计器Generation

Schema 生成器实战指南:设计严格的 JSON Schema 与确定性的 AI 提示词

json schemaai 提示词数据抽取结构化输出管道
Senrok Team
作者Senrok Team
发布于

大多数 AI 抽取管道都在同一个地方失败:模型返回了一个几乎对的东西。字段叫 phone_number 而不是 phone。日期是 "2026-07-11" 而不是 "2026-07-11T00:00:00Z"。嵌套对象被拍平了。本该接收结构化输出的下游系统抛错,然后得有人手改这些坏行。

Schema 设计器是我们用来防住这种失败模式的工具。它会一并生成两个工件——一个严格的 JSON Schema 和一个能产出匹配该 schema 输出的确定性 AI 提示词。这一对是从脏的真实世界输入下活下来的最小工作单元。本指南是它的操作手册:如何设计一个在奇怪输入下不崩的 schema,如何写一个模型真的遵循的提示词,以及如何把两者接入生产管道。

两个工件

设计器并列产出两件必须一起设计的事:

  1. 一个 JSON Schema,定义你想要的结构化输出的精确形状、类型和约束。
  2. 一条系统提示词,告诉模型如何从非结构化输入中抽取这个输出。

schema 是契约。提示词是指令。两者都必需;缺一个就是半成品。没有提示词的 schema 让模型自己解读 schema(它会解读,但不一致)。没有 schema 的提示词把输出形状留给随机性。

输出会作为一整块 JSON 导出:schema、提示词、调用签名。你把两者一起塞进管道;管道对每次响应强制执行 schema。

设计一个在脏输入下活下来的 schema

设计抽取 schema 时我们遵守的几条规则。不是理论——这是我们跑过 PDF 发票、合同 PDF、邮件正文、扫描表单之后学到的。

把必填字段说清楚。 如果一个字段必填,就标必填。如果可选,标可选,并决定缺失时模型该做什么(省略、null 或空串)。这里的歧义是下游错误的最大单一来源。

对任何有标准格式的东西用 format format: "date-time" 用于 ISO 8601 时间戳。format: "email" 用于邮箱。format: "uri" 用于 URL。schema 命名了格式,模型就更可能输出正确格式的值。

约束枚举。 如果一个字段只能是三个值中的一个,用 enum 声明。模型会遵循约束,你就不会在输出里清理 "pending" vs "Pending" vs "PENDING"

刻意地嵌套对象。 扁平 schema 读着容易但难校验。如果输入是多段文档(带明细行的发票、带条款的合同),用匹配的嵌套。line_items 数组带自己的 item schema 比 15 个顶层的 line_item_1_* 字段容易强制。

在每个对象层加 additionalProperties: false 这是抓模型漂移最有效的一个设置。如果 schema 说对象正好有四个字段而模型返回了五个,是 schema 错了,不是模型错了。最严格的模式在解析时就抓到 bug,而不是下游。

写一个模型真遵循的提示词

schema 告诉模型输出长什么样。提示词告诉模型怎么产出这个输出。提示词侧的几条规则:

把边界情况说清楚。 "如果日期不明确,返回 null" 比 "抽取日期" 好。第一条指令去掉了一类错误;第二条邀请模型去猜。

给一个例子,不要给三个。 一个做完的例子足够锚定格式。三个例子挤占提示词,邀请模型最贴近最后一个。如果你要三个例子,多半要修 schema。

告诉模型忽略什么。 "忽略公司地址这类 boilerplate" 和 "忽略页脚文字" 是发票和合同抽取里最有效的两条指令。它们告诉模型噪声在哪,防止它把页脚内容灌进你的 schema。

系统消息放指令,用户消息放文档。 一个常见 bug 是把抽取指令和文档放同一条消息。模型会把文档当主内容、把指令当上下文。分开更快、更便宜、更可靠。

抽取工作把 temperature 约束到 0。 抽取是确定性的;schema 是契约。temperature 0.0 是对的设置。更高的 temperature 留给创造性工作。

常见模式

我们生产里用过的一组 schema + 提示词对。它们不是模板——是起点。按你的输入调字段名和约束。

发票抽取

schema 含 invoice_numberinvoice_datedue_datevendor.namevendor.addressline_items[](含 descriptionquantityunit_pricetotal)和 total_amount。必填:invoice_numberinvoice_dateline_itemstotal_amount。可选:due_datevendor.address。提示词说:"抽取发票号、日期、供应商、明细行。如果明细行在表格里,保持顺序。如果值看不清,返回 null。"

合同条款抽取

schema 含 parties[](含 nameroleentity_type)、effective_dateterm_lengthtermination_clausegoverning_lawkey_obligations[]。提示词说:"抽取协议各方、生效日期、合同期限、终止条件、适用法律、以及各方的核心义务。忽略签名块和 recitals 这类 boilerplate。"

邮件分流

扁平 schema 含 intent(枚举:inquirycomplaintrequestother)、urgency(枚举:lowmediumhigh)、summary(字符串,1-2 句)、requires_response(布尔)。提示词说:"按意图和紧急度对邮件分类。用一两句话总结它。决定它是否需要回复。"

接入生产管道

设计器的导出是为嵌入管道而生的。典型集成:

  1. 解析时 schema 校验。 每条模型响应在写入数据库前都按 schema 校验。校验失败进人工审核队列,不要静默丢弃。
  2. 校验失败时带反馈重试。 如果 schema 没通过,把原始输入和校验错误信息一起送回模型。模型通常在第二轮就修好。
  3. 重试 N 次后升级人工。 两次重试后,转人工。模型第三次也不会对,长重试循环的成本不值。
  4. 按 schema 跟踪校验成功率。 60% 通过率的 schema 是坏 schema。要么 schema 对输入太严,要么提示词不够具体。跟踪这个指标,掉下来就修 schema。

整个循环就这些。schema 是契约;提示词是指令;校验器是闸门;人工是兜底。

什么情况下 schema 不是对的工具

几种 JSON Schema 不是对的抽象的场景:

  • 输出是长文本响应。 schema 用于结构化输出。如果模型要写 200 字总结,schema 就是错形状。用一个带 type: "string" 和最大长度的单字段,或者完全跳过 schema。
  • 输出是带成千 label 的分类。 带很大 enum 数组的 schema 又贵又慢。对高基数分类,用多阶段:先分到大桶,再细化。
  • 输出是多模态的。 schema 处理不了图片或音频输出。如果模型既产结构化数据又生成图片,schema 是更大输出规格的一部分。

上述任何一种情况下,对的解法是另一种抽象。Schema 设计器是对结构化抽取对的工具。它不是对所有事对的工具。

什么时候该升级到自建系统

如果你通过设计器跑的 schema 超过几个,就到了一个自建系统更划算的临界点。几个信号:

  • 你有一个几十个 schema 的库,需要一个 registry 来管理。
  • 你需要带版本的 schema,并且能在新版本把通过率拉下来时回滚。
  • 你需要一个 CI 闸门,在部署新提示词版本前对最新模型 checkpoint 跑校验套件。
  • 你需要在团队间强制 schema 合规,不只是在一个项目里。

上述任何一种情况下,对的解法是一套自定义 schema 管理系统,可能背靠一个专用的评估 harness。免费设计器是合适的起点,不是终局。


设计器地址:/tools/schema-generator。完全在浏览器里跑;没有任何东西发到服务器。你设计的 schema 和提示词能作为一整块 JSON 导出,准备好塞进管道。