LangGraph State 学习笔记

1. State 是什么

State 可以理解为:

LangGraph 中各个节点之间共享和传递的数据。

节点执行时:

复制代码
从 State 读取数据
      ↓
执行节点逻辑
      ↓
return 部分字段
      ↓
更新 State

所以 State 本质上就是整个 Graph 的共享数据空间。


2. TypedDict 在 State 中的作用

LangGraph 中经常使用 TypedDict 定义 State:

复制代码
from typing import TypedDict

class ChatState(TypedDict):
    user_message: str
    intent: str
    response: str

TypedDict 的作用是:

定义一种固定字段和字段类型的字典结构。

它虽然使用 class 语法:

复制代码
class ChatState(TypedDict):

但实际使用的仍然是字典:

复制代码
state["intent"]

而不是:

复制代码
state.intent

可以记成:

TypedDict 本质上是给字典定义类型结构,只是语法上使用了 class。


3. 全局 State 是什么

例如:

复制代码
class ChatState(TypedDict):
    user_message: str
    intent: str
    response: str

然后:

复制代码
builder = StateGraph(ChatState)

这里的 ChatState 就定义了这个 Graph 的核心共享状态结构。

可以理解为:

复制代码
Graph 主要维护:

user_message
intent
response

所以全局 State 的作用是:

定义整个 Graph 主要有哪些共享状态字段,以及这些字段是什么类型、如何更新。

需要注意:

"定义了字段"不代表每个字段在运行一开始就一定已经有值。

所以经常写:

复制代码
state.get("intent", "")

而不是:

复制代码
state["intent"]

这样可以防止字段尚未出现时报错。


4. 节点输入 State

节点函数一般会接收一个 State:

复制代码
def node(state: ChatState):
    ...

这里的:

复制代码
state: ChatState

表示这个节点需要读取哪些状态字段。

例如:

复制代码
def recognize(state: ChatState):
    message = state["user_message"]

相当于:

复制代码
Graph 当前状态
      ↓
按照节点输入 State 的定义
      ↓
把节点需要的字段传进去

所以可以理解为:

节点函数的输入 State 决定这个节点从 Graph 状态空间中读取哪些数据。


5. 节点返回值

节点执行完成以后,一般返回一个字典:

复制代码
return {
    "intent": "submit_leave"
}

这个返回值不是一个新的完整 State。

它表示:

对当前 Graph State 做一次局部更新。

例如原来的状态:

复制代码
{
    "user_message": "我要请假",
    "intent": "",
    "response": ""
}

节点返回:

复制代码
{
    "intent": "submit_leave"
}

更新以后:

复制代码
{
    "user_message": "我要请假",
    "intent": "submit_leave",
    "response": ""
}

所以节点通常只返回自己需要修改的字段。


6. 节点输入和节点返回的关系

可以统一理解成:

复制代码
Graph State
   ↓
节点输入 state
   ↓
读取需要的数据
   ↓
执行逻辑
   ↓
return {...}
   ↓
更新 Graph State

一句话:

输入 State 是读,return 是写。


7. 私有 State 是什么

私有 State 是:

只在 Graph 内部节点之间传递,不作为主要输入或最终输出暴露的数据。

例如:

复制代码
class PrivateState(TypedDict):
    intent: str

某个节点写入:

复制代码
def node_a(state):
    return {
        "intent": "submit_leave"
    }

后续节点读取:

复制代码
def node_b(state: PrivateState):
    print(state["intent"])

这里的 intent 可以作为内部中间状态使用。

"私有"不是 Python 中:

复制代码
__intent

这种私有属性。

它真正的意思是:

这个字段主要服务于 Graph 内部节点通信,而不是暴露给 Graph 外部。


8. 私有 State 不是另一套独立状态

私有 State 并不是重新创建一份完全独立的数据。

可以把 LangGraph 理解成内部维护一个更大的共享状态空间:

复制代码
Graph 内部状态空间

user_message
intent
response
temp_result
search_result
...

其中:

复制代码
user_message
response

可能属于公开状态。

而:

复制代码
temp_result
intent

也可能只是内部节点使用的状态。

所以私有状态仍然属于 Graph 的共享状态空间。


9. 为什么全局 State 没有某字段,私有 State 还能使用

因为 Graph 内部实际维护的状态空间可以比对外暴露的 State 更大。

例如:

复制代码
class OverallState(TypedDict):
    user_message: str
    response: str

再定义:

复制代码
class PrivateState(TypedDict):
    intent: str

那么 Graph 内部可以理解为:

复制代码
{
    user_message,
    response,
    intent
}

其中:

复制代码
user_message
response

属于主要状态。

而:

复制代码
intent

属于内部状态。

所以节点可以:

复制代码
return {"intent": "submit_leave"}

后续节点也可以:

复制代码
state["intent"]

10. 私有状态会保存多久

通常可以理解为:

私有状态会在这一次 Graph 执行期间持续存在。

例如:

复制代码
节点 A 写入 temp_result
        ↓
节点 B 可以读取
        ↓
节点 C 也可以继续读取
        ↓
直到 Graph 本次运行结束

如果后续节点更新同名字段:

复制代码
return {
    "temp_result": "new value"
}

旧值就会被更新。

至于 Graph 执行结束以后是否继续保存,则取决于是否使用了:

复制代码
checkpointer
thread
持久化机制

普通一次性运行结束以后,运行时状态通常也就结束了。


11. 同名字段会怎样

如果两个节点顺序写同一个普通字段:

复制代码
return {"intent": "A"}

然后:

复制代码
return {"intent": "B"}

最终一般是:

复制代码
intent = "B"

也就是:

后写覆盖前写。

如果两个节点并行写同一个普通字段,则可能发生冲突。


12. Reducer 的作用

有些字段不是覆盖,而是合并。

例如:

复制代码
from typing import Annotated
from operator import add

class ChatState(TypedDict):
    logs: Annotated[list[str], add]

这里:

复制代码
add

就是 reducer。

如果一个节点返回:

复制代码
{"logs": ["A"]}

另一个节点返回:

复制代码
{"logs": ["B"]}

则可以合并成:

复制代码
["A", "B"]

而不是简单覆盖。

所以:

复制代码
普通字段
→ 默认更新/覆盖

Annotated[..., reducer]
→ 按 reducer 规则合并

13. Node 和 State 的关系

Node 是 Graph 中的执行单元。

例如:

复制代码
builder.add_node("recognize", recognize_node)

其中:

复制代码
"recognize"

是节点。

复制代码
recognize_node

是节点执行的函数逻辑。

节点执行时:

复制代码
读取 State
   ↓
执行函数
   ↓
返回 State 更新

所以 State 是节点之间通信的桥梁。


14. 最终心智模型

可以把整个 LangGraph 想象成:

复制代码
              Graph 共享状态空间
        ┌────────────────────────┐
        │ user_message           │
        │ intent                 │
        │ response               │
        │ task_result            │
        │ temp_result            │
        │ logs                   │
        └────────────────────────┘
            ↑              ↓
         节点写入        节点读取
            ↑              ↓
          Node A         Node B

其中:

复制代码
全局 State

定义 Graph 的主要共享状态结构。

复制代码
节点输入 State

决定节点读取哪些状态。

复制代码
节点 return

决定这次更新哪些状态。

复制代码
私有 State

表示只在 Graph 内部节点之间使用的状态字段。

复制代码
Reducer

决定同一个字段多次更新时如何合并。


15. 最后一句总结

LangGraph 的 State 可以记成:

Graph 有一个共享状态空间,节点从中读取数据,并通过 return 对它进行局部更新;全局 State 定义主要状态结构,私有 State 用于内部节点通信,Reducer 决定字段更新时是覆盖还是合并。

相关推荐
Omics Pro1 小时前
00后大3休学创业!AI虚拟细胞
大数据·数据库·人工智能·算法·机器学习·自然语言处理
JAI科研1 小时前
CT重建(二) | 3D高斯泼溅:实时渲染的革命
图像处理·人工智能·计算机视觉·3d·视觉检测·ct重建
打工仔折腾 AI1 小时前
从零写一个CAD 04:中键拖动平移,抓住一个点让它一直待在鼠标底下
人工智能·后端·python·性能优化·计算机外设·ai agent 实战
HEJOO91 小时前
Go 语言结构体定义与实例详解
开发语言·算法·golang
workflower1 小时前
从生成式模型开始的技术延伸
人工智能·机器学习·机器人·云计算·无人机
(Charon)1 小时前
【C++面试】手写智能指针(一):从unique_ptr理解独占所有权与移动语义
开发语言·c++
kali-Myon1 小时前
ARTEX:AI 驱动的自动化漏洞挖掘平台
人工智能·安全·ai·自动化·web
论文复现现场1 小时前
RTX 3090 24GB 适合科研吗?单卡论文复现、PyTorch 显存检查与 OOM 排错
人工智能·pytorch·python·深度学习·cuda·rtx3090