Spring AI实战:Java生态的大模型集成与Agent编排

发布时间:2026/9/15 8:11:09
Spring AI实战:Java生态的大模型集成与Agent编排 说句实话Spring AI这名字刚在Java圈传开的时候我是带着怀疑的。毕竟大模型接入这事从2023年开始就已经被Python生态的LangChain、LlamaIndex占据了话语权Java社区除了零星几个SDK封装一直没拿出一个能打的框架。后来我实际在项目里试了一轮态度从这又是一个套壳封装变成了这才是Spring生态该有的东西。如果你是个Java开发者想把大模型能力接进现有系统或者打算从零做一个带AI功能的Spring Boot应用这篇文章就是给你写的。Spring AI能做的事一句话概括是把和大模型打交道这件事变成Spring风格的声明式开发。对话补全、提示词管理、结构化输出、向量检索、工具调用、多Agent编排这些原本要自己拼SDK、拼HTTP请求、拼Prompt的活它都做成了starter和接口。比如接OpenAI、通义千问、智谱GLM这类模型切换时只需要改配置业务代码不需要重写。这跟当年Spring JDBC把各种数据库方言统一成一个DataSource模式的思路一脉相承。更关键的是Spring AI不是孤军奋战。它背后有两条线同时在推进官方主线的1.x到2.0版本以及阿里主导的Spring AI Alibaba分支。前者在解决怎么把Agent工作流、MCP协议、Skill技能这些东西标准化后者在解决怎么在企业里可视化地编排和管理这些Agent。这篇文章我会从最基础的工程搭建开始把模型接入、2.0新特性、MCP工具调用、Alibaba的Docker部署一直聊到最终选型全程按我实际踩过的坑来写。1. Spring AI到底解决了Java开发者什么问题1.1 大模型接入的碎片化现状在没有Spring AI之前Java项目接大模型基本是三种状态。第一种直接用HTTP客户端手写调用各家模型的OpenAI兼容接口自己拼JSON请求体、自己处理SSE流式响应、自己解析Token用量。第二种找第三方的Java SDK比如OpenAI官方Java SDK、智谱的Java SDK、阿里的DashScope Java SDK但每家SDK的API风格都不一样模型一换调用层代码基本得重写。第三种把Python的LangChain单独部署成一个中间服务Java这边只负责转发请求等于凭空多维护了一套跨语言链路。这三种状态有一个共同的痛点大模型的能力始终游离在业务系统之外没法像数据库、消息队列、缓存那样成为Spring容器里的一个一等公民。你要做RAG得自己管向量库连接要做提示词版本管理得自己设计模板方案要做Agent工具调用得自己解析模型返回的function_call参数。这些工作不是说做不了是每个团队都在重复造同一批轮子。1.2 Spring AI的答案把LLM变成Spring组件Spring AI做的事就是把上面那堆重复劳动抽象成一套统一接口。核心是几个概念ChatModel负责和大模型通信ChatClient提供链式调用的编程模型Prompt与Message统一了提示词结构Advisor可以在调用链上做修饰和拦截VectorStore抽象了向量数据库Tool定义了模型可调用的工具Agent与Graph用于构建复杂流程。这套设计最大的价值是让换模型变成一个配置问题。项目里定义一个ChatModel Bean底层用的是OpenAI还是DashScope还是Ollama完全由配置文件里的spring.ai.model.chat相关属性决定。业务代码只依赖ChatClient这个门面哪怕今天用GPT、明天换GLM、后天切回通义千问逻辑代码一行都不用动。这一点在企业级项目里尤其重要因为模型厂商的定价、能力、合规要求随时在变绑定一家就等于绑死。1.3 和LangChain、厂商SDK的定位差异很多人问既然已经有LangChain了为什么还要Spring AI我的理解是两者解决的问题域重叠但服务的人群完全不同。LangChain从诞生起就是Python生态的工具链它的Expression Language、Chain、Memory设计跟Python的函数式、异步模型深度绑定。Java团队引入LangChain要么用Python重写一个服务要么用LangChain4j这种移植版但移植版跟官方主线的进度、文档、社区资源都存在gap。厂商SDK的问题更直接它只解决怎么调用这个模型的问题不解决怎么把AI能力工程化的问题。你要做上下文记忆、做多轮对话管理、做工具调用、做模型切换厂商SDK全都甩给你自己实现。Spring AI站在了中间层既不像LangChain那样自成一套生态也不像厂商SDK那样只做API封装它选择的是把AI能力塞进Spring这套成熟的工程体系里让你用已经熟悉的IoC、AOP、Starter习惯去写AI代码。2. 从零搭建第一个Spring AI应用依赖、配置与首次对话2.1 工程脚手架与依赖引入版本先行新建Spring Boot项目的时候第一个坑就是版本。Spring AI的版本跟Spring Boot版本强绑定1.0.x系列要求Spring Boot 3.4及以上2.0版本则需要Spring Boot 3.5或更高。我见过太多人直接在Spring Initializr里选了个最新稳定版Spring Boot然后引入spring-ai-starter一启动就报NoSuchBeanDefinitionException或者ClassNotFoundException最后发现是版本矩阵对不上。稳妥的做法是到Spring Initializr官网生成项目时在Spring AI依赖一栏直接勾选它会自动帮你匹配兼容版本。如果你用Maven手动引入依赖结构大致是这样parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.5.3/version /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI基础的ChatClient支持 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-chat-client/artifactId /dependency !-- 具体模型实现这里用OpenAI兼容接口配置里指向智谱或通义 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-model-openai/artifactId /dependency /dependencies dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version2.0.0/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement注意我这里的模型依赖用了spring-ai-starter-model-openai但实际对接的却是智谱GLM这样做是有原因的国内绝大多数模型厂商都提供了OpenAI兼容的HTTP接口直接用OpenAI的starter把base-url一改就能省去引入一堆专用SDK的麻烦。2.2 模型配置与对接GLM这类OpenAI兼容接口配置层面Spring AI 1.x和2.0的配置项有过一次大的调整。1.x时代用spring.ai.openai.api-key、spring.ai.openai.base-url这样的前缀2.0开始统一收敛成spring.ai.model.chat这类结构。以对接智谱GLM为例我在application.yml里的配置是这样的spring: ai: model: chat: openai: api-key: ${ZHIPU_API_KEY} base-url: https://open.bigmodel.cn/api/paas/v4 options: model: glm-4-plus temperature: 0.7 max-tokens: 2048这里的一个关键点是base-url必须填到/v4这个层级不要带后面的/chat/completions。因为Spring AI在内部拼接请求路径时会自动加上/chat/completions你填多了反而拼出错误URL。我在早期接入时在这里吃过一次亏接口报404排查了很久才发现是base-url多写了一层。如果接的是通义千问直接用spring-ai-starter-model-dashscopespring: ai: model: chat: dashscope: api-key: ${DASHSCOPE_API_KEY} options: model: qwen-plus这种切换方式业务代码完全不需要感知。你只需要在配置里换starter依赖、改几行配置其余代码该怎么样还怎么样。这也是Spring AI最打动我的一点模型厂商可以随时替换架构层面永远保留选择权。2.3 用ChatClient完成第一次对话依赖和配置都就绪后第一次对话的代码比我预期中简单得多。Spring AI 2.0里ChatClient已经被做成了单独的starter用构建器方式注入然后在Service里直接调用Service public class ChatService { private final ChatClient chatClient; public ChatService(ChatClient.Builder builder) { this.chatClient builder.build(); } public String ask(String question) { return chatClient.prompt() .user(question) .call() .content(); } }如果要做流式输出把call()换成stream()public FluxString askStream(String question) { return chatClient.prompt() .user(question) .stream() .content(); }这两段代码跑通之后一个最基础的大模型对话接口就完成了。不要小看这个起点后面要做的系统提示词、多轮记忆、工具调用、Agent编排全都是在ChatClient这条链路上叠加能力。提示2.0里ChatClient不再从Spring Boot自动配置里直接拿到一个Bean而是通过注入ChatClient.Builder来构建。这个设计让每个调用方可以持有自定义超时、自定义顾问链的独立客户端不会互相污染。3. Spring AI 2.0真正的变化Graph、Multi-Agent与Skill3.1 从单轮对话到流程编排的演进逻辑Spring AI 2.0出来之前大部分人用它就是做请求-响应式的对话调用复杂点的加个向量库做RAG。但2.0版本的定位明显往上走了一层它不再满足于当一个模型调用器而是想成为Java领域构建Agent应用的底座。这一点从它发布的几个核心特性就能看出来Graph、Multi-Agent、Skill。我的理解是Spring AI团队看到了一个趋势真实业务里的AI应用很少是用户问一句、AI回一句就结束的。更多时候是AI接到一个任务后需要自主判断、拆解步骤、调用多个工具、查多个数据源然后汇总结果。这个过程就是Agent而Agent的本质是流程编排。视图对象图上跑状态机这个模式恰好是工程上治理复杂流程最成熟的手段。3.2 Agent编排用Graph把工作流状态管理起来Spring AI 2.0的Graph能力简单说就是把Agent的执行流程定义成一张有向图每个节点是一个处理步骤节点之间通过边传递状态。这跟工作流引擎的思路很像只不过节点里跑的不只是正常的代码逻辑还可能是让大模型做一次决策。我在项目里用Graph做过一个项目周报自动生成器。流程节点依次是收集代码仓库提交记录、调用大模型分析提交内容并总结重点、去需求管理系统拉取本周完成事项、让大模型把两份内容合并成结构化周报。传统写法是if-else顺序调用每加一个环节就要改主流程换成Graph之后每个节点变成独立单元我在关键节点之间还能插入是否需要补充测试数据这类条件判断边。Graph带来的另一个好处是状态可观测。每个节点执行前后的上下文、Token消耗、耗时都能挂载Advisor做监控。这对生产环境排查问题有决定性帮助——大模型调用的不确定性本来就高如果连执行链路都看不见出了问题只能靠猜。3.3 Multi-Agent协作让两个AI角色相互配合Multi-Agent是2.0另一个让我觉得这才是AI应用该有的形态的功能。它解决的问题是单个模型中系统提示词对抗的极限。你想让一个Agent既做代码分析又做代码风格审查往往顾此失彼提示词稍微重点它就变成复读机轻了又守不住人设。拆成两个专职Agent之后每个Agent只负责一件事职责边界极其清晰。我搭过的一个实际场景是代码评审双Agent评审Agent负责检查逻辑缺陷、注入风险、事务处理问题代码风格Agent只盯命名规范、圈复杂度、注释覆盖率。两个Agent共享同一份代码上下文但各自有独立的系统提示词和温度参数。评审Agent查出来的问题会作为另一个Agent的输入让它给出具体的修改建议。最终结果合并成一份评审报告按严重级别排序返回给开发者。这套机制跑起来的工程含义是每个Agent可以独立测试、独立优化提示词互不干扰。后续想加一个安全漏洞专查Agent不需要动已有流程在编排层多加一个节点和一条边就行。这对团队协作也很友好不同人负责不同Agent边界天然清晰。3.4 Skill给Agent装上可复用的业务技能Skill是Spring AI 2.0里我觉得最接地气的一个抽象。它的意思是把某一类特定问题的解决能力封装成一个可插拔的模块Agent运行时会判断当前任务是否匹配某个Skill匹配就加载它。我最常用的是DocumentSkill它把加载文档、拆分、向量化、检索、拼接上下文整个RAG流程封装好Agent再回答问题时如果发现需要查知识库会自动调用。我试着用这个能力做了一个产品FAQ自动应答系统。训练阶段只需要把产品手册扔给它运行阶段用户问导出功能支持哪些格式Agent会先在文档切片里做向量检索找到相关片段再结合片段生成答案。整个过程没有硬编码任何文档标题全靠Agent自己判断该不该触发文档查询。现在社区里已经有人在整理各种开箱即用的Skill包比如SQL生成、Excel数据分析、日志诊断。这个方向很像当年Spring生态里的各种Starter——把特定场景的重复劳动沉淀成依赖引入即用。我现在新项目的第一步就是先看有没有现成Skill能省掉一半开发量。4. MCP与Function Calling让AI从会说话到能办事4.1 MCP协议对Java生态的价值聊完2.0的新特性必须要说MCP这个词在spring ai mcp热搜里的热度非常高。MCP全称Model Context Protocol翻译成人话就是给AI模型统一一套调用外部工具和访问数据源的标准协议。以前每个模型厂商都有自己的函数调用格式OpenAI的function_call、Anthropic的tool_use互不兼容。MCP试图做那个通用插座一次接入到处复用。对Java生态来说MCP的意义比Python那边更大。因为Java应用往往长在企业内网环境里周围全是数据库、消息队列、内部的API系统、权限中心。要让AI触达这些资源标准化的工具接入协议是不可少的。Spring AI 2.0把MCP客户端做成了starter我在Spring Boot应用里接入一个MCP服务整个过程不超过半小时。4.2 在Spring AI里挂载一个MCP客户端MCP服务器有两种常见暴露方式stdio本地进程以及HTTP SSE跨机器调用。在企业环境里跨机器才是常态。我实际使用的场景是把一个内部订单查询服务封装成MCP服务器用Docker部署在服务器上暴露SSE端点然后Spring AI应用通过配置直接连上去。依赖层面引入dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-client/artifactId /dependency配置文件里声明MCP服务器的连接方式spring: ai: mcp: client: connections: order-center: type: sse url: http://192.168.1.100:8081/sseSpring AI启动时会自动连上这台MCP服务器把里面声明的工具拉取注册到模型工具列表里。用户在对话里问订单S1002现在是什么状态模型判断需要工具调用就通过MCP协议调用订单查询工具拿到结果再组织语言返回。整个过程中的工具发现、参数校验、结果回传都是框架自动完成的。4.3 工具调用与Function Calling实战在Spring AI里定义可以让模型调用的工具最直白的做法是Tool注解。我要给AI加一个查询今天会议室空闲情况的能力代码是这样的Component public class MeetingRoomTools { Tool(description 查询会议室在指定时间段的空闲状态) public String checkRoomAvailability(String roomName, String startTime) { // 实际逻辑查询会议室预订表返回空闲或占用 return bookingService.check(roomName, startTime); } }前提是把该组件注册到ChatClient构建过程里。ChatClient client ChatClient.builder(chatModel) .defaultTools(new MeetingRoomTools()) .build();之后模型在对话中发现用户意图是查会议室就会自动把这个工具的参数填好、发起调用最终返回结果。这里面最花时间的不是写方法而是把description写清楚。模型不会自己猜工具用途它完全依赖描述来判断触发时机。我调过的工具里凡是描述写得含糊的模型基本都不触发或乱触发。经验工具的描述要带上触发条件、参数含义、返回值格式甚至可以给一个典型问法示例。比如当用户询问会议室是否可用时调用参数roomName是会议室名称startTime格式为yyyy-MM-dd HH:mm。描述越具体模型的调用准确率越高。5. Spring AI Alibaba与Admin控制台Docker部署实录5.1 为什么Spring生态会出现阿里系适配Spring AI Alibaba这个项目说白了就是阿里云在Spring AI主干之上做的企业级增强。它一方面把阿里云百炼平台上的通义千问系列模型接入Spring AI另一方面深度定制了一套可视化的开发、调试、运维工具链。为什么值得关注因为企业落地AI应用时卡点往往不在模型能力上而在于开发态生产态割裂。在纯Spring AI里开发时你要看日志、调参数、测工具全部通过控制台输出和配置文件来回折腾。Spring AI Alibaba的Admin控制台把这些做了可视化可以在界面上编排Agent工作流、管理技能、监控调用链路、调整模型参数。这东西等于把Spring AI从代码工具的体验拉到了平台产品的体验。5.2 Docker跑通Spring AI Alibaba Admin我按照社区实践用Docker部署阿里那边的Admin控制台。先把镜像拉下来。docker pull springaialibaba/spring-ai-alibaba-admin:latest启动前需要准备好数据库连接串以及阿里云DashScope的API密钥。Admin服务会把Agent定义、Skill配置、运行时数据都持久化到数据库所以这一步不能省略。docker run -d --name spring-ai-alibaba-admin \ -p 8080:8080 \ -e SPRING_DATASOURCE_URLjdbc:mysql://localhost:3306/spring_ai_admin?useUnicodetruecharacterEncodingutf8 \ -e SPRING_DATASOURCE_USERNAMEroot \ -e SPRING_DATASOURCE_PASSWORDyourpassword \ -e AI_DASHSCOPE_API_KEYsk-xxxxxxxx \ springaialibaba/spring-ai-alibaba-admin:latest启动完成后浏览器访问http://localhost:8080进入控制台。首次进入时系统会引导我配置模型供应商、创建Agent应用、选择基础模型比如qwen-plus、qwen-max这类通义千问的商业版模型。这一步的体验很像在给一个低代码平台做配置但对开发者来说它降低了上手门槛。如果你是团队里负责搭AI基座的人可以考虑用另外一台服务器单独部署Admin然后让业务服务通过API方式调用它编排好的Agent这样开发态和生产态能彻底分离。5.3 用DashScope模型跑通第一个可视化Agent在Admin控制台上创建Agent应用时我的操作路径是先新建应用选择通义千问qwen-plus模型然后在技能一栏挂一个RAG技能再上传产品文档建立向量索引。整个配置过程不需要写一行代码所有动作都是界面点选。配置完成后控制台提供了个在线调试窗口我输入根据文档说明导出功能支持哪几种格式只见调试窗口显示Agent先触发文档检索技能从索引里召回相关片段再把这些片段拼进提示词最后生成答案返回。这个执行链路会被详细记录每一步的输入输出、Token消耗、耗时都看得见。这一步对团队的意义是非研发人员比如产品和运营也能参与到Agent行为调优中来直接在控制台里测试不同提示词、调整文档内容看看效果。而研发人员只需要维护底层的Spring AI应用和MCP工具两者分工很自然。6. 生成Spring Boot项目时到底该选哪个AI方案6.1 选择AI框架本质是在选择什么生成Spring Boot时选择哪个AI框架这个热搜我猜很多人其实是问我该不该用Spring AI。我的回答是你选择的不是某个SDK好不好用而是在选择这个团队后续怎么维护AI应用这条线。这是个长期决策。我的判断维度有三个。第一是团队技术栈如果团队全是JavaSpring AI带来的集成收益远超一切。第二是模型锁定程度如果老板哪天说换一个更便宜的模型Spring AI这种靠配置切换模型的能力能帮你省下大几周的改造工作量。第三是对Agent复杂度的预期如果业务只是做一个智能客服问答Spring AI的ChatClient加点RAG就够如果要做多Agent流程编排和工具调度那就需要2.0的Graph、Skill和MCP这套组合拳。6.2 四类方案对比与适用场景判断为了更直观地说明选型思路我把目前Java届的几个主流路线放在一起做了个对比方案适用场景优点代价直接调用厂商SDK一次性演示、短平快脚本上手最快无中间层换模型要重写代码无工程化能力Spring AI需要长期维护的Java企业应用模型抽象好、Spring生态集成、Go功能齐全版本迭代快学习曲线陡LangChain4j已有LangChain思维、Java项目API风格贴近LangChain社区小于官方主线组件化程度不如Spring AI自研HTTP封装需求极其固定接口就一两个可控性最高后续加功能全都自己承担我个人的倾向很明确除了纯演示性质的项目其余都优先考虑Spring AI。因为大模型领域的演进速度太快今年流行的架构明年可能就过时一个能快速跟上变化的框架比一个当下最精简的实现值钱得多。6.3 部署与稳定性层面的几个真实坑最后聊几个我实际部署Spring AI应用时踩过的坑这可能是全文最值钱的部分。第一OpenAI兼容接口的base_url不能配「带接口路径」的完整地址只能配到根路径层级。比如https://open.bigmodel.cn/api/paas/v4是OK的再往后多写一截就会404。这个规则在新手期能拦住一大半人。第二流式响应一定要设置读超时。大模型生成长文时SSE连接保持打开但可能几秒钟才推一个chunk默认HTTP客户端超时设置很容易误杀连接。我用的做法是把spring.ai.model.chat.openai.options和HTTP客户端的connect-timeout、read-timeout分开配置连接超时短一点读超时长一点避免长回答被中途断开。第三生产环境一定要把Token用量监控起来。模型调用本身有成本每个Agent节点还会产生额外的Prompt拼接Token。如果某个环节的上下文策略写得不好Token消耗会呈指数级增长。我在项目里把每次调用的usage数据接入日志配合Prometheus做成指标设置告警阈值不然月底账单会让人措手不及。第四2.0版本的自动配置变化比较大。升级时要重点看spring-ai-bom版本是否与Spring Boot匹配以及老的ChatModel自动配置是否被新结构替代。我的经验是升级依赖之后先跑一遍启动日志不要只看编译是否通过很多AI相关的Bean在启动阶段才会暴露问题。根据我实际用下来的体会Spring AI虽然还没有LangChain在Python生态里那种统治力但它已经在走一条更贴合Java工程基因的路。它不搞花哨的语法糖而是把模型接入、工具调用、Agent编排这些能力一点一点沉淀成Spring风格的组件。如果你团队本来就是Spring技术栈2025年这个时间点非常适合切入。不需要等生态完全成熟再上车先跑通一个最小对话应用再逐步叠加Graph、Skill和MCP这个过程本身就是对AI应用架构理解的最快提升方式。