跨模型结构化输出:用一份领域 Schema 隔离供应商差异
OpenAI、Anthropic 与 Gemini 都提供结构化输出能力,但它们的请求字段、支持的 JSON Schema 子集、严格程度、流式事件和错误形态并不相同。最危险的抽象是建立一个“通用参数字典”,然后把 OpenAI 字段名发给所有供应商。更稳健的设计是一个领域 Schema,加三个独立 adapter,各自遵守官方合同。
领域类型先于供应商 Schema
假设产品需要对支持工单分类。领域层定义版本化结果,不导入任何 SDK:
from typing import Literal
from pydantic import BaseModel, Field
class TicketDecisionV1(BaseModel):
schema_version: Literal["ticket-decision.v1"]
category: Literal["billing", "bug", "account", "other"]
urgency: int = Field(ge=1, le=5)
evidence: list[str] = Field(min_length=1, max_length=4)
needs_human: bool
枚举来自业务,不来自某家模型的推荐。Schema 变更需要版本:新增可选字段可以保持兼容,改枚举含义或必需字段则创建 v2。保存结果时同时记录 schema、provider、model id、adapter 和 prompt 版本。
每个 adapter 自己翻译
OpenAI adapter 按其结构化文本格式提交 schema;Anthropic adapter 使用其官方 structured outputs 接口;Gemini adapter 使用 response schema 配置。三者都返回统一 TicketDecisionV1 或统一错误类型,但不假装请求参数相同。
adapter 启动时验证领域 schema 是否落在供应商支持子集。遇到不支持 keyword,不应静默删除约束;要么用应用层后验证补上并记录差异,要么拒绝该 provider。保留一张能力表:额外属性、枚举、嵌套、optional、数组上限、递归、流式和拒答怎样表示。
两层验证缺一不可
供应商保证或努力保证 JSON 符合 schema,只解决语法和部分结构。解析后仍运行领域验证:证据必须来自输入,紧急级别与规则一致,敏感工单强制人工,文本长度和字符集符合存储限制。模型不能通过给出 schema 合法值来授权退款或账户变更。
错误分成 transport、provider refusal、schema unsupported、parse、domain validation 和 policy denial。只有瞬时 transport 或明确可修复格式错误适合有限重试。领域规则失败通常应转人工或降级,不要无限要求模型“再试一次直到通过”。
流式输出停在展示层
JSON 在结束前可能不是合法对象。界面可以显示进度,但业务逻辑必须等待完整解析与验证。各家流式事件不同,adapter 内部累积并在完成时提交领域对象;上游不依赖 token 或 event 名称。连接中断丢弃半对象或标为 incomplete,不能把已看到字段当批准结果。
如果产品确实需要增量结构,设计事件协议而不是解析半截 JSON,例如 classification_started、evidence_found 和最终 decision_committed。只有最后事件携带经过验证的对象。
评测可移植性
同一数据集、领域 schema、prompt 意图和后验证规则对三个 adapter 运行。比较解析成功、领域合格、事实正确、拒答、延迟、token 与错误类型。prompt 语法可以为供应商本地化,但记录差异;不要为了“公平”强迫完全相同字符串,也不要偷偷给某家更多证据。
加入额外字段、错误枚举、恶意输入要求改变 schema、长数组、Unicode、空输出和拒答案例。契约测试使用 mock provider response 验证 adapter,不需每次调用付费 API;定期集成评测再验证真实模型。
供应商切换不是一个布尔开关
fallback 前确认数据政策、模型能力和 schema 支持。主 provider 超时时切到备用可能造成两次成功结果,使用请求 id 与幂等保存。将 provider 选择记录在结果中,监控不能把不同模型混成一个指标。
结论
跨模型结构化输出的稳定层不是共同参数,而是版本化领域 Schema、独立 adapter、统一错误与第二层业务验证。尊重每家支持子集和流式语义,无法表达的约束显式补验或拒绝。这样供应商变化被限制在边界,业务代码只依赖自己能够解释和验证的对象。