背景与问题描述 (Background & Problem)
在将 codebuddy2api 作为各类支持推理思考链的客户端(如 DeepSeek Harness, OpenCode/OMP, Claude Code, Cherry Studio 等)的上游反代时,发现多轮对话中存在**“上轮 Assistant 的思考过程被丢弃,下轮模型无法感知前序思考”**的问题:
- 下行流式正常:流式 SSE 能正确产出思考过程,并在客户端渲染折叠块。
- 上行回放丢失:下一轮对话中,客户端回传上一轮 assistant 消息中的
reasoning_content。但由于直接原样将 JSON 转发给腾讯 CodeBuddy 上游接口,腾讯网关在反序列化强类型消息体时,只读取 role、content、tool_calls 等白名单字段,客户端附带的非标扩展字段 reasoning_content 被服务端静默丢弃。
- 模型层结果:上游组装给底层模型(如 DeepSeek-v4-flash、混元等)的上下文里完全缺失思考部分,底层模型的自注意力机制(Self-Attention)无法看到上一轮推导的中间逻辑,Prompt Tokens 增加量也为 0,导致长上下文或需要延续上轮思路的多步代码重构中频繁出现“思维断层”。
根本原因 (Root Cause)
- 上游服务严格白名单反序列化:腾讯私有网关不接收非标字段
reasoning_content;
- 大模型注意力机制依赖正文:现代推理大模型底层对历史思考的自注意力捕捉,严重依赖其作为正文文本存在(如
<thought>...</thought> 或 <think>...</think>)。
建议解决方案 (Suggested Fix)
在网关将客户端请求转发给腾讯 CodeBuddy 上游前,针对 messages 数组做一层快速拦截:
- 遍历所有
role === "assistant" 的历史记录;
- 若消息包含
reasoning_content,且尚未包含 <thought> 标签,将其提取并包装为 <thought>\n${reasoning_content}\n</thought> 前置拼入 content 首部;
- 这样上游网关只看到完全合规的标准
content 正文字符串,底层模型也能够实打实地读取历史思考。
参考伪代码 (Node.js / TypeScript):
function injectAssistantReasoning(messages: any[]) {
if (!Array.isArray(messages)) return;
for (const msg of messages) {
if (msg.role !== 'assistant') continue;
const reasoning = msg.reasoning_content || msg.reasoning;
if (!reasoning || typeof reasoning !== 'string' || !reasoning.trim()) continue;
const thoughtBlock = `<thought>\n${reasoning.trim()}\n</thought>`;
if (typeof msg.content === 'string') {
if (!msg.content.trim().startsWith('<thought>')) {
msg.content = msg.content.trim()
? `${thoughtBlock}\n\n${msg.content}`
: thoughtBlock;
}
} else if (Array.isArray(msg.content)) {
const firstTextPart = msg.content.find((p: any) => p.type === 'text');
if (firstTextPart && typeof firstTextPart.text === 'string' && !firstTextPart.text.trim().startsWith('<thought>')) {
firstTextPart.text = `${thoughtBlock}\n\n${firstTextPart.text}`;
}
}
}
}
实测验证与收益
经实测:
- 加上该正文注入后,无论模型是 DeepSeek 还是混元,均能在多轮对话中精准回忆上轮思考细节;
- 同时保持了与上游网关的完全兼容,不会触发 400 格式错误或 WAF 拦截。
- 建议作为可选开关(默认推荐启用)加入到请求转换管道中。
背景与问题描述 (Background & Problem)
在将
codebuddy2api作为各类支持推理思考链的客户端(如 DeepSeek Harness, OpenCode/OMP, Claude Code, Cherry Studio 等)的上游反代时,发现多轮对话中存在**“上轮 Assistant 的思考过程被丢弃,下轮模型无法感知前序思考”**的问题:reasoning_content。但由于直接原样将 JSON 转发给腾讯 CodeBuddy 上游接口,腾讯网关在反序列化强类型消息体时,只读取role、content、tool_calls等白名单字段,客户端附带的非标扩展字段reasoning_content被服务端静默丢弃。根本原因 (Root Cause)
reasoning_content;<thought>...</thought>或<think>...</think>)。建议解决方案 (Suggested Fix)
在网关将客户端请求转发给腾讯 CodeBuddy 上游前,针对
messages数组做一层快速拦截:role === "assistant"的历史记录;reasoning_content,且尚未包含<thought>标签,将其提取并包装为<thought>\n${reasoning_content}\n</thought>前置拼入content首部;content正文字符串,底层模型也能够实打实地读取历史思考。参考伪代码 (Node.js / TypeScript):
实测验证与收益
经实测: