from typing import TypedDict, List, Annotated, Optional
from langgraph.graph import StateGraph, END
# ===== 状态类型定义 =====
class AgentState(TypedDict):
input: str # 用户原始输入
plan: Optional[dict] # 执行计划
past_steps: List[str] # 已完成的步骤记录
response: Optional[str] # 最终响应
# ===== 节点函数定义 =====
# 1. 计划生成节点
def planning_node(state: AgentState):
"""将用户输入转化为执行计划"""
user_input = state["input"]
# 模拟LLM生成计划的过程
example_plan = {
"goal": f"处理请求:{user_input}",
"steps": [
"分析核心需求",
"收集必要信息",
"生成初始草稿",
"验证内容准确性"
]
}
return {"plan": example_plan}
# 2. 任务执行节点
def execution_node(state: AgentState):
"""执行单个任务步骤"""
current_step = len(state["past_steps"])
steps = state["plan"]["steps"]
if current_step >= len(steps):
return {"response": "所有步骤已完成"}
task = steps[current_step]
# 模拟任务执行
print(f"正在执行步骤:{task}")
result = f"{task}完成于2024-02-20" # 替换为实际执行逻辑
return {
"past_steps": state["past_steps"] + [result],
"response": None # 清空中间响应
}
# 3. 用户确认节点
def user_confirm_node(state: AgentState):
"""请求用户确认是否继续"""
# 模拟用户输入(实际应替换为真实交互)
confirm = input(f"步骤 {len(state['past_steps'])+1} 失败,是否重试?(y/n): ")
return {"need_retry": confirm.lower() == 'y'}
# 4. 响应生成节点
def response_node(state: AgentState):
"""生成最终响应"""
return {
"response": f"处理完成。执行记录:{state['past_steps']}"
}
# ===== 构建状态图 =====
builder = StateGraph(AgentState)
# 添加节点
builder.add_node("plan", planning_node)
builder.add_node("execute", execution_node)
builder.add_node("confirm", user_confirm_node)
builder.add_node("response", response_node)
# 设置边
builder.set_entry_point("plan")
builder.add_edge("plan", "execute")
# 条件边:执行结果判断
def route_after_execute(state):
if state.get("response"):
return END # 所有步骤完成
if len(state["past_steps"]) < len(state["plan"]["steps"]):
return "execute" # 继续执行
return "confirm" # 需要用户确认
builder.add_conditional_edges(
"execute",
route_after_execute,
{
"confirm": "confirm",
"execute": "execute",
END: "response"
}
)
# 用户确认后的流程
builder.add_conditional_edges(
"confirm",
lambda s: "execute" if s["need_retry"] else "plan", # 重试或重新规划
{"execute": "execute", "plan": "plan"}
)
builder.add_edge("response", END)
# ===== 编译执行 =====
app = builder.compile()
# 运行示例
result = app.invoke({
"input": "需要生成季度报告",
"plan": None,
"past_steps": [],
"response": None
})
print("\n最终结果:", result["response"])
代码结构解析
1. 状态设计
class AgentState(TypedDict):
input: str # 用户原始输入
plan: Optional[dict] # 计划结构体
past_steps: List[str] # 执行历史
response: Optional[str] # 输出结果
使用TypedDict确保状态结构的类型安全,各字段含义:
input
:原始用户请求的持久化存储plan
:动态生成的执行计划past_steps
:记录每个步骤的执行结果response
:最终输出或中间状态
2. 核心工作流
3. 关键节点说明
planning_node
- 输入:原始用户请求
- 处理:生成结构化计划(实际应集成LLM调用)
- 输出:更新
plan
字段
execution_node
- 机制:
- 通过
past_steps
长度判断当前步骤 - 按顺序执行
plan.steps
中的任务 - 记录执行结果到
past_steps
- 通过
user_confirm_node
- 模拟用户交互场景
- 返回
need_retry
布尔值指导流程走向
4. 条件路由逻辑
def route_after_execute(state):
# 如果已产生最终响应
if state.get("response"):
return END
# 判断是否所有步骤完成
steps_done = len(state["past_steps"])
total_steps = len(state["plan"]["steps"])
if steps_done < total_steps:
return "execute" # 继续执行
else:
return "confirm" # 请求用户确认
该函数实现三种状态转换:
- 正常完成 → 结束流程
- 步骤未完成 → 继续执行
- 异常完成 → 进入确认环节
运行示例输出
当执行代码时会看到类似以下交互流程:
正在执行步骤:分析核心需求
正在执行步骤:收集必要信息
步骤 3 失败,是否重试?(y/n): y
正在执行步骤:生成初始草稿
正在执行步骤:验证内容准确性
最终结果: 处理完成。执行记录:[
'分析核心需求完成于2024-02-20',
'收集必要信息完成于2024-02-20',
'生成初始草稿完成于2024-02-20',
'验证内容准确性完成于2024-02-20'
]
扩展建议
- 真实集成LLM:
from langchain_community.llms import OpenAI
def real_planner(state):
llm = OpenAI()
prompt = f"将以下请求分解为步骤:{state['input']}"
return {"plan": llm.invoke(prompt)}
- 错误处理增强:
def execution_node(state):
try:
# 执行逻辑
except Exception as e:
return {"error": str(e)}
- 持久化存储:
from langgraph.checkpoint import FileCheckpoint
app = builder.compile(
checkpointer=FileCheckpoint("./checkpoints/")
)