前两篇我们解决了:
- Graph 是什么
- State 如何流转
- Node 如何更新 State
但是目前的流程:
css
START
↓
Node A
↓
Node B
↓
END
还是固定路线。
而真实 Agent 最大的特点:
下一步往往不是提前确定的,而是根据当前结果动态决定。
这就是 Conditional Edge 和 Loop。
1. 普通 Edge:固定流程
先回顾:
arduino
.addEdge("A", "B")
表示:
css
A
|
↓
B
无论发生什么:
永远走 B。
例如:
用户登录
↓
查询用户信息
↓
返回结果
这种流程非常适合固定业务。
但是 Agent 不一样。
2. Agent 为什么需要条件路由?
例如:
用户输入:
帮我计算 1+2
和:
介绍一下 LangGraph
处理方式完全不同。
如果只有一个 Agent:
用户问题
↓
LLM自己判断
↓
选择工具
所有能力都塞在一个大脑里。
另一种方式:
拆成不同节点:
markdown
query
↓
router
/ \
/ \
mathNode chatNode
router 负责:
判断应该去哪。
3. Conditional Edge 是什么?
代码:
php
.addConditionalEdges(
"router",
state => state.route,
{
math:"mathNode",
chat:"chatNode"
}
)
拆开理解。
第一个参数
arduino
"router"
表示:
从哪个节点开始判断。
也就是:
yaml
router
|
↓
?
第二个参数
ini
state => state.route
这是:
路由函数。
它读取当前 State。
例如:
当前:
css
{
query:"1+2",
route:"math"
}
执行:
ini
state=>state.route
返回:
lua
math
第三个参数
css
{
math:"mathNode",
chat:"chatNode"
}
这是映射关系。
意思:
lua
返回 math
↓
进入 mathNode
返回 chat
↓
进入 chatNode
完整流程:
perl
router
↓
(state)=>state.route
↓
"math"
↓
mathNode
4. 为什么需要映射表?
你之前问过:
为什么不直接返回节点名?
其实可以。
例如:
javascript
const router=(state)=>{
return {
route:"mathNode"
}
}
然后:
perl
(state)=>state.route
直接返回:
mathNode
也可以。
但是很多项目会分开:
业务状态:
lua
math
chat
图节点:
mathNode
chatNode
原因:
解耦。
比如以后改名字:
mathNode
↓
calculatorAgentNode
业务逻辑不用改。
5. 循环:Agent 为什么不是一次执行?
真实 Agent 经常:
执行 → 检查 → 修改 → 再执行。
例如:
代码生成 Agent:
用户需求
↓
生成代码
↓
测试
↓
失败?
↓
修改代码
↓
重新测试
这是循环。
Graph:
markdown
┌──────────┐
↓ |
生成代码 → 测试 ───┘
↓
成功
↓
END
6. LangGraph 如何实现循环?
关键:
Edge 可以指向自己。
例如:
php
.addConditionalEdges(
"check",
state=>state.success,
{
retry:"generate",
end:END
}
)
如果:
ini
success=false
走:
sql
check
↓
generate
重新生成。
如果:
ini
success=true
走:
sql
END
7. 一个完整重试 Demo
State:
javascript
const StateAnnotation = Annotation.Root({
tries:Annotation({
reducer:(prev,next)=>next,
default:()=>0
}),
ok:Annotation({
reducer:(prev,next)=>next,
default:()=>false
})
});
节点:
ini
const attempt=(state)=>{
const tries=state.tries+1;
return {
tries,
ok:tries>=3
}
}
流程:
sql
START
↓
attempt
↓
判断ok
↓
false
↓
attempt
true
↓
END
执行:
第一次:
ini
tries=1
失败
第二次:
ini
tries=2
失败
第三次:
ini
tries=3
成功
结束。
8. Conditional Edge 和普通 Edge 区别
| 普通 Edge | Conditional Edge | |
|---|---|---|
| 路径 | 固定 | 动态 |
| 判断 | 没有 | 根据 State |
| 场景 | 流水线 | Agent决策 |
| 例子 | A→B | 成功→结束,失败→重试 |
9. 到这里 LangGraph 有了 Agent 的味道
前三篇组合起来:
yaml
State
|
↓
Node执行任务
|
↓
Edge控制流程
|
↓
Conditional Edge动态选择
|
↓
Loop不断优化
这已经不是简单 Chain:
css
A → B → C
而是:
markdown
判断
↓
执行 → 检查 → 重试
↓
完成
总结
一句话:
Conditional Edge 让 LangGraph 根据 State 动态选择下一步,Loop 让 Agent 能够反复执行、检查和优化,这也是 Graph 工作流区别于线性 Chain 的核心能力。