结构化输出兼容性
定义
结构化输出兼容性 在本文语境中,不是泛泛的“模型兼容性”或“API 能不能调用”,而是专指:某个模型通过某个 provider 或部署通道接入 Hyper-Extract Provider System 时,是否支持结构化抽取所需的 JSON 输出能力,尤其是 json_schema、schema 约束、约束解码,以及从首个 token 开始就满足 JSON 语法的输出前提。
这类兼容性直接决定 with_structured_output、AutoGraph 等能力是否可用、是否稳定,以及失败时是报错、输出脏内容,还是悄悄返回不符合 schema 的结果。
在 Hyper-Extract 中的语境
在 Hyper-Extract Provider System 中,多个云端或本地接入方式表面上共用同一套 create_client() 接口,但“接口一致”不等于“结构化输出能力一致”。
Hyper-Extract 支持通过 OpenAI、阿里云 Bailian 和本地 vLLM 接入模型;然而对于结构化抽取来说,真正关键的不是调用方式统一,而是该渠道下的模型是否支持 json_schema 与受约束的 JSON 生成。
因此,结构化输出兼容性 讨论的不是模型总体能力高低,而是模型 + provider + 部署方式这一组合,在结构化输出场景下是否可靠。
关键机制
1. json_schema 支持是硬条件之一
如果 provider 或模型不支持 json_schema,那么即使普通聊天能工作,依赖 schema 约束的结构化抽取也可能失败。
在 Hyper-Extract 的已验证兼容性说明里,Bailian 渠道下的 qwen-max 和 deepseek-v3 被明确指出不支持 json_schema。这类情况下,用户可能遇到两种典型现象:
-
报错:
messages must contain the word 'json' -
没有直接报错,但返回的并不是合法 JSON
这说明问题不只是“输出格式不优雅”,而是 provider 侧对结构化输出协议的支持本身不完整,导致 schema 约束无法稳定落地。
2. 约束解码要求首 token 就是 JSON
结构化输出往往依赖 constrained decoding。它要求模型从第一个输出 token 起就进入 JSON 轨道,而不是先输出解释、思考过程或额外标签,再开始 JSON。
如果模型先吐出任何非 JSON 内容,即使后面跟着一个看起来正确的 JSON,对严格的结构化输出链路来说也可能已经算失败。
3. thinking 输出会破坏这个前提
本地部署时,thinking 类模型会输出 <think>...</think>。这会直接破坏“首 token 即 JSON”的前提,因此与 constrained decoding 冲突。
Hyper-Extract 的建议非常明确:本地 vLLM 部署应优先使用非 thinking 模型;如果部署的是 Qwen3.5 的 thinking 模式,需要显式关闭 thinking。
对应部署参数示例是:
--default-chat-template-kwargs '{"enable_thinking": false}'
这不是可有可无的优化,而是为了让结构化输出链路能够成立。
已验证的兼容性事实
Bailian 下已知不兼容组合
在 Bailian 渠道中,以下模型被明确标注为不支持 json_schema:
qwen-maxdeepseek-v3
遇到这类组合时,可能出现以下问题:
- 接口报
messages must contain the word 'json' - 返回非 JSON 输出
- 结构化抽取不稳定,无法可靠用于
with_structured_output
Bailian 下的替代建议
对于上述不兼容情况,Hyper-Extract 给出的替代模型建议是:
qwen-plusqwen-turbodeepseek-r1
这几个替代项的意义不是“模型更强”,而是它们在该 provider 语境下更适合承担结构化输出任务。
DeepSeek-R1 通过 Bailian 已验证可用
deepseek-r1 通过 Bailian 已被明确验证可用于 AutoGraph 与 with_structured_output。
原因并不只是模型本身,而是 Bailian 会在后端过滤 <think> 标签。这样一来,虽然 DeepSeek-R1 本身属于会产生思维链式输出的模型,但通过 Bailian 接入时,最终交给结构化输出链路的内容仍能满足首 token 进入 JSON 的要求。
这说明同一个 thinking 模型,并非绝对不能做结构化输出;关键在于 provider 是否做了合适的后处理。
本地部署的细节与约束
本地 vLLM 更容易暴露 thinking 冲突
在本地 vLLM 部署中,provider 通常不会替你清洗 thinking 标签,因此 <think>...</think> 会原样进入输出流。
一旦开启 thinking 模式,就很容易破坏 constrained decoding,使结构化抽取失败,或者让 with_structured_output 无法按 schema 正常工作。
所以 Hyper-Extract 明确建议:
- 本地尽量用 non-thinking 模型
- 如果是 Qwen3.5 一类支持 thinking 的模型,要显式关闭 thinking 模式
- 只有在确认首 token 可直接进入 JSON 时,结构化输出才值得信赖
关闭 thinking 的部署示例
在 vLLM 启动 LLM 服务时,Hyper-Extract 给出的示例包含:
vllm serve /path/to/qwen3.5-9b-gptq-marlin \
--served-model-name Qwen/Qwen3.5-9B \
--trust-remote-code \
--quantization gptq_marlin \
--dtype bfloat16 \
--max-model-len 8192 \
--gpu-memory-utilization 0.90 \
--default-chat-template-kwargs '{"enable_thinking": false}' \
--port 8000 \
--api-key dummy
这里的 --default-chat-template-kwargs '{"enable_thinking": false}' 对结构化输出兼容性尤其关键。
相关但不同的问题:量化兼容性
Hyper-Extract 还建议量化时优先用 GPTQ-Marlin 而不是 AWQ,因为 AWQ 与 vLLM 0.21.0 存在兼容性问题。
但这属于部署与推理栈兼容性,不等于本文所说的 结构化输出兼容性。两者可能同时影响结果,但要区分:前者偏运行环境,后者偏 JSON/schema/约束解码行为。
边界与例外
同一个模型,经不同渠道接入,兼容性可能不同
这是 结构化输出兼容性 最容易被误解的地方。问题不一定来自模型本身,也可能来自接入渠道的协议支持、模板设置或后处理行为。
同一个模型在不同 provider 下,可能出现完全不同的结果:
- 在某个渠道下不支持
json_schema - 在某个渠道下会原样输出
<think>标签 - 在另一个渠道下,provider 会过滤思维标签,因此结构化输出反而可用
DeepSeek-R1 经 Bailian 可用于 AutoGraph 与 with_structured_output,就是这个边界的典型例子;如果通过其他渠道访问 DeepSeek-R1,thinking 输出仍可能导致问题。
“能输出 JSON”不等于“支持结构化输出”
有些模型偶尔能生成看起来正确的 JSON,但如果不能稳定遵守 schema、不能满足 constrained decoding,或者首 token 前会插入额外文本,那么它在 Hyper-Extract 语境里仍不能算结构化输出兼容。
因此判断标准不是“试了一次像是成功”,而是:
- 是否支持
json_schema - 是否能在受约束模式下稳定工作
- 是否从首 token 起就是 JSON
- 是否能可靠支撑
with_structured_output与 AutoGraph
实务判断方法
在 Hyper-Extract 场景中,遇到结构化抽取失败时,可以优先按以下顺序判断:
- 当前 provider 与模型组合是否已知不支持
json_schema - 返回内容是否出现非 JSON 前缀,尤其是
<think>...</think> - 是否使用了 thinking 模型但未关闭 thinking
- 问题是否其实来自 provider 的后处理差异,而非模型本体
如果是在 Bailian 下使用 qwen-max 或 deepseek-v3,应优先切换到 qwen-plus、qwen-turbo 或 deepseek-r1。如果是本地 vLLM,则应先检查是否启用了 thinking 模式。
相关条目
- Hyper-Extract Provider System
- Provider System - Hyper-Extract 摘要
- 本地 vLLM 部署约束
- AutoGraph
- with_structured_output