ai-agent框架spring ai/alibaba 原理源码分析(五)graph III 图执行
图执行上文分析了图编译编译后图具备高效执行的数据结构本文分析图执行图执行可分两部分主图执行MainGraphExecutor负责主图执行主要是图执行控制 包括START END中断点执行NodeExecutor负责节点处理。图执行使用响应式流如下图可以认为图遍历的过程是Flux(数据源)连接成响应式管道并加上处理的过程Flux是节点Action执行的返回。做个类比Flux链好比流水线输送数据(材料)数据处理类比员工材料到工位加工处理流水线的开关类比Flux的订阅这里看出响应式编程的特点先构建好数据流动管道加上相应的处理开关打开(调用block方法)数据发射触发处理实现异步无等待的处理检查点本节首先介绍一下检查点检查点是图的执行期重要的组件负责保存执行环境用作中断/恢复回溯等关键功能也是图执行容错机制的支撑也是agent的短期记忆组件。上图检查点的类图CheckPoint检查点保存着图执行的上下文用于中断恢复容错回放等idcheckpoint idstate全局状态OverAllStatenodeId/nextNodeId 当前执行的nodeId下一个执行nodeId检查点整体存储类似文件夹文件夹id就是threadId(会话id)通常外部传入checkpoints按时间倒序list存储BaseCheckPointSaver检查点存储接口有多种实现redismemorymysql等执行类图下面分析参与执行的类图上图是参与执行的类图关于图的数据结构参看系列-图I和系列-图II分析了图结构编译后的数据结构GraphRunner执行入口负责GraphRunnerContext构建和初始然后调用MainGraphExecutor执行图GraphRunnerContext运行的上下文包括全局的状态OverAllState运行配置RunnableConfig运行标的CompiledGraph负责识别是新执行还是恢复执行还有2个重要的职责nextNodeId计算遍历的下一个节点addCheckpoint记录检查点MainGraphExecutor/NodeExecutor执行器前者负责主图执行后者负责节点执行主图执行重点是START节点END节点中断等节点执行交给NodeExecutor节点执行完返回MainGraphExecutor这样交替推进图的执行RunnableConfig运行时配置包含执行所需的参数设置其中关键属性threadId, checkPointId, nextNodenodeFactories/Node.ActionFactory/AsyncNodeActionWithConfig nodeFactories是图的节点集在系列-编译图介绍过。Node.ActionFactory构建节点Action类型是AsyncNodeActionWithConfigGraphResponse图执行返回结构包括NodeOutputreturnValue属性前者包含全局状态后者可以承载多种类型主要用于中断metadata也有其他用途有一点值得注意中断metadata是继承NodeOutput总结图执行使用响应式编程构建flux流给流数据添加处理逻辑订阅后发射事件触发处理可以认为MainGraphExecutor/NodeExecutor做的不是执行图而是构建action执行返回的flux流添加数据处理的过程好比部署好流水线工位待流水启动物料流动工位加工物料最终输出成品MainGraphExecutor 负责执行的控制包括构建起始/结束事件中断行为控制NodeExecutor 负责执行action连接action返回的flux添加处理包括返回的转换, 构建发射事件(GraphResponseNodeOutput类型)添加处理其中职责合并action新增的或修改的最新全局状态也就是图执行最终返回的结果触发执行是 stream(inputs, config).last().map(NodeOutput::state).block() 的block方法 saa Graph的Flux不同于一般的响应式流内置检查点Checkpoint组件赋予了Flux流“记忆”和“暂停”支持中断和恢复下面分析图执行代码比较多分4部分执行入口主图执行节点执行执行返回处理执行入口GraphRunner.run是图的执行入口首先处理图执行的两种情况新开始和恢复GraphRunnerContext上图识别图执行是新开始还是恢复判别是否恢复依据是是否有用户反馈或者运行配置设置了checkPointId后者通常是用户获取checkpoint列表指定checkpoint恢复点上两图是新开始和恢复执行的上下文初始化初始化当前NodeId下一个NodeId全局状态恢复执行从checkpoint获取恢复还设置resumeFrom这个标志在主图执行分析主图本节分析主图执行负责图执行整体的控制处理START/END节点中断处理中断-returnFromEmbedsaa graph支持中断和恢复中断方式有4种本节分析其中一种设置returnFromEmbedMainGraphExecutor的execute上图GraphRunnerContext的returnFromEmbed属性类型是中断metadata设置该属性有两种情况一是interruptAfter中断action有3个方法interrupt-apply-interruptAfterreturnFromEmbed是interruptAfter设置二是action没有实现InterruptableAction但返回中断metadata这种情况在源码中发现并作了测试验证附件的SensitiveOperationNode.java修改自interruptable-action-example示例的SensitiveOperationNode.java直接替换可进行测试。上述两种情况在action apply后处理action结果时不能直接返回因此采取设置上下文returnFromEmbed的方式回到主图执行处理中断-markNodeAsInterrupted中断的第二种方式RunnableConfig的markNodeAsInterrupted方法设置MainGraphExecutor的execute​上图RunnableConfig的markNodeAsInterrupted方法设置中断目前没发现有使用看上去可用来在图执行时动态设置中断节点例如出现工具不在线异常动态设置工具调用节点中断要求人工确认工具是否正常恢复执行撤销中断中断-resumeFrom中断的第三种方式实现InterruptableActionMainGraphExecutor的execute​上图是InterruptableAction的interrupt执行后用户介入恢复执行再次进入MainGraphExecutor的execute上下文识别恢复执行设置了resumeFrom值是中断的nodeId。InterruptableAction的3个方法interrupt-apply-interruptAfterinterrupt是action执行前的中断interruptAfter是action执行后InterruptableAction执行在后面节点执行分析。​INTERRUPT_AFTER是action结果处理时加上去的逻辑节点如下图的箭头2​计算了nextNodeIdsetNextNodeId就是覆盖了INTERRUPT_AFTER后续这个计算了nextNodeIdsetNextNodeId当前节点移到下一节点中断不会执行我理解后面执行action的apply-interruptAfter重复了去掉INTERRUPT_AFTER。中断-compileConfig设置这是中断的第四种方式compileConfig配置​上图compileConfig配置中断这种方式相对简单指定节点支持interruptsBefore和interruptsAfter。shouldInterrupt判断包括上节INTERRUPT_AFTER的判断结合上节分析排除重复的中断配置可以看到主图好大的篇幅在处理中断saa很重视中断4种实现中断的方式1 实现InterruptableAction2 RunnableConfig的markNodeAsInterrupted设置中断3 action返回InterruptionMetadata4 compileConfig配置中断节点执行​最后 交给NodeExecutor执行节点节点NodeExecutor负责节点的执行分为Action执行和执行结果处理两阶段图执行是响应式节点执行是构建flux链设定数据流处理真正的处理在flux订阅后NodeExecutor构建flux链添加处理设定处理节点获取actionNodeExecutor的executNode​设定执行节点获取节点的action系统-图II一文分析过编译图的数据结构action通过Node.ActionFactory构建后者在图的节点集nodeFactories获取中断执行NodeExecutor的executNode​上图是中断action处理这里可以是第一次进入也可以是外部确认后的再(n)次恢复进入RunnableConfig.STATE_UPDATE_METADATA_KEY有值说明是恢复进入带来外部信息需合并到全局状态再执行中断这样正确判断是否(继续)中断。回顾主图3)中断-resumeFrom, 这里执行interrupt方法flux中断返回中断metadata给用户用户介入后重新进入上下文设置resumeFrom。执行actionNodeExecutor的executNode​上图中断处理完首先看到通知NODE_BEFORE即action执行前框架自身目前观测组件监听对应Observation的onStart详情参看系列-观测I和系列-观测II。执行action的apply方法后面处理action的返回action返回结果处理本节分析action执行结果处理首先了解下action返回​上图典型的异步action的返回map类型上图的action简单设置一个返回实际可以返回多个元素的map这也是导致处理action结果的复杂性NodeExecutor的handleActionResult方法​可能是注释有问题并行有并行分支和多Command的条件并行对应的都是第三种第二种现在代码并没有用到所以backward compatibility应该是第二项的注释上图3类action返回结果的处理分普通acton并行的action两种情况并行分支和多Command条件处理逻辑是转换action返回的flux类型为GraphResponseNodeOutput, 构建发射事件(GraphResponseNodeOutput类型)添加事件处理下面先分析中断action的interruptAfter第6节再分析flux类型处理中断action处理上面3种返回如果有flux类型返回到这里表示没有flux只有静态的状态NodeExecutor的handleActionResult方法​上图是interruptAfter方法执行InterruptableAction的3个方法interrupt-apply-interruptAfter在上两节执行了前两个方法这里执行interruptAfter这里执行带了updateStateaction apply的执行结果若返回中断metadata先合并新状态然后计算下一个node再记录checkpoint返回。有两点注意一这里检查点计算了netxNodeId恢复回来直接执行下一节点这点与interrupt不同意味着interruptAfter只是给用户反馈action的执行结果没有介入功能二如果前面有flux处理这里不执行那么interruptAfter什么时候执行下面以嵌入flux处理分析嵌入flux本节插入flux分析下一节继续分析NodeExecutor的handleActionResult6.1) 获取嵌入fluxNodeExecutor的getEmbedFlux​过滤Flux类型而且只要第一个也就是action返回多个flux也只有一个有用transformFluxToGraphResponse转换flux结果包括ChatResponseNodeOutput的返回包装成GraphResponse重新构造事件放入flux流6.2) 处理flux上节在action返回找到flux转换类型本节分析flux处理NodeExecutor的processGraphResponseFlux​上图主要是将flux返回放到临时变量给下面更新上下文使用​上图更新上下文副作用操作不涉及fluxsetReturnFromEmbedWithValue在主图执行分析过action没有实现InterruptableAction但返回InterruptionMetadata在这里设置returnFromEmbed注意saa图限制并行的分支不支持中断因此3类action flux处理只有这里处理中断并行分支多command并行即使返回中断metadata也忽略。​上图partialState是action返回的状态过滤调flux留下静态的返回更新到上下文有两点注意一combinedUpdateState还是上下文更新都是updateState在后覆盖partialStateWithoutFlux二红框部分是在中断action处理的问题答案interruptAfter在action返回flux的情况的调用​计算下一个node再记录checkpoint设置returnFromEmbedWithValue待回到主图执行器处理6.x) flux流串联​最后处理完的 Flux数据流等待节点状态更新后续流串联Mono.thenMany mono转flux的方法强调 这里的处理是挂在Flux的处理是构建flux流的过程继续action返回处理前面5) 分析中断action的interruptAfter后插入action返回flux处理本节继续分析action返回处理​上图另一种中断compileConfig设定的nodeId以下图配合说明​箭头1指向的是当前节点interruptsAfter().contains(context.getCurrentNodeId()) 当前节点设定为interruptsAfter并且interruptBeforeEdgetrue即中断点在箭头2位置边之前这里就是INTERRUPT_AFTER逻辑节点插入的地方可以回顾到中断-resumeFrom那节完成节点处理​构建NodeOutput和记录检查点flux流连接图返回处理最后本节分析图执行返回结果图执行有同步和流式两种CompiledGraph上图上两个是同步调用第三个是流式调用同步调用也是使用流式调用last方法只要最后一个结果block方法订阅数据流触发flux发射事件流式调用返回fluxclient需要自行订阅自行处理flux流附件非InterruptableAction的action实现中断替换spring-ai-alibaba-graph-example的interruptable-action-example同名类即可测试SensitiveOperationNode.java

相关新闻

HarmonyOS API 23 ArkTS 实战:实现一个轻量级实时数字时钟工具

HarmonyOS API 23 ArkTS 实战:实现一个轻量级实时数字时钟工具

开发环境:HarmonyOS NEXT 6.1.0(API 23)、Stage应用开发模型、DevEco Studio 6.1 Beta、Hvigor增量编译构建体系核心技术栈:ArkTS强类型静态编程、声明式UI架构、单向响应式数据流、系统时间获取、定时器实时刷新、时间格式化处理…

2026/10/17 18:55:08 阅读更多 →
人形机器人高动态运动控制:从武术表演到产业应用的技术解析

人形机器人高动态运动控制:从武术表演到产业应用的技术解析

1. 从“功夫梦”到“功夫机器人”:一场技术驱动的文化奇观最近,一段关于人形机器人表演中国武术的视频在网络上火了。视频里,几个机器人整齐划一地打出一套行云流水的拳法,甚至完成了高难度的侧空翻和腾空踢腿,动作之流…

2026/10/16 13:11:42 阅读更多 →
直流减速电机 + Arduino 接线方案

直流减速电机 + Arduino 接线方案

总体接线图12V电源├── BTS7960 → 37GB545D电机动力线└── LM2596 → 5V → Arduino / 编码器 / 传感器Arduino├── D5 → BTS7960 RPWM├── D6 → BTS7960 LPWM├── D2 ← 编码器A相├── D3 ← 编码器B相├── D7 ← HOME限位└── A0 ← FSR压力传感器1.BTS79…

2026/10/16 10:25:13 阅读更多 →

最新新闻

超表面透镜逆向设计:MATLAB中的伴随梯度与相位优化实现

超表面透镜逆向设计:MATLAB中的伴随梯度与相位优化实现

简介:《光学工程:MATLAB开发超表面透镜逆向设计优化算法》是一份面向光学工程与计算成像领域的高阶技术笔记,主要服务于需要掌握超表面器件设计与优化算法的科研人员、工程师及研究生。文档从光学工程与超表面透镜的基本概念入手,…

2026/10/17 23:48:45 阅读更多 →
Oracle EBS ASCP高级计划排程:三层BOM完整计划案例解析

Oracle EBS ASCP高级计划排程:三层BOM完整计划案例解析

简介:针对Oracle EBS高级计划排程(ASCP)模块的方案设置测试文档,主要面向制造企业供应链计划员、EBS实施顾问以及需要深入理解高级排程的学员。文档以YY手机公司多工厂、多分销中心的实际业务为背景,完整覆盖ASCP方案从…

2026/10/17 23:48:45 阅读更多 →
Oracle EBS ASCP 高级计划排程:一份能直接照做的供应链计划配置路径

Oracle EBS ASCP 高级计划排程:一份能直接照做的供应链计划配置路径

简介:供应链计划是企业运营的中枢,决定物料需求能否转化为可执行的生产与采购指令。在 Oracle EBS 这类主流 ERP 中,高级计划排程(ASCP)负责跨组织供需平衡,但计划引擎要跑得准,物料、BOM、工艺…

2026/10/17 23:48:45 阅读更多 →
【收藏必备】LangGraphGo+Skills插件实战:从零构建AI漫画生成智能体,附完整代码与踩坑经验|TaoToken 统一 Key 接入

【收藏必备】LangGraphGo+Skills插件实战:从零构建AI漫画生成智能体,附完整代码与踩坑经验|TaoToken 统一 Key 接入

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

2026/10/17 23:48:45 阅读更多 →
Claude Code v2.1.203 瘦身 7MB 后冷启动实测:macOS 挂起 20 秒回归怎么排查?TaoToken 统一 Key 通道配置记录

Claude Code v2.1.203 瘦身 7MB 后冷启动实测:macOS 挂起 20 秒回归怎么排查?TaoToken 统一 Key 通道配置记录

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

2026/10/17 23:48:45 阅读更多 →
IP地址如何工作:从寻址原理到网络排查实战

IP地址如何工作:从寻址原理到网络排查实战

写这篇总结之前,我先随手翻了翻之前的几篇笔记。基础概念系列连起来看,前面已经把分层模型、以太网、交换机转发这些底子打过了,这一篇正好接上:IP地址是怎么在网络里被"用"起来的。说白了,就是回答一个很实…

2026/10/17 23:47:45 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/16 14:23:36 阅读更多 →