前言
在LangGraph中,条件边(Conditional Edges)是一个强大的特性,它允许我们根据状态的值动态地选择执行路径。这使得我们可以构建具有决策能力的工作流,根据不同的输入或中间状态执行不同的处理逻辑。本文将通过分析示例,深入讲解条件边的概念、实现方式和应用场景。
条件边基础概念
条件边是StateGraph中的一种特殊边,它不直接连接两个节点,而是根据一个路由函数(router function)的返回值来决定下一步执行哪个节点。这种机制使得我们可以在工作流中实现条件分支逻辑,类似于编程语言中的if-else
语句或switch-case
语句。
条件边的核心组件包括:
- 路由函数:根据当前状态返回目标节点名称的函数
- 映射关系:将路由函数的返回值映射到实际节点名称的字典
示例代码
python
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langchain_core.runnables.graph_mermaid import MermaidDrawMethod
print("======= 示例2: 使用条件边 =======")
# 定义状态类型
class ConditionalState(TypedDict):
number: int
path: str
result: str
# 定义节点函数
def check_number(state: ConditionalState) -> ConditionalState:
"""检查数字的节点"""
return state # 这个节点仅用于路由,不改变状态
def process_even(state: ConditionalState) -> dict:
"""处理偶数的节点"""
result = f"{state['number']} 是偶数,已乘以2: {state['number'] * 2}"
return {"result": result, "path": "even"}
def process_odd(state: ConditionalState) -> dict:
"""处理奇数的节点"""
result = f"{state['number']} 是奇数,已加1: {state['number'] + 1}"
return {"result": result, "path": "odd"}
# 创建StateGraph
conditional_graph = StateGraph(ConditionalState)
# 添加节点
conditional_graph.add_node("check_number", check_number)
conditional_graph.add_node("process_even", process_even)
conditional_graph.add_node("process_odd", process_odd)
# 添加边
conditional_graph.add_edge(START, "check_number")
# 添加条件边
def router(state: ConditionalState) -> str:
"""根据数字奇偶性路由到不同节点"""
if state["number"] % 2 == 0:
return "process_even"
else:
return "process_odd"
conditional_graph.add_conditional_edges(
"check_number", # 起始节点
router, # 路由函数
{"process_even": "process_even", "process_odd": "process_odd"} # 映射关系
)
conditional_graph.add_edge("process_even", END)
conditional_graph.add_edge("process_odd", END)
# 编译图
compiled_conditional_graph = conditional_graph.compile()
# 执行图 - 测试偶数
result_even = compiled_conditional_graph.invoke({"number": 4, "path": "", "result": ""})
print(f"输入偶数: {{'number': 4, 'path': '', 'result': ''}}")
print(f"输出: {result_even}")
# 执行图 - 测试奇数
result_odd = compiled_conditional_graph.invoke({"number": 5, "path": "", "result": ""})
print(f"输入奇数: {{'number': 5, 'path': '', 'result': ''}}")
print(f"输出: {result_odd}")
# 示例说明:
# 1. 这个示例展示了如何使用条件边根据状态值动态选择执行路径
# 2. 定义了一个router函数,根据输入数字的奇偶性决定执行哪个处理节点
# 3. 使用add_conditional_edges方法配置条件路由
# 4. 可以看到对于偶数和奇数输入,会得到不同的处理结果
代码解析:条件边的实现与应用
1. 定义状态类型
python
class ConditionalState(TypedDict):
number: int
path: str
result: str
这个状态类型定义了三个字段:
number
:整数类型,用于存储要判断的数字path
:字符串类型,用于记录执行路径("even"或"odd")result
:字符串类型,用于存储处理结果
2. 定义节点函数
python
def check_number(state: ConditionalState) -> ConditionalState:
"""检查数字的节点"""
return state # 这个节点仅用于路由,不改变状态
def process_even(state: ConditionalState) -> dict:
"""处理偶数的节点"""
result = f"{state['number']} 是偶数,已乘以2: {state['number'] * 2}"
return {"result": result, "path": "even"}
def process_odd(state: ConditionalState) -> dict:
"""处理奇数的节点"""
result = f"{state['number']} 是奇数,已加1: {state['number'] + 1}"
return {"result": result, "path": "odd"}
这里定义了三个节点函数:
check_number
:一个特殊的节点,它不改变状态,仅作为路由的起点process_even
:处理偶数的节点,将数字乘以2并更新结果process_odd
:处理奇数的节点,将数字加1并更新结果
3. 创建和配置StateGraph
python
# 创建StateGraph
conditional_graph = StateGraph(ConditionalState)
# 添加节点
conditional_graph.add_node("check_number", check_number)
conditional_graph.add_node("process_even", process_even)
conditional_graph.add_node("process_odd", process_odd)
# 添加边
conditional_graph.add_edge(START, "check_number")
这部分代码创建了StateGraph实例并添加了三个节点,然后从START
节点连接到check_number
节点。
4. 添加条件边
python
# 定义路由函数
def router(state: ConditionalState) -> str:
"""根据数字奇偶性路由到不同节点"""
if state["number"] % 2 == 0:
return "process_even"
else:
return "process_odd"
# 配置条件边
conditional_graph.add_conditional_edges(
"check_number", # 起始节点
router, # 路由函数
{"process_even": "process_even", "process_odd": "process_odd"} # 映射关系
)
conditional_graph.add_edge("process_even", END)
conditional_graph.add_edge("process_odd", END)
这是条件边实现的核心部分:
- 首先定义了一个
router
函数,它接收当前状态,根据number
字段的奇偶性返回目标节点的名称 - 然后使用
add_conditional_edges
方法配置条件边:- 第一个参数是起始节点名称("check_number")
- 第二个参数是路由函数(
router
) - 第三个参数是映射关系字典,将路由函数的返回值映射到实际的节点名称
- 最后,从
process_even
和process_odd
节点分别连接到END
节点
5. 编译和执行图
python
# 编译图
compiled_conditional_graph = conditional_graph.compile()
# 执行图 - 测试偶数
result_even = compiled_conditional_graph.invoke({"number": 4, "path": "", "result": ""})
print(f"输入偶数: {{'number': 4, 'path': '', 'result': ''}}")
print(f"输出: {result_even}")
# 执行图 - 测试奇数
result_odd = compiled_conditional_graph.invoke({"number": 5, "path": "", "result": ""})
print(f"输入奇数: {{'number': 5, 'path': '', 'result': ''}}")
print(f"输出: {result_odd}")
编译图后,我们分别用偶数(4)和奇数(5)测试了图的执行。从输出结果可以看到,对于不同的输入,图会执行不同的处理节点,产生不同的结果。
执行流程分析
让我们详细分析一下整个图的执行流程:
对于偶数输入(例如4):
- 初始化 :
invoke()
方法接收初始状态{"number": 4, "path": "", "result": ""}
- 执行
check_number
节点 :从START
开始,首先执行check_number
节点,返回原始状态 - 执行路由函数 :调用
router
函数检查数字的奇偶性,返回"process_even" - 执行
process_even
节点 :根据路由函数的返回值,执行process_even
节点,将number
乘以2并更新result
和path
字段 - 结束 :从
process_even
节点连接到END
节点,执行结束并返回最终状态
对于奇数输入(例如5):
- 初始化 :
invoke()
方法接收初始状态{"number": 5, "path": "", "result": ""}
- 执行
check_number
节点 :从START
开始,首先执行check_number
节点,返回原始状态 - 执行路由函数 :调用
router
函数检查数字的奇偶性,返回"process_odd" - 执行
process_odd
节点 :根据路由函数的返回值,执行process_odd
节点,将number
加1并更新result
和path
字段 - 结束 :从
process_odd
节点连接到END
节点,执行结束并返回最终状态
为什么使用条件边?
条件边为StateGraph带来了以下优势:
- 动态决策:可以根据运行时的状态值动态选择执行路径
- 逻辑分离:将不同条件下的处理逻辑分离到不同的节点中
- 可扩展性:可以轻松添加新的条件分支,而不需要修改现有代码
- 可视化:条件分支逻辑可以通过图的可视化清晰地展示出来
条件边的实际应用场景
- 智能对话系统:根据用户的意图或问题类型选择不同的处理流程
- 工作流引擎:根据任务状态或条件选择下一步操作
- 决策系统:实现基于规则的决策逻辑
- 数据处理管道:根据数据特征选择不同的处理算法
总结
通过本文的学习,我们了解了LangGraph中条件边的概念、实现方式和应用场景。条件边是StateGraph中的一个强大特性,它允许我们根据状态的值动态地选择执行路径,从而构建具有决策能力的工作流。
这个示例展示了如何使用条件边实现基于数字奇偶性的简单路由,但条件边的应用远不止于此。在实际应用中,你可以根据业务需求实现更复杂的路由逻辑,构建更加智能和灵活的工作流系统。