Skip to content

LangGraph 热身:从图开始理解

学习方式:苏格拉底式推导 + 前端知识类比 核心思路:不背定义,从已知推未知

一、代码执行结构的演化

1.1 最初的认知:一条线

我们写的大多数业务逻辑,直觉上是一条从上到下的时间线

检查表单 → 发送请求 → 处理响应 → 跳转页面

用 function 封装、组合,保持 SOLID 原则,看起来清晰有序。

1.2 遇到分叉:线变成了树

当"发送请求"出现成功/失败两种结果时,这条线分叉了:

                    ✅ 成功 → 处理响应 → 跳转页面
发送请求 ──判断──
                    ❌ 失败 → 弹出错误 → 停留表单页

这时候,代码的执行结构从「线」变成了「有分叉的树」。

1.3 遇到重试:树变成了图

用户停留在表单页,修改后重新提交——流程回到了之前已经存在的节点(检查表单)。

停留表单页 ──────────────────────────┐
                                     ↓(回边)
检查表单 → 发送请求 → 判断 → 处理响应 → 跳转页面

                    弹出错误 → 停留表单页

这条"往回指的箭头",叫做 Back Edge(回边)。它让结构从「树」变成了「有环图(Cyclic Graph)」。

1.4 升维视角:封装的本质

时代前端AI 开发
原始期直接操作 DOM直接 fetch 调 OpenAI API
封装期jQuery / 工具函数库封装 callLLM() 函数
框架期React / Vue(操作状态而非 DOM)LangChain(操作流程而非 API)
编排期状态机 / 微前端LangGraph / Multi-Agent(操作图而非流程)

每一次升维,都是把「你手写的重复细节」抽象掉,让你站在更高的层面思考问题。

二、图的核心概念

2.1 Node 节点

图里每一个「方块」就是一个节点。

节点做三件事:

  1. 读取 state(我需要什么输入?)
  2. 执行自己的逻辑(我该干什么?)
  3. 返回新的 state(我产出了什么?)
js
// 一个节点就是一个函数
function sendRequest(state) {
  const response = await fetch('/api/login', { body: state.formData })
  return { response }  // 返回新的 state 片段
}

前端类比: 一个组件 / 一个纯函数

2.2 Edge 顺序边

节点之间固定的连接,表示「执行完 A,下一步一定去 B」。

js
graph.addEdge("检查表单", "发送请求")

前端类比: 顺序函数调用链 a() → b() → c()

2.3 Conditional Edge 条件边

根据 state 的内容,动态决定下一步去哪个节点。

图里用菱形表示,它只判断、不干活,返回一个「路牌」。

js
// 判断函数:只负责返回"路牌",不做业务逻辑
function judgeResult(state) {
  if (state.response.ok) return "success"
  else return "fail"
}

// 注册条件边
graph.addConditionalEdges(
  "发送请求",       // 从哪个节点出发
  judgeResult,     // 判断函数(菱形)
  {
    "success": "处理响应",   // 返回 "success" → 去这个节点
    "fail":    "弹出错误",   // 返回 "fail"    → 去这个节点
  }
)

前端类比: if/else / switch / 策略模式

  • if/else = 菱形判断本身
  • 策略模式 = 菱形 + 把两边的执行者也抽象化

2.4 Back Edge 回边

从「后面的节点」指回「前面的节点」,形成循环。

停留表单页 ──回边──→ 检查表单

前端类比: while 循环 / 递归

2.5 END 终止节点

图的出口。走到 END,这次执行就结束了。

一张图可以有多个 END 出口:

登录成功 → END ✅
账号锁定 → END 🔒

前端类比: 函数的 return / 页面的终态

2.6 State 状态

节点之间传递信息的「共享数据包」。

js
// 图运行过程中,state 的样子
const state = {
  formData:    { username: "xxx", password: "***" },  // 表单节点写入
  response:    { ok: false, error: "密码错误" },       // 请求节点写入
  errorMsg:    "密码错误,请重试",                      // 错误节点写入
  retryCount:  3,                                      // 每次回环累加
}
Vue/React StateLangGraph State
是什么组件间共享的数据节点间共享的数据
谁来读组件读取来渲染 UI节点读取来执行逻辑
谁来写事件 / action 更新每个节点执行完更新
谁来判断computed / watchConditional Edge

注意: 框架自动追踪「当前走到哪个节点」,不需要你手动存入 state。

2.7 Thread 线程实例

图的定义是蓝图(共享),每次执行是独立的实例。

js
// 同一张图的定义(蓝图)
const loginGraph = new StateGraph(...)

// 每个账号,是一个独立的 Thread(state 互不干扰)
await loginGraph.invoke(input, { configurable: { thread_id: "user_A" } })
await loginGraph.invoke(input, { configurable: { thread_id: "user_B" } })
// user_C 被锁定,完全不影响 user_A 和 user_B
前端类比LangGraph
模板 / 蓝图组件定义 function MyComponent()Graph 定义
运行实例组件渲染出的具体实例Thread
实例的数据组件自己的 state每个 Thread 独立的 state

前端类比: 组件定义 vs 组件实例。同一个 <LoginForm /> 组件,可以在页面上渲染多个,各自有独立的 state。

三、完整概念总览

概念一句话前端类比
Node 节点干活的单元一个函数 / 组件
Edge 顺序边固定的下一步顺序函数调用链
Conditional Edge 条件边根据结果决定走哪if/else / 策略模式
Back Edge 回边回到之前的节点while 循环
END 终止节点图的出口,可以有多个return / 页面终态
State 状态节点间传递的数据组件的 state / store
Thread 实例图的一次独立执行组件的一个实例

四、一个完整的例子:登录流程图

START

[检查表单]

[发送请求]

◇ 请求成功?
  ├── ✅ 成功 ──→ [处理响应] → [跳转页面] → END ✅
  └── ❌ 失败 ──→ [弹出错误]

                  ◇ retryCount ≥ 5?
                    ├── 是 🔒 ──→ [锁定账号] → END 🔒
                    └── 否 🔄 ──────────────────→ 回到 [检查表单]

这张图包含了:

  • ✅ 顺序边(主流程)
  • ✅ 条件边(成功/失败判断、次数判断)
  • ✅ 回边(重试循环)
  • ✅ 多个 END 出口(成功 / 锁定)
  • ✅ State 在节点间流转(formData、response、retryCount)
  • ✅ Thread 隔离(每个账号独立跑,互不影响)

五、下一步:进入 LangGraph

思考题(带着这个问题进入下一阶段):

把「登录流程」换成「AI 对话流程」: 用户发消息 → AI 思考 → AI 回复 → 用户再发 → ...

  • 哪个部分会变成「回边」?
  • 这个图什么时候才会走到 END

想清楚这个,你就准备好正式写 LangGraph 了。