展开本页目录
开始前准备什么
- 确认模型与渠道接受 response_format=json_schema
- Python、OpenAI SDK 与 jsonschema
- 先定义最小字段及缺失值规则,再补复杂嵌套
- 定义输出契约
- 发送最小请求
- 检查完成与拒绝
- 验证类型和事实
拒绝、截断、Schema、业务数值和原文事实五层检查。
2026-10-25 资料复核与操作补充
继续操作前,核对当前配置与执行范围
先检查choices是否存在,再处理refusal、finish_reason、JSON解析、Schema与事实。普通JSON Mode返回可解析对象也可能不符合目标结构;本批原生031/033首次响应就是实际形状违约,不能称服务端strict失效,因为请求并未使用strict。
python3 -m venv .venv-schema
source .venv-schema/bin/activate
python -m pip install openai==3.37.0 jsonschema==4.26.0
# 使用下方v2脚本;先检查choices,再检查refusal、终态、结构与事实。原记录范围:本页保留原有配置、离线检查和历史记录;本轮没有新增该客户端或协议的在线运行记录。 下列相邻实验各有自己的日期、模型和产物,不替代本篇客户端或协议的原生验收。
JSON 合法,不等于字段可靠
仅在提示词中要求“返回 JSON”,仍可能得到 Markdown 或非预期字段。JSON Mode 着重可解析的 JSON;Schema 再限定字段和类型。哪一种服务端约束可用,取决于具体模型与接口。
例如数量可以是合法整数,但负数仍不符合订单规则。日期字段存在,也可能是模型猜出的日期。结构约束和事实验证必须分开看。
未知日期用 null,所有字段明确 required
下面的订单契约始终包含 order_id、quantity、delivery_date。未知日期为 null,而不是空字符串、今天的日期或删除字段。additionalProperties=false 防止悄悄新增未经处理的字段。
官方严格模式只支持 JSON Schema 的一个子集,复杂规则未必在服务端生效。将长度、范围、日期格式和业务关系继续放在本地检查。
json
{
"type": "object",
"properties": {
"order_id": {
"type": "string"
},
"quantity": {
"type": "integer"
},
"delivery_date": {
"type": [
"string",
"null"
]
}
},
"required": [
"order_id",
"quantity",
"delivery_date"
],
"additionalProperties": false
}完整 Python 示例:先看终态,再解析
示例先拒绝 refusal 和非 stop 的输出,然后 json.loads,再进行 Schema 和数量规则校验。最后与输入事实核对:QR-101、3、null。只匹配类型还不能通过这份验收。
developer-json-schema.py
import json
import os
from jsonschema import Draft202012Validator
from openai import OpenAI
SCHEMA = {"type": "object", "properties": {
"order_id": {"type": "string"}, "quantity": {"type": "integer"},
"delivery_date": {"type": ["string", "null"]}},
"required": ["order_id", "quantity", "delivery_date"], "additionalProperties": False}
def validate_record(record):
Draft202012Validator(SCHEMA).validate(record)
if record["quantity"] < 0:
raise ValueError("quantity must not be negative")
return record
def main():
client = OpenAI(api_key=os.environ["tokenba_API_KEY"],
base_url="https://api.apizt.com/v1", timeout=60, max_retries=0)
response = client.chat.completions.create(
model=os.environ["tokenba_MODEL"],
messages=[{"role": "user", "content": "提取订单:订单号 QR-101,数量 3,未约定交付日期。未知日期填 null。"}],
response_format={"type": "json_schema", "json_schema": {
"name": "order", "strict": True, "schema": SCHEMA}})
if not response.choices:
raise RuntimeError("Empty choices; preserve the response before retrying")
choice = response.choices[0]
if getattr(choice.message, "refusal", None):
raise RuntimeError("Model refused; do not treat this as an order")
if choice.finish_reason != "stop" or not choice.message.content:
raise RuntimeError("Incomplete output; do not parse a partial JSON record")
record = validate_record(json.loads(choice.message.content))
if record != {"order_id": "QR-101", "quantity": 3, "delivery_date": None}:
raise RuntimeError("Schema passed but source facts did not match")
print(json.dumps(record, ensure_ascii=False))
print("usage:", response.usage)
if __name__ == "__main__":
main()
安装与运行
如果接口返回 400,先读服务端错误,核实 json_schema、strict 和可用 Schema 子集。不要删除 strict 后把普通提示词输出继续标注为严格 Schema 约束。
bash
python -m pip install -U openai jsonschema
export tokenba_MODEL="REPLACE_WITH_SUPPORTED_MODEL_ID"
# tokenba_API_KEY 通过你的终端或部署环境设置
python developer-json-schema.pyResponses 的 Schema 放在 text.format
Responses 的 text.format 直接包含 type、name、schema、strict;Chat 的 response_format 内再嵌套 json_schema。这是请求结构差异,不能仅修改 endpoint。
python
response = client.responses.create(
model=model, input=source_text, store=False,
text={"format": {"type": "json_schema", "name": "order",
"schema": SCHEMA, "strict": True}}
)
if response.status != "completed":
raise RuntimeError("未完成,不能入库")拒绝、截断与验证失败如何分流
- 模型拒绝:保存拒绝状态,不向订单表写入空对象。
- 输出上限导致截断:不要拼补括号硬解析,调整预算或缩小任务后明确重新提交。
- 额外字段或类型错误:保留失败原文,标记校验失败。若使用提示词降级方案,要在产品中标明校验方式。
- 字段值找不到证据:进入人工核对,不让结构正确掩盖内容错误。
批量入库前保留来源与版本
给每份 Schema 标记版本,并保存 row_id、来源文档、模型 ID、请求时间、完成状态与 usage。模型或渠道切换后,对同一组边界样本重新验证。
为缺字段、空文本、Unicode、超长输入、错误枚举、负数量和拒绝输出各准备一个样本。成功样本与失败样本都要能定位,才能解释为什么一条数据被接受或拒绝。
怎样确认已经完成
- 正常输入返回 QR-101、3、null
- 缺字段、额外字段、字符串数量与负数量都失败
- 拒绝与截断不会进入解析入库流程
- 模型事实与原文逐项匹配
常见问题
strict=true 是否保证答案真实?
不保证。它约束支持范围内的输出结构;事实、权限和业务规则仍需要验证。
网关不支持 json_schema 怎么办?
明确改为提示词输出加本地校验,校验失败停止或人工处理,不把降级方式称为服务端严格结构约束。