radar

结构化输出真正改变了什么:从解析 JSON 到约束接口

结构化输出的价值不只是少写一次 JSON.parse,而是把模型结果变成可以验证、观测和演进的工程接口。

模型返回一段看起来像 JSON 的文本,并不等于系统获得了一个可靠对象。早期原型里,我们常在提示词末尾加一句“只输出 JSON”,然后删除 Markdown 围栏、尝试修复尾逗号,再把结果交给 JSON.parse。演示通常能跑通,但一旦输入变长、字段增多或模型拒答,修复逻辑就会迅速变成新的不确定性来源。

变化不在语法,而在接口

结构化输出把约束提前到生成阶段:调用方声明允许的字段、类型和枚举,模型在约束范围内组织结果。它并没有让内容天然正确,却把一类“格式能否被程序消费”的问题从提示词习惯变成了接口契约。

这一区分很重要。可靠性至少有三层:

  1. 语法可靠:结果能够被解析;
  2. 结构可靠:字段和类型符合约定;
  3. 语义可靠:字段里的判断与事实确实正确。

结构化输出主要解决前两层,第三层仍需要证据、规则或人工复核。把三层混为一谈,会让团队高估系统已经获得的保证。

一个最小的消费边界

下面的例子故意保留运行时校验。即使上游承诺遵循 schema,服务边界仍应验证数据,避免版本漂移或错误配置悄悄进入核心逻辑。

type Triage = {
  priority: 'low' | 'normal' | 'high';
  summary: string;
  needsHuman: boolean;
};

export function acceptTriage(value: unknown): Triage {
  if (!value || typeof value !== 'object') {
    throw new Error('triage must be an object');
  }

  const item = value as Record<string, unknown>;
  const priorities = new Set(['low', 'normal', 'high']);
  if (!priorities.has(String(item.priority)) || typeof item.summary !== 'string') {
    throw new Error('triage contract mismatch');
  }

  return item as Triage;
}

适合先落地的场景

我会优先把它放在分类、抽取、路由和工具参数生成这类任务中,因为输出空间相对清楚,失败也容易被检测。对于开放式写作或需要大量引用的研究任务,schema 只能整理结果的外形,不能替代来源核验。

上线前还应记录 schema 版本、验证失败次数、拒答分支和人工改写比例。只有这些信号被观测,团队才能判断变化究竟减少了多少胶水代码,又把多少失败转移到了语义层。

(示例内容,用于站点骨架验证)

原始来源:https://platform.openai.com/docs/guides/structured-outputs(在新窗口打开)