Replies: 1 comment
|
结论:确认。两层成因都在 HEAD( 第一层(协议翻译): case 'thinking':
content = { type: 'reasoning', text: string(native.thinking) }
第二层(渲染): 修复位置建议:两条路都成立,我倾向你已采用的 renderer 侧跳过——与 未验证:52/400 的会话统计、fork 测试数字与本地验证结果(这些是你的测量)。 如果方便,附一条最短复现会话的 |
|
结论:确认。两层成因都在 HEAD( 第一层(协议翻译): case 'thinking':
content = { type: 'reasoning', text: string(native.thinking) }
第二层(渲染): 修复位置建议:两条路都成立,我倾向你已采用的 renderer 侧跳过——与 未验证:52/400 的会话统计、fork 测试数字与本地验证结果(这些是你的测量)。 如果方便,附一条最短复现会话的 |
Uh oh!
There was an error while loading. Please reload this page.
TL;DR (English) — On 0.1.6-alpha.2, when the model answers with text and no thinking, Chat still shows an empty "思考 / Think" block. The Messages protocol emits a
block-start(reasoning)for a signature-only emptythinkingblock, the harness persists{"type":"reasoning","text":""}into the assistant message, and the Chat renderer draws a Think row for every reasoning block.Summary
模型没有产生思考内容、直接输出正文(且不是工具调用)时,Chat 里会出现一个标题为“思考”但内容为空的思考块;该空块同时被写进会话日志的 assistant 消息内容里。
ddefc45fbc),Windowsdeepseek-official/ modeldeepseek-flash(Messages 协议,thinking enabled)packages/llm/llm-deepseek/src/protocols/messages/translate.ts、packages/client/ui-chat/src/client/chat/AssistantMarkdown.tsxReproduction
deepseek-official/deepseek-flash(Messages 协议)发一条会直接作答、不需要推理的请求,例如“只回复两个字:收到”。session.v3.jsonl中该条assistant/message的content以空 reasoning 块开头。复现证据(本机真实会话,节选自
assistant/message的stream记录):{ "type": "chunk", "chunk": { "type": "block-start", "index": 0, "blockType": "reasoning" } }, { "type": "chunk", "chunk": { "type": "block-end", "index": 0, "block": { "type": "reasoning", "text": "" } } }, { "type": "chunk", "chunk": { "type": "block-start", "index": 1, "blockType": "text" } },持久化结果:
{ "role": "assistant", "content": [ { "type": "reasoning", "text": "" }, { "type": "text", "text": "..." } ], "source": { "kind": "model", "provider": "deepseek-official", "model": "deepseek-flash", "replayState": { "response": { "kind": "deepseek-messages", "version": 1 }, "blocks": [ { "type": "reasoning", "signature": "…" }, { "type": "text" } ] } } }本机已有会话统计:400 条
assistant/message中 52 条带空 reasoning 块,形状均为["reasoning","text"]或["reasoning","tool-call"]。Current behavior
content_block_start(type: "thinking")就发出block-start(reasoning);DeepSeek Messages 在没有思考内容时仍会返回带signature的空 thinking 块且没有任何thinking_delta,于是block-end落下{ "type": "reasoning", "text": "" },被BlockAssembler组装进 assistant 消息并持久化。AssistantMarkdown对每个reasoning块无条件渲染ReasoningRow,空 reasoning 块因此渲染成空“思考”行(组件快照中data-variant="think",摘要<span class="_summaryText_…">为空)。assistant.ts的blockIsVisible、turn-process.ts的visibleChunk、llm的isVisibleChunk),只有最终渲染循环漏掉了;chat-completions协议也已有“空 reasoning 不建块”的等价保护,messages协议没有。Expected behavior
未产生思考内容时不应出现任何思考块:Chat 不渲染空 reasoning 行,assistant 消息也不应因这次“假思考”而多出内容块。
Fix (verified locally)
packages/client/ui-chat/src/client/chat/AssistantMarkdown.tsx:新增paintsContent,与assistant.ts的可见性判定对齐——text/reasoning仅在去除空白后非空时算可见;渲染循环跳过空白 reasoning 块,hasVisible也改用它,避免只剩空块时画出空壳。新增测试
packages/client/ui-chat/tests/coverage-tails.client.spec.tsx:空 reasoning 不渲染 Think 行、流式下等首个思考 token 到达才出现 Think 行、仅空 reasoning 时不渲染根壳。移除修复后这 3 条测试全部失败(已本地验证)。本地验证:
test:gui433 个测试文件 / 6183 用例通过,run-oxlint无告警,pnpm run build成功,运行中的dsh web实时 graph 已在提供含修复的@deepseek-ai/dsh-client-ui-chatbundle。可选的上游修复(更彻底,未采用):让
messages/translate.ts推迟发出thinking块的block-start,使空 thinking 块根本不进入持久化内容;需同时保持replayState.blocks与message.content的下标对齐。All reactions