多模型 API 网关中的结构化输出:JSON 架构、工具调用和语义护栏
跨多个 LLM 提供商的可靠结构化输出的实用适配器模式:规范化模式、验证响应、处理工具调用、记录故障并在不安全操作到达生产工作流程之前阻止它们。
提示模型“返回 JSON”不是生产合同。它可能会生成具有错误枚举的有效 JSON、省略所需的业务规则或自信地请求用户从未授权的操作。在多提供商工作流程中,问题变得更加困难:每个提供商都公开不同的结构化输出和工具使用机制,并且每个提供商仅支持 JSON 架构宇宙的一部分。
实际的解决方案不是一个神奇的提示。它是一种分层网关模式:标准化开发人员所需的架构,在可能的情况下将其转换为提供者本机结构化输出或工具调用格式,验证返回的对象,并在出现任何副作用之前应用语义护栏。
本指南区分了经常混合在一起的三个不同目标:
- 语法有效性:响应可解析JSON.
- 架构有效性:JSON 匹配必填字段、类型、枚举和结构规则。
- 业务正确性:该对象是安全的、忠实于用户意图并且对下游操作有效。
生产失败:有效JSON,错误操作
考虑使用支持自动化来路由收到的工单:
{
"ticket_id": "t_481",
"category": "billing",
"priority": "urgent",
"action": "refund_customer",
"amount_usd": 499
}
该对象在语法上是有效的。如果 action 是字符串并且 amount_usd 是数字,它甚至可以传递一个简单的模式。但它仍然可能是错误的。也许客户只要求发票副本。也许 100 美元以上的退款需要经理批准。也许用户根本无权触发退款。
结构化输出可减少解析失败。它们不会取代授权、政策检查、库存检查、定价检查、幂等性或风险操作的人工确认。
事实:提供商结构化输出模式承诺什么和不承诺什么
提供商格局变化很快,但有几个稳定的事实对架构很重要:
- JSON 模式可以帮助生成有效的 JSON,但有效的 JSON 与符合特定架构不同。
- 提供者原生结构化输出模式旨在提高架构遵从性,但它们通常仅支持JSON架构的子集。
- 工具调用通常比自由格式更适合操作 JSON,因为模型会选择声明的工具并返回结构化参数,而应用程序仍然负责执行。
- 不同的提供商公开不同的合约。一种可能使用严格的 JSON 架构响应格式,另一种可能使用工具输入架构,另一种可能需要验证和重试回退。
- 即使架构有效的输出在到达数据库、工作流程或付费操作之前也可能存在语义错误。
架构含义很简单:兼容OpenAI的API可以标准化客户端接口,但可靠性层仍必须了解提供程序的功能并在生成后验证输出。
推荐架构:结构化输出适配器
在应用代码和提供商 API 之间使用网关端适配器。应用程序发送一个模式意图。网关将该意图映射到最强大的支持提供程序机制。
1.接受来自应用程序的一个规范化请求
客户端不需要为每个提供商提供单独的代码路径。实用的请求信封包括模型首选项、任务输入、架构、架构元数据和风险级别:
{
"model": "auto:accurate",
"messages": [
{"role": "system", "content": "Extract invoice fields. Do not infer missing values."},
{"role": "user", "content": "Invoice text..."}
],
"structured_output": {
"schema_id": "invoice_extraction",
"schema_version": "2026-08-01",
"mode": "json_schema",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["invoice_number", "vendor_name", "total", "currency", "due_date"],
"properties": {
"invoice_number": {"type": "string"},
"vendor_name": {"type": "string"},
"total": {"type": "number", "minimum": 0},
"currency": {"type": "string", "enum": ["USD", "EUR", "GBP"]},
"due_date": {"type": "string", "format": "date"},
"confidence": {"type": "number", "minimum": 0, "maximum": 1}
}
}
},
"metadata": {
"workflow": "accounts_payable",
"risk_level": "medium"
}
}
此合同为网关提供了足够的信息来选择提供商本机实现、运行验证并记录有意义的失败数据。
2.维护提供商能力矩阵
网关应保留机器可读的功能矩阵,而不是依赖于诸如“所有 OpenAI 兼容模型都支持相同架构行为”之类的假设。有用的矩阵包括:
- 提供商和型号名称。
- 支持JSON模式。
- 支持JSON架构响应格式。
- 支持工具调用。
- 支持严格架构模式。
- 已知JSON架构子集限制。
- 并行工具调用是否与严格架构模式兼容。
- 请求的模式不受支持时的后备行为。
能力记录示例:
{
"provider": "provider_a",
"model": "model_x",
"json_mode": true,
"json_schema_response": true,
"tool_calls": true,
"strict_schema": true,
"schema_limitations": ["no oneOf", "limited format validation"],
"fallback": "reject_or_route_to_compatible_model"
}
该矩阵应进行版本控制和测试。当提供商更改行为或添加新模型时,应在生产路由之前验证结构化输出兼容性。
3.转换为最强大的提供商原生合约
适配器应遵循明确的优先顺序:
- 当所选模型和架构支持时,使用严格的提供商原生结构化输出。
- 使用提供商原生工具调用操作和类似函数的任务。
- 使用非严格结构化输出或 JSON 模式,在严格模式不可用时进行验证和重试。
- 拒绝请求,路由到兼容的后备模型,或针对高风险工作流程返回无操作响应。
不要悄悄地将高风险操作从严格架构模式降级为“尽力而为JSON”。如果应用程序请求严格的行为,而所选的提供商无法支持它,则网关应通过错误、路由决策或显式降级标志来使其可见。
执行前的三个验证层
第 1 层:解析验证
首先,确定响应是否可以解析为预期的信封。在格式错误的 JSON、缺少工具调用块、截断的响应或混合自然语言以及合同禁止的情况下快速失败 JSON。
function parseStructuredResponse(raw) {
try {
return { ok: true, value: JSON.parse(raw) };
} catch (error) {
return { ok: false, failure_type: "parse_failure", error: String(error) };
}
}
提供程序原生工具调用可能不需要解析原始文本 blob,但仍需要信封验证:模型是否选择了已知工具、是否提供了参数以及是否按预期停止工具执行?
第 2 层:JSON架构验证
接下来,使用服务器端验证器根据声明的架构验证对象。即使提供者声称严格的模式支持,也要这样做。网关端验证为您提供一致的故障日志记录、防止集成错误并捕获下游不兼容性。
const validate = schemaValidator.compile(schema);
const valid = validate(object);
if (!valid) {
return {
ok: false,
failure_type: "schema_failure",
errors: validate.errors
};
}为了实现可移植性,请在设计架构时考虑公共子集:
- 首选显式
type、required、properties、enum和additionalProperties: false。 - 避免复杂的组合,例如深度嵌套的
oneOf、anyOf和条件架构,除非您知道目标提供程序支持它们。 - 保持行动论点小而具体。
- 除非下游系统需要其他类型,否则请使用 ID、日期和代码字符串。
- 使用
confidence、missing_fields或requires_human_review等字段明确表示不确定性。
第 3 层:语义和业务验证
最后,验证结构化结果对于任务是否正确。该层是特定于域的,不能单独外包给JSON架构。
对于发票提取,语义检查可能包括:
- 总计为非负值并且与容差范围内的订单项匹配。
- 货币显示在源文档中。
- 截止日期在过去或将来并不是不可能的。
- 该供应商存在于已批准的供应商列表中。
- 置信度足够高,可以自动输入。
对于潜在客户资格,检查可能包括:
- 所选细分是销售团队的活跃细分之一。
- 当用户未提供预算时,请求的预算就不会被发明。
- 除非用户明确要求,否则不会执行“图书演示”操作。
对于合作伙伴 API 自动化,检查可能包括:
- 经销商帐户有权创建所请求的客户或密钥。
- 请求的支出限额符合合作伙伴政策。
- 该操作具有幂等性密钥。
- 该操作在执行前会记录在审核日志中。
工具调用:将模型输出视为请求,而不是执行
当模型需要要求应用执行某些操作时,工具调用是正确的模式:创建票证、发送 Telegram 机器人命令、查找定价、更新客户记录或启动工作流程。
安全工具循环如下所示:
- 应用声明可用的工具及其输入架构。
- 模型返回带有结构化参数的工具调用。
- 网关验证工具名称和参数。
- 应用会检查授权、政策、幂等性和用户确认要求。
- 只有这样应用程序才会执行该工具。
- 如果对话需要继续,工具结果将发送回模型。
切勿将工具调用视为该操作应该发生的证据。将其视为结构化提案。应用程序仍然具有副作用的权威。
多模型工作流程的安全后备阶梯
网关应在事件发生之前定义后备行为。实用的梯子是:
- 主要:首选模型上的严格结构化输出。
- 兼容后备:支持相同严格架构要求的另一个模型。
- 验证和重试:没有严格支持的提供商,仅在风险允许的情况下使用。
- 人工审核:将结构化结果和源内容排队等待批准。
- 无操作响应:说明系统无法安全完成操作。
重试对于格式化或轻微架构故障很有用,但它们不是安全策略。如果对象在语义上不安全,则重复提示可能会将正确的拒绝变成危险的可执行对象。对于高风险的操作,优先考虑审查或拒绝,而不是反复尝试强制成功。
可观察性:记录每个结构化输出决策
结构化输出故障是操作信号。使用足够的详细信息记录它们,以改进路由、架构和提示,而不会暴露不必要的敏感内容。
推荐字段:
schema_id和schema_version.- 提供商和模型。
- 请求的模式和实际使用的模式。
- 解析失败状态。
- 架构失败状态和验证错误。
- 语义验证失败原因。
- 重试次数。
- 延迟时间。
- 令牌使用和费用。
- 最终操作状态:已执行、已排队、已拒绝或返回给用户。
- 团队、项目、API密钥或合作伙伴帐户标识符(如果适用)。
这些日志支持调试、成本分析、提供商比较和团队API治理。它们还有助于回答诸如“哪个架构版本导致重试次数最多?”之类的问题。以及“哪个后备模型通过了语法但未通过业务验证?”
架构版本控制规则
架构是生产接口。将它们视为API合同。
- 在请求元数据和日志中包含
schema_id和schema_version。 - 不要默默更改现有自动化的必填字段。
- 在客户端迁移时保持旧架构可用。
- 添加新的可选字段,然后将其设为必填字段。
- 针对路由池中的每个提供程序和后备模型测试架构。
- 记录每个副作用操作使用的架构版本。
版本控制对于代理机构、经销商和合作伙伴 API 自动化尤为重要,因为许多下游客户可能依赖稳定的结构化合同。
何时不执行结构化结果
出现以下任一情况时请紧急停止:
- 响应不可解析。
- 对象未通过JSON架构验证。
- 枚举值不受支持或被发明。
- 数量、价格、日期或货币是不可能的。
- 结果与用户声明的意图相冲突。
- 模型表示置信度较低或证据缺失。
- 用户说明不明确。
- 该操作有副作用并且缺乏确认。
- 帐户、团队或API密钥未获得授权。
- 提供商响应包括拒绝或与安全相关的不回答。
建议与预测
建议: 在可用的情况下使用提供商原生结构化输出,验证每个响应网关端,更喜欢使用工具调用操作,维护功能矩阵、版本架构并阻止副作用,直到语义检查通过。
预测: 提供商对结构化输出的支持可能会变得更强、更一致,但可移植性仍将是一个网关问题,因为模型系列、架构子集和工具调用循环不会在一夜之间变得相同。现在,构建验证、可观察性和架构版本控制的团队将能够更好地采用新的提供程序功能,而无需重写每个工作流程。
可行的实施清单
- 为您的应用定义标准化结构化输出请求格式。
- 为路由池中的每个模型创建提供商能力矩阵。
- 使用可移植的JSON架构子集设计架构。
- 在支持时将请求转换为严格的提供商原生机制。
- 生成后验证可解析性、架构一致性和业务正确性。
- 使用工具调用进行副作用操作。
- 需要模型外的授权、幂等性和确认。
- 记录架构版本、提供程序、验证失败、重试、延迟、费用和操作状态。
- 按工作流程风险级别定义后备行为。
- 保持旧架构可用,直到依赖的自动化迁移。
实际目标不是让每个模型都表现相同。就是给应用开发者一份稳定的合约,而网关则诚实地处理提供商的差异。结构化输出是可靠 AI 自动化的必要基础设施,但生产边界是决定对象是否可以安全使用的验证器和策略层。