LLM - 基于 Spring AI Alibaba Graph 重构多智能体订单助手:从单体 Agent 到图工作流的工程实践

LLM - 基于 Spring AI Alibaba Graph 重构多智能体订单助手:从单体 Agent 到图工作流的工程实践

文章目录

在这里插入图片描述

Pre

LLM - 从生成式到 Agentic (Java技术栈)

在这一版 Demo 中,多智能体订单助手的核心是在 Spring AI 上手动编排 Orchestrator + ProductAgent + OrderAgent + RefundAgent 的调用逻辑。
这一版,将用 Spring AI Alibaba Graph 把它重构成「图工作流 + 多智能体」形态,让复杂逻辑变成一张清晰的状态图,具备更好的可维护性与扩展性。


背景:为什么要上 Graph?

传统基于代码 if-else 的 Orchestrator 很快会遇到几个问题:路由逻辑越写越乱、Agent 越加越多、人工插入 Human-in-the-loop 很痛苦。
Spring AI Alibaba Graph 用 StateGraph + Node + Edge + OverAllState 四个核心概念,把复杂业务拆成多个清晰节点,通过有向图描述执行流程与多智能体协作。

  • StateGraph:整张「订单助手」流程图,描述有哪些节点、怎么跳转。
  • Node:一个节点就是一个「步骤」,例如意图识别、商品咨询 Agent、订单查询 Agent、退款 Agent 等。
  • Edge:节点间的连线,可以是固定跳转,也可以是根据上下文条件路由。
  • OverAllState:全局状态,贯穿整个流程,存放用户输入、上下文、中间结果等。

这样做的好处是:

  • 业务逻辑从 if-else 中抽离出来,以图结构可视化管理。
  • 支持多智能体协作、并行节点和条件边,后续要加新 Agent 只需加节点和边。
  • 原生支持 streaming、Human-in-the-loop、快照与恢复,适合企业级智能体系统。

项目结构:按真实工程拆分

示例采用 Maven 多模块结构,参考官方与社区最佳实践,将 AI 能力与业务工程解耦。

springai-order-assistant/ ├── ai-starter/ # 封装 Spring AI Alibaba&Graph 的通用配置 ├── ai-graph-order/ # 本文核心:订单助手 StateGraph+Nodes 实现 ├── ai-domain/ # 领域模型与仓储(Order、Product 等) ├── ai-web/ # REST Controller,对外的 HTTP API └── pom.xml # 父工程 
  • ai-starter:统一引入 Spring AI Alibaba 依赖、模型配置、日志与监控等。
  • ai-graph-order:只关心「订单助手这张图」,包含 StateGraph、节点实现与状态定义。
  • ai-domain:普通领域模块,负责订单、商品等数据访问,与 AI 解耦。
  • ai-web:Spring Boot Web 启动入口 + Controller,接收用户请求并触发图执行。

订单助手 Graph 设计:从多 Agent 视角出发

业务场景回顾

订单助手要解决三类需求:

  • 商品咨询:用户问「这款耳机支持降噪吗?」
  • 订单查询:用户说「查一下我上次买的耳机能不能退」
  • 退货退款:用户想执行「帮我退掉昨天那单」

对应之前的四个 Agent 角色:

  • OrchestratorAgent:理解意图并路由。
  • ProductAgent:商品问答 / 推荐。
  • OrderAgent:订单查询。
  • RefundAgent:退款判断与创建。

在 Graph 版本中,这四个角色将对应 4 个主要节点,外加 1 个入口节点与 1 个结束节点,构成一张简单而清晰的状态图。

Graph 拆分为节点

用 Spring AI Alibaba Graph 的术语,可以设计如下节点:

  • entry:入口节点,初始化全局状态(如 userId、原始输入)。
  • intent_router:意图识别节点,决定走 PRODUCT / ORDER / REFUND 分支。
  • product_agent:商品咨询 Agent 节点。
  • order_agent:订单查询 Agent 节点。
  • refund_agent:退款 Agent 节点。
  • end:结束节点,返回最终回复。

图上的边关系为:

  • entry → intent_router
  • intent_router → product_agent / order_agent / refund_agent / end(条件边)
  • product_agent / order_agent / refund_agent → end

在真实项目中,只要 OverAllState 设计合理,后面要加「人工校验节点」「日志审计节点」「风控节点」都可以通过新增 Node+Edge 实现。


实战:定义 OverAllState 与 Graph

定义 OverAllState

OverAllState 是整条工作流共享的状态,一般包括:

  • userId、sessionId
  • 用户原始输入与模型回复
  • 意图识别结果(route)
  • 各 Agent 的中间结果(订单列表、退款条件判断等)

示例代码(放在 ai-graph-order 模块):

@DatapublicclassOrderAssistantState{// 上下文字段privateString userId;privateString sessionId;// 本轮输入与最终输出privateString userInput;privateString finalReply;// 路由结果:PRODUCT / ORDER / REFUND / UNKNOWNprivateString route;// 中间结果:订单、退款判断等privateList<Order> orders;privateboolean refundable;}

在 Graph 执行过程中,所有节点对状态的修改都会写回 OverAllState,确保后续节点可以复用信息。

构建 StateGraph

使用 Spring AI Alibaba Graph 的 StateGraph 定义节点和边。

@ConfigurationpublicclassOrderAssistantGraphConfig{@BeanpublicStateGraph<OrderAssistantState>orderAssistantGraph(EntryNode entryNode,IntentRouterNode intentRouterNode,ProductAgentNode productAgentNode,OrderAgentNode orderAgentNode,RefundAgentNode refundAgentNode,OrderAssistantStateSerializer stateSerializer){StateGraph<OrderAssistantState> graph =newStateGraph<>("order-assistant", stateSerializer);// 1. 注册节点 graph.addNode("entry",node(entryNode)); graph.addNode("intent_router",node_async(intentRouterNode)); graph.addNode("product_agent",node_async(productAgentNode)); graph.addNode("order_agent",node_async(orderAgentNode)); graph.addNode("refund_agent",node_async(refundAgentNode));// 2. 设置起始节点 graph.setStart("entry");// 3. 固定边:entry -> intent_router graph.addEdge("entry","intent_router");// 4. 条件边:intent_router -> 具体 Agent 或结束 graph.addConditionalEdges("intent_router",edge_async(newIntentRouteDispatcher()),Map.of("PRODUCT","product_agent","ORDER","order_agent","REFUND","refund_agent","END",StateGraph.END // 直接结束));// 5. 各 Agent 节点到结束节点 graph.addEdge("product_agent",StateGraph.END); graph.addEdge("order_agent",StateGraph.END); graph.addEdge("refund_agent",StateGraph.END);return graph;}}

这里使用了同步 node 与异步 node_async,对于需要调用外部服务或 LLM 的 Agent 节点,推荐异步以提高吞吐。


节点实现:把 Agent 融入 Graph

1. 入口节点 EntryNode

负责从 HTTP 请求参数构建初始状态。

@ComponentpublicclassEntryNodeimplementsNode<OrderAssistantState>{@OverridepublicOrderAssistantStateapply(OrderAssistantState state){// 一般通过外层传入已有 state,这里可以做一些初始化// 例如:写入时间戳、初始化列表等return state;}}

实际项目里通常由外层 Controller 构造好 state,再交给 Graph 执行,EntryNode 可以留空或作为「预处理」节点。

2. 意图路由节点 IntentRouterNode

对应之前 Orchestrator 里那段「只返回 PRODUCT / ORDER / REFUND」的逻辑,这里做成一个独立 Node。

@ComponentpublicclassIntentRouterNodeimplementsNode<OrderAssistantState>{privatefinalChatModel chatModel;publicIntentRouterNode(ChatModel chatModel){this.chatModel = chatModel;}@OverridepublicOrderAssistantStateapply(OrderAssistantState state){String instruction =""" 你是一个意图识别Agent。根据用户输入, 只返回以下四种之一:PRODUCT / ORDER / REFUND / END。 - PRODUCT:商品咨询或推荐 - ORDER:订单查询 - REFUND:退货或退款 - END:闲聊、问候等非业务问题 用户输入:%s """.formatted(state.getUserInput());ChatResponse resp = chatModel.call(newPrompt(instruction));String route = resp.getResult().getOutput().getContent().trim(); state.setRoute(route);return state;}}

Graph 执行到这里后,不直接决定下一个节点,而是交给条件边上的 IntentRouteDispatcher 来根据 route 决定跳转目标。

3. 条件边分发器 IntentRouteDispatcher

publicclassIntentRouteDispatcherimplementsEdgeDispatcher<OrderAssistantState>{@OverridepublicStringdispatch(OrderAssistantState state){String route =Optional.ofNullable(state.getRoute()).orElse("END");returnswitch(route){case"PRODUCT"->"PRODUCT";case"ORDER"->"ORDER";case"REFUND"->"REFUND";default->"END";};}}

配合前面的 addConditionalEdges 使用,使得 intent_router 节点可以被复用于更多复杂路由,而不是在节点内部写死 if-else。

4. 商品 Agent 节点 ProductAgentNode

这里直接复用前文 ProductAgent 的核心逻辑,把它包装成一个 Node,注意从 state 中拿 userInput,并把结果写回 state.finalReply。

@ComponentpublicclassProductAgentNodeimplementsNode<OrderAssistantState>{privatefinalChatClient productChatClient;publicProductAgentNode(ChatModel chatModel,ChatMemory chatMemory,ProductTools productTools){this.productChatClient =ChatClient.builder(chatModel).defaultSystem("你是专业的商品顾问,擅长基于商品知识库回答用户问题。").defaultTools(ToolSpecifications.from(productTools)).defaultAdvisors(newMessageChatMemoryAdvisor(ChatMemoryAdvisorSpec.builder().withChatMemory(chatMemory).withConversationIdProvider( s -> s.getSessionId()).build())).build();}@OverridepublicOrderAssistantStateapply(OrderAssistantState state){String reply = productChatClient.prompt().user(state.getUserInput()).call().content(); state.setFinalReply(reply);return state;}}

同理,实现 OrderAgentNodeRefundAgentNode 时,只需要替换工具集与 System Prompt,同时可在 state 中填充订单列表与退款判断结果以供后续节点使用。


对外暴露:Controller 触发 Graph 执行

Graph 本身只是一个可以被调用的「状态机」,需要一个入口来接收 HTTP 请求、构造初始状态并执行 Graph。

ai-web 模块中定义 Controller:

@RestController@RequestMapping("/api/order-assistant")publicclassOrderAssistantController{privatefinalStateGraphExecutor<OrderAssistantState> executor;publicOrderAssistantController(@Qualifier("orderAssistantGraph")StateGraph<OrderAssistantState> graph,OrderAssistantStateSerializer serializer){this.executor =newStateGraphExecutor<>(graph, serializer);}@PostMapping("/chat")publicResponseEntity<ChatResponseDto>chat(@RequestBodyChatRequestDto request){OrderAssistantState initState =newOrderAssistantState(); initState.setUserId(request.userId()); initState.setSessionId(request.sessionId()); initState.setUserInput(request.message());OrderAssistantState endState = executor.execute(initState);returnResponseEntity.ok(newChatResponseDto(endState.getFinalReply()));}}
  • StateGraphExecutor 封装了 Graph 的执行流程与状态序列化 / 反序列化。
  • 每次调用都会从入口节点开始,根据节点逻辑与条件边推进,直到 END。
  • 最终通过 finalReply 字段返回字符串响应,前端可以直接展示。

工程落地经验:从 Demo 到生产

1. 按模块拆分职责

  • Graph 与节点只负责「流程与智能体」,不直接依赖 Web、数据库细节。
  • 领域模块(ai-domain)负责订单、商品、用户等实体与仓储。
  • ai-starter 中统一管理模型、工具与监控配置,避免在每个业务模块重复引入依赖。

这种分层有利于:

  • 后续增加新的 Graph(如客服助手、营销 Agent)时复用 Starter 与领域模块。
  • 把 Graph 部分抽象成「AI 能力中台」,供多个业务线共享。

2. Graph 与多智能体的演进路径

  • 第一阶段:像本文这样,将之前单工程 Orchestrator 重构为 Graph,保持 Agent 逻辑基本不变。
  • 第二阶段:引入并行节点(ParallelNode),例如同时查询多个业务系统或同时跑多个推荐策略。
  • 第三阶段:加 Human-in-the-loop 节点,让关键步骤(如退款审批)必须经过人工确认后再继续。
  • 第四阶段:配合 Spring AI Alibaba Admin 或自研控制台,对 Graph 的配置、版本与监控进行可视化管理。

3. 与治理 / 观测体系集成

  • 在 Graph 层统一注入 TraceId / SpanId,利用阿里云或自建链路追踪体系做全链路观测。
  • 为每个节点打点:包括 LLM 调用次数、平均成本、错误率,支持按节点与按 Graph 分析瓶颈。
  • 对敏感节点(如 RefundAgentNode)增加审计日志与强制 HITL,避免业务风险。

小结

通过 Spring AI Alibaba Graph,将原本在 Spring AI 中手写 Orchestrator 的多 Agent 订单助手,重构为「状态图 + 节点 + 条件边」的架构,使智能体编排和业务工作流融为一体。
对于已经在 Java / Spring 生态中的团队,这种方式可以在保持熟悉技术栈的前提下,快速获得多智能体、工作流编排、Human-in-the-loop、可观测与治理等一整套能力,为 2025 年之后更大规模的智能体落地打好工程基础。

扩展阅读

一、Spring AI Alibaba Graph(核心概念 & 官方实现)

这一组是Graph / Agent 编排的中枢知识源


二、Spring AI 多 Agent / 编排(Orchestrator & Workflow)

这组回答的是:Agent 如何分工?如何调度?如何协作?


三、Spring AI Alibaba 最佳实践 & 教程

工程落地 + 实战经验,非常适合你这种偏架构视角的人:


四、Graph / Agent 原理解析 & 深度解读(中文社区)

适合写**“为什么要 Graph?”、“和传统流程引擎有什么本质区别?”**这种文章:


五、阿里云 / 企业级案例 & 生态视角

企业实践、平台化思路


在这里插入图片描述

Read more

【直接可用源码免费送】计算机毕业设计精选项目:50969+ssm方方二手房公司管理系统:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制

【直接可用源码免费送】计算机毕业设计精选项目:50969+ssm方方二手房公司管理系统:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制

ssm方方二手房公司管理系统 摘 要 随着我国经济的不断增长,人们对所居住的环境也有很大的要求,使得我们现在的房地产一直保持着繁荣的局面。近几年,不仅新楼盘销售旺盛,二手房市场也不断升温。 二手房公司管理系统主要功能模块包括首页、公共管理(轮播图、留言板)通知公告(通知公告)资源管理(房源委托、资讯分类)系统用户(管理员、买家用户、卖家用户、经纪人用户)模块管理(房源分类、房屋户型、地区管理、房源委托、房源信息、预约看房、交易订单、购房合同、客户信息、数据统计)采取面对对象的开发模式进行软件的开发和硬体的架设,能很好的满足实际使用的需求,完善了对应的软体架设以及程序编码的工作,采取MySQL作为后台数据的主要存储单元,采用ssm框架、Java技术进行业务系统的编码及其开发,实现了本系统的全部功能。本次报告,首先分析了研究的背景、作用、意义,为研究工作的合理性打下了基础。针对二手房公司管理系统的各项需求以及技术问题进行分析,证明了系统的必要性和技术可行性,然后对设计系统需要使用的技术软件以及设计思想做了基本的介绍,最后来实现二手房公司管理系统和部署运行使用它。

By Ne0inhk
Python(32)Python内置函数全解析:30个核心函数的语法、案例与最佳实践

Python(32)Python内置函数全解析:30个核心函数的语法、案例与最佳实践

目录 * 引言 * 基础数据类型操作 * 1. len() * 2. range() * 3. enumerate() * 4. zip() * 5. sorted() * 函数式编程工具 * 6. map() * 7. filter() * 8. reduce() * 9. any() * 10. all() * 输入输出与文件操作 * 11. open() * 12. print() * 13. input() * 14. exec() * 15. eval() * 元编程与高级功能 * 16. dir() * 17. help() * 18. type() * 19. isinstance() * 20. hasattr() * 21. getattr() * 22. setattr(

By Ne0inhk