先把当时的情况摆出来。用 pydantic 2.9 的 model_json_schema 生成 strict 工具的 schema,有个字段写了 Field(default=None),请求回 400,原文是 Invalid schema: default is not permitted。

排查方向其实有限,先把可能性排一排。严格模式不允许 default 关键字。还有一种是Optional 字段会生成 anyOf 加 null。

还有一种情况,嵌套模型的 title 字段也被带上。另外,schema 没做清洗直接发给接口。

上来先导出 schema 看多余关键字

python dump_schema.py --model models.Order --strip-defaults

去掉 default 与 title 后再发

python strip_schema.py --in schema.json --out schema_fix.json

再往下用 strict 请求验证

curl https://api.openai.com/v1/chat/completions -H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d @strict.json

回归一遍必填字段

python validate_out.py --schema schema_fix.json --in cases.jsonl

这台环境是别人交接的,不少默认值被动过,只能一项项核。

同事提醒我看一下最近一次发布,时间点确实对得上。

命令输出我都留了记录,免得改完记不清原来的值。

改之前先确认了最近有没有人动过配置,避免白查一遍。

恢复的判定其实很直接。请求返回 200,必填字段全部出现,可选字段缺失时下游有默认值兜底。

默认值属于业务逻辑,不该交给 schema 表达,清洗 schema 时统一去掉能少踩很多兼容问题。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189