跳到主要内容

Tongyi DeepResearch — 架构与原理

30 秒导读: Tongyi DeepResearch 是阿里通义实验室开源的「深度研究」智能体。核心是一个 300 亿参数(每 token 只激活 33 亿)的模型 + 一段 ReAct 循环:模型一边想、一边调用「网页搜索 / 读网页 / 学术搜索 / Python 沙箱 / 文件解析」这几样工具,把结果读回上下文,循环几十轮,最后吐出一段 <answer>。这份文档解剖的是仓库里真正能跑的推理代码(inference/),不是模型权重也不是训练。

1. 这是什么(零基础也能懂)

  • 一句话定义: 一个会自己上网查资料、读网页、算数,然后写出带引证的研究报告的 AI 智能体。

  • 解决什么问题 / 给谁用: 假设你问一个需要「查好几个网站、交叉验证、还得算一下」才能答的刁钻问题(例:某冷门赛事第 3 名选手母校的现任校长是谁)。普通聊天模型只能凭记忆瞎猜;Tongyi DeepResearch 会像人一样反复搜索、点开网页、提炼、再搜,直到凑齐证据。它面向做深度信息检索、评测 agentic 能力的研究者和开发者。

  • 它能做什么(功能):

    • 批量 Google 网页搜索、Google Scholar 学术搜索
    • 访问网页并自动摘要成「证据 + 总结」
    • 沙箱里跑 Python(算数、数据处理)
    • 解析本地上传的 PDF / DOCX / 音视频等文件
    • 长程多轮推理(默认最多 100 轮 LLM 调用,单题上限 2.5 小时)
  • 用起来什么样: 准备一个 .jsonl,每行一条问题,然后:

    # 1) 配好 API key(Serper 搜索、Jina 读网页、沙箱端点……)
    cp .env.example .env && vim .env
    # 2) 一键起 vLLM 服务 + 跑推理
    bash inference/run_react_infer.sh

    脚本会用 vLLM 把模型托起来(见 inference/run_react_infer.sh:30-37),再让 run_multi_react.py 并发地把每道题喂给 agent 循环。

  • 一句话直觉 / 类比: 把它想成一个只会用便利贴记事的实习研究员——每一轮它先在便利贴上写下「我在想什么、要查什么」,派人去查(工具),把查来的结果贴回笔记本(上下文),再看着整叠笔记想下一步。笔记本(上下文窗口)贴满了(超 110K token)就必须马上下结论交差。

2. 顶层全景(它大概怎么转)

整个系统分三层:起服务 → 跑 agent 循环 → 评分。核心价值在中间那层的 ReAct 循环。

怎么读这张图: 从上到下是一次推理任务的生命周期;中间虚线框内是每道题都要转很多圈的主循环。

┌───────────────────────────────────────────────┐
│ run_react_infer.sh:起 8 个 vLLM 服务(6001-6008)│
└───────────────────────┬───────────────────────┘

┌────────────────────────▼──────────────────────┐
│ run_multi_react.py:读数据集、按题分派端口、 │
│ 线程池并发、每题跑 roll_out_count 次(默认 3) │
└────────────────────────┬──────────────────────┘
│ 每个 (题, rollout) 一个任务
┌────────────────────────▼──────────────────────┐
│ MultiTurnReactAgent._run │
│ ┌ ─ ─ ─ ─ ─ ─ ─ 主循环(每题几十轮) ─ ─ ─ ─ ┐ │
│ ① call_server → 模型输出「思考+工具调用」 │
│ ② 解析 <tool_call> → 派发给某个工具 │
│ ③ 工具结果包成 <tool_response> 塞回上下文 │
│ ④ 出现 <answer> 或超时/超长 → 收尾 │
│ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │
└────────────────────────┬──────────────────────┘
│ 每轮结果写成 iterN.jsonl
┌────────────────────────▼──────────────────────┐
│ evaluate_deepsearch_official.py: │
│ LLM-as-judge 判对错 → 算 Pass@1 / Pass@3 │
└───────────────────────────────────────────────┘

部件一句话职责:

部件干什么在哪个文件
run_react_infer.sh拉起 8 个 vLLM 推理服务,再启动推理脚本inference/run_react_infer.sh
run_multi_react.py读数据、分片、按题粘性分配端口、线程池并发跑inference/run_multi_react.py
MultiTurnReactAgentReAct 主循环本体:调模型、派工具、管上下文inference/react_agent.py
SYSTEM_PROMPT告诉模型自己是谁、有哪些工具、输出格式inference/prompt.py
Search / Scholar调 Serper 打 Google / Google Scholarinference/tool_search.pytool_scholar.py
Visit用 Jina 抓网页 + LLM 摘要成证据inference/tool_visit.py
PythonInterpreter把代码丢进 SandboxFusion 沙箱执行inference/tool_python.py
FileParser解析本地文件 / 音视频inference/tool_file.py
evaluate_*LLM-as-judge 打分 + Pass@k 统计evaluation/

主线走一遍(高层,不进代码):

  1. 一道题进来,拼上 SYSTEM_PROMPT(含工具清单 + 当天日期)作为对话开头。
  2. 模型回一段:先 <think>…</think> 想,再要么 <tool_call>…</tool_call> 调工具,要么直接 <answer>…</answer> 交卷。
  3. 若是工具调用 → 派发执行 → 结果包成 <tool_response> 追加到对话,回到第 2 步。
  4. 直到模型给出 <answer>,或触发三种「刹车」(轮数用完 / 超 2.5 小时 / 上下文超 110K token)。
  5. 每道题独立跑 3 次(rollout),每次结果落一个 iterN.jsonl;评测脚本再用一个「裁判模型」逐条判对错,算出 Pass@1 / Pass@3。

3. 阅读地图(建议顺序)

先读 §1、§2 建立全景,再按下面顺序下钻:

  1. 01-react-loop.md先读这个。主循环是整个项目的心脏:一次「思考→工具→观察」怎么滚成多轮,<tool_call> / <answer> 怎么被解析,三种刹车怎么触发。
  2. 02-tools.md — 五个工具各自怎么实现、Python 工具为什么走「JSON + <code> 双段」这条特殊路径、工具派发的 custom_call_tool 有哪些坑。
  3. 03-context-and-robustness.md — 128K 上下文怎么算、怎么在超限前一步「强制收尾」、各层重试/降级/容错的设计。
  4. 04-evaluation.md — 多次 rollout + LLM-as-judge + Pass@k 的评测闭环,以及它对不同数据集换不同裁判模型的做法。

一个诚实的前置说明: README 宣传两种推理范式——ReActHeavy(基于 IterResearch 的测试时扩展)。但仓库 FAQ.md 明确写道 Heavy Mode 尚未完全开源("The Heavy Mode is not fully open-sourced yet")。所以这套文档只讲真实存在于 inference/ 的 ReAct 实现;凡涉及 Heavy 的部分,以「代码里没有」如实标注,不臆测。