首页/新闻资讯/正文详情

第 17 章 · 编排 AI 流程:StateGraph 节点、条件边与意图路由

发布时间:2026/9/24 7:39:27 来源:云帆数科 栏目:资讯中心
第 17 章 · 编排 AI 流程:StateGraph 节点、条件边与意图路由
版本LangGraph4j 1.8.25目标在StateGraph上加节点、普通边、条件边跑通一张意图三路分支图。本章不接模型classify用规则写死只练拓扑。StateGraph是可变蓝图挂 schema、节点、边再compile()得到可执行的CompiledGraph。START/END是虚拟锚点业务逻辑只写在节点里。17.1 直线图节点 普通边addNode接收的是异步节点。同步逻辑写成NodeAction再用AsyncNodeAction.node_async包一层和第 15 章一样。import static org.bsc.langgraph4j.StateGraph.END; import static org.bsc.langgraph4j.StateGraph.START; import static org.bsc.langgraph4j.action.AsyncNodeAction.node_async; ​ NodeActionMyState retrieve state - Map.of(docs, search(state.Stringvalue(query).orElse())); ​ NodeActionMyState generate state - Map.of(answer, ok); ​ var graph new StateGraph(schema, MyState::new) .addNode(retrieve, node_async(retrieve)) .addNode(generate, node_async(generate)) .addEdge(START, retrieve) .addEdge(retrieve, generate) .addEdge(generate, END);普通边是固定下一跳source → target。同一 source 挂多条无条件边编译后会扇出成并行不是二选一。互斥分支必须用条件边。17.2 条件边返回映射表的 keyEdgeAction根据状态返回一个String。这个字符串是映射表里的key框架再用映射翻成真正的节点 id。import static org.bsc.langgraph4j.action.AsyncEdgeAction.edge_async; ​ EdgeActionMyState byIntent state - state.Stringvalue(intent).orElse(unknown); ​ graph.addConditionalEdges(classify, edge_async(byIntent), Map.of( faq, faq, // key → 节点 id order, order, unknown, fallback ));本例里 key 和节点 id 同名读起来方便也可以写成faq → faq_handler只要EdgeAction返回的 key 能在表里查到。常用挂法对照API用途addNode(id, AsyncNodeAction)普通节点同步用node_async包addNode(id, AsyncNodeActionWithConfig)节点里要读RunnableConfigaddEdge(source, target)固定下一跳addConditionalEdges(source, edge, mappings)按状态选下一跳Command可以同时指定「下一跳 状态更新」new Command(fallback, Map.of(reason, unrecognized));条件边若用AsyncCommandAction返回的是Command用EdgeAction/AsyncEdgeAction时只负责选路状态仍由节点返回的 partial Map 更新。17.3 意图路由一整张能跑的图上图就是下面这份代码classify写出intent条件边按faq/order/unknown三路各自接到END。import static org.bsc.langgraph4j.StateGraph.END; import static org.bsc.langgraph4j.StateGraph.START; import static org.bsc.langgraph4j.action.AsyncEdgeAction.edge_async; import static org.bsc.langgraph4j.action.AsyncNodeAction.node_async; ​ import java.util.ArrayList; import java.util.List; import java.util.Map; ​ import org.bsc.langgraph4j.CompiledGraph; import org.bsc.langgraph4j.StateGraph; import org.bsc.langgraph4j.action.EdgeAction; import org.bsc.langgraph4j.action.NodeAction; import org.bsc.langgraph4j.state.AgentState; import org.bsc.langgraph4j.state.Channel; import org.bsc.langgraph4j.state.Channels; ​ public class IntentRoutingGraph { ​ public static class RouteState extends AgentState { public static final String INTENT intent; public static final String REPLY reply; public static final String LOGS logs; ​ public static final MapString, Channel? SCHEMA Map.of( INTENT, Channels.base(() - ), REPLY, Channels.base(() - ), LOGS, Channels.appenderWithDuplicate(ArrayList::new) ); ​ public RouteState(MapString, Object initData) { super(initData); } } ​ public static void main(String[] args) throws Exception { NodeActionRouteState classify state - { String text state.Stringvalue(text).orElse(); String intent; if (text.contains(订单) || text.contains(物流)) { intent order; } else if (text.contains(怎么) || text.contains(什么)) { intent faq; } else { intent unknown; } return Map.of( RouteState.INTENT, intent, RouteState.LOGS, List.of(classify: intent) ); }; ​ NodeActionRouteState faq state - Map.of( RouteState.REPLY, 这是 FAQ 答复, RouteState.LOGS, List.of(faq) ); NodeActionRouteState order state - Map.of( RouteState.REPLY, 这是订单答复, RouteState.LOGS, List.of(order) ); NodeActionRouteState fallback state - Map.of( RouteState.REPLY, 没听清意图请换种说法, RouteState.LOGS, List.of(fallback) ); ​ EdgeActionRouteState byIntent state - state.Stringvalue(RouteState.INTENT).orElse(unknown); ​ CompiledGraphRouteState compiled new StateGraph(RouteState.SCHEMA, RouteState::new) .addNode(classify, node_async(classify)) .addNode(faq, node_async(faq)) .addNode(order, node_async(order)) .addNode(fallback, node_async(fallback)) .addEdge(START, classify) .addConditionalEdges(classify, edge_async(byIntent), Map.of( faq, faq, order, order, unknown, fallback)) .addEdge(faq, END) .addEdge(order, END) .addEdge(fallback, END) .compile(); ​ compiled.invoke(Map.of(text, 我的订单到哪了)) .ifPresent(s - { System.out.println(s.value(RouteState.INTENT).orElse()); System.out.println(s.value(RouteState.REPLY).orElse()); System.out.println(s.value(RouteState.LOGS).orElse(List.of())); }); // → order // → 这是订单答复 // → [classify:order, order] } }读代码时对照上图核对三件事classify只负责写出intent不自己跳转。byIntent读intent返回的字符串必须能在映射表里找到。三条业务边各自addEdge(..., END)图不会悬空。需要核对拓扑时System.out.println(compiled.getGraph( org.bsc.langgraph4j.GraphRepresentation.Type.MERMAID, Intent Routing).content());17.4 常见错误现象原因与处理本想二选一却两个分支都跑了互斥写成了多条addEdge改成addConditionalEdges路由报错或走不到目标节点映射漏了 key或EdgeAction返回值与 key 对不上图悬空、编译失败某条分支没接到后续节点或END条件边返回了节点 id却不在映射表里返回的应是key把该 id 配进映射或让返回值等于已有 key直线图先compile跑通再改成条件三路每步导出 Mermaid看边有没有接错。

相关推荐

Akka Streams 与 Reactive Streams 互操作指南:Publisher / Subscriber / Processor 的无缝桥接实战
Akka Streams 与 Reactive Streams 互操作指南:Publisher / Subscriber / Processor 的无缝桥接实战

后端并发编程异步编程 【免费下载链接】akka-core A platform to build and run apps that are elastic, agile, and resilient. SDK, libraries, and hosted environments. 项目地址: https://gitcode.com/gh_mirrors/ak/akka-core 点击查看 免费下载 Akka Stream… · 2026/9/24 7:39:15

Flink Working Directory 完全指南:进程工作目录配置与跨重启本地恢复实战
Flink Working Directory 完全指南:进程工作目录配置与跨重启本地恢复实战

大数据流处理批处理数据工程 【免费下载链接】flink 项目地址: https://gitcode.com/gh_mirrors/fli/flink 点击查看 免费下载 Working Directory(工作目录)是 Flink 为 JobManager 与 TaskManager 进程提供的本地持久化目录,用于… · 2026/9/24 7:39:08

codeburn sync 团队同步指南:将本地 AI 用量遥测安全推送到共享 OTLP 后端
codeburn sync 团队同步指南:将本地 AI 用量遥测安全推送到共享 OTLP 后端

【免费下载链接】codeburn Free, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn 项目地址: https://gitcode.com/gh_mirrors/co/cod… · 2026/9/24 7:39:02

智能手表晶振拆解:32.768kHz与MEMS选型及布局指南
智能手表晶振拆解:32.768kHz与MEMS选型及布局指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 8:28:50

learn-harness-engineering 项目 04 实战:以运行时反馈与架构约束修正 Agent 行为——增量索引的可观测性工程
learn-harness-engineering 项目 04 实战:以运行时反馈与架构约束修正 Agent 行为——增量索引的可观测性工程

【免费下载链接】learn-harness-engineering Harness engineering beginner tutorial, from 0 to 1 项目地址: https://gitcode.com/gh_mirrors/le/learn-harness-engineering 点击查看 免费下载 本篇是 learn-harness-engineering 教程中「Project 04: Runtime Fe… · 2026/9/24 8:28:31

LPDDR4X的VDDQ为什么是0.6V?电源设计的几个坑
LPDDR4X的VDDQ为什么是0.6V?电源设计的几个坑

做DDR硬件设计,电源是另一个容易被忽略的环节。很多人DDR信号调得不错,结果一上电就不稳定,查了半天发现是电源纹波太大,或者电压精度不够。这篇文章讲讲LPDDR4X的电源设计要点,特别是VDDQ这个0.6V的电源。一、LPDDR4X… · 2026/9/24 8:28:25

从零构建股票回测系统:架构设计、成交模拟与绩效分析实战
从零构建股票回测系统:架构设计、成交模拟与绩效分析实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 8:28:18

AI Agent开发课怎么选?从LLM到Agent系统设计的完整学习路径
AI Agent开发课怎么选?从LLM到Agent系统设计的完整学习路径

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 8:28:06

昇腾AscendC中TBuf InitBuffer报错507035根因解析
昇腾AscendC中TBuf InitBuffer报错507035根因解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 8:27:35

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码