快速结论:这个报错通常出现在 LiteLLM 的 Responses→Chat bridge 路径上:Codex CLI 每个请求都会带上 reasoning: {"effort": ..., "summary": "auto"},bridge 的 summary 分支把整个 dict 当成 chat 的 reasoning_effort 转发,严格 schema 的 OpenAI 兼容上游(Go 后端)直接拒绝。优先排查上游是否只支持 /v1/chat/completions、模型是否走了 bridge 路径,以及 LiteLLM 版本是否包含 #36363 的修复。
适用环境:LiteLLM 1.98.0 复现(Python 3.14,proxy/SDK);当前 main 分支未变。另在 Ollama 后端(gpt-oss:120b)上复现,稳定版 1.102.0 仍含旧代码。1.103.0.dev2 含 #36363 修复。
最快修复方案:升级到包含 #36363 的版本(1.103.0.dev2 已验证包含,稳定版需等 1.103.0 或更高版本)。该 PR 只在模型确实要桥回 Responses API 时才重新附加 summary,作用域正确。
注意事项:截至本 Issue 讨论,修复未进入任何稳定版(1.102.0 仍为旧代码)。Codex CLI 始终发送 summary,客户端侧无绕过方式。若停留在稳定版,只能等待或临时使用含修复的 dev/rc 版本。
问题场景
使用 LiteLLM 代理或 SDK 时,模型配置为 use_chat_completions_api: true,上游只提供 /v1/chat/completions 且为严格 Go-backed OpenAI 兼容 schema。Codex CLI 在每次请求中发送 reasoning: {"effort": "...", "summary": "auto"},Responses→Chat bridge 把整个 dict 保留并作为 chat 的 reasoning_effort 发往上游,导致每个请求都失败;Codex 随后不断重试并撞上路由限流(Maximum 8 requests within 1 minutes),形成与 Ollama 报告相同的重连循环。
报错原文
litellm.InternalServerError: OpenAIException - json: cannot unmarshal object into Go struct field
GeneralOpenAIRequest.reasoning_effort of type string
Ollama 后端复现时:
Ollama_chatException - {"error":"think must be a boolean or string (...)"}
原因分析
核心原因是 Responses→Chat bridge 的 summary 分支保留了 dict。在 litellm/responses/litellm_completion_transformation/transformation.py(约 L275-291)中,当 reasoning_param 是 dict 且包含 summary 时,代码把整个 dict 赋给 reasoning_effort:
if isinstance(reasoning_param, dict):
if "summary" in reasoning_param:
reasoning_effort = reasoning_param # dict -> chat wire
elif "effort" in reasoning_param:
reasoning_effort = reasoning_param.get("effort") # correct string
Chat Completions 的线格式要求 reasoning_effort 是字符串,而 summary 是 Responses-only 字段,在 Chat Completions 中没有意义。该分支本意是给 Responses-native 提供方转发,但同一代码也位于 chat bridge 路径上。宽容的提供方(如 OpenAI 自身)会掩盖该问题,所以只在按提供方逐个暴露。
LiteLLM 内部其实已有正确归一化:OpenAIGPT5Config._map_openai_params(litellm/llms/openai/chat/gpt_5_transformation.py 约 L215-223)会把 {"effort": ..., "summary": ...} 转成 effort 字符串,但它仅对匹配 is_model_gpt_5_model 的模型生效;其他走 openai/ adapter 的模型(例如 z-ai/glm-5.3-free)走的是基础 OpenAIGPTConfig 路径,没有这个归一化。
环境排查
- 确认 LiteLLM 版本:1.98.0 可复现;稳定版 1.102.0 仍含旧代码;
1.103.0.dev2含 #36363 修复。检查litellm/responses/litellm_completion_transformation/transformation.py是否存在if "summary" in reasoning_param: reasoning_effort = reasoning_param分支。 - 确认 Python 版本(复现环境为 Python 3.14)。
- 确认模型是否走
openai/adapter 且不属于 GPT-5 系列,从而绕过已有的归一化。 - 确认上游是否为严格 schema 的 OpenAI 兼容服务,且只支持
/v1/chat/completions。 - Ollama 后端需确认 adapter 的
optional_params["think"]是否收到了整个 dict。 - 客户端确认 Codex CLI 是否总是发送
summary。
解决步骤
- 先做最小复现:对 bridge 路由
POST /v1/responses,reasoning: {"effort": "low"}应成功;改成{"effort": "low", "summary": "auto"}应稳定失败。直接对上游/v1/chat/completions测试:reasoning_effort: "high"(字符串)返回 200,reasoning_effort: {"effort": "high"}或带summary触发同样的 unmarshal 错误,以确认差异纯粹是 dict vs 字符串。 - 若确认命中,优先升级到包含 #36363 的版本(已验证
1.103.0.dev2包含修复)。该 PR 的修复函数为_transform_reasoning_for_chat_completion和ResponsesReasoningChatForm,只在模型会桥回 Responses API 时才重新附加summary。 - 如果当前只能停留在稳定版,可优先尝试使用含修复的 dev/rc 版本;稳定版中暂无客户端侧绕过(Codex CLI 始终发送
summary)。 - 若使用自维护分支,可按 #36363 的方式在 bridge 处提取 effort 字符串并丢弃
summary;该方式同时可覆盖 #37452 与 #35649 的共同根因(同样 dict 到达OllamaChatConfig.map_openai_params及其他 adapter)。
验证方法
升级后重新对 bridge 路由发送带 reasoning: {"effort": "low", "summary": "auto"} 的 /v1/responses 请求,应不再出现 cannot unmarshal object ... of type string;对 Ollama 后端也应不再出现 think must be a boolean or string。上游 reasoning_effort 应仅收到字符串。Codex CLI 不应再进入重试/限流循环。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


