ai-agent框架spring ai/alibaba源码原理分析(五) graph II 编译图
简介
saa是java的ai agent框架,本系列将深入剖析 Spring AI Alibaba 的源码实现与核心原理,不仅可以指导agent的开发,更可以改造框架,增加新特性
系列内容:
系列(一)架构完成
系列(三)调用
I工具完成
II MCP
-1 MCP MCP能力,工具,资源,Prompts,sampling,。。。;springboot自动配置完成
-2分布式 MCP
-3 MCP security
III skills完成
系列(四) RAG完成
I知识库,文档读取,分块;嵌入,向量store
II检索,增强生成,模块化;混合检索,融合重排
系列(二)模型 model模型完成
chat模型,消息,提示词,结构化输出,记忆
chat client,advisor组件
系列(五) graph图结构,节点和边;StateGraph
推理框架graph映射示例: ReAct,relection,CoT,Plan-And-Execute
CompiledGraph;图执行,状态和存储
系列(六) agent组件分析,ReactAgent,钩子和拦截器,记忆,结构化输出,人工介入
系列(七) MAS
I flow agent; handoffs模式,toolcalling模式;
II分布式agent,A2A,分布式运行
系列(九) agent管理平台(admin) agent发现(a2a),agent列表,提示词管理,会话管理,skill管理,MCP管理;chat;评估;观测
系列(八) I观测:观测组件(micrometer-observation),观测点:chatClient,chat模型,工具(tracing) II 模型评估
本文分析graph,图编译
based spring ai alibaba v1.1.2.2
关键词
agent
graph
缩写
spring ai缩写sa
spring ai alibaba缩写saa
参考资料
概览 | Spring AI Alibaba spring ai alibaba官网文档
https://docs.spring.io/spring-ai/reference/index.html spring ai官方文档
SAA概览
上图是saa原理源码分析场景视图,每个包对应着saa/sa组件或特性,是本文分析的目录
model大模型的封装,模型包括Chat,嵌入,audio,image等类型,其中chat模型包括,advisor组件,提示词,记忆等
agent/graphsaa agent,多agent与图紧密相关,可以认为saa agent/多agent是一种既定的”图”形,实现推理框架,开发人员可以使用graph底层api直接构建graph,使用agent获得既定的图形,简化agent的开发
外部调用(calling)工具,MCP,skills
RAG检索增强生成
MASA2A,FlowAgent,子agnet,agent Tool;agent 集群
studio简易的agent管理工具,嵌入到agent,带有agent面板,列表agent;提供chat界面,用于调试agent,是开发agent的便利工具
admin管理台, agent的发布,列表,管理,执行;提示词工程,评估和数据集,观测
graph
saa graph-core是saa的图组件,以图的结构,节点,边构建处理流程,节点执行动作,边决定下一个节点,对应的,agentic是另一种模式,整个流程大模型自主编排,agentic省心省事,但同时agentic容易失控,纯粹看大模型心情,因此,目前比较好的方案,主体使用flowable,需要的时候使用agentic节点。
spring ai alibaba,agent的推理框架映射成graph,多agent角色也映射成graph,以图的节点承载执行逻辑,边决定下一节点,支持检查点保存执行状态,实现执行的暂停和恢复
外部介入
本节介绍saa的中断机制,中断等待外部干预,例如,人工验证,同时生成检查点(CheckPoint),用于恢复执行
上图是中断机制两种实现方式,
- InterruptableAction实现该接口的NodeAction,执行器识别Action类型,中断,返回提示,等候外部恢复
- interruptsBefore/interrupteAfter设置interruptsBefore/ interrupteAfter,在CompileConfig设置哪个节点的前/后中断,执行时识别,中断处理
还有两种中断方式,将在执行图中分析
编译图
前面分析了状态图,状态图是图的结构,目的是为了方便构建图,编译图扁平化邻接表数据结构,目的是为了高效执行
上图是编译图类图,编译把整个图,包括子图的数据结构转换为扁平化的邻接表结构,大大降低遍历复杂度;并行处理,使用并行节点/action,节点内处理并行,执行器不需处理。
图中类下面详细分析,可以适时返回参看类图
下面分析原理和源码
扁平化邻接表
ProcessedNodesEdgesAndConfig负责扁平化状态图数据结构,代码比较多,用示例解释代码逻辑,注释版的代码放到附录
首先介绍一下邻接表,
'A': ['B'], 'B': ['C'], 'C': [] |
左:连接点结构,左是head节点,右是数组,head节点连接的节点;右:对应的图
进一步,若B是子图节点,其子图 D->E, D->F,E->G,F->G
ProcessedNodesEdgesAndConfig处理过后
'A': ['B-D'], 'B-D': ['B-E', 'B-F'], 'B-E': ['B-G'], 'B-F': ['B-G'], 'B-G': ['C'], 'C': [] |
主图子图扁平化,合并到一个邻接表结构,主图与子图节点(B)的连接重定向到子图的节点,子图节点名称修改,格式%s-%s
最后,返回子图的Node写入到nodeFactoryes,id为key,action工程为value的map
CompiledGraph.CompiledGraph()
nodeFactoryes是最终的邻接表head节点集
边和并行处理
ProcessedNodesEdgesAndConfig处理后,返回边(edges)是list,图遍历按节点找边需要遍历list,因此边数据需要转为map,以sourceNodeId为key,即,List<Edge>类型转为Map<String, EdgeValue>,另外,图有并行分支,编译使用并行节点替代,并行执行在节点action完成,不需要执行器介入
首先上图回顾一下图的边模型,边处理分多targes和单个target处理,
单个target
单个target又可以分为,nodeId,单command条件,多command条件(带条件的并行)3个情况
其中nodeId,EdgeValue是NodeId;单command条件,返回一个NodeId,均可直接put到Map<String, EdgeValue>即可
多command条件使用ConditionalParallelNode/ConditionalParallelNodeAction处理,并行在其action处理,不需执行器处理,这也是编译的一个关键任务,下面分析源码,
下面的代码来自CompiledGraph.CompiledGraph()方法
接上节,图扁平化处理返回
处理单target,进一步分为nodeid,单command条件,多command条件3种情况
首先处理多command条件,插入条件并行节点,负责并行执行,边原来的source节点连接到新增的并行节点
上图展示示例图,通过返回节点名称映射(mappings),找出返回节点集,即示例的A1,A2
查找返回节点集的汇聚点,上图的B,graph组件的约束,分支后需要汇聚到同一节点,最后并行节点连到B
即,A-- edge(mappings[a1:A1, a2:A2]) --B 变成 A--> 并行节点 -->B
上面的isEmpty判断是错误的,数量只能是1,v2.0版本已经修改了
最后,单target的其余两种情况,单comman条件和nodeId直接增加到edges
多target
并行分支处理,与上面多command条件类似,用ParallelNode/AsyncParallelNodeAction处理并行
上面展示示例图,A1,A2,A3是并行分支,首先找到A1,A2,A3的汇聚点,即B
上图检验,并行分支汇聚到一节点,分支的边不能带条件
获取并行节点的acton,构建ParallelNode
插入新的并行节点,重新连接
总结:
上图是示例编译后的图,可以理解为是一个”降维”的处理,”摆平”多层的主图子图结构,”摆平”并行处理,降低执行器复杂度,提高执行效率
编译前后对比
本节对比编译前后类图
- 编译前
上图编译前类图,为了清晰,边部分类图放在下图
图遍历需要使用状态图的数据结构,遍历Node,执行NodeAction,若Node是子Node,深度递归遍历,并行,包括并行分支,多command边条件,需要执行器处理
- 编译后
图编译后图的数据结构
编译后,邻接表结构,节点集在nodeFactories, nodeFactories的values存放ActionFatory,节点连接的边放到edges,注意,虽然名字与原状态图一样,但类型变了,编译后,edges是map类型,状态图相当于list类型。
并行处理替换为并行节点/action,执行阶段并行执行与执行一般的action一样,编译图与代码编译的意义是一样的,减少执行的工作,提高执行效率
附录
ProcessedNodesEdgesAndConfig的代码注释
