能力概述
结构化输出(Structured Outputs)让模型的回复严格遵循你定义的 JSON Schema,确保返回值可以直接被程序解析,无需正则或后处理。
与在 prompt 中要求模型”请返回 JSON”不同,结构化输出基于受约束解码(Constrained Decoding):上游将 JSON Schema 编译为语法规则,在推理过程中逐 token 约束生成,模型不可能产出违反 Schema 的内容。
典型场景:
- 从非结构化文本中提取实体和字段
- 分类 / 打标签 / 情感分析
- 多步推理中间结果的标准化传递
- Agent 工具调用参数的强类型约束
各协议参数对照
三种协议的参数名不同,但底层机制一致:模型输出严格匹配你提供的 JSON Schema。
| 协议 | 参数 | 支持模型 |
|---|
OpenAI Chat /v1/chat/completions | response_format.type: "json_schema" | Claude 4.5+、GPT-4o / GPT-5 系列、Gemini 系列 |
Anthropic Messages /v1/messages | output_config.format.type: "json_schema" | Claude 4.5+(直连 / Vertex / Bedrock) |
OpenAI Responses /v1/responses | text.format.type: "json_schema" | 随上游模型能力 |
快速开始
OpenAI 协议(推荐)
适用于所有支持结构化输出的模型,跨厂商通用。
from openai import OpenAI
client = OpenAI(
api_key="<AIHUBMIX_API_KEY>",
base_url="https://aihubmix.com/v1",
)
response = client.chat.completions.create(
model="claude-sonnet-5",
messages=[
{"role": "user", "content": "Extract the following: John, 28, San Francisco"}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person_info",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"],
"additionalProperties": False
}
}
}
)
import json
data = json.loads(response.choices[0].message.content)
print(data)
# {"name": "John", "age": 28, "city": "San Francisco"}
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "<AIHUBMIX_API_KEY>",
baseURL: "https://aihubmix.com/v1",
});
const response = await client.chat.completions.create({
model: "claude-sonnet-5",
messages: [
{ role: "user", content: "Extract the following: John, 28, San Francisco" },
],
response_format: {
type: "json_schema",
json_schema: {
name: "person_info",
strict: true,
schema: {
type: "object",
properties: {
name: { type: "string" },
age: { type: "integer" },
city: { type: "string" },
},
required: ["name", "age", "city"],
additionalProperties: false,
},
},
},
});
const data = JSON.parse(response.choices[0].message.content);
console.log(data);
curl https://aihubmix.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <AIHUBMIX_API_KEY>" \
-d '{
"model": "claude-sonnet-5",
"messages": [
{"role": "user", "content": "Extract the following: John, 28, San Francisco"}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person_info",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"],
"additionalProperties": false
}
}
}
}'
使用其他模型(GLM-5.2 示例)
同一套 OpenAI 协议参数适用于所有支持结构化输出的模型,切换 model 即可。
from openai import OpenAI
client = OpenAI(
api_key="<AIHUBMIX_API_KEY>",
base_url="https://aihubmix.com/v1",
)
response = client.chat.completions.create(
model="glm-5.2",
messages=[
{"role": "user", "content": "Extract the following: John, 28, San Francisco"}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person_info",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"],
"additionalProperties": False
}
}
}
)
import json
data = json.loads(response.choices[0].message.content)
print(data)
# {"name": "John", "age": 28, "city": "San Francisco"}
Claude 原生协议
使用 Anthropic SDK 直接调用,参数为 output_config.format。
import anthropic
client = anthropic.Anthropic(
api_key="<AIHUBMIX_API_KEY>",
base_url="https://aihubmix.com",
)
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "Extract the following: John, 28, San Francisco"}
],
output_config={
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"],
"additionalProperties": False
}
}
}
)
import json
data = json.loads(response.content[0].text)
print(data)
curl https://aihubmix.com/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: <AIHUBMIX_API_KEY>" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Extract the following: John, 28, San Francisco"}
],
"output_config": {
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"city": {"type": "string"}
},
"required": ["name", "age", "city"],
"additionalProperties": false
}
}
}
}'
Schema 编写要点
必需字段
所有 object 类型必须显式声明 additionalProperties: false,否则部分上游会拒绝请求。
{
"type": "object",
"properties": {
"name": { "type": "string" },
"score": { "type": "number" }
},
"required": ["name", "score"],
"additionalProperties": false
}
嵌套对象
嵌套的 object 同样需要 additionalProperties: false:
{
"type": "object",
"properties": {
"user": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" }
},
"required": ["name", "email"],
"additionalProperties": false
}
},
"required": ["user"],
"additionalProperties": false
}
跨协议 Schema 差异
| 特性 | OpenAI 协议 | Anthropic 协议 |
|---|
name 字段 | 必需 | 不支持(网关跨协议调用时自动处理) |
strict 字段 | 可选,推荐 true | 不支持 |
数值约束 (minimum, maximum 等) | 支持 | 不支持(网关自动清理,不影响请求) |
字符串约束 (minLength, maxLength) | 支持 | 不支持(网关自动清理) |
使用 OpenAI 协议调用 Claude 模型时,网关会自动转换 Schema 格式并清理不兼容的关键字,无需手动适配。
自动降级机制
网关默认为所有请求开启结构化输出的自动降级保护。当模型或平台不支持时,网关不会返回错误,而是自动剥离 Schema 约束并在响应头中标记降级原因。你的请求仍然会得到正常的模型回复,只是输出不受 Schema 强制约束。
这意味着你可以放心地在客户端统一启用结构化输出,而无需针对每个模型做兼容判断:
- 多模型切换无忧:同一套代码在 Claude、GPT、Gemini、GLM 之间切换模型时,即使目标模型不支持结构化输出,请求也不会报错
- 兜底透明:即使实际处理请求的模型版本不支持结构化输出,请求仍然正常完成,仅通过响应头标记降级
- 客户端逻辑简化:不需要维护一份”哪些模型支持结构化输出”的列表,网关已自动处理;客户端只需检查响应头决定是否需要额外解析
响应头
X-Structured-Output-Degraded: <reason>
| reason | 含义 |
|---|
model_unsupported | 该模型(或该模型在当前平台上)不支持结构化输出 |
json_object_unsupported_on_anthropic | json_object 模式无法转换为 Anthropic 格式 |
json_schema_missing_schema | 指定了 json_schema 类型但缺少 schema 字段 |
schema_keywords_stripped | Schema 中的部分约束关键字被清理(如 minimum、maxLength) |
检测示例
import httpx
response = httpx.post(
"https://aihubmix.com/v1/chat/completions",
headers={
"Authorization": "Bearer <AIHUBMIX_API_KEY>",
"Content-Type": "application/json",
},
json={
"model": "claude-sonnet-5",
"messages": [{"role": "user", "content": "Extract: John, age 28"}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {"name": {"type": "string"}, "age": {"type": "integer"}},
"required": ["name", "age"],
"additionalProperties": False,
}
}
}
}
)
# 检查是否发生降级
degraded = response.headers.get("X-Structured-Output-Degraded")
if degraded:
print(f"结构化输出已降级:{degraded}")
# 此时模型回复仍然正常,但输出不受 Schema 强制约束
else:
import json
data = json.loads(response.json()["choices"][0]["message"]["content"])
print(data) # {"name": "John", "age": 28}
与 json_object 模式的区别
| json_schema (结构化输出) | json_object |
|---|
| 输出保证 | 严格匹配指定 Schema | 仅保证是合法 JSON |
| 字段控制 | 字段名、类型、是否必需均受约束 | 无约束 |
| 适用协议 | OpenAI / Anthropic / Responses | 仅 OpenAI 兼容协议 |
| Claude 支持 | 通过 output_config.format | 不支持 |
json_object 模式不支持转换到 Claude 原生协议。如果你通过 OpenAI 协议向 Claude 发送 response_format: {"type": "json_object"},响应头会标记 json_object_unsupported_on_anthropic 降级。建议直接使用 json_schema 类型。
常见问题
哪些模型支持 Structured Outputs?
Claude 系列(通过 Anthropic API 的 output_config.format):
- Opus / Sonnet / Haiku 4.5 及以上版本
- Fable / Mythos 5 及以上版本 OpenAI 系列(通过
response_format):
- GPT-4o 及以上、GPT-5 系列
Gemini 系列(通过 responseSchema):可通过 模型列表页 查看各模型的能力标签。 跨协议调用时 JSON Schema 会被修改吗?
会。当通过 OpenAI 协议调用 Claude 模型时,网关自动:
- 将
response_format 转换为 output_config.format
- 移除 Anthropic 不支持的 Schema 关键字(
minimum、maxLength 等)
- 如果有关键字被清理,响应头标记
schema_keywords_stripped
反向(Claude 协议调用 OpenAI 模型)同样自动转换。 Structured Outputs 可以和 Extended Thinking 同时使用吗?
可以。output_config 中的 format(结构化输出)和 reasoning 中的 effort(思考强度)是独立参数,可以同时设置:{
"output_config": {
"format": {
"type": "json_schema",
"schema": { ... }
}
},
"reasoning": {
"effort": "high"
}
}
与 OpenRouter 等聚合平台相比,降级机制有什么不同?
大多数 API 聚合平台在模型不支持结构化输出时会直接返回错误。AIHubMix 采用优雅降级策略:自动剥离不兼容的参数,正常返回模型响应,并通过 X-Structured-Output-Degraded 响应头告知客户端降级原因。你的应用不会因此中断。