py
# 完整代码
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
## 定义状态
class MyState(TypedDict, total=False):
node1: str
node2: str
TypedDict:说明这个类是「类型描述字典」,用来约定state的数据结构,给IDE类型提示。total=False:默认情况下 TypedDict 要求你必须提供所有字段;total=False意思:字段可选,可以不存在。node1和node2:state中的通道(channel) ,是state字典里的key,用来存放数据。⚠️ 注意:不是运行节点,这里只是刚好和节点同名,容易混淆。
py
## 实例化图
workflow = StateGraph(MyState)
这句代码的意思是告诉graph:整个工作流所依据的数据容器,必须符合 MyState 这个结构。
py
## 定义节点
def node1(state: MyState):
return {"node1": "node1 result"}
def node2(state: MyState):
return {"node2": "node2 result"}
state:当前最新的状态字典。图运行到这个节点时,框架自动把当前 state 传给函数。return:返回的字典不是完整新 state,是增量补丁 patch。只会更新指定通道,不会覆盖整个state。
py
## 添加节点和边
(
workflow.add_node("node1", node1)
.add_node("node2", node2)
.add_edge(START, "node1")
.add_edge("node1", "node2")
.add_edge("node2", END)
)
这个workflow的工作流为:START ------ node1 ------ node2 ------ END。
py
## 编译及运行
graph = workflow.compile()
result = graph.invoke({})
运行过程
- invoke 传入初始 state:
{} - START 触发,进入节点 node1
- node1 收到 state
{},返回 patch{"node1": "node1 result"} - LangGraph 合并,state 变成
{"node1": "node1 result"} - 静态边流转,走到节点 node2
- node2 收到 state
{"node1": "node1 result"},返回 patch{"node2": "node2 result"} - LangGraph 合并,state 变成
{"node1": "node1 result", "node2": "node2 result"} - node2 执行完,走到 END,图终止,返回最终 state
疑惑自解
Q1: node节点在定义时,要传参state,但是workflow在add_node时,传入的node并没有带state参。 A1:workflow.add_node("node1", node1),这段代码,将node1函数在workflow进行登记,并将该节点命名为"node1"。 至于node1执行的时机,是在执行graph.invoke({}),图开始执行时:
- LangGraph 拿到当前全局 state
- 找到要执行的节点对应的函数(也就是我们注册进去的
node1) - LangGraph 自动调用
node1(state),把当前 state 当做第一个参数塞进去。
核心区分:
- 构建期:add_node只是登记函数,不执行,不需要传state
- 运行期:invoke启动图,框架自动调用节点函数并传入state
概念区分(重点)
-
节点(Node):
def node1这个函数,代表一段业务逻辑 -
通道(Channel):state里的key,
node1/node2,用来存储数据本示例只是名字碰巧一样,二者完全不是同一个东西。