第 08 课:LangGraph 有状态工作流精讲

📅 2026/7/9 4:27:49 👁️ 阅读次数 📝 编程学习
第 08 课:LangGraph 有状态工作流精讲

第 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 观察每个节点输出。

四、状态设计原则

状态字段不要随意堆。建议分层:

  • 输入字段:questionuser_id
  • 控制字段:routestepretry_count
  • 数据字段:contextdocuments
  • 输出字段:answersources
  • 质量字段:confidencepassed_check
  • 错误字段:error

状态设计得好,图就清楚;状态混乱,图会很难维护。

五、节点设计原则

一个节点应该只负责一类任务:

  • 路由节点;
  • 检索节点;
  • 生成节点;
  • 检查节点;
  • 工具节点;
  • 人工审核节点。

节点返回局部更新,不要在一个节点里偷偷修改所有状态。这样更容易测试和复用。

六、什么时候从 Agent 升级到 LangGraph

继续用create_agent

  • 工具数量少;
  • 只是常规工具调用;
  • 不需要复杂分支;
  • 不需要人工审核;
  • 不需要自定义状态。

升级到 LangGraph:

  • 要精确控制每一步;
  • 要可恢复执行;
  • 要人机协作;
  • 要多 Agent;
  • 要复杂路由;
  • 要自定义检查和重试;
  • 要清晰测试节点。

七、LangGraph 与 RAG

RAG 很适合用图表达:

输入 -> 问题改写 -> 检索 -> 检索质量检查 -> 答案生成 -> 答案检查 -> 输出

如果检索质量不够:

检索质量检查 -> 改写查询 -> 再检索

如果答案风险高:

答案检查 -> 人工审核 -> 输出

这类流程用普通链会很绕,用 LangGraph 更自然。

八、流式观察图

LangGraph 的stream可以输出每个节点的更新,这对调试非常重要。你能看到:

  • 路由结果;
  • 检索上下文;
  • 生成答案;
  • 检查结果;
  • 错误节点。

开发复杂 Agent 时,不要只看最终答案。要观察每个节点状态。

九、常见坑

  1. 状态字段太随意,后期难维护。
  2. 节点做太多事,难测试。
  3. 条件边逻辑不完整,出现死路。
  4. 没有限制循环次数,可能无限重试。
  5. 没有错误字段,失败后难定位。
  6. 简单任务过早使用 LangGraph,增加复杂度。

十、自测清单

  • 我能解释 State、Node、Edge、Conditional Edge。
  • 我能写一个最小 StateGraph。
  • 我知道节点应该返回 state 更新。
  • 我能判断什么时候用 create_agent,什么时候用 LangGraph。
  • 我知道如何用 stream 观察图执行。

十一、课后练习

  1. 给课程图新增rewrite_question节点。
  2. 当问题少于 5 个字时先改写,再检索。
  3. 新增check_answer节点,答案为空时进入重试。
  4. 设计一个human_review节点,用于高风险答案。