先看现象。结构化输出里有个可空字段,schema 写成 type 为 [string, null],OpenAI 返回 400,原文 Invalid schema: type must be a string,换成 anyOf 两个分支后 strict 又报 required 字段不全。
排查方向其实有限,先把可能性排一排。strict 模式不接受 type 数组这种写法。还有一种是可空字段要用 anyOf 加一个 null 分支。
还有一种情况,strict 要求所有属性都出现在 required 里。
另外,对象还要补 additionalProperties 为 false。
第一件事是把出错的 schema 片段单独打印
python -c "import json;print(json.load(open('schema.json'))['properties']['note'])"
随后改成 anyOf 两个分支的写法
python -c "import json;print(json.dumps({'anyOf':[{'type':'string'},{'type':'null'}]}))"
补齐 required 与 additionalProperties
python -c "import json;d=json.load(open('schema.json'));d['required']=list(d['properties']);d['additionalProperties']=False;json.dump(d,open('schema2.json','w'))"
剩下的就是用一次真实请求确认 schema 被接受
python struct_probe.py --schema schema2.json --model gpt-4o-mini
同事提醒我看一下最近一次发布,时间点确实对得上。
命令输出我都留了记录,免得改完记不清原来的值。
改之前先确认了最近有没有人动过配置,避免白查一遍。
恢复的判定其实很直接。请求返回 200,可空字段有时返回字符串有时返回 null,解析层两种情况都能处理。
提醒一点。各家对 JSON Schema 的支持是子集,写 schema 时按最保守的写法来,anyOf 加 required 全列,通用性最好。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
