LangGraph图:State、Node、Edge(一)

一、LangGraph图

LangGraph 的图,本质上是一个有向图:节点是"处理单元",边是"数据流向"。数据在节点之间流动,每个节点对数据做一次加工。

和普通流程图不同的是:LangGraph 的图共享一个全局状态(State),每个节点读取它、修改它,而不是把数据从一个节点"传给"下一个节点。

这个设计是 LangGraph 的核心:节点之间不直接通信,所有数据都通过 State 中转。

二、State:图的"共享容器"

State 是贯穿整个图的数据容器。它通常用 TypedDict 定义。

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

class MyState(TypedDict):
    messages: Annotated[list, add]  # 追加式更新
    count: int                       # 覆盖式更新
    result: str
1. 普通字段 vs Annotated 字段
写法 更新行为
count: int 节点返回的新值直接覆盖旧值
messages: Annotated[list, add] 节点返回的新值追加到旧值后面
复制代码
def node_a(state):
    return {"count": 10}   # count 被覆盖为 10

def node_b(state):
    return {"messages": ["新消息"]}  # 追加到 messages 列表

为什么需要 add? 因为对话消息需要累积,而不是每次覆盖。如果 messages 是普通字段,第二个节点返回的消息会把第一个节点返回的消息冲掉。

2. 常用的 reducer
reducer 作用
add 追加(列表相加、数字相加)
operator.or_ 字典合并
自定义函数 任意逻辑
复制代码
def merge_dict(left: dict, right: dict) -> dict:
    return {**left, **right}

class MyState(TypedDict):
    data: Annotated[dict, merge_dict]
3. 状态更新的本质

每个节点返回的字典,会经过 reducer 处理后,合并回全局 State。

三、Node:图的"处理单元"

节点就是一个普通的 Python 函数,接收 State,返回更新字典。

复制代码
def my_node(state: MyState) -> dict:
    # 读取 state
    current_count = state["count"]
    # 返回更新
    return {"count": current_count + 1}
1. 节点的形参规则

LangGraph 会根据函数的参数名来决定传入什么:

形参名 传入内容
state 全局状态
config 运行配置(如 thread_id)
runtime 运行时上下文(LangGraph 1.0+)
复制代码
def my_node(state: MyState, config: RunnableConfig, runtime: Runtime):
    ...

顺序必须固定 :state, config, runtime,且参数名不能改。

2. 节点的返回值

节点必须返回一个字典 ,表示对 State 的更新。返回空字典 {} 表示不更新。

复制代码
def no_change(state) -> dict:
    return {}
3. 节点可以有异步版本
复制代码
async def my_async_node(state: MyState) -> dict:
    result = await some_async_call()
    return {"result": result}

四、Edge:图的"连接线"

边定义了节点之间的执行顺序。

1. 入口和出口
复制代码
from langgraph.graph import START, END

builder.add_edge(START, "first_node")   # 入口
builder.add_edge("last_node", END)      # 出口
2. 普通边

固定跳转,从 A 到 B。

复制代码
builder.add_edge("node_a", "node_b")
3. 设置入口点的两种方式
复制代码
# 方式一:用 START
builder.add_edge(START, "first_node")

# 方式二:用 set_entry_point
builder.set_entry_point("first_node")

两种写法等价。

五、示例

复制代码
from typing import TypedDict, Annotated
from operator import add
from langgraph.graph import StateGraph, START, END

# 1. 定义 State
class MyState(TypedDict):
    messages: Annotated[list, add]
    count: int

# 2. 定义节点
def node_a(state: MyState) -> dict:
    print(f"节点A收到 count={state['count']}")
    return {"count": state["count"] + 1, "messages": ["A执行了"]}

def node_b(state: MyState) -> dict:
    print(f"节点B收到 count={state['count']}")
    return {"count": state["count"] + 10, "messages": ["B执行了"]}

# 3. 构建图
builder = StateGraph(MyState)
builder.add_node("node_a", node_a)
builder.add_node("node_b", node_b)
builder.add_edge(START, "node_a")
builder.add_edge("node_a", "node_b")
builder.add_edge("node_b", END)

# 4. 编译并运行
graph = builder.compile()
result = graph.invoke({"count": 0, "messages": []})
print(result)

输出:

复制代码
节点A收到 count=0
节点B收到 count=1
{'count': 11, 'messages': ['A执行了', 'B执行了']}

执行过程:

  1. 初始 State:{count: 0, messages: []}

  2. 节点A执行:count 变成 1,messages 追加 "A执行了"

  3. 节点B执行:count 变成 11(1+10),messages 追加 "B执行了"

  4. 到达 END,返回最终 State

State 的关键理解

  1. State 是全局的:所有节点共享同一份 State,不是节点之间互相传参。

  2. 更新是增量的:节点只返回需要变更的字段,不需要返回完整 State。

  3. 合并靠 reducer :普通字段覆盖,Annotated 字段按 reducer 逻辑合并。

相关推荐
梦想不只是梦与想5 小时前
向量数据库Milvus: 管理与工具
大模型·milvus·attu
段一凡-华北理工大学6 小时前
大模型与智能体在工业的应用~系列文章03:提示词工程:与大模型正确对话的“说明书“
大模型·智能体·提示词工程·工业智能化·大模型对话·高炉智能化
王国强20096 小时前
Deep Agents Code 源码阅读(一):怎么避免在一个 6000 多行的 main.py 中迷失
langchain
VIP_CQCRE8 小时前
用 Ace Data Cloud 快速接入 GLM Chat Completion API:OpenAI 兼容格式,一套接口调用主流大模型
ai·大模型·api·glm·acedatacloud
YIAN9 小时前
从 SSE 流式到结构化输出:LangChain 三大 OutputParser 与 ToolCall 方案全实战
前端·langchain·node.js
YIAN9 小时前
从 SSE 流式原理到 LangChain 结构化输出:打字机效果与 JSON 解析全方案实战
前端·langchain
10年前端老司机10 小时前
Next.js+LangGraph.js+ 简历工具AI Agent完整落地
前端·langchain·agent
BreezeJiang15 小时前
从 LangChain 到 LangGraph:多 Agent 不是玄学,是 token 账本和干扰问题
langchain·agent
YIAN15 小时前
LangChain.js 对话记忆体系(一):内存存储与文件持久化,让 AI 拥有对话记忆
前端·后端·langchain