LangGraph实战教程:defer延迟节点——让收尾工作自动排到最后

  1. LangGraph 入门基础全解析
  2. LangGraph中的Reducer是什么
  3. LangGraph 核心概念详解:从编译到可视化
  4. LangGraph实战教程:一文搞懂图的状态(State)管理
  5. LangGraph实战教程:状态管理与graph.invoke入参深度解析
  6. LangGraph高级教程:Multi Schema多状态管理详解
  7. LangGraph实战教程:预定义状态MessagesState与AgentState
  8. LangGraph实战教程:控制流详解

一、场景引入

想象这样一个场景:你的图里有好几个节点并行执行任务,比如一个写诗、一个写笑话。等它们都完成后,你想做个审计------检查一下诗和笑话是不是都生成了。

通常的做法是:给每个任务节点都连一条线到审计节点。

但如果任务节点很多,或者图结构很复杂,这种做法就很麻烦。

有没有更简单的办法?有!用 defer=True

二、defer到底是什么?

defer的意思是"推迟"。在LangGraph中,给节点加上 defer=True,就相当于告诉框架:

"这个节点先别急着执行,等其他所有常规节点都跑完了,再让它上场。"

ini 复制代码
builder.add_node("audit_node", audit_node, defer=True)

就这么简单的一行,审计节点就会自动排到最后执行。

三、一个完整的例子

下面这个图有三个节点:一个写诗、一个写笑话、一个做审计。

python 复制代码
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
from langchain.messages import HumanMessage
from langchain_deepseek import ChatDeepSeek
from loguru import logger

from dotenv import load_dotenv
load_dotenv(override=True)

model = ChatDeepSeek(
    model="deepseek-v4-flash",
    extra_body={"thinking": {"type": "disabled"}}
)

class OverAllState(TypedDict):
    topic: str
    poem: str
    joke: str

def node_a(state: OverAllState) -> OverAllState:
    """生成诗歌"""
    poem = model.invoke([HumanMessage(f"写一首关于 {state['topic']} 的七言绝句")]).content
    return {"poem": poem}

def node_b(state: OverAllState) -> OverAllState:
    """生成笑话"""
    joke = model.invoke([HumanMessage(f"写一个关于 {state['topic']} 的笑话")]).content
    return {"joke": joke}

def audit_node(state: OverAllState) -> OverAllState:
    """审计节点:在所有任务完成后执行"""
    logger.info(
        f"任务全部完成,"
        f"诗 {'✅ 已生成' if state.get('poem') else '❌ 未生成'},"
        f"笑话 {'✅ 已生成' if state.get('joke') else '❌ 未生成'}"
    )
    return {}

# 构建图
builder = StateGraph(state_schema=OverAllState)
builder.add_node("node_a", node_a)
builder.add_node("node_b", node_b)
builder.add_node("audit_node", audit_node, defer=True)  # 👈 关键:defer=True

# 所有节点都从START出发
builder.add_edge(START, "node_a")
builder.add_edge(START, "node_b")
builder.add_edge(START, "audit_node")  # 虽然也从START出发,但不会立即执行

builder.add_edge("node_a", END)
builder.add_edge("node_b", END)
builder.add_edge("audit_node", END)

graph = builder.compile()
res = graph.invoke({"topic": "布偶狗"})
print(res)

输出结果:

css 复制代码
2026-05-28 17:07:09.618 | INFO | 任务全部完成,诗 ✅ 已生成,笑话 ✅ 已生成

{
    'topic': '布偶狗',
    'poem': '《咏布偶狗》\n绸身棉腑自憨娇...',
    'joke': '这是一个关于布偶狗的笑话:\n有一只布偶狗...'
}

四、执行流程

这个图的执行过程分为三步:

第一步:常规节点先跑

sql 复制代码
START → node_a(写诗)→ 完成 ✅
START → node_b(写笑话)→ 完成 ✅
START → audit_node(⚠️ 被延迟,先不动)

node_anode_b正常执行,audit_node虽然也被触发了,但因为 defer=True,它先"睡一会儿"。

第二步:常规节点全部完成

node_anode_b都跑完了,状态中也写入了诗和笑话。

此时常规流程结束。

第三步:延迟节点被唤醒

复制代码
audit_node(审计)→ 执行 ✅

audit_node醒来,读取状态------这时候诗和笑话都已经有了,所以它能正确地做审计。

五、defer到底解决了什么问题?

没有 defer 的时候:

如果你想在所有任务完成后做审计,需要这样画图:

sql 复制代码
START → node_a → audit_node → END
START → node_b → audit_node → END

每个任务节点都要单独连到审计节点。如果任务有10个,就要连10条线。

有 defer 的时候:

sql 复制代码
START → node_a → END
START → node_b → END
START → audit_node → END  (defer=True,自动最后执行)

代码更简洁,结构更清晰,而且不管加多少任务节点,审计节点都会自动排到最后。

六、defer适合做什么?

场景 是否适合 说明
日志记录 ✅ 非常适合 记录哪些节点执行了,耗时多久
审计检查 ✅ 非常适合 检查所有任务是否按要求完成
结果汇总 ✅ 适合 把各个节点的输出汇总到一起
收尾清理 ✅ 适合 关闭文件、释放资源等
核心业务逻辑 ❌ 不适合 defer节点出错不会回滚前面的结果

七、一句话总结

defer=True就像给节点贴了个"压轴出场"的标签------所有常规节目演完了,它才登台谢幕。


八、相关面试题

面试题1:defer=True和把审计节点放在最后位置有什么区别?

打个比方:

  • 放在最后位置:就像排队,你必须站在最后一个人的后面
  • defer=True:就像买了"免排队"票,不管前面有多少人,你都最后上场

放在最后位置需要给每个前驱节点都连线,而 defer=True只需要设置一个参数。

面试题2:如果我有两个 defer=True的节点,谁先执行?

答案: ​ 不确定。它们会在同一个时刻被唤醒,谁先执行取决于调度顺序。

如果两个延迟节点之间有依赖关系(比如B需要A的结果),就不要都用 defer=True,而是用普通边建立先后关系。

面试题3:defer节点里出错了怎么办?

答案: ​ 常规节点的结果已经保存了,不会回滚。所以不要把关键的业务逻辑放在 defer节点里。

举个例子:如果 defer节点是做日志记录的,日志写失败了没关系,诗和笑话还在。但如果 defer节点是做数据校验的,校验失败了但数据已经生成,你就需要额外处理这个异常。

面试题4:defer节点能不能更新状态?

答案: ​ 可以。defer节点也可以返回状态更新。只不过它更新完之后,通常不会有其他节点再被触发了(除非还有其他 defer节点)。


希望这个通俗版的教程能帮你轻松掌握 defer的用法!

相关推荐
前端工作日常1 小时前
我学习到的Java中domain和dto区别
java·后端
kite01211 小时前
Go语言Map深度解析与最佳实践
开发语言·后端·golang
70asunflower1 小时前
别再混淆 CUDA 的三个版本:`nvidia-smi`、`nvcc`、`torch.version.cuda` 一次讲清
人工智能
kyriewen1 小时前
我用了三周Claude Code Skills——总结出5条铁律,第3条最反直觉
前端·ai编程·claude
就是一顿骚操作1 小时前
词嵌入 word2vec:Skip-Gram 与 CBOW 经典解读
人工智能·自然语言处理·word2vec·论文解读
阳光是sunny1 小时前
LangGraph实战教程:控制流详解
前端·人工智能·后端
黄华SJ520it1 小时前
AI智能穿搭系统开发:从技术选型到落地实践
人工智能·系统开发
szxinmai主板定制专家2 小时前
RK3568+FPGA高速并行采集|半导体探针测试设备多通道同步数据采集系统设计
人工智能·嵌入式硬件·计算机视觉·fpga开发
格尔曼Noah2 小时前
Safari浏览器中如何只允许指定网站下载
前端·safari