首页 › G LangGraph Agent 编排 › G2 控制流进阶 › 02

G2-02 · Send 并行分发:多任务同时处理

进阶阶段约 180 分钟阶段:G2 控制流进阶

阶段:G2-控制流进阶 | 预计耗时:60 分钟 | 前置:G2-01 Command 与动态跳转 代码:要你自己敲成 langgraph-learn/examples/g2_send.py 对应 知识全景 2.4 map-reduce——S2 票据项目"批量并行处理"的核心机制

学习目标

  1. 掌握 Send(node_name, state):运行时动态开出 N 个并行分支(数量事先不知道也行)
  2. 理解 map-reduce 结构在图里的长相:分发 → 并行处理 → Reducer 汇聚
  3. 实测并行比串行快多少(本机 CPU 上 LLM 调用是网络 IO,并行真提速)

核心知识

1. Send 解决什么问题

  • 条件边一次只能去一个节点;Command 一次也只能 goto 一个地方
  • "10 篇文章各自摘要"如果逐个循环调用 = 串行 10 次等待;Send 一次分发 10 份,同时开跑
  • 关键:分发数量和每份的数据都是运行时决定的——Send 在"路由函数"里返回一个列表

2. 标准三段式(map-reduce)

from langgraph.types import Send

def fan_out(state: State) -> list[Send]:            # 路由函数:发多少份
    return [Send("summarize", {"article": a}) for a in state["articles"]]

def summarize(payload: dict) -> dict:               # 每个并行分支收到自己那份
    return {"summaries": [f"摘要:{payload['article'][:20]}..."]}

builder.add_conditional_edges(START, fan_out, ["summarize"])   # Send 用条件边语法挂载
builder.add_edge("summarize", "reduce")                        # 全部完成后汇聚
  • 每个 Send 携带独立的小状态(不是共享大 State)——天然隔离
  • summaries 字段必须有追加型 Reducer,否则 10 个分支互相覆盖只剩 1 份(G1-02 大坑的并行版)

3. 与"循环逐个处理"的本质区别

循环 = 时间换空间,一个节点跑 N 次;Send = 空间换时间,N 个分支同时跑。但有副作用顺序要求时(比如流水号),并行反而添乱——这个判断进 G5 反模式篇。

实验任务

任务 1:纯逻辑版(不需要 LLM,20 分钟)

上面骨架里的 summarize 用假函数即可,10 篇"文章"用 10 个字符串。重点观察: - summaries 是不是 10 份全在?(Reducer 功劳) - 把 Reducer 拿掉再跑——剩几份?

任务 2:真 LLM 并行版(25 分钟,花极少额度)

summarize 里换成真实调用(Qwen3.5-4B,max_tokens=50),10 篇短文摘要: - 记录并行总耗时;再改成 for 循环逐篇调用的串行总耗时 - 对比写进观察笔记(预期:并行约为串行的 1/4~1/6)

任务 3:混合分发(15 分钟)

fan_out 里按文章长度走不同分支:短的进 summarize_fast、长的进 summarize_deep——体会 Send 能按内容路由到不同节点,这是固定条件边做不到的。

验收标准

衔接下一阶段

会横向铺开了 → G2-03 Subgraph 子图:把复杂流程分层封装。

小测验(3 题)

答完立即判分,错题给解析;得分存本地。实验与实操题不上网测:回对话找老师验收。