惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Latest news
Latest news
T
Troy Hunt's Blog
V
Vulnerabilities – Threatpost
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
V
V2EX
博客园 - 司徒正美
B
Blog RSS Feed
AWS News Blog
AWS News Blog
MyScale Blog
MyScale Blog
Scott Helme
Scott Helme
Cisco Talos Blog
Cisco Talos Blog
Last Week in AI
Last Week in AI
NISL@THU
NISL@THU
博客园 - Franky
P
Proofpoint News Feed
博客园_首页
C
CERT Recently Published Vulnerability Notes
雷峰网
雷峰网
S
Schneier on Security
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
G
GRAHAM CLULEY
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
WordPress大学
WordPress大学
The Hacker News
The Hacker News
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
A
Arctic Wolf
Microsoft Azure Blog
Microsoft Azure Blog
T
The Exploit Database - CXSecurity.com
Engineering at Meta
Engineering at Meta
罗磊的独立博客
T
The Blog of Author Tim Ferriss
D
Darknet – Hacking Tools, Hacker News & Cyber Security
I
Intezer
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
SecWiki News
SecWiki News
云风的 BLOG
云风的 BLOG
美团技术团队
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
C
Cyber Attacks, Cyber Crime and Cyber Security
B
Blog
S
Security Affairs

博客园 - Zhentiw

[GenAI] Migration Plan: Flat API → Layered Architecture [Skill] Frontend Design Skill Claude Code Hooks: Complete Guide [GenAI] Pre-retieval overview [GenAI] About Indexing [GenAI] Indexing overview [Vibe Coding] 降低大模型幻觉 - 重试机制 [Vibe coding] 降低大模型幻觉 - JSON 安全输出提示词 [Node.js] WebSocket基础知识 [LangGraph] 应用结构 [LangGrpah] Unit testing [LangGraph] Functional API [LangGraph] 中断注意事项 [LangGraph] 中断相关细节 [LangGrpah] 静态断点 [LangGrpah] 非阻塞式中断 [LangGraph] 阻塞式中断 [LangGraph] 语义搜索 [LangGraph] 长期记忆 [LangGraph] 管理短期记忆 [LangGraph] 自定义checkpointer [LangGraph] 短期记忆 [LangGraph] 时间旅行 [LangGraph] checkpoint常用API [LangGraph] 元数据标记 [LangGraph] 流 [Vitest] mockClear, mockReset, mockRestore
[LangGraph] 将子图添加为节点
Zhentiw · 2026-02-24 · via 博客园 - Zhentiw

核心概念

子图直接“嵌入”到父图内,成为父图的一部分,与父图共享 state 的 key。

示意图:

父图节点  ===>  { 子图内部的很多节点 } ===> 父图下一个节点

看起来像父图的一个 node,但内部却是一个完整的 graph。

也正因为如此:

  • 子图与父图使用同一个 state(共享部分或全部 key)

  • 子图内部的 node 可以读写父图 state

子图不再是一个“黑盒”,而是父图的一部分

适用场景:

  • 多团队协作,把一段流程拆成一个子图
  • 想复用一段常用流程(比如全局日志链路、消息管道)
  • 子图需要访问父图的多个 state 字段,不止输入/输出

快速上手

场景

客户注册需要执行复杂的 KYC(身份核验)流程:

子图负责:

  • OCR 身份证识别
  • 人脸对比
  • 风险评分
  • 写入结果到父图的 shared state

父图负责:

  • 收集用户信息
  • 调用 KYC 子图验证
  • 根据验证结果决定是否注册成功

示意图

flowchart TD %% ---------- 父图 ---------- subgraph ParentGraph[父图:用户注册流程] P_START([START]) P1[父节点:kycFlow<br/>(子图作为复合节点)] P2[父节点:finish<br/>根据 kycPassed 生成注册结果] P_END([END]) P_START --> P1 --> P2 --> P_END end %% ---------- 子图 ---------- subgraph Subgraph[子图:KYC 验证流程(共享父图 State)] S_START([START]) S1[子节点:OCR 校验<br/>ocrPassed] S2[子节点:人脸比对<br/>faceMatch] S3[子节点:KYC 汇总<br/>kycPassed] S_END([END]) S_START --> S1 --> S2 --> S3 --> S_END end %% ---------- 连接关系 ---------- %% 说明:父图的 kycFlow 节点 == 整个子图执行 P1 -. 调用并共享 state .-> S_START S_END -. 返回更新后的 state .-> P2

index.ts

import { mainGraph } from "./mainGraph.ts";

async function main() {
  // 模拟数据
  const input = {
    userName: "张三",
    idCardImage: "path/idcard.jpg",
    selfImage: "path/selfie.jpg",
  };

  const result = await mainGraph.invoke(input);

  console.log("\n=== 最终结果 ===");
  console.log(result);
}
main();

mainGraph.ts

// 父图
import { StateGraph, START, END } from "@langchain/langgraph";
import { z } from "zod/v4";
import { kycSubgraph } from "./kycSubgraph.ts";

// 父图的状态
const MainState = z.object({
  // 用户注册的基本信息
  userName: z.string().describe("用户名"),
  idCardImage: z.string().describe("用户身份证图片"),
  selfImage: z.string().describe("用户相关的图片"),

  // 各种验证
  ocrPassed: z.boolean().optional().describe("ocr验证是否通过"),
  faceMatch: z.boolean().optional().describe("人脸匹配是否通过"),
  kycPassed: z.boolean().optional().describe("kyc验证是否通过"),

  // 最终注册的结果
  registerResult: z.string().optional().describe("最终注册的结果"),
});

type TMainState = z.infer<typeof MainState>;

function finish(state: TMainState) {
  if (state.kycPassed) {
    return {
      registerResult: "注册成功",
    };
  }
  return {
    registerResult: "注册失败,KYC验证没有通过",
  };
}

export const mainGraph = new StateGraph(MainState)
  .addNode("kycFlow", kycSubgraph)
  .addNode("finish", finish)
  // 边
  .addEdge(START, "kycFlow")
  .addEdge("kycFlow", "finish")
  .addEdge("finish", END)
  .compile();

kycSubgraph.ts

// 做身份验证的子图
import { StateGraph, START, END } from "@langchain/langgraph";
import { z } from "zod/v4";

const KycState = z.object({
  // 用户注册的基本信息
  userName: z.string().describe("用户名"),
  idCardImage: z.string().describe("用户身份证图片"),
  selfImage: z.string().describe("用户相关的图片"),

  // 各种验证
  ocrPassed: z.boolean().optional().describe("ocr验证是否通过"),
  faceMatch: z.boolean().optional().describe("人脸匹配是否通过"),
  kycPassed: z.boolean().optional().describe("kyc验证是否通过"),
});

type TKycState = z.infer<typeof KycState>;

// 检查的节点:1. OCR验证   2. 人脸比对
async function ocrCheck() {
  const randomPass = Math.random() > 0.5; // 90% 通过

  console.log("🔍 [子图] OCR 检查:", randomPass);

  return { ocrPassed: randomPass };
}

async function faceMatchCheck() {
  const randomPass = Math.random() > 0.5; // 80% 通过

  console.log("🔍 [子图] 人脸比对:", randomPass);

  return { faceMatch: randomPass };
}

// 汇总节点
async function summary(state: TKycState) {
  // 这两项验证都通过了,那就是通过了
  const passed = state.ocrPassed && state.faceMatch;

  return {
    kycPassed: passed,
  };
}

export const kycSubgraph = new StateGraph(KycState)
  .addNode("ocrCheck", ocrCheck)
  .addNode("faceMatchCheck", faceMatchCheck)
  .addNode("summary", summary)
  // 边
  .addEdge(START, "ocrCheck")
  .addEdge("ocrCheck", "faceMatchCheck")
  .addEdge("faceMatchCheck", "summary")
  .addEdge("summary", END)
  .compile();