动态图ReAct和串行链式ReAct
前言:👀这篇文档之前建议去力扣刷一下课程表(207. 课程表 - 力扣(LeetCode))这道题,会对你有意想不到的帮助!串行链式 ReAct(Linear / Sequential ReAct)传统 ReAct 本质:Thought -> Action -> Observation ↓ ...
字数: 1510 | 语雀原文
前言:👀这篇文档之前建议去力扣刷一下课程表()这道题,会对你有意想不到的帮助!
串行链式 ReAct(Linear / Sequential ReAct)
传统 ReAct 本质:
Thought -> Action -> Observation
↓
Thought -> Action -> Observation
↓
Thought -> Action -> Observation
即:
- 一步一步串行推进
- 当前步骤完成后才能进入下一步
- 上下文是线性的
- 每次只维护一个执行路径 典型特点:
| 特征 | 串行链式 ReAct |
|---|---|
| 执行方式 | 单链路串行 |
| 状态结构 | Linear Context |
| 推理模式 | 单线程思考 |
| Tool调用 | 顺序调用 |
| 容错 | 弱 |
| 可恢复 | 一般 |
| 并行能力 | 无 |
| 复杂任务 | 容易爆context |
适合场景
适用于:
- 简单问答
- 单工具任务
- 一次性推理
- 短链路 Agent 例如:
用户:北京天气?
Thought: 需要查询天气
Action: weather_api(Beijing)
Observation: 26℃
Answer: 北京26℃
这是经典 ReAct。
动态图 ReAct(Graph-based ReAct)
动态图 ReAct 的核心:
不是“链”。
而是:
一个动态扩展的任务图(Task Graph)
结构类似:
Root Thought
│
├─► Tool A ──► Result
│
├─► Tool B ──┬─► Subtask B1 ──► B1 Result
│ └─► Subtask B2
│
└─► Tool C ──┬─► Memory Recall
└─► Planner (Re-plan)
它本质是:
ReAct + DAG Runtime + Stateful Scheduler
核心区别
| 维度 | 串行链式 ReAct | 动态图 ReAct |
|---|---|---|
| 执行结构 | 链表 | DAG/Graph |
| 推理方式 | 单路径 | 多路径 |
| Context | 单上下文 | 节点级上下文 |
| Tool调用 | 串行 | 可并行 |
| 状态管理 | Prompt里硬塞 | Runtime State |
| 容错 | Retry困难 | 节点恢复 |
| 长任务 | 容易崩 | 可持续执行 |
| Memory | 临时上下文 | 图状态持久化 |
| 调度 | 无 | Scheduler |
| 适合 | Chat Agent | Production Agent |
为什么动态图更先进
因为真实 Agent 任务不是线性的。
例如:
“帮我分析公司财报并生成投资建议”
实际上会拆成:
1. 拉取财报
2. 拉取行业数据
3. 拉取新闻
4. 分析风险
5. 分析增长
6. 汇总生成报告
这里天然就是 DAG:
拉取数据
/ \
风险分析 增长分析
\ /
最终汇总
不是线性链。
动态图 ReAct 的关键组件
- Planner(任务规划)
先把任务拆图:
Goal -> Subtasks
例如:
{
"nodes": [
"search_news",
"analyze_finance",
"generate_report"
]
}
- Runtime State
每个节点有独立状态:
NodeState:
status
retries
outputs
dependencies
而不是全部塞 prompt。
- Scheduler(调度器)
决定:
- 哪些节点可以执行
- 哪些依赖完成
- 哪些失败重试
- 哪些并行 类似:
Airflow / Ray / Temporal
思想。
- Memory Graph
记忆不再只是:
conversation history
而是:
Task Graph State
+
Semantic Memory
+
Working Memory
例如:
节点A输出 -> 节点D输入
直接图连接。
一个直观例子
串行 ReAct
Thought
↓
Search
↓
Observation
↓
Thought
↓
Code
↓
Observation
像:
流水线工人
动态图 ReAct
Planner
↓
┌──────────┼──────────┐
Search Code Memory
│ │ │
└──────Merge/Summary───┘
像:分布式调度系统
最直观的感受,是执行速度加快了,因为毕竟并行度增加了
区别
串行链式 ReAct
本质:
Prompt 驱动推理
动态图 ReAct
本质:
Runtime 驱动智能体
即:
LLM 不再直接控制全部流程。
而是:
LLM 负责认知
Runtime 负责执行
Scheduler 负责调度
Memory 负责状态
这是现代 Agent 的核心方向。
业界演进趋势
大致路线:
Chain-of-Thought
↓
ReAct
↓
Plan-and-Execute
↓
Graph-based Agent
↓
Stateful Runtime Agent
代表:
- OpenAI Deep Research
- Anthropic Computer Use
- LangChain LangGraph
- Microsoft AutoGen
- Temporal Technologies Temporal Agent Runtime 基本都在:
ReAct Runtime 化
而不是继续做 Prompt chaining。
动态图的实现方法
Kahn Topological Sort
是业界 DAG Runtime 最常见的一种实现思路。
本质流程:
1. 找入度为0的节点
2. 执行
3. 删除边
4. 更新其他节点入度
5. 继续调度
但真正的 Agent Runtime / Workflow Engine 里,会在这个基础上再加:
- 状态机
- 调度器
- 优先级
- 并行池
- 重试机制
- Future/Promise
- 依赖追踪 最后就演化成:
DAG Scheduler Runtime
最基础 DAG 执行模型
例如:
A → C
B → C
C → D
数据结构
一般:
class Node:
id
deps # 依赖谁
nexts # 后继节点
indegree # 入度
图:
graph = {
"A": ["C"],
"B": ["C"],
"C": ["D"]
}
入度:
A:0
B:0
C:2
D:1
经典 Kahn 算法
Step1 初始化队列
把:
indegree == 0
的节点放进去。
即:
[A, B]
Step2 执行节点
执行:
A
然后:
A -> C
这条边被“删除”。
于是:
C indegree:
2 -> 1
再执行:
B
则:
C indegree:
1 -> 0
于是:
C 可执行
进入队列。
为什么很多系统用小顶堆
因为:
多个节点同时可执行
时,需要:
调度策略
例如:
| 策略 | 小顶堆排序依据 |
|---|---|
| BFS | depth |
| 优先级 | priority |
| 最早创建 | timestamp |
| 最短任务优先 | cost |
| AI Agent | importance score |
所以:
heapq.heappush(heap, (priority, node))
而不是普通 queue。
现代 Runtime 会怎么做
真正复杂的是:
节点执行不是同步函数
而是:
Future / Async Task
例如:
async def execute(node):
result = await tool_call()
于是 Scheduler 会:
提交任务
↓
等待完成
↓
更新依赖
↓
激活下游节点
这已经接近:
- Ray DAG
- Airflow
- Prefect
- Temporal
- LangGraph 了。
Agent Runtime 比普通 DAG 多的东西
普通 DAG:
节点 = 函数
但 Agent:
节点 = LLM Cognitive Step
于是节点状态会变成:
class AgentNode:
thought
action
observation
retries
memory
tool_result
不是单纯函数调用。
真正工业级 Scheduler
一般会维护:
- Ready Queue
所有 indegree=0 且未执行节点
- Running Set
当前执行中的节点
- Finished Set
完成节点
- Failed Set
失败节点
- Dependency Map
dependency_map = {
"C": ["A", "B"]
}