Skip to content

[Bug] 流式响应中思考内容混入 content 字段逐词推送,导致 TUI 中 Thought 块刷屏 #40864

Description

@Jsliu28

环境

  • opencode 版本:1.18.x(Windows 11,PowerShell 终端)
  • 模型:deepseek-v4-flash(通过 OpenAI 兼容接口接入)
  • 接入方式:第三方中转服务(OpenAI 兼容协议)

问题描述

通过中转接入的模型在流式输出时,思考(reasoning)内容没有被放到标准的 reasoning_content 字段,而是被直接混入 content 字段,并且以**极细粒度(每 chunk 1~4 个字符)**逐词推送。

opencode 将 content 流的开头部分(正式回答之前的思考文字)渲染成 Thought 思考块,因为粒度极细,产生一行一个 Thought 的刷屏现象,终端滚动失控。

复现步骤

  1. 配置 OpenAI 兼容中转 provider,接入支持思考的模型(如 deepseek-v4-flash)
  2. 发起一个能触发深度思考的复杂问题
  3. 观察 TUI:思考阶段出现大量单行 Thought 提示快速滚动刷屏

SSE 证据(抓包原始数据)

1. 所有 chunk 的 reasoning_content 均为空

对同一请求抓取的 2081 个流式 chunk 中,0 个 chunk 携带非空 reasoning_content 字段:

data: {"id":"xxx-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":"","reasoning_content":"","function_call":null,"refusal":"","tool_calls":[]},"finish_reason":""}],"usage":null}

2. 思考内容被逐词塞进 content 字段

2079 个非空 content chunk,内容为思考文字被切成 1~4 字符的碎片:

data: {"id":"xxx-...","choices":[{"index":0,"delta":{"content":"这个","reasoning_content":"","..." }},"finish_reason":""}]}
data: {"id":"xxx-...","choices":[{"index":0,"delta":{"content":"问题","reasoning_content":"","..." }},"finish_reason":""}]}
data: {"id":"xxx-...","choices":[{"index":0,"delta":{"content":"涉及","reasoning_content":"","..." }},"finish_reason":""}]}
data: {"id":"xxx-...","choices":[{"index":0,"delta":{"content":"分布式","reasoning_content":"","..." }},"finish_reason":""}]}
...

3. chunk 长度统计

  • 总 chunk 数:2081
  • 含非空 reasoning_content:0
  • 非空 content chunk:2079
  • content 总字符数:4438
  • chunk 平均长度:2.1 字符
  • 93% 的 chunk 长度 ≤ 4 字符

4. 拼接后的 content 结构

将 2079 个 chunk 拼接后,可见内容依次是:一段"我将通过……路径构建方案"的思考铺垫 → 完整回答。思考段与正式回答之间没有协议层面的分隔标记(无 reasoning_content、无 thinking 字段),opencode 无法区分二者。

预期行为

思考内容应走标准字段(如 OpenAI 的 reasoning_content / Anthropic 的 thinking),或 content 流中思考与正文之间应有可识别的边界;opencode 不应将普通 content 流开头的文字误判为思考块并逐 chunk 渲染。

影响

  • 终端刷屏,对话不可读
  • /thinking 切换无法隐藏该提示行(只能隐藏 reasoning 块本身,但该内容走的 content 字段,隐藏无效)
  • 无法在保留模型推理能力的同时关闭视觉噪音

备注

问题根源疑似在中转服务对上游思考流的透传方式不规范;同时 opencode 对 content 流中思考文字的识别/渲染策略也可以更稳健(例如检测连续高频短 chunk 时合并渲染)。具体责任归属待 opencode 维护者确认。

附件

  • 完整 SSE 抓包文件:wb_stream2.txt(681KB,2081 个 chunk)
  • 分析脚本:analyze_stream.py(路径中不含任何服务商信息)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions