LangGraph工作流模式
概述
LangGraph支持多种工作流模式,用于构建复杂的、有状态的LLM应用。本章将介绍常见的工作流模式,包括顺序执行、条件分支、并行执行、循环执行等。
基础模式
1. 顺序执行模式
节点按顺序依次执行:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from typing import TypedDict
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
input (str): 输入数据
step1_result (str): 步骤1的处理结果
step2_result (str): 步骤2的处理结果
output (str): 最终输出
"""
input: str
step1_result: str
step2_result: str
output: str
# 定义节点函数
def step1(state: State) -> State:
"""
步骤1节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
# 处理输入数据
return {"step1_result": f"步骤1处理: {state['input']}"}
def step2(state: State) -> State:
"""
步骤2节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
# 处理步骤1的结果
return {"step2_result": f"步骤2处理: {state['step1_result']}"}
def step3(state: State) -> State:
"""
步骤3节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
# 生成最终结果
return {"output": f"最终结果: {state['step2_result']}"}
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("step1", step1)
graph.add_node("step2", step2)
graph.add_node("step3", step3)
# 设置顺序边
# 顺序执行模式:节点按顺序依次执行
graph.set_entry_point("step1") # 设置入口点
graph.add_edge("step1", "step2") # step1 -> step2
graph.add_edge("step2", "step3") # step2 -> step3
graph.add_edge("step3", END) # step3 -> 结束
# 编译和执行
app = graph.compile()
# 执行图
result = app.invoke({
"input": "测试数据",
"step1_result": "",
"step2_result": "",
"output": ""
})
print(result["output"])2. 条件分支模式
根据条件选择不同的执行路径:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from typing import TypedDict
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
input (str): 用户输入
category (str): 分类结果(weather/news/general)
output (str): 处理结果
"""
input: str
category: str
output: str
# 定义节点函数
def classify(state: State) -> State:
"""
分类节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:根据输入内容进行分类
"""
input_text = state["input"].lower()
# 根据关键词分类
if "天气" in input_text:
category = "weather"
elif "新闻" in input_text:
category = "news"
else:
category = "general"
return {"category": category}
def handle_weather(state: State) -> State:
"""
处理天气查询
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
return {"output": f"天气查询结果: {state['input']}"}
def handle_news(state: State) -> State:
"""
处理新闻查询
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
return {"output": f"新闻查询结果: {state['input']}"}
def handle_general(state: State) -> State:
"""
处理一般查询
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
return {"output": f"一般查询结果: {state['input']}"}
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("classify", classify)
graph.add_node("weather", handle_weather)
graph.add_node("news", handle_news)
graph.add_node("general", handle_general)
# 设置条件边
def route_function(state: State) -> str:
"""
路由函数
参数:
state (State): 当前状态
返回值:
str: 路由目标
"""
return state["category"]
# 添加条件边
# 条件分支模式:根据条件选择不同的执行路径
graph.add_conditional_edges(
"classify", # 起始节点
route_function, # 路由函数
{
"weather": "weather", # 天气路由
"news": "news", # 新闻路由
"general": "general" # 一般路由
}
)
# 设置出口
graph.add_edge("weather", END)
graph.add_edge("news", END)
graph.add_edge("general", END)
# 编译和执行
graph.set_entry_point("classify")
app = graph.compile()
# 执行图
result = app.invoke({
"input": "北京天气怎么样?",
"category": "",
"output": ""
})
print(result["output"])3. 并行执行模式
多个节点并行执行:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
import asyncio # 异步IO库
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
input (str): 输入数据
results (List[str]): 任务结果列表
output (str): 合并后的输出
"""
input: str
results: List[str]
output: str
# 定义异步节点函数
async def task1(state: State) -> State:
"""
任务1(异步)
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
# await asyncio.sleep(1):模拟异步操作
await asyncio.sleep(1)
return {"results": [f"任务1结果: {state['input']}"]}
async def task2(state: State) -> State:
"""
任务2(异步)
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
await asyncio.sleep(1)
return {"results": [f"任务2结果: {state['input']}"]}
async def task3(state: State) -> State:
"""
任务3(异步)
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
await asyncio.sleep(1)
return {"results": [f"任务3结果: {state['input']}"]}
def merge_results(state: State) -> State:
"""
合并结果节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
# 合并所有任务的结果
return {"output": "合并结果: " + ", ".join(state["results"])}
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("task1", task1)
graph.add_node("task2", task2)
graph.add_node("task3", task3)
graph.add_node("merge", merge_results)
# 设置并行边
# 并行执行模式:多个节点可以并行执行
graph.set_entry_point("task1")
graph.add_edge("task1", "task2") # task1完成后执行task2
graph.add_edge("task1", "task3") # task1完成后同时执行task3
graph.add_edge("task2", "merge") # task2完成后执行merge
graph.add_edge("task3", "merge") # task3完成后执行merge
graph.add_edge("merge", END) # merge完成后结束
# 编译和执行
app = graph.compile()
# 执行图
result = app.invoke({
"input": "测试数据",
"results": [],
"output": ""
})
print(result["output"])高级模式
1. 循环执行模式
重复执行直到满足条件:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from typing import TypedDict
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
count (int): 当前执行次数
max_iterations (int): 最大迭代次数
output (str): 输出结果
"""
count: int
max_iterations: int
output: str
# 定义节点函数
def process(state: State) -> State:
"""
处理节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
# 增加计数
count = state["count"] + 1
return {"count": count}
def should_continue(state: State) -> str:
"""
判断是否继续执行
参数:
state (State): 当前状态
返回值:
str: 决定下一步
"continue":继续执行
"end":结束执行
"""
# 检查是否达到最大迭代次数
if state["count"] >= state["max_iterations"]:
return "end"
return "continue"
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("process", process)
# 设置条件边
# 循环执行模式:重复执行直到满足条件
graph.add_conditional_edges(
"process", # 起始节点
should_continue, # 条件函数
{
"continue": "process", # 继续执行,回到process节点
"end": END # 结束执行
}
)
# 编译和执行
graph.set_entry_point("process")
app = graph.compile()
# 执行图
result = app.invoke({
"count": 0,
"max_iterations": 5,
"output": ""
})
print(f"执行次数: {result['count']}")2. 人机交互模式
在关键节点等待人工输入:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver # 内存检查点
from typing import TypedDict
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
messages (list): 消息列表
human_input (str): 人工输入
approved (bool): 是否已批准
"""
messages: list
human_input: str
approved: bool
# 定义节点函数
def process(state: State) -> State:
"""
处理节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
return {
"messages": state["messages"],
"human_input": "",
"approved": False
}
def human_approval(state: State) -> State:
"""
人工审批节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:等待人工审批
"""
print("需要人工审批")
return {
"messages": state["messages"],
"human_input": "approved", # 模拟人工输入
"approved": True
}
def final(state: State) -> State:
"""
最终节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
return {
"messages": state["messages"],
"human_input": state["human_input"],
"approved": True
}
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("process", process)
graph.add_node("human_approval", human_approval)
graph.add_node("final", final)
# 设置边
graph.set_entry_point("process")
graph.add_edge("process", "human_approval")
graph.add_edge("human_approval", "final")
graph.add_edge("final", END)
# 使用检查点
# MemorySaver():内存检查点,用于保存和恢复状态
checkpointer = MemorySaver()
# 编译图,启用检查点和中断
# interrupt_before=["human_approval"]:在human_approval节点前中断执行
app = graph.compile(checkpointer=checkpointer, interrupt_before=["human_approval"])
# 执行配置
# config:配置字典,包含thread_id用于标识执行线程
config = {"configurable": {"thread_id": "1"}}
# 执行图
result = app.invoke({
"messages": [],
"human_input": "",
"approved": False
}, config)3. 状态机模式
实现复杂的状态机逻辑:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from typing import TypedDict, Literal
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
current_state (str): 当前状态(A/B/C)
input (str): 输入数据
output (str): 输出结果
"""
current_state: str
input: str
output: str
# 定义状态转换函数
def state_a(state: State) -> State:
"""
状态A
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
# 根据输入决定状态转换
if "触发" in state["input"]:
return {"current_state": "B", "output": "从A转换到B"}
return {"current_state": "A", "output": "保持在A"}
def state_b(state: State) -> State:
"""
状态B
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
if "完成" in state["input"]:
return {"current_state": "C", "output": "从B转换到C"}
return {"current_state": "B", "output": "保持在B"}
def state_c(state: State) -> State:
"""
状态C(最终状态)
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
"""
return {"current_state": "C", "output": "最终状态C"}
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("A", state_a)
graph.add_node("B", state_b)
graph.add_node("C", state_c)
# 设置条件边
def route_function(state: State) -> str:
"""
路由函数
参数:
state (State): 当前状态
返回值:
str: 路由目标
"""
return state["current_state"]
# 添加条件边
# 状态机模式:实现复杂的状态机逻辑
graph.add_conditional_edges(
"A", # 从状态A
route_function,
{
"A": "A", # 保持在A
"B": "B" # 转换到B
}
)
graph.add_conditional_edges(
"B", # 从状态B
route_function,
{
"B": "B", # 保持在B
"C": "C" # 转换到C
}
)
# 设置出口
graph.add_edge("C", END) # 状态C是最终状态
# 编译和执行
graph.set_entry_point("A")
app = graph.compile()
# 执行图
result = app.invoke({
"current_state": "A",
"input": "触发",
"output": ""
})
print(result["output"])实际应用模式
1. RAG工作流模式
实现检索增强生成工作流:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
query (str): 用户查询
documents (List[str]): 检索到的文档列表
context (str): 上下文信息
answer (str): 生成的回答
"""
query: str
documents: List[str]
context: str
answer: str
# 定义节点函数
def retrieve(state: State) -> State:
"""
检索节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:从知识库中检索相关文档
"""
# 这里应该是实际的检索逻辑
# 示例:模拟检索结果
documents = [f"文档1: {state['query']}", f"文档2: {state['query']}"]
return {"documents": documents}
def rerank(state: State) -> State:
"""
重排序节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:对检索结果进行重排序
"""
# 这里应该是实际的重排序逻辑
# 示例:将文档合并为上下文
context = "\n".join(state["documents"])
return {"context": context}
def generate(state: State) -> State:
"""
生成节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:基于上下文生成回答
"""
# 这里应该是实际的生成逻辑
# 示例:模拟生成回答
answer = f"基于上下文的回答: {state['context']}"
return {"answer": answer}
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("retrieve", retrieve)
graph.add_node("rerank", rerank)
graph.add_node("generate", generate)
# 设置边
# RAG工作流模式:检索 -> 重排序 -> 生成
graph.set_entry_point("retrieve")
graph.add_edge("retrieve", "rerank")
graph.add_edge("rerank", "generate")
graph.add_edge("generate", END)
# 编译和执行
app = graph.compile()
# 执行图
result = app.invoke({
"query": "什么是人工智能?",
"documents": [],
"context": "",
"answer": ""
})
print(result["answer"])2. 多Agent协作模式
实现多Agent协作工作流:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
task (str): 任务描述
research_result (str): 研究结果
analysis_result (str): 分析结果
final_report (str): 最终报告
"""
task: str
research_result: str
analysis_result: str
final_report: str
# 定义节点函数(Agent)
def researcher(state: State) -> State:
"""
研究员Agent
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:执行研究任务,收集信息
"""
# 这里应该是实际的研究逻辑
research_result = f"研究结果: {state['task']}"
return {"research_result": research_result}
def analyst(state: State) -> State:
"""
分析师Agent
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:分析研究结果
"""
# 这里应该是实际的分析逻辑
analysis_result = f"分析结果: {state['research_result']}"
return {"analysis_result": analysis_result}
def writer(state: State) -> State:
"""
作家Agent
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:撰写最终报告
"""
# 这里应该是实际的写作逻辑
final_report = f"最终报告: {state['analysis_result']}"
return {"final_report": final_report}
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("researcher", researcher)
graph.add_node("analyst", analyst)
graph.add_node("writer", writer)
# 设置边
# 多Agent协作模式:研究 -> 分析 -> 写作
graph.set_entry_point("researcher")
graph.add_edge("researcher", "analyst")
graph.add_edge("analyst", "writer")
graph.add_edge("writer", END)
# 编译和执行
app = graph.compile()
# 执行图
result = app.invoke({
"task": "人工智能在医疗领域的应用",
"research_result": "",
"analysis_result": "",
"final_report": ""
})
print(result["final_report"])3. 对话管理模式
实现复杂的对话管理:
python
# 导入LangGraph核心组件
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
# 定义状态类型
class State(TypedDict):
"""
状态定义
属性:
messages (List[dict]): 对话消息列表
intent (str): 用户意图
context (dict): 上下文信息
response (str): 生成的响应
"""
messages: List[dict]
intent: str
context: dict
response: str
# 定义节点函数
def understand_intent(state: State) -> State:
"""
理解意图节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:分析用户意图
"""
# 获取最后一条消息
last_message = state["messages"][-1]["content"]
# 根据关键词判断意图
if "天气" in last_message:
intent = "weather"
elif "新闻" in last_message:
intent = "news"
else:
intent = "chat"
return {"intent": intent}
def gather_context(state: State) -> State:
"""
收集上下文节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:收集和整理上下文信息
"""
# 收集上下文信息
context = {
"intent": state["intent"],
"history": state["messages"]
}
return {"context": context}
def generate_response(state: State) -> State:
"""
生成响应节点
参数:
state (State): 当前状态
返回值:
State: 更新后的状态
功能:根据意图和上下文生成响应
"""
# 这里应该是实际的响应生成逻辑
response = f"基于意图{state['intent']}的响应"
return {"response": response}
# 创建图
graph = StateGraph(State)
# 添加节点
graph.add_node("understand", understand_intent)
graph.add_node("gather", gather_context)
graph.add_node("generate", generate_response)
# 设置边
# 对话管理模式:理解意图 -> 收集上下文 -> 生成响应
graph.set_entry_point("understand")
graph.add_edge("understand", "gather")
graph.add_edge("gather", "generate")
graph.add_edge("generate", END)
# 编译和执行
app = graph.compile()
# 执行图
result = app.invoke({
"messages": [{"role": "user", "content": "北京天气怎么样?"}],
"intent": "",
"context": {},
"response": ""
})
print(result["response"])最佳实践
1. 模式选择
- 顺序执行:简单的线性流程
- 条件分支:需要根据条件选择路径
- 并行执行:需要同时处理多个任务
- 循环执行:需要重复执行直到满足条件
2. 状态设计
- 最小化状态:只包含必要的状态信息
- 清晰的类型:使用TypedDict定义状态
- 合理的更新:每个节点只更新相关的状态
- 错误处理:在状态中包含错误信息
3. 性能优化
- 并行执行:独立任务并行执行
- 缓存结果:缓存中间结果
- 异步处理:使用异步节点提升性能
- 资源管理:合理管理资源
常见问题
1. 执行流程问题
- 死循环:设置最大迭代次数
- 条件判断错误:仔细检查条件函数
- 节点执行失败:添加错误处理
2. 状态管理问题
- 状态不一致:确保所有节点正确更新状态
- 状态丢失:使用检查点持久化状态
- 状态验证:添加状态验证逻辑
3. 性能问题
- 执行慢:优化节点函数
- 内存占用高:减少状态大小
- 并发限制:使用异步执行