/api/generate silently ignores think when format is set; /api/chat does not

在 Ollama 中,当对支持思考(thinking)的模型调用 /api/generate 并同时设置 think 与 format (如 format=json 或 JSON Schema)时,思考阶段会被静默跳过,返回结果可能只是占位符或无效 JSON;同一请求改用 /api/chat 则正常

快速结论:在 Ollama 中,当对支持思考(thinking)的模型调用 /api/generate 并同时设置 thinkformat(如 format=json 或 JSON Schema)时,思考阶段会被静默跳过,返回结果可能只是占位符或无效 JSON;同一请求改用 /api/chat 则正常。优先改用 /api/chat 规避。

适用环境:Issue 中已确认的环境为 Ollama 0.32.5 与 0.32.9,macOS,测试模型包括 qwen3:0.6b 与带内置解析器的 gpt-oss:20b。Issue 未提供 Python、CUDA、PyTorch、显卡等版本信息。

最快修复方案:暂无确认的一步修复方案。Issue 中已验证可用的规避方式是把同样的请求改发到 /api/chat,它会在思考阶段结束后再应用 format 语法约束。

注意事项:/api/generate 不会返回错误或警告,HTTP 状态码仍为 200,因此很难通过状态码发现。显式传入 think 等级(如 think:"medium")并不能绕过该问题。使用带内置解析器的模型(如 gpt-oss:20b)时,故障表现更严重:推理文本会直接落入 response,结果完全不是合法 JSON,且 thinkingnull

问题场景

用户在调用 Ollama 本地服务的 /api/generate 端点时,同时对支持思考能力的模型启用了 thinkformat 两个参数。例如让 qwen3:0.6b 在 JSON Schema 约束下回答「17 * 23」,或让 gpt-oss:20bformat:"json" 下输出固定 JSON。此时 Ollama 不会报错,但返回内容明显错误;换成 /api/chat 端点的同样请求则表现正常。

报错原文

/api/generate silently ignores think when format is set; /api/chat does not

/api/generate  think=true format=set -> thinking=    0 chars  response={"answer": "user_answer"}
/api/chat      think=true format=set -> thinking= 1650 chars  content ={ "answer": "391" }

/api/generate  think=medium format=json -> thinking = None       response = 'The user says: ":", "    }'
/api/chat      think=medium format=json -> thinking= 328 chars  content  = '{"ok":true}'

原因分析

根据 Issue 中的代码分析,ChatHandler 在处理结构化输出时采用了两阶段逻辑:当请求带有 Format、模型具备思考能力且尚未进入强制立即输出状态时,会先把语法约束推迟到思考结束之后(currentFormat = nil),即 structuredOutputsState 的双请求路径。GenerateHandler 虽然同样具备 builtinParserthinkingState,却没有等价逻辑,而是直接把 Format: req.Format 传给 Completion。结果是 JSON 语法从第一个 token 就开始约束,模型没有空间进行推理,思考阶段被静默跳过,甚至把推理内容混入最终响应。

环境排查

  • 确认 Ollama 版本:Issue 确认受影响版本包括 0.32.5 和 0.32.9。
  • 确认操作系统:Issue 报告环境为 macOS。
  • 确认所用模型是否具备思考能力,例如 qwen3:0.6bgpt-oss:20b
  • 确认请求端点:问题仅出现在 /api/generate/api/chat 为正常对照。
  • 确认请求中是否同时设置了 thinkformat;单独使用 think(不带 format)时 /api/generate 可正常思考。
  • Issue 未提供 Python、CUDA、PyTorch、显卡驱动等依赖版本,无需在排错时假定这些因素。

解决步骤

  1. 先确认最小复现:对同一模型分别向 /api/generate/api/chat 发送内容相同的请求,且都带 thinkformat,对比两端的 thinking 字段长度和最终内容。
  2. 如果业务不依赖 /api/generate,可将调用切换到 /api/chat。这是 Issue 中明确给出的可用规避方式,适用于任何带思考能力且设置了 format 的模型。
  3. 不要依赖显式指定 think 等级来规避:Issue 已验证 think:"medium" 同样失效,不能绕过该问题。
  4. 如果必须继续使用 /api/generate,可在调用前判断响应是否出现异常:thinking 为空或 nullresponse 为占位符、response 不是合法 JSON。发现异常时记录请求参数并回退到 /api/chat
  5. 关注上游修复进展。Issue 中维护者表示的方向是让 /api/generate 在启用思考时采用与 /api/chat 相同的两阶段格式处理,并保持非思考请求和显式 think:false 的现有行为;修复尚未在报告版本中提供。

验证方法

使用同一模型、同一 prompt、同一 seedtemperature 设置,分别请求两个端点,并检查 jq 输出中的 thinking 字段:修复后 /api/generate 应能返回非空思考内容,且 response 应为符合 format 约束的有效 JSON,而不是占位符或混入推理文本的残缺字符串。对 gpt-oss:20b 这类带内置解析器的模型,还需确认 thinking 不再为 nullresponse 可被 JSON 解析器正常解析。

参考来源

ollama/ollama #17544

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 25208

发表回复

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