LLM 结构化输出总翻车?先关掉思考模式

Forest Liu · 多家公司数据营销负责人#llm#structured-output#json-parsing

摘要

AutoSEM 管线的 JSON 输出翻车追到思考模式泄漏进结构化响应——content 返回空字符串。解法:关思考、每批约 20 条、强硬的 system prompt、分层回退解析、prompt 里不放 JSON 示例。

快速答案

结构化调用显式关掉思考模式(如 enable_thinking=False),否则 content 返回空字符串;批次要小;system prompt 强硬声明"只返回合法 JSON";解析分多层回退(直接 → 代码块 → 截断修复 → 逐对象);用户消息里永远不放 JSON 示例。

我们的 AutoSEM 管线靠 LLM 返回干净的 JSON 吃饭——关键词批次、广告组结构、搜索词分析。但连续几周,同一个 bug 反复出现:模型返回空字符串,或者一段夹杂自然语言的 JSON 数组,解析直接失败。翻了 12 条失败记录之后,我们把这些翻车大多追到了一个根因上。这些经验一点都不玄学:失败日志无聊、重复、可修——同样的空字符串、同样的散文夹数组,一遍又一遍。下面这几条,就是让日志安静下来的那几招。

根因:思考模式泄漏进返回内容

现在很多模型默认开启"思考模式"。推理在内部生成,但在结构化输出调用里,推理过程可能被写进响应;更糟的是,因为模型把推理写在了本该是答案的位置,真正的 content 返回了空字符串。你的 JSON 解析器没坏,是模型压根没产出 JSON。

五条把问题修掉的规则

  1. 显式关掉思考。结构化调用必须关思考——在我们的模型上,这个开关是 enable_thinking=False。不关,content 就会返回空字符串。
  2. 分批而不是堆量。输入太长,模型就会退回自然语言。我们每批只放约 20 条,让模型始终保持在 JSON 格式上。
  3. system prompt 要强硬。写死"MUST respond with ONLY a valid JSON",不寒暄、不给备选。
  4. 多层回退解析。先直接解析,再提取代码块,再截断修复,最后逐对象提取。回退链比重试循环便宜。
  5. 别给模型看 JSON 示例。我们把示例格式贴进用户消息后,模型学的是示例旁边的说明文字而不是产出数据。示例不要进 prompt。

为什么思考模式比结构化调用更伤

思考是聊天的特性,不是抽取的特性。对抽取任务来说,模型的活是把输入翻译成 schema——一个狭窄任务,加推理只会多花 token、增加延迟和失败面,而不是提高准确率。

可复用清单:可靠 JSON 5 条

  1. 结构化调用关掉思考。
  2. 批次足够小,模型不会退回散文。
  3. system prompt 强硬声明"只返回合法 JSON"。
  4. 解析分层:直接 → 代码块 → 截断修复 → 逐对象。
  5. 用户消息里不放示例格式。

这些规则全部来自我们管线自己的失败日志。如果你也在做 LLM 驱动的营销自动化,我们的增长引擎跑的就是这套结构化输出实践。

关于系统说明:iport 平台持续迭代。本文涉及的系统功能、界面或流程为该文写作时的版本,可能与最新版本存在出入;系统细节介绍以最新版为准。

常见问题

为什么模型会返回空的 content 字段?

开启思考模式时,模型把推理过程写进响应,真正的 content 就返回空。结构化调用我们显式设置 enable_thinking=False。

为什么不能给模型看个 JSON 示例?

我们把示例贴进去后,模型模仿的是示例旁边的说明文字而不是产出数据。用户消息里的示例教会的是格式模仿,而不是抽取。

如果响应还是解析失败怎么办?

把解析器分层:先直接解析,再提取代码块,再截断修复,最后逐对象提取。回退链比重试模型便宜。

继续阅读