Skip to content

第 8 章 · 子图与明确的输入输出边界 ​

把可复用文本清理流程封装为子图。父图只关心输入文本与最终摘要,不应知道子图内部的临时字段。

工作机制与设计选择 ​

当父子图状态键一致时,可把编译后的子图直接作为节点。键不一致时,用包装节点显式转换输入和输出。本例采取转换方式,防止子图内部词列表泄露到父状态。子图复用的是执行逻辑,并不自动提供不同用户的权限隔离。检查点继承、跨调用记忆与子图流式观察仍需按运行场景配置。

示例 ​

python
from typing import TypedDict
from langgraph.graph import StateGraph, START, END

class ChildState(TypedDict):
    raw: str
    cleaned: str

def clean(state: ChildState):
    return {"cleaned": " ".join(state["raw"].split())}

child_builder = StateGraph(ChildState)
child_builder.add_node("clean", clean)
child_builder.add_edge(START, "clean")
child_builder.add_edge("clean", END)
child = child_builder.compile()

class ParentState(TypedDict):
    text: str
    summary: str

def prepare(state: ParentState):
    result = child.invoke({"raw": state["text"], "cleaned": ""})
    return {"summary": result["cleaned"][:60]}

parent_builder = StateGraph(ParentState)
parent_builder.add_node("prepare", prepare)
parent_builder.add_edge(START, "prepare")
parent_builder.add_edge("prepare", END)
graph = parent_builder.compile()
result = graph.invoke({"text": "  reusable   graph  ", "summary": ""})
assert result["summary"] == "reusable graph"
assert "raw" not in result
print(result)

运行与验收 ​

无需模型;运行后只应出现父图字段。单独调用 child.invoke,验证子图也能独立使用。这个例子不启用持久化,避免把状态映射与生命周期问题混在一起。

容易踩的坑 ​

不要让父图直接依赖子图所有内部键,否则稍改子图就破坏调用方。对子任务上下文做裁剪,但保留它完成任务所需的明确验收标准。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. 状态键不同怎么办?

2. 子图是权限隔离吗?

3. 父图应依赖什么?

4. 可独立测试子图吗?

动手实践 ​

  1. 给子图添加内部计数,断言父图不暴露该键。
  2. 复用同一子图服务两个父流程,比较边界是否稳定。
  3. 写一个子图失败用例,明确父图应传播还是转换异常。

官方参考 ​

核验日期:2026-09-17。