BaseModel to jsonschema for Structured Outputs

这个报错通常出现在用 Pydantic BaseModel 给 Structured Outputs / Batch API 生成 response_format 时, to_strict_json_schema 输出里带了 $defs 和 $ref ,看起来不像期望的扁平 schema。优先排查的

快速结论:这个报错通常出现在用 Pydantic BaseModel 给 Structured Outputs / Batch API 生成 response_format 时,to_strict_json_schema 输出里带了 $defs$ref,看起来不像期望的扁平 schema。优先排查的是:这些键其实是被支持的,问题往往在于 schema 包装方式或 Batch 请求体写法,而不是要手工删掉 $defs/$ref

适用环境:Issue 已确认的是 OpenAI Python SDK(openai/openai-python)。Issue 中未提供操作系统、Python 版本、CUDA、显卡或具体依赖版本,不要自行补齐。

最快修复方案:暂无确认的一步修复方案。Issue 中验证过的处理方向是:对 Batch Chat Completions,把 type_to_response_format_param(YourModel) 放进每个 JSONL 请求的 body.response_format;这是导入私有 helper 的 workaround,不是公开接口。

注意事项:from openai.lib._parsing._completions import type_to_response_format_param 属于私有 helper,后续版本可能变动,不建议长期依赖。官方维护者明确说明 $defs$ref 是受支持的,不需要移除。公开接口方式可参考 #2656 中 Pydantic schema-export 的做法并使用 Chat Completions 的 json_schema 包装;支持公开 helper 的 #2695 和 #2993 仍在推进中,目前尚未合并。

问题场景

用户使用 OpenAI Python SDK 时,希望从 Pydantic BaseModel 直接生成符合 Structured Outputs 要求的 JSON Schema,用于 response_format。典型场景是无法像普通接口那样直接传 Pydantic 实例,例如 Batch API 的 JSONL 请求里只能放 JSON 对象,因此需要先把模型导出成 schema。用户尝试 to_strict_json_schema 后,发现输出包含 $defs$refs,怀疑这不符合要求。

报错原文

BaseModel to jsonschema for Structured Outputs

I tried with `to_strict_json_schema` but it doesn't work as expected, it puts keys like $defs and $refs.

原因分析

可能原因一:对 Structured Outputs 的 schema 支持范围理解有偏差。维护者已明确说明 $defs$ref 是受支持的,因此它们并不需要被删除,也不一定是失败的直接原因。

可能原因二:Batch API 不会自动帮你把 Pydantic 模型转换好。Batch 使用底层端点的请求参数,所以需要你提前把每个请求的 body.response_format 填成正确的 schema 参数结构。

可能原因三:调用的辅助函数不是公开接口,或者包装层级不对。Issue 中给出的 type_to_response_format_param 属于私有模块,行为可能在版本间变化;公开接口应参考 Pydantic schema-export 的方式并配合 Chat Completions 的 json_schema 包装。

环境排查

  • 确认使用的 OpenAI Python SDK 版本,以及该版本中 type_to_response_format_param 是否存在(这是私有模块,不是稳定公开 API)。
  • 确认运行场景:是普通 Chat Completions 请求,还是 Batch API 的 JSONL 文件。
  • 检查传给 response_format 的结构是否符合当前端点要求,尤其是 Chat Completions 下需要的 json_schema 包装。
  • 检查 Batch JSONL 中是否把 schema 放进了每个请求的 body.response_format,而不是放在文件顶层。
  • 如果 schema 较大或包含嵌套模型,确认是否出现 $defs/$ref,但不要因为它们出现就直接判断为错误。

解决步骤

  1. 先确认你的 schema 输出里出现 $defs$ref 不是问题本身。官方文档说明这些定义是被支持的,不需要手工移除。
  2. 如果是 Batch Chat Completions,对每个请求单独生成 response_format,放到 JSONL 的 body.response_format 字段中。Issue 中验证过的写法是使用 type_to_response_format_param(YourModel)
  3. 如果不想依赖私有 helper,可优先尝试公开接口方向:参考 #2656 中 Pydantic schema-export 的指导,使用 Chat Completions 的 json_schema 包装来构造 response_format
  4. 把最小可复现的 schema 和实际 API 返回的错误一起提交。维护者在关闭该 issue 时明确要求:如果仍然失败,请提供 minimal schema 和 API error。
  5. 如果你在 Responses API 场景,Issue 中还提到过 from openai.resources.responses.responses import _type_to_text_format_param,同样属于私有 helper workaround,使用前先确认版本中是否存在。

验证方法

用一个小型 Pydantic 模型生成 response_format,发起一次实际请求(或 Batch 请求),确认 API 不再返回 schema 相关错误并返回符合模型结构的输出。如果仍失败,保留最小 schema 和完整 API error 作为后续排查依据。注意:验证点不是“输出里没有 $defs”,因为 $defs/$ref 本身是被支持的。

参考来源

openai/openai-python #2093

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 23505

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注