第 08 课:LangGraph 有状态工作流精讲
📅 2026/7/9 4:27:49
👁️ 阅读次数
📝 编程学习
第 08 课:LangGraph 有状态工作流精讲
配套代码仓库:https://gitee.com/wang-zeyong111/lang-chain-lecture
本课定位
LangChain 的create_agent适合快速创建常见 Agent,但当你需要精确控制状态、分支、节点、人机协作、暂停恢复时,就需要 LangGraph。LangGraph 让你把 LLM 应用设计成图:节点执行任务,边决定流向,状态在图中传递和更新。
学习目标
- 理解状态图的基本概念。
- 掌握 StateGraph、节点、边、条件边。
- 能构建一个无需 API Key 的路由问答图。
- 理解 LangChain Agent 与 LangGraph 的关系。
- 能判断什么时候需要从 Agent 升级到 LangGraph。
一、为什么需要图
简单链是线性的:
输入 -> prompt -> model -> parser但真实应用常常不是线性的:
- 问题短则先改写,问题长则直接检索;
- 检索不到则换查询再检索;
- 答案高风险则人工审核;
- 工具失败则重试;
- 用户中断后稍后恢复;
- 多个 Agent 轮流处理。
这些需求用普通链会越来越乱,用图可以清楚表达。
二、LangGraph 的核心概念
State
状态是图中流动的数据。可以是 TypedDict,包含:
- 用户问题;
- 当前路由;
- 检索上下文;
- 中间结果;
- 最终答案;
- 错误信息;
- 审核结果。
Node
节点是一个函数,读取 state,返回要更新的字段。
defretrieve_context(state):return{"context":"..."}Edge
边连接节点,表示执行顺序。
Conditional Edge
条件边根据 state 决定下一步。例如:
- 需要检索 -> retrieve;
- 不需要检索 -> answer_directly;
- 审核失败 -> human_review。
START 和 END
图的入口和结束。
三、StateGraph 的基本写法
典型步骤:
graph=StateGraph(MyState)graph.add_node("route",route_question)graph.add_node("retrieve",retrieve_context)graph.add_node("answer",answer)graph.add_edge(START,"route")graph.add_conditional_edges("route",decide_next,{...})graph.add_edge("answer",END)app=graph.compile()编译后的app可以像 Runnable 一样调用:
app.invoke(initial_state)也可以 stream 观察每个节点输出。
四、状态设计原则
状态字段不要随意堆。建议分层:
- 输入字段:
question、user_id; - 控制字段:
route、step、retry_count; - 数据字段:
context、documents; - 输出字段:
answer、sources; - 质量字段:
confidence、passed_check; - 错误字段:
error。
状态设计得好,图就清楚;状态混乱,图会很难维护。
五、节点设计原则
一个节点应该只负责一类任务:
- 路由节点;
- 检索节点;
- 生成节点;
- 检查节点;
- 工具节点;
- 人工审核节点。
节点返回局部更新,不要在一个节点里偷偷修改所有状态。这样更容易测试和复用。
六、什么时候从 Agent 升级到 LangGraph
继续用create_agent:
- 工具数量少;
- 只是常规工具调用;
- 不需要复杂分支;
- 不需要人工审核;
- 不需要自定义状态。
升级到 LangGraph:
- 要精确控制每一步;
- 要可恢复执行;
- 要人机协作;
- 要多 Agent;
- 要复杂路由;
- 要自定义检查和重试;
- 要清晰测试节点。
七、LangGraph 与 RAG
RAG 很适合用图表达:
输入 -> 问题改写 -> 检索 -> 检索质量检查 -> 答案生成 -> 答案检查 -> 输出如果检索质量不够:
检索质量检查 -> 改写查询 -> 再检索如果答案风险高:
答案检查 -> 人工审核 -> 输出这类流程用普通链会很绕,用 LangGraph 更自然。
八、流式观察图
LangGraph 的stream可以输出每个节点的更新,这对调试非常重要。你能看到:
- 路由结果;
- 检索上下文;
- 生成答案;
- 检查结果;
- 错误节点。
开发复杂 Agent 时,不要只看最终答案。要观察每个节点状态。
九、常见坑
- 状态字段太随意,后期难维护。
- 节点做太多事,难测试。
- 条件边逻辑不完整,出现死路。
- 没有限制循环次数,可能无限重试。
- 没有错误字段,失败后难定位。
- 简单任务过早使用 LangGraph,增加复杂度。
十、自测清单
- 我能解释 State、Node、Edge、Conditional Edge。
- 我能写一个最小 StateGraph。
- 我知道节点应该返回 state 更新。
- 我能判断什么时候用 create_agent,什么时候用 LangGraph。
- 我知道如何用 stream 观察图执行。
十一、课后练习
- 给课程图新增
rewrite_question节点。 - 当问题少于 5 个字时先改写,再检索。
- 新增
check_answer节点,答案为空时进入重试。 - 设计一个
human_review节点,用于高风险答案。
编程学习
技术分享
实战经验