【Deep Research 拆解系列】04:不会思考的研究员

yelixin_117 2026-03-18 15:27 1

04:任务派下去之后发生了什么




承接上篇:研究简报锁定意图,Supervisor 驱动决策。两者共同构成报告质量的天花板。


但 Supervisor 不搜索、不阅读、不整理——它只派任务。派下去之后,真正干活的是 Researcher。


这篇讲的是:一个任务从被派发到被交回,中间发生了什么。




一、Researcher 手上有什么


Researcher 拿到任务后,能用的东西很少。三件工具,一个硬性约束:




























装备 作用
搜索工具 唯一的外部信息入口,返回经过预处理的搜索结果
think_tool 搜索间隙的工作笔记——已知什么、还缺什么、下一步搜什么
ResearchComplete 判断信息足够时,主动退出搜索循环
工具调用次数上限(非工具) 无论是否搜完,达到上限强制结束

每件装备背后都有设计细节。




1.1 搜索工具:看到的不是原始世界


Researcher 拿到的不是原始网页。原始网页几十 KB——导航栏、广告、评论区,夹杂几段有用信息。全量塞进上下文,两三次搜索就撑满窗口。


所以搜索结果返回前,每个网页会被一次 LLM 调用自动压缩成 「摘要 + 关键引语」



Your summary should be significantly shorter than the original content but comprehensive enough to stand alone as a source of information. Aim for about 25-30 percent of the original length.



体量压到原文四分之一。页面布局、广告、无关段落丢掉,关键事实、数据点、时间线保留。针对不同内容类型,压缩策略也不同:




  • For news articles: Focus on the who, what, when, where, why, and how.

  • For scientific content: Preserve methodology, results, and conclusions.

  • For opinion pieces: Maintain the main arguments and supporting points.

  • For product pages: Keep key features, specifications, and unique selling points.



这本质是上下文空间和信息完整性之间的取舍。丢掉的是原始细节——Researcher 不知道原始网页长什么样,也不知道预处理丢了什么。换来的是一个更内聚、更没有噪声的上下文:模型的注意力不会被广告和导航栏稀释,每一轮搜索占用的 token 更少,同样的上下文窗口里能跑更多轮搜索、追更多条线索。




1.2 think_tool:搜一次,想一次


实现极其简单——把输入原样返回,没有副作用。唯一作用是给模型一个停顿位置,把推理写进消息历史。


但框架对使用节奏有明确要求:



CRITICAL: Use think_tool after each search to reflect on results and plan next steps. Do not call think_tool with the tavily_search or any other tools.



每次搜索之后都要反思,且不允许和搜索并行调用。 反思内容被框定为三个问题:



After each search tool call, use think_tool to analyze the results:



  • What key information did I find?

  • What’s missing?

  • Do I have enough to answer the question comprehensively?



搜到了什么?还缺什么?够了吗? 理想节奏不是"搜搜搜",而是 “搜-想-搜-想-搜-想”


当然,这是 prompt 级别的指令,不是代码强制的。模型有时会跳过 think_tool 直接连续搜索。但设计意图清晰:搜索不是目的,反思才驱动调查方向。


上一篇提到 Supervisor 也有 think_tool。区别在于:Supervisor 用它判断"发现够不够、下一轮怎么安排"——管理者的反思;Researcher 用它推进搜索策略——执行者的工作笔记。同一个工具,不同层不同角色。不只是"干活"分出去了,"想"也分出去了。




1.3 ResearchComplete:谁来决定"够了"


Researcher 判断信息足够时,调用 ResearchComplete 退出循环。框架给了明确的停止条件:



Stop Immediately When:



  • You can answer the user’s question comprehensively

  • You have 3+ relevant examples/sources for the question

  • Your last 2 searches returned similar information



尤其最后一条——连续两次搜索返回相似信息,说明线索已饱和,继续搜只是消耗预算。


但模型没有停的内在动力——"继续搜"永远是阻力最小的路径。所以硬性约束兜底:工具调用次数达到 max_react_tool_calls 强制结束。模型信号是正常出口,资源上限是安全网。




1.4 工具集如何塑造角色


回头看一眼工具箱。think_tool 和 ResearchComplete 都是"空工具"——think_tool 把输入原样返回,ResearchComplete 只是一个终止信号。没有实际副作用,不搜索、不写入、不调用外部服务。


但它们在系统里的作用完全不同。think_tool 是停顿,ResearchComplete 是退出。一个让模型继续,一个让模型结束。两个空壳工具,加上一个真正做事的工具,就定义了一个角色的全部行为空间:


























Supervisor think_tool ConductResearch(派活) ResearchComplete
Researcher think_tool tavily_search(搜索) ResearchComplete

结构完全对称,但"做"那一列的性质不同——Supervisor 的动作是派活给别人,Researcher 的动作是自己搜索。这个差异决定了两层的角色:Supervisor 是规划者,Researcher 是执行者。


更准确地说,Researcher 的角色是忠实的信息搬运工——搜索、整理、交回,不做判断。它的工具集里没有"分析"“推理”"生成结论"的工具,只有搜索和反思。搜索循环结束后,compress_research 的设计目标也印证了这个定位:



DO NOT summarize the information. I want the raw information returned, just in a cleaner format.



不是"提炼观点",而是"原样整理"。Researcher 负责把信息从外部世界搬进来,保真地传递给上层。判断和决策留给 Supervisor,综合和推理留给 Synthesizer。每一层只做自己该做的事。


两层底层都是同一个 ReAct 循环:LLM 看上下文,决定调哪个工具,拿到结果,再决定下一步。但 Supervisor 的工具集里没有"自己干活"的选项,再加上 prompt 要求"派活前先 think,收到结果后再 think"——模型在循环里的自然行为就变成了:想清楚→派活→看结果→再想→再派或停。


这就是上一篇提到的 Plan-and-Execute。它不是代码层面强制的流程编排,而是工具集的约束 + prompt 的引导下,ReAct 循环里涌现出来的行为模式。工具集决定了模型能做什么,prompt 引导了模型怎么做,两者叠加让同一个 ReAct 引擎在不同层表现出不同的工作节奏。




三件工具加一个约束,就是 Researcher 的全部装备。工具少、上下文隔离、调用次数有上限——一个被刻意约束过的执行者。理解了这一点,看它在具体场景里怎么工作。




二、从派发到交回


上一章看的是 Researcher 手里有什么。这一章看它怎么用——从 Supervisor 并发派发任务开始,到压缩摘要交回,完整走一遍。


先看全景:


flowchart TD
SUP["Supervisor<br/>拆解任务,并发派发"]
SUP --> R

subgraph PAR ["× N 并行执行 · 状态隔离"]
R["Researcher<br/>搜索 ⇄ 反思"]
end

R --> CP["compress_research<br/>保真去重,整理摘要"]
CP --> NOTES["摘要汇入 Supervisor notes"]

三个关键阶段:分头出发、各自搜索、压缩汇报。用一个场景把它们串起来。




2.1 分头出发


毕业季,你和同学计划一次毕业旅行。目的地没去过,出发前大家都在忙论文答辩,一个人查不过来。


分工:



  • 小 A:机票和住宿,怎么最划算

  • 小 B:当地有什么值得去的

  • 小 C:天气、签证、交通和注意事项


三个人各自打开手机开始查。小 B 不会等小 A 选完航班再决定推荐景点,小 C 也不会等小 B 定了行程再查天气。等来等去,出发前都查不完。


分头查的前提:各干各的,互不等待。


在 ODR 里,这就是状态隔离。每个 Researcher 是独立的子图实例,asyncio.gather 同时启动,各自有独立上下文,互不知晓对方的存在。这不是疏漏,是并行的前提——共享上下文意味着速度退化为串行,上下文被无关信息稀释,搜索质量下降。




2.2 小 B 是怎么查的


小 B 的任务:查当地有什么值得去的地方。他的搜索过程是这样的:





















































动作 工具 内容
tavily_search 搜"XX 旅游攻略",发现一个小众寺庙
think_tool 只有一个景点,寺庙值得深挖吗?
tavily_search 搜寺庙名字,发现附近观景台日出要早上五点
think_tool 有寺庙和观景台了,还缺美食、户外
tavily_search 搜"XX 夜市",评价两极分化
think_tool 三个方向了,还缺户外活动
tavily_search 搜"XX 徒步",找到半日路线
ResearchComplete 四个方向够了,整理笔记

这就是第一章提到的节奏:搜-想-搜-想。每一次"想"对应一次 think_tool——搜到了什么?还缺什么?够了吗?


注意循环里没有"计划"步骤。Researcher 不会在开头列完整搜索计划——它边搜边想边调整。这就是 ReAct(Reason-Act-Observe):行动产生观察,观察驱动推理,推理引导下一次行动。


为什么不用 Supervisor 层的 Plan-and-Execute?因为搜索本质是探索性的——搜之前不知道会搜到什么。小 B 出发时根本不知道有个小众寺庙,是搜索中偶然发现的。ReAct 的灵活性,恰好适配这种任务。


可控性在决策层,灵活性在执行层。 两层用不同模式,是任务性质决定的。




2.3 什么时候必须收工


小 B 这次是自己判断"四个方向够了"主动停的。但如果他是个完美主义者,觉得"还可以再查查当地手工艺品市场",然后"再看看有没有小众咖啡馆"——查到天黑也停不下来怎么办?


出发前你给每个人定了规矩:最多查两个小时,到点必须交结果。


在 ODR 里,这就是 max_react_tool_calls——工具调用次数的硬上限。无论 Researcher 是否觉得信息足够,达到上限就强制结束。


两个出口并存:























出口 触发条件 性质
ResearchComplete 模型判断信息足够 正常出口
max_react_tool_calls 工具调用次数达到上限 安全网

这个设计在两层都存在。Researcher 有工具调用上限,Supervisor 有调查轮次上限(max_loops)。每一层都有模型信号和资源上限两道关卡——模型信号让正常情况下的退出是智能的,资源上限确保异常情况下系统不会无限运转。


对于 Deep Research 这类系统,budget 控制不是可选的优化,而是必要的约束。模型被要求做深度研究,它的自然倾向是持续推进——没有硬性边界,它不会主动停下。




2.4 晚饭时每人说三分钟


三个人各自查了一下午。晚饭时坐下来:“每人说说重点。”



  • 小 A:直飞比转机贵 400,推荐两个航班。老城区酒店性价比最高。最便宜的组合是红眼航班加民宿,凌晨两点到。

  • 小 B:小众寺庙值得去,附近观景台看日出要早上五点。夜市评价两极分化。有条半日徒步路线。

  • 小 C:免签,偶尔阵雨带伞,打车便宜,没特别的安全问题。


几个小时的调查,几分钟说完。


在 ODR 里,这一步对应 compress_research——它不是搜索循环的一部分,而是 Researcher 子图中的一个独立节点。当 ResearchComplete 被调用或工具调用次数达到上限时,流程从搜索循环跳转到这个节点。


它的输入是 Researcher 在搜索循环中积累的全部消息历史——每一次搜索的返回结果、每一次 think_tool 的反思记录、模型的每一步决策。这些消息被交给一次独立的 LLM 调用,整理成结构化摘要。


原则不是"总结",而是保真去重



All relevant information should be repeated and rewritten verbatim, but in a cleaner format.



一条都不丢,去掉重复和噪声。所有来源链接完整保留。摘要交回 Supervisor 的 notes 列表,作为判断"继续还是收尾"的依据。




三、这套设计换来了什么


并行、隔离、压缩——这三个选择不是各自独立的,它们是同一个设计决策的三个面。选择了并行,就必须隔离;隔离之后信息分散,就必须压缩汇聚。理解收益和代价,要把它们放在一起看。


3.1 收益




























收益 说明
速度 调查时间取决于最慢的 Researcher,而非所有任务的总和。三个课题并行,耗时接近一个课题,而不是三倍
聚焦 每个 Researcher 上下文里只有自己的线索。查机票的不会被景点信息稀释注意力,查景点的不会被签证政策分心。上下文越干净,搜索决策越精准
容错 小 C 搜签证政策时走了弯路,但小 A 和小 B 完全不受影响。某一条线的质量波动被隔离在那条线内部,不会传染
上下文效率 原始网页压缩到四分之一,工作历史再经 compress_research 整理成摘要。两层压缩后,所有线索的体量小到能塞进一次 LLM 调用——让最终 Synthesizer 能同时看到所有线索,做全局推理。前面压缩,正是为了最后能一次综合



3.2 代价


先从第一性原理看这个问题。


信息在这条链路中被压缩了两次:原始网页 → 预处理摘要(四分之一体量),Researcher 工作历史 → compress_research 结构化摘要。每一次压缩,本质上都是一次"什么值得保留"的判断。


这个判断有两个根本性的局限:


做判断的模型不知道下游需要什么。 压缩网页的模型不知道 Researcher 会追哪条线索;压缩研究历史的模型不知道 Supervisor 会拿摘要和哪些其他线索做交叉推断。每一层的"相关性"判断都是局部的——它只能基于当前上下文判断,无法预见信息在全局中的关联价值。


隔离让跨线索关联在压缩时不可见。 小 A 压缩时不知道小 B 的发现,"凌晨两点到"在小 A 的上下文里只是航班的附带信息,看起来不值得强调。但放到全局,它和小 B 的"早上五点日出"构成矛盾——这个关联在压缩时根本无从判断。


用一个具体的例子看这两个局限如何叠加:


flowchart TD
subgraph A ["小 A · 机票住宿(独立上下文)"]
A1["发现:红眼航班最便宜,凌晨两点到"]
end
subgraph B ["小 B · 景点推荐(独立上下文)"]
B1["发现:观景台日出很美,早上五点出发"]
end

A1 -->|"压缩:'凌晨到'是附带信息,不强调"| S["Supervisor 看到两份摘要"]
B1 -->|"压缩:'早起'是附带信息,不强调"| S

S --> D["选了最便宜的航班<br/>凌晨两点到,三点才睡<br/>日出没看到"]

"凌晨两点到"和"早上五点出发"各自在对方的视野之外。两条信息分别经过压缩,各自被判定为非核心细节。等它们汇聚到 Supervisor 时,关联可能已经模糊甚至消失了。




3.3 框架的应对


框架并非对此毫无应对。实际上有多层缓解机制:


压缩的保真原则。 compress_research 的设计目标不是"总结"而是"保真去重"——要求逐条原样保留相关信息。这降低了"凌晨两点到"这类细节在压缩环节被丢掉的概率。


Supervisor 的多轮反思。 Supervisor 收到摘要后,用 think_tool 反思"还缺什么?信息之间有没有矛盾?"。此时它同时看到所有线索的摘要——如果"凌晨两点到"和"早上五点日出"都保留了下来,Supervisor 在反思时有机会发现冲突,并在下一轮派出针对性任务来解决。


Synthesizer 的全局视野。 最终综合阶段,Synthesizer 同时看到全部摘要,在写报告时也是一个发现跨线索矛盾的机会。


Supervisor prompt 对隔离的显式承认。 框架在 prompt 中明确告知 Supervisor:



When calling ConductResearch, provide complete standalone instructions - sub-agents can’t see other agents’ work



这让 Supervisor 在派发任务时充分意识到隔离的存在,从而给出更完整、更自包含的任务描述。


这些机制都在起作用,但它们有一个共同特点:每一层都依赖模型的判断能力。压缩时模型要判断"凌晨两点到"是否值得保留;Supervisor 要在反思时把两条信息关联起来;Synthesizer 要在写报告时发现不一致。这些都可能发生,但不是必然发生。


框架用多层概率性的缓解来应对一个结构性的代价。 每多一层,遗漏的概率降低一些,但无法降到零。




3.3 值得吗




























得到 失去
三条线同时推进,调查耗时大幅缩短 搜索中的实时交叉感知
上下文干净聚焦,搜索质量更稳定 跨线索关联只能事后推断
单条线的质量波动不传染 压缩可能吃掉关联细节
全链路压缩后,最终综合能一次看全 压缩本身是有损的

绝大多数场景下值得。调查线索通常相对独立——机票价格和景点推荐之间不存在因果关系。并行的效率收益远大于偶尔丢失的关联。


理解代价的意义不是质疑选择,而是知道边界:当问题本质是一条因果链而非独立线索时,需要格外留意摘要是否保留了足够的关联细节。




四、接下来


一个任务从派发到交回,经历了隔离、搜索、压缩。每个阶段都有明确的设计选择和代价。


三份摘要交回之后,还有最后一步:把分散的发现整合成一份报告。报告质量取决于全链路每一层保留了什么、丢掉了什么。


下一篇,从头到尾串一遍这条信息链。




← 03:谁在决定你的报告质量

最新回复 (11)
  • Grogu 03-18 15:31
    1

    前排学习,感谢佬友分享 ^-^

  • 大帅哥 03-18 15:57
    2

    感谢!学不动了

  • Venis 03-18 16:12
    3

    标记学习!谢谢佬!

  • 初春饰利 03-18 16:40
    4

    怎么是什么的解析哇!?

  • yelixin_117 楼主 03-18 16:59
    5


    一个开源的 deepresearch 的框架

  • poontsung 03-19 17:15
    6

    学起来学起来,别停 ^-^

  • starmelon 03-26 15:30
    7

    学习了,佬什么时候整合一下啊

  • yelixin_117 楼主 03-26 18:08
    8

    感谢支持。

    哈哈,应该还剩最后一篇,发完就整合一下。

    后面再来找一个 rag 的框架。

  • starmelon 03-26 19:36
    9

    期待佬的作品

  • sylfilic 03-26 19:47
    10

    前排学习

  • salsal101 08-25 03:09
    11

    写的好好啊 总结呢佬 而且现在过了快半年了 openai的dr感觉都没什么进步 感觉资源还变少了 有新的框架更新吗

* 帖子来源Linux.do
返回