Skip to content

[BUG]deepseek-stream.ts 中 SEARCH 控制标记无条件过滤问题 #142

Description

@2256593769

问题描述

使用非 search 模型(如 deepseek-chat)且未启用 web_search 时,若模型回答中的单词 search / Search / SEARCH 正好出现在某个 SSE 内容片段的开头,会被正则无条件剥离,导致回答内容丢失。该行为会影响到ClaudeCode的search功能。

复现步骤

  1. 使用 deepseek-chat 模型(禁用 web search)
  2. 发送消息:你能输出search这个单词吗
  3. 模型回复:当然可以,这个单词就是:("search" 被剥离)

根因

src/main/proxy/adapters/deepseek-stream.ts 在以下 5 个位置使用正则 /^(SEARCH|WEB_SEARCH|SEARCHING)\s*/i 过滤内容片段开头的控制标记,未加任何条件守卫

# 方法 行号(原) 触发条件
1 sendContent 243 每个内容片段
2 handleNonStream 389 片段类型 fragment
3 handleNonStream 403 response/fragments
4 handleNonStream 440 数组内嵌内容
5 handleNonStream 452 字符串内容

这些 SEARCH / WEB_SEARCH / SEARCHINGDeepSeek 启用联网搜索后 在响应中插入的状态标记。当不使用联网搜索时,这些标记从不出现,正则不应执行。
正则的 i 标志导致大小写不敏感匹配,因此自然语言中的 search Search SEARCH 如果恰好在一个内容片段开头,就会被误判为控制标记而剥离。

修复方案

在过滤前增加条件判断:仅在实际启用了联网搜索时才执行 SEARCH 标记过滤。

条件

this.webSearchEnabled || this.model.includes('search')
修改要点
sendContent 方法(第 243 行):
// Before:
const filteredForSearch = cleanedValue.replace(/^(SEARCH|WEB_SEARCH|SEARCHING)\s*/i, '')
// After:
const shouldFilterSearch = this.webSearchEnabled || this.model.includes('search')
const filteredForSearch = shouldFilterSearch
  ? cleanedValue.replace(/^(SEARCH|WEB_SEARCH|SEARCHING)\s*/i, '')
  : cleanedValue
handleNonStream 方法(第 358 行新增标志):
const isSearchModel = this.model.includes('search') || this.webSearchEnabled
handleNonStream 中其余 4 处过滤(第 389、403、440、452 行):
// Before:
cleanedFragment = cleanedFragment.replace(/^(SEARCH|WEB_SEARCH|SEARCHING)\s*/i, '')
// After:
if (isSearchModel) {
  cleanedFragment = cleanedFragment.replace(/^(SEARCH|WEB_SEARCH|SEARCHING)\s*/i, '')
}

修复提交:309c1d2

PR:#141

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions