阶段:G2-控制流进阶 | 预计耗时:60 分钟 | 前置:G2-02 Send 并行分发 代码:要你自己敲成
langgraph-learn/examples/g2_subgraph.py这是 G1-03"数学解题图"的升级——把单张图变成可复用的模块
学习目标
- 掌握子图三种接法:当节点直接挂 / 共享 State / 命名空间隔离(重点前两种)
- 亲手把"解题子图"套进"路由外壳",理解分层的价值:每层独立开发、独立测试、独立复用
- 会把 G1-03 的成果真正变成一个可插入模块
核心知识
1. 子图 = 编译好的图当节点用
solver = build_solver_graph().compile() # 你 G1-03 写的解题图
builder.add_node("solver", solver) # 就这一行——图当节点挂
builder.add_edge("router", "solver")
前提:两层图的 State 结构兼容(子图输出的 key 主图能读)。最省心的做法是主图 State 是子图 State 的超集。
2. 为什么要分层(工程视角)
| 单张巨图 | 分层子图 |
|---|---|
| 节点几十个,图看不懂 | 每层 3-5 个节点,Studio 逐层看 |
| 改一处怕牵全身 | 子图内部随便改,外壳无感 |
| 没法复用 | 解题子图可插到客服图、教学图里 |
| 无法分团队开发 | 子图=微服务的最小仿真 |
3. 命名空间隔离(了解)
子图与主图 State 不兼容时,包一层"转接节点"做字段映射(def bridge(state): return {"problem": state["text"]})。G7 实战项目多模块拼接时你会用到。
实验任务
任务 1:把 G1-03 的解题图改造成子图(25 分钟)
- 把
g1_handmade_react.py的 builder 部分封装成def build_solver_graph(): ...返回编译后图 - 新建
g2_subgraph.py:路由外壳图(router 节点判断"数学题还是闲聊"——可以先用关键词 if/else,不用 LLM),数学题 → 挂上去的 solver 子图,闲聊 → 直接回复节点 - 外壳 State:
{"text": str, "reply": str, "messages": Annotated[list, add_messages]}——messages 字段与子图对接
任务 2:Studio 里分层看(15 分钟)
langgraph.json 加一行挂上这个新图,在 Studio 里观察:外壳图上 solver 显示为一个节点;点进去看它内部展开的循环结构——这就是"封装"的视觉含义。
任务 3:复用性测试(15 分钟)
再搭一个 10 行的"教学外壳"(教学语气回复 + 同一个 solver 子图)——同一份子图服务两个外壳,一行 import 都不用改 solver。这就是分层的回报。
验收标准
衔接下一阶段
控制流三件套(Command/Send/Subgraph)齐了 → G3-01 Checkpointer 与 thread_id:进入本框架的灵魂——持久化。