LangGraph == 顺序结构

4.1. 顺序结构

4.1.1. add_edge

add_edge 用于在两个节点之间添加一条有向边。边是图结构中最基本的元素之一,节点之间的执行顺序、分支跳转以及循环控制,最终都依赖节点和边共同表达。

因此,在 LangGraph 中,基础的控制流结构都可以通过 add_edge 进行构建。

示例如下:

复制代码
from langgraph.graph import StateGraph, START, END
from typing import TypedDict, NotRequired


class OverAllState(TypedDict):
    username: NotRequired[str]
    greeting: NotRequired[str]
    output: NotRequired[str]

def node_a(state: OverAllState) -> OverAllState:
    return {
        "greeting": "Dear " + state["username"]
    }

def node_b(state: OverAllState) -> OverAllState:
    return {
        "output": state["greeting"] + ",你好!"
    }

builder = StateGraph(state_schema=OverAllState)
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)

graph = builder.compile()
res = graph.invoke({"username": "小黄"})
print(res)

from IPython.display import display

display(graph)

输出如下:

复制代码
{'username': '小黄', 'greeting': 'Dear 小黄', 'output': 'Dear 小黄,你好!'}

在上述示例中,图的执行流程如下:

复制代码
START -> node_a -> node_b -> END

其中:

  • START -> node_a 表示图从 node_a 开始执行;
  • node_a -> node_b 表示 node_a 执行完成后,继续执行 node_b;
  • node_b -> END 表示 node_b 执行完成后,图进入结束状态。

4.1.2. add_sequence

如果需要构建一组按顺序执行的节点,也可以使用 add_sequence。

add_sequence 支持传入一个可执行对象列表。LangGraph 会按照列表顺序依次添加节点,并在相邻节点之间自动添加边。默认情况下,函数名会被用作节点名称。

示例如下:

复制代码
from langgraph.graph import StateGraph, START, END
from typing import TypedDict, NotRequired


class OverAllState(TypedDict):
    username: NotRequired[str]
    greeting: NotRequired[str]
    output: NotRequired[str]

def node_a(state: OverAllState) -> OverAllState:
    return {
        "greeting": "Dear " + state["username"]
    }

def node_b(state: OverAllState) -> OverAllState:
    return {
        "output": state["greeting"] + ",你好!"
    }

builder = StateGraph(state_schema=OverAllState)

builder.add_edge(START, "node_a")
builder.add_sequence([node_a, node_b])
builder.add_edge("node_b", END)

graph = builder.compile()
res = graph.invoke({"username": "小黄"})
print(res)

from IPython.display import display

display(graph)

输出如下

复制代码
{'username': '小黄', 'greeting': 'Dear 小黄', 'output': 'Dear 小黄,你好!'}

上述代码中:

复制代码
builder.add_sequence([node_a, node_b])

大致等价于:

复制代码
builder.add_node("node_a", node_a)
builder.add_node("node_b", node_b)
builder.add_edge("node_a", "node_b")

因此,完整执行流程仍然是:

复制代码
START -> node_a -> node_b -> END

相比手动调用多次 add_node 和 add_edge ,add_sequence 更适合用于构建简单的线性执行流程。

4.1.3. 省略指向 END 的边

在 LangGraph 中,图的终止并不完全依赖某个真实执行的特殊节点。

从运行机制上看,LangGraph 会在每个 SuperStep 开始时,根据当前发生更新的 Channel 以及节点之间的触发关系,计算本轮需要执行的任务列表。如果没有新的节点被激活,也就没有新的任务需要执行,图运行自然结束。

需要注意的是,END 并不是运行阶段真正执行的节点 。也就是说,指向 END 的边不会像指向普通节点的边那样,触发一个真实的节点任务。它更多用于表达图结构中的"终止语义":当前路径执行到这里即可结束。

因此,在一些简单的线性流程中,即使省略指向 END 的边,最后一个节点执行完成后,如果没有后续节点被触发,图也可以正常结束。

示例如下:

复制代码
from langgraph.graph import StateGraph, START
from typing import TypedDict

class OverAllState(TypedDict):
    username: str
    greeting: str
    output: str

def node_a(state: OverAllState) -> OverAllState:
    return {
        "greeting": "Dear " + state["username"]
    }

def node_b(state: OverAllState) -> OverAllState:
    return {
        "output": state["greeting"] + ",你好!"
    }

builder = StateGraph(state_schema=OverAllState)
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")

graph = builder.compile()
res = graph.invoke({"username": "小黄"})
print(res)

from IPython.display import display

display(graph)

输出如下

复制代码
{
  "username": "小黄",
  "greeting": "Dear 小黄",
  "output": "Dear 小黄,你好!"
}

在这个例子中,虽然没有显式添加:

复制代码
builder.add_edge("node_b", END)

但是 node_b 执行完成后,没有新的节点被触发,图运行会自然结束。

不过,可以省略指向 END 的边,并不表示 END 没有意义。

显式添加 END 边可以让图结构更加完整,也能更清晰地表达"流程到此结束"的语义。尤其是在分支、条件跳转、循环退出等场景中,显式指向 END 通常更利于阅读和维护。

和 END 不同,START 通常不能省略 。因为 START 不只是一个语义上的起点标记,它还用于告诉 LangGraph:图运行时应当从哪些节点开始执行。也就是说,下面这条边是启动图执行的关键:

复制代码
builder.add_edge(START, "node_a")

如果没有从 START 出发的边,或者没有通过其他方式指定入口节点,LangGraph 就无法确定图的初始执行节点。

因此,在实际开发中,建议保留指向 END 的边。虽然在某些简单流程中省略这些边也能正常运行,但显式添加它们,可以让图结构更加完整、语义更加清晰,便于后续维护。

相关推荐
思码梁田2 小时前
CSS 浏览器厂商前缀:从「写 5 遍」到现代自动化兼容
前端·css·css3·border-radius·1024程序员节·box-shadow·厂商前缀
羞儿2 小时前
【DSH】创造模式与内核边界:一切皆插件的递归与自证
agent·1024程序员节·harness
hsg772 小时前
简述:基于Ubuntu24编译发布rust开发的html+web后端服务的方法
rust·1024程序员节
ljt27249606612 小时前
Vue笔记(十五)--自定义引用
笔记·1024程序员节
小羊斩肖恩2 小时前
具身智能的临界点:从数字幻觉走向物理真实的2026
1024程序员节
Sirens.2 小时前
网络通信基础:IP、端口、协议分层与数据封装
java·网络·网络协议·tcp/ip·java-ee·1024程序员节
Ruiery2 小时前
Linux 6.6内核并发与同步(一):原子操作与内存屏障 — 内核同步的硬件底座
linux·运维·服务器·1024程序员节
小冯不疯2 小时前
直播切片带货分账:3 类分成模型 × 4 道结算节点 × 2 类税务坑
1024程序员节
我是大猴子2 小时前
py how claude work项目分析
运维·服务器·windows·1024程序员节