当前位置: 首页 > news >正文

spring-ai-alibaba 之 graph 槽点

函数式编程

spring-ai-alibaba-graph-core 的代码也学习有一段时间了,有些地方确实还不尽如人意

其中有些底层设计感觉确实不太符合java开发人员的习惯,不太容易理解

究其根源,个人感觉应该是照搬 langgraph 的逻辑,强行使用函数式编程,没有进行java面向对象的适配导致的(反正我是不承认我不习惯大范围使用 java 的函数式编程的 :))

毕竟在 langgraph 的官网介绍中都说了,Nodes 和 Edges 仅仅是 Python 函数

但做 Java 开发从没听过“仅仅是 Java Lambda表达式”或者“仅仅是Java Function”的说法,类比应该是“仅仅是 Java 类”或“仅仅是 Java 接口”

举个例子

原先 langgraph 的使用逻辑可能类似下面这样

def chatbot(state: State):return {"messages": [llm.invoke(state["messages"])]}llmNode = Node(chatbot)
graph_builder.add_node("chatbot", llmNode)

在python中,函数本身也是一种对象,可以当做参数进行传递

但是在java中,如果要完全复制这种操作,就需要引入Function等函数式编程,进行一层封装

NodeAction llmAction = overallState -> {Map<String, Object> map = ...//业务逻辑return map;
}Node llmNode = new Node(llmAction)

 Node及NodeAction的定义如下,其中NodeAction是一个继承了Function接口的接口

public class Node {@FunctionalInterfacepublic interface NodeAction {Map<String, Object> apply(OverAllState state) throws Exception;}private final String id;private final NodeAction actionFactory;
}

但是这不够,在python中一个函数就能将参数转为异步

def chatbot(state: State):return {"messages": [llm.invoke(state["messages"])]}llmNode = Node(chatbot)
graph_builder.add_node("chatbot", async(llmNode))

那怎么办?spring-ai-alibaba-graph-core 为了支持这种写法,在外面又套了一层

public class Node {@FunctionalInterfacepublic interface AsyncNodeAction extends Function<OverAllState, CompletableFuture<Map<String, Object>>> {CompletableFuture<Map<String, Object>> apply(OverAllState state);@FunctionalInterfacepublic interface NodeAction {Map<String, Object> apply(OverAllState state) throws Exception;}static AsyncNodeAction node_async(NodeAction syncAction);}private final String id;private final AsyncNodeAction asyncActionFactory;
}

然后,python还支持多参数,即节点函数的入参包括State和RunnableConfig

def chatbot(state: State, runnableConfig: RunnableConfig):return {"messages": [llm.invoke(state["messages"])]}llmNode = Node(chatbot)
graph_builder.add_node("chatbot", async(llmNode))

那就在AsyncNodeAction外面再套一层AsyncNodeActionWithConfig,继承BiFunction

具体代码我就不贴了,后面还又套了一层ActionFactory

总之,让习惯java写法的人非常不习惯

如果是java开发一般会怎么写?一个接口搞定

public interface GraphNode {Map<String, Object> action(OverAllState state);default Map<String, Object> action(OverAllState state, RunnableConfig config) {return action(state);}default CompletableFuture<Map<String, Object>> asyncAction(OverAllState state) {return CompletableFuture.supplyAsync(() ->  action(state));}default CompletableFuture<Map<String, Object>> asyncAction(OverAllState state, RunnableConfig config) {return CompletableFuture.supplyAsync(() ->  action(state, config));}}

甚至普通节点都不需要异步,异步放到并行节点里去就ok了

public interface GraphNode {Map<String, Object> action(OverAllState state);default Map<String, Object> action(OverAllState state, RunnableConfig config) {return action(state);}}public interface ParallelNode extends GraphNode {default CompletableFuture<Map<String, Object>> asyncAction(OverAllState state) {return CompletableFuture.supplyAsync(() ->  action(state));}default CompletableFuture<Map<String, Object>> asyncAction(OverAllState state, RunnableConfig config) {return CompletableFuture.supplyAsync(() ->  action(state, config));}}

边其实也存在同样的问题,要封装为函数式的EdgeAction来操作

异步

在graph的代码中可以看到大量的CompletableFuture,但实际跟踪invoke代码执行会发现,这边刚提交了异步,转头就调用CompletableFuture的get方法阻塞在那了,完全失去了异步的作用,并没有与其他代码并行

可以说整个graph可能就只有ParallelNode那里有一点点并行

而且graph,也就是图,或者叫状态机,本身的机制就是一个节点执行完,才会进入下一个节点,本身就带有很强的顺序执行的特性,完全没必要搞一堆CompletableFuture,只需要在并行节点内部进行一点特殊处理就ok了

如果实在想异步处理节点,需要自行调用 CompiledGraph 的 stream 方法,然后实现一个异步处理器(可以参考spring-ai-alibaba-deepsearch 的 GraphProcess 类)

http://www.lryc.cn/news/609240.html

相关文章:

  • 无人机集群协同三维路径规划,采用冠豪猪优化器(Crested Porcupine Optimizer, CPO)实现,Matlab代码
  • 基于BiLSTM+CRF实现NER
  • JavaWeb学习------SpringCloud入门
  • 最小半径覆盖问题【C++解法+二分+扫描线】
  • 研报复现|史蒂夫·路佛价值选股法则
  • [硬件电路-138]:模拟电路 - 什么是正电源?什么是负电源?集成运放为什么有VCC+和VCC-
  • 【RH124 问答题】第 8 章 监控和管理 Linux 进程
  • MySQL学习之MVCC多版本并发控制
  • 浅谈Python中的os.environ:环境变量交互机制
  • [硬件电路-141]:模拟电路 - 源电路,信号源与电源,能自己产生确定性波形的电路。
  • IO流-数据流
  • LLM的训练:RLHF及其替代方案
  • 2025年6月电子学会青少年软件编程(C语言)等级考试试卷(七级)
  • 当Windows远程桌面出现“身份验证错误。要求的函数不受支持”的问题
  • 电机结构设计与特性曲线分析:基于MATLAB和FEMM的仿真研究
  • 【软考中级网络工程师】知识点之 IS-IS 协议
  • AI Agent 重塑产业发展新格局
  • SpringAI的使用
  • 图像张量中的通道维度
  • 【C 学习】04.1-数字化基础
  • Spring Boot 整合 Minio 实现高效文件存储解决方案(本地和线上)
  • Monaco Editor 开发流程详解
  • Flutter Dart类的使用
  • Redisson高并发实战:守护Netty IO线程的关键指南
  • 一加Ace5无法连接ColorOS助手解决(安卓设备ADB模式无法连接)
  • 【MySQL】MySQL 中的数据排序是怎么实现的?
  • FreeRTOS源码分析三:列表数据结构
  • 深度学习-读写模型网络文件
  • 03.一键编译安装Redis脚本
  • 07.config 命令实现动态修改配置和慢查询