【特别篇:DeepSeek V4 正式版原生联网搜索实测——搜索质量很好几乎免费,但结果是个黑盒】
【特别篇:DeepSeek V4 正式版原生联网搜索实测——搜索质量很好几乎免费,但结果是个黑盒】
系列专栏【打造你自己的 Agent】特别篇 · 2026-08-01 真实 API 实测 · 代码/数据来自 Rescene
Agent 要联网,绕不开两条路:
- 自己接搜索 API(Bing / Tavily / Serper…):要注册、要 Key、结果可控
- 用模型厂商的服务端搜索(DeepSeek
web_search):零接入成本,但结果是个黑盒
昨天 DeepSeek V4 正式版的 Responses API 上线了服务端联网搜索,我立刻花真金白银实测了一整天。这篇把两件事讲透:DS 服务端搜索到底返回什么(机制),以及一次联网搜索到底多少钱(成本)。
一、机制:搜索在服务端发生,客户端只拿到「动作记录」
DS 的服务端搜索只在 Responses API(/responses) 可用——chat/completions 端点会 400 拒绝 web_search 工具(2026-08-01 实测)。请求长这样:
{
"model": "deepseek-v4-flash",
"input": "今天北京天气怎么样?",
"tools": [{"type": "web_search"}],
"stream": false
}
模型自主决定搜不搜(tool_choice 默认 auto)。关键在响应结构——web_search_call item 只有 action 一个字段,两种形态:
// 形态1:search 动作 —— 只有搜索词
{"type":"web_search_call","id":"call_00_...","status":"completed",
"action":{"type":"search","queries":["北京 今天 天气 实时","北京 天气预报 今日",
"Beijing weather today","ws_call_id=call_00_..."]}}
// 形态2:open_page 动作 —— 只有 URL(模型主动决定打开的页面)
{"type":"web_search_call","id":"call_01_...","status":"completed",
"action":{"type":"open_page",
"url":"https://weather.com/zh-CN/cn/city/beijing/today#ws_call_id=call_01_..."}}
核心结论(实测确认,非猜测):
| 你想要的 | 能不能拿到 | 说明 |
|---|---|---|
| 搜索结果内容(标题+摘要+正文) | ❌ 拿不到 | 服务端直接注入 LLM 上下文,模型「看到」了才能作答,但 API 不外吐 |
| 引用 URL | ❌ search 动作无 URL | search 动作的 action 只有 queries,没有 URL 字段;URL 只在 open_page 动作里暴露 |
| 新闻标题 | ❌ 完全没有 | 响应里不存在任何 title 字段 |
| 搜索词 queries | ✅ 有 | 但会混入 ws_call_id=call_xx 服务端追踪尾巴,要过滤 |
| 最终回答 | ✅ 有 | message.output_text,模型基于注入的搜索结果生成 |
一句话:DS 服务端搜索是「黑盒注入」——搜索质量很好(模型真的会去开页面、读内容再回答),但搜索结果列表(含 URL)客户端拿不到。
流式事件形态(stream: true,无 [DONE],以 response.completed 收尾)
response.output_item.added → web_search_call item(in_progress)
response.web_search_call.in_progress → 只有 item_id
response.web_search_call.searching → 只有 item_id(无 URL 无 queries)
response.web_search_call.completed → 只有 item_id,action=null!
response.output_item.done → 完整 item 带 action(queries 或 url 都在这里)
注意:completed 事件 action=null,URL 要到 output_item.done 才出现——前端如果提前渲染会闪「未找到来源」。
Rescene 的真实处理(main-backend/internal/handler/model_router.go 的 drainResponsesStream):
// web_search_call.* → search 卡片、completed → usage。
// 实测 DeepSeek 此事件 action=null,URL 在 output_item.done 才到——
// 所以保持「搜索中」扫描线,等 output_item.done 聚合完再一次性展示。
case "response.web_search_call.searching":
// 不等 output_item.done——否则汇报完才见卡片
case "response.web_search_call.completed":
// action=null,只能更新状态,不能急着渲染 URL
case "response.output_item.done":
// 完整 item 带 action(queries 或 url 在这里),聚合后一次性渲染
二、成本:一次联网搜索 ≈ 0.2~1 分钱
官方定价(deepseek-v4-flash,元/百万 tokens)
| 计费项 | 单价 |
|---|---|
| 输入(缓存命中 cached) | 0.02 元 / 百万 |
| 输入(缓存未命中) | 1 元 / 百万 |
| 输出 | 2 元 / 百万 |
⚠️ 官方公告:即将采用峰谷定价,高峰时段(北京时间 9:00~12:00、14:00~18:00)价格为平时 2 倍,适用所有计费项。
两次真实调用的账单
实测 1:一次完整流式对话(问「中国今天有什么重要新闻」,模型搜了 3 次 + 开了 2 个页面):
input_tokens = 17569(cached 10112,未命中 7457)
output_tokens = 1044
成本 = 7457/1e6×1 + 10112/1e6×0.02 + 1044/1e6×2
= 0.00975 元 ≈ 0.97 分
实测 2:一次非流式单轮(问「北京天气」,搜 1 次 + 开 2 个页面):
input_tokens = 6917(cached 4096,未命中 2821)
output_tokens = 681
成本 = 2821/1e6×1 + 4096/1e6×0.02 + 681/1e6×2
= 0.00426 元 ≈ 0.43 分
结论
- 一次联网搜索大概 0.2~1 分钱(冷启动 0.4~1 分;热缓存后单次可低至 0.2~0.3 分——连续测试十几次总成本仅 4 分钱)
- 成本大头是「缓存未命中的输入」:一次搜索注入就 7K~17K tokens,按 1 元/百万算就是几千分之几元
- 缓存命中是省钱关键:命中部分 0.02 元/百万(便宜 50 倍)。系统提示词/工具定义/搜索注入的固定内容在连续调用间反复命中缓存
- 缓存命中率实测约 59%,多轮对话、重复搜索会越来越便宜
- 高峰时段记得 ×2
对比:某 Search API(免费档 1000 次/月,超出后约 2 分/次)+ 自己把结果拼进 prompt(还要额外算模型输入 token)。DS 服务端搜索的隐藏优势是搜索 + 注入 + 回答一次完成,省了集成成本,缺点是结果不可见、不可控。
三、证据链:为什么「不 open_page 就拿不到 URL」
把完整的 2442 行原始流式响应(ds3.txt)全量扫描后的证据,逐条列出,避免再踩坑:
| 检查项 | 结果 |
|---|---|
search 动作的 action 字段 |
只有 queries(搜索词),没有 url 字段(4 次 search 动作,0 个 url) |
url 字段出现次数 |
全响应只有 4 次,全部在 open_page 动作里 |
| item type 全集 | message / reasoning / web_search_call——没有 web_results / citations 类型 |
| title / snippet / description | 0 个 |
message 的 annotations |
"annotations":[] 空数组(OpenAI 的 responses 通常用 annotations 带引用 URL,DS 返回空) |
open_page 动作 |
也只有 url,同样没有 title 字段(4 个 open_page 全验证过) |
search_context_size / user_location |
官方文档明确:被忽略,无法通过参数要更多结果 |
结论:DS 服务端搜索是彻底的「黑盒注入」——搜索结果的 URL 列表、标题、摘要只存在于注入给 LLM 的上下文里,客户端 API 任何字段都拿不到。URL 暴露给客户端的唯一通道是模型主动执行 open_page 动作;而 open_page 也只给 url,不给 title。
重要:open_page 不是搜索的必要条件。 不 open_page,搜索结果照样注入 LLM、照样正常回答——open_page 的唯一作用是把「模型实际打开的页面 URL」暴露给客户端,供前端展示引用来源。所以:
- ❌ 想拿完整搜索结果列表(含 URL)做前端展示 → 做不到
- ❌ 想让模型「搜索但不开页面」还能拿 URL → 做不到
- ✅ 想展示「模型实际打开的页面」→ 可以,open_page 的 url 就是
- ✅ 想展示「新闻标题」→ 需要额外手段:前端对 open_page URL 发请求抓
<title>,或让模型在回答正文里引用
四、给 Agent 开发者的建议
- 能接受「来源不可见」就用服务端搜索——集成成本为零,搜索质量在线
- 要做完整搜索结果展示(像 Perplexity 那样列出所有引用来源+标题)——服务端搜索不够,得自己接搜索 API(Tavily/Serper)或对 open_page URL 做标题抓取
- 流式处理注意:URL 只在
output_item.done出现,别在completed事件就急着渲染——前端保持「搜索中」扫描线,等output_item.done聚合完再一次性渲染,否则用户会看到「先没结果、后出结果」的闪变 ws_call_id=/#ws_call_id=尾巴记得剥,那是服务端追踪标识,不是数据- 想省 open_page 的 token:在 instructions 里引导模型「搜索后最多打开 1 个最相关页面」——URL 有了,token 也压到最低
- 前端需要展示引用来源时,可在 instructions 里引导模型 open_page 2-4 个页面;不需要展示时关掉(1 个或纯搜索)不影响搜索功能本身
关于 Rescene
本文实测来自我手写的开源项目 Rescene——专攻前端设计、浏览器自动化、Computer Use 的二次元 Agent:
- 🔋 免费模型每日更新:每天自动探测各厂商免费档模型(含 DeepSeek 免费档),免费池永远是真能跑的
- 🔄 Agent 后台与并行任务:工作流支持后台运行、多任务并行调度(
dispatch_agent子代理 goroutine 并行执行) - 🎨 专攻前端设计:内置 54 个真实设计系统参考,Agent 写完直接真实渲染给你看
- 🔧 4+4+2 Agent 工作流:40% 计划 → 40% 验证 → 20% 编码
🔗 官网:https://rescene.shanca.me/ (全速下载最新发行版)
🐙 GitHub:https://github.com/Rescenix/ResceneAgent
📌 素材备注:数据来自 2026-08-01 对 https://api.deepseek.com/responses 的真实调用;完整原始流式响应见 Rescene 仓库 main-backend/ds3.txt;官方定价页 https://api-docs.deepseek.com/zh-cn/quick_start/pricing
更多推荐



所有评论(0)