智能体编排:从链式到图式#
“先检索、再分析、后写作”——这是链式编排,线性、好理解、但死板。真实任务不是线性的:有的分支要并行、有的要条件跳转、有的要回退重试。图式编排(DAG)是复杂 Agent 任务的答案。
一、链式编排:够用但死板#
问题:
适用:流程固定的任务(面试流程:开场→提问→评分)。
二、图式编排:DAG(有向无环图)#
核心概念:
| 概念 |
作用 |
| 节点(Node) |
一个任务单元(检索/分析/写作) |
| 边(Edge) |
依赖关系(B 依赖 A 的结果) |
| 条件边 |
满足条件才走(审校通过 → 交付) |
| 并行 |
无依赖的节点同时跑 |
| 循环(可) |
重试/回退(审校不过 → 重写) |
三、实现:LangGraph 模式#
LangGraph 是图式编排的代表实现,核心概念:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
from langgraph.graph import StateGraph
# 1. 定义状态(节点之间传什么)
class TaskState(TypedDict):
question: str
search_results: list
draft: str
reviewed: bool
# 2. 定义节点(每个节点一个函数)
def search(state): # 检索
return {"search_results": search_engine(state["question"])}
def write(state): # 写作
return {"draft": llm.write(state)}
def review(state): # 审校
return {"reviewed": check(state["draft"])}
# 3. 定义图(节点 + 边 + 条件)
graph = StateGraph(TaskState)
graph.add_node("search", search)
graph.add_node("write", write)
graph.add_node("review", review)
graph.add_edge("search", "write")
graph.add_conditional_edge("review", # 条件边
lambda s: "done" if s["reviewed"] else "write", # 不过就回去重写
{"done": END, "write": "write"})
|
状态(State)是图式编排的灵魂:
四、从链式到图式的演进路径#
别一上来就画大图(复杂图 = 难调试 = 难维护):
我的实践路径:
关键认知:状态机是"受限的图",图是"泛化的状态机"。 大部分生产场景状态机就够——图留给真复杂的(多 Agent 协作、多阶段生成)。
五、图式编排的工程要点#
1. 状态持久化#
1
2
3
4
5
|
# 图执行到一半挂了 → 能从断点恢复
graph = StateGraph(TaskState)
app = graph.compile(checkpointer=MemorySaver()) # 持久化状态
# 恢复:传 thread_id,从上次中断继续
app.invoke({"question": q}, config={"thread_id": "s-001"})
|
价值:长任务(分钟级)中途失败不用从头跑。
2. 中断与人工介入#
3. 可观测#
4. 超时与重试#
六、选型决策#
| 需求 |
方案 |
| 固定流程 |
状态机(手写,可控) |
| 少量分支 + 并行 |
简单编排(LangGraph 轻量用) |
| 复杂多 Agent + 循环 + 人工介入 |
LangGraph / 自研 DAG |
| 纯 LLM 调用链 |
链式 + 函数调用就够 |
不要为编排而编排:单 Agent + 工具调用能解决的,别上 DAG——图式编排的成本是调试复杂度。
七、踩坑记录#
- 状态字段随意增删:节点间契约不稳定 → 状态定义版本化,节点只读写声明字段
- 图太深:10+ 层嵌套,一个节点错全链路错 → 深度 ≤ 5,中间节点可观测
- 循环失控:审校不过无限重写 → 重试次数上限 + 降级路径
- 并行过度:10 个节点全并行 → token 和延迟爆炸 → 并行只给真正独立的
图式编排的核心认知:
- 链式 → 条件 → 并行 → 图:逐步演进,别一步到位
- 状态是灵魂:节点间通过状态契约协作
- 状态机是受限图:大部分生产场景状态机够用
- 工程四件套:持久化、人工介入、可观测、超时重试
编排的终点不是"图越复杂越好",是"任务的真实结构被准确表达"。 线性任务用链,复杂任务用图——表达对了,Agent 才可控。
微信公众号「福清而不淡」
后端架构 · AI 工程 · 云原生的一线实践,扫码关注,不错过更新。
本文已同步发布到公众号,欢迎留言交流。