先说一个实际问题

这波国产大模型在代码和 agent 任务上进步明显。GLM-5.2、Kimi3 这一代出来后,我自己就在用百炼跑这些模型做 coding agent——模型推理没问题,写代码、改 bug、读仓库都顺手。但有一类场景经常卡住:让 agent 自己去搜个网、读篇文档。

不是模型笨,是联网搜索这一层工具链没跟上。模型 API(百炼的 GLM/Kimi 也是)多是纯推理形态,搜索不是推理自带的能力,得 agent 框架自己接工具;而接的工具要么覆盖有限,要么对国内开发者常查的纵向源(微信公众号、B站、Reddit、HN)够不着。结果就是 agent 干活干到一半要查资料,经常还得我手动搜了喂回去——那还用 agent 干嘛。

百度搜技术问题,前排广告位占了好几个,自然结果相关度也一般;Google 在国内访问不便;必应质量时好时坏。手动搜能解决,但来回粘贴没意思。

deuseek 就是冲这个缺口做的:一个 CLI,把多源搜索 + 全文抓取补回来,给 GLM/Kimi 这类 agent 接上联网。

为什么模型 API 的联网搜索经常是短板

这块说清楚点。模型 API 的联网搜索,大致两道坎:

一是形态——很多模型 API(包括百炼这种 chat completion 形态)是纯推理,不带服务端搜索 tool,联网这一层得 agent 框架自己接。

二是覆盖——就算接了服务端搜索(有些平台实现了),它对纵向源也基本够不着:Twitter 实时讨论、Reddit 深度评论、微信公众号文章、B站技术视频,服务端搜索都覆盖不到。

deuseek 绕开这两道坎,走客户端实现:直接走 Algolia / yt-dlp / gh / 各搜索 API,对外是一个轻量 CLI。

deuseek 是什么

一个 CLI + 一个 Skill。作者把能力分了三层,都放在同一个 repo 里:

实现 职责 状态
search deuseek search 全网定位,返 metadata + URL,不取内容
fetch deuseek fetch 给定 URL 取全文 markdown
parse (未实现) 视频/音频解析(字幕/STT) 🔜 没启动

设计上对标了 Anthropic 自己的拆法:他们有 WebSearch(找)和 WebFetch(取)两个独立 tool,这里有 deuseek searchdeuseek fetch 两个子命令。每层 do one thing well,不让搜索被解析任务拖累 token 和延迟。parse 暂不做,真有需求才加(YAGNI),视频解析现在走 yt-dlp / whisper 组合。

真枪实弹:search

我跑了一条:

deuseek search --json "python asyncio"

返回一个标准化 envelope(第一条):

{
  "query": "python asyncio",
  "ts": "2026-07-24T04:54:12.861843Z",
  "results": [
    {
      "source": "hackernews",
      "adapter": "builtin",
      "title": "How Python asyncio works: recreating it from scratch",
      "url": "https://jacobpadilla.com/articles/recreating-asyncio",
      "author": "jpjacobpadilla",
      "ts": "2024-05-07T00:50:11+00:00",
      "score": 0.564,
      "engagement": {"likes": 282, "comments": 57, "shares": null, "views": null},
      "cost": "free",
      "raw_score": 0.91
    }
    // ...
  ],
  "errors": [
    {"source": "web", "error": "timeout (>15.0s)", "category": "failed"}
  ]
}

几个设计点值得说:

  • engagement 把 likes / comments / views normalize 成统一结构,不管上游是 HN 还是 Reddit 还是 B站,下游 agent 拿到的字段都一样。HN 没有 views 字段,normalize 成 null,让 agent 知道是 “unknown” 而不是 “0”——这俩语义不一样,差一个字段就可能导致 agent 误判热度。
  • cost 字段标 free / paid,付费源在 TTY 显示 💎 前缀,便于审计。
  • content 字段有意截到 500 字 + “…”,全文留给 fetch 层。搜索是定位用的,不必在 SERP 里就读全文,费 token;真要全文,deuseek fetch <url> 单独取。上游本身就返全文的源(wechat / exa / tavily),完整 payload 留在 raw 字段里,result.raw["text"] 直接取。
  • errors[] 把每个失败源单独列出来(这次 web 源超时了),不藏错。agent 自己读 errors 决定信不信结果。这一条我如实贴出来,包括失败的那个源。

限定源也行:

deuseek search --on hackernews --json "show hn"
deuseek search --on bilibili --json "编程教程"
deuseek search --on wechat --json "claude 4.7"   # 微信公众号,走 Sogou 免费搜索

真枪实弹:fetch

一条命令把常规网页转成 markdown:

deuseek fetch --json "https://example.com/"

返回:

{
  "url": "https://example.com/",
  "backend": "fetcher",
  "fetched_at": "2026-07-24T06:48:17.438169Z",
  "content_markdown": "Example Domain\n==============\n\nThis domain is for use in documentation examples without needing permission. Avoid use in operations.\n\n[Learn more](https://iana.org/domains/example)",
  "status_code": 200,
  "errors": [],
  "sections": [{"heading": "Example Domain", "level": 1, "has_code": false}],
  "content_stats": {"word_count": 22, "code_block_count": 0}
}

说明一下范围:这是 example.com,一个最简单的静态页。真实网页情况复杂得多——Cloudflare 重保护的、需要登录态的、JS 动态渲染的,不一定一次成功。文章后面会讲它怎么处理这些。

两个结构化字段是关键:

  • sections:把页面的标题树提取出来,每个标题标 has_code(后面有没有代码块)。agent 可以跳读到"有完整代码示例"的章节,不用线性读 5000 字。
  • content_stats:word_count + code_block_count,agent 拿这俩就能判断"这文章值不值得读、有没有代码",不用先 fetch 全文再数。

这俩治的是"agent 线性读全文浪费 token":以前 fetch 一篇文章,5000 字 markdown 灌进去 token 哗哗流;现在先看 sections 和 stats,有代码块的章节精读,没代码的扫标题就过。

技术含金量:三层 fetch 引擎 + DomainKB

fetch 不是 requests.get。底层是 Scrapling,一个把 HTTP 抓取 / 浏览器隐身 / 自适应解析 / 多页 Spider 收敛到一起的爬虫框架。FetchRouter 按 domain 路由,默认 fallback 链是三层递进

下面这些耗时数字是项目文档里给的 benchmark,不是我实测的,我照搬过来供参考:

引擎 实现 项目文档给的耗时 用途
Fetcher Scrapling Fetcher(curl_cffi HTTP + TLS 指纹 impersonate) 0.4-3.9s 默认引擎,大部分 URL 走这里,纯 HTTP 无浏览器开销
jina Jina Reader SaaS(服务端 IP) 2.2-5.7s Fetcher 失败 / 被拦时的 fallback,服务器 IP 能穿透部分反爬
StealthyFetcher Scrapling StealthyFetcher(patchright 隐身 Chrome)+ solve_cloudflare 7.8s(无 CF)/ 37s(解 CF) 兜底,过 Cloudflare Turnstile/Interstitial

三层递进的逻辑:Fetcher 快但遇 Cloudflare 就废,StealthyFetcher 能破 CF 但 37s 慢,不能当默认。路由器先试快的,失败才升级——像急诊分诊,小病先门诊,治不了的推重症。

DomainKB 是 domain → backend 的记忆:每个 domain 记"哪个引擎能 work、哪些被 block",避免每次都 trial-and-error 走一遍三层。项目文档里给的真实 benchmark:

nopecha.com(Cloudflare demo)第一次:
  Fetcher 0.5s ❌ → jina 5.7s ❌ → StealthyFetcher+CF 37s ✅   ← 总 43s

DomainKB 记下 "nopecha.com → stealthy" 后第二次:
  直接 StealthyFetcher+CF ✅                                   ← 跳过前两层

43s → 直接命中。entry 带 24h TTL,过期强制 re-probe,防止站点改了反爬配置后知识库变陈旧。

BrowserPool:StealthyFetcher / DynamicFetcher 每次冷启 Chrome 要 2-4s。BrowserPool 维护常驻 warm session,后续复用,冷启降到约 1s;空闲 5 分钟自动 shrink 关浏览器(一个实例占 200-500MB,不能一直挂着)。

super:一句话出多源 + 全文

旗舰命令 super 把 search → fetch → extract 串成流水线。v0.11.1 从串行改成 pipeline:第一个搜索结果一到就立刻开抓,跟剩余搜索重叠

旧(串行):    search-all (5s) ──────► fetch-all (6s)            = 11s
新(pipeline): search-stream ──► fetch-stream (overlap)          = ~6-7s  (~40% ↓)

这组提速数字也是项目文档给的,我没有自己搭场景复测。

deuseek super "iPhone 16 评测"
deuseek super "React 19" --extract-fields '{"title":"h1::text"}'   # 顺带结构化提取

还有验证码自动升级:fetch 返回内容做关键词启发式(环境异常 / 完成验证后即可继续访问 / Cloudflare / Just a moment),命中验证码页时,envelope errors[]captcha_suspected,若 StealthyFetcher 可用且本次没试过,自动重试 StealthyEngine.fetch(url, solve_cloudflare=True)。graceful degrade——agent 自己读 errors 决定信不信,markdown 字段保留。

源矩阵

状态 依赖 说明
hackernews ✅ 零配置 直连 Algolia
web ✅ 零配置 DuckDuckGo(ddgs),我这次跑遇到过超时
rss ✅ 零配置 内置 feedparser query 得是 URL
wechat ✅ 零配置 微信公众号,Sogou 免费搜索;deuseek fetch <mp.weixin.qq.com URL> 走 OpenCLI 登录态 Chrome 绕验证码
bilibili ✅ 零配置 B站官方 search API
youtube 需 setup yt-dlp deuseek setup youtube
github 需 setup gh CLI + 登录 deuseek setup github
reddit 需 setup rdt-cli + 登录 deuseek setup reddit
twitter / 小红书 / tiktok / 抖音 重型 OpenCLI + Chrome 扩展 需登录态
💎 tavily / brave / perplexity / exa 可选付费 各自 API Key 质量更高,免费够用

我实际跑 deuseek doctor 时,youtube / github / reddit 的依赖本地没装,显示 ok=false。所以"零配置"的只有 web / hn / rss / wechat / bilibili 这五个,其余源要 deuseek setup <源> 装依赖。微信公众号、B站做了原生支持,这是国产生态里比较实用的部分。

怎么装

uv tool install git+https://github.com/Daily-AC/deuseek.git
deuseek init                  # 写默认 ~/.deuseek/preferences.toml
deuseek search "vibe coding"  # HN 立即可用,零配置

deuseek 是个 CLI,接百炼跑 GLM/Kimi 的 agent 框架,只要能调 shell 就能接(我用的就是这套)。另外它打包成 Claude Code Skill,装了能在对话里直接说"用 deuseek 搜一下 …"。

Agent 调用有个约定要提:永远显式 --json,或 export DEUSEEK_FORCE_JSON=1。有些 agent 终端给子进程分真 PTY,isatty() 返回 True,自动 JSON 检测会失效,TTY 表格一 wrap 字段就抠不出来。显式 --json 是保险写法。

一点说明

这个工具还在 alpha,功能有边界——我上面贴的 fetch 用的是最简单的 example.com,真实复杂网页抓不全的情况会有;三层引擎的耗时数字是项目文档的 benchmark,不是我实测;search 的 web 源我这次就遇到了超时。写这篇不是吹它多强,是把它摆在"给百炼上的 GLM/Kimi agent 补联网搜索"这个具体场景里——在这个场景下,它够用。

代码 MIT,在 github.com/xyva-yuangui/deuseek。遇到坑欢迎提 issue,deuseek doctor 输出贴上就行,定位问题快。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐