十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring AI Alibaba实战:从零搭建大模型应用与Admin部署

Spring AI Alibaba实战:从零搭建大模型应用与Admin部署 Spring AI Alibaba 这个项目我第一次接触是在 2024 年年底当时手头要做一个企业内部知识库问答系统Java 技术栈又想快速接大模型一个月里试过轻量调用 HTTP 接口、自己封装 SSE 流式响应后来发现重复代码太多对话历史、工具调用、向量检索这些能力散落在各个 service 里根本没法维护。后来换了 Spring AI Alibaba链路瞬间清爽很多接入通义千问只需要一个 starter对话、函数调用、RAG 都有现成的扩展点再配合它自带的 Admin 控制台连模型的调用情况都能可视化查看。这篇教程我不打算做概念复读机而是直接带你从头搭一个能跑的项目把 Spring AI Alibaba 的核心模块、配置方式、Docker 部署 Admin 的完整流程捋一遍适合刚接触 Spring AI 的 Java 开发者也适合想知道这东西到底能省多少事的后端老手。1. Spring AI Alibaba 到底是什么先搞清楚它在整个大模型开发里的位置1.1 从 Spring AI 说起Spring 官方在 2025 年发布了 Spring AI 的稳定版本它的设计思路和 Spring 生态里的 JDBC 抽象如出一辙。Java 开发者在 JDBC 出现之前操作不同数据库要写不同厂商的驱动代码有了 JDBC 之后只需要切换驱动和方言配置业务代码里的 SQL 接口是统一的。Spring AI 做的就是类似的事情把 OpenAI、Anthropic、通义千问、Ollama 这些不同来源的大模型 API 抽象成统一的 ChatClient、EmbeddingModel、VectorStore 等接口。你写业务代码的时候不需要关心底层是这个模型还是那个模型调chatClient.prompt().user(你好).call()就能得到一个回复。如果你项目里之前已经接了一些模型依赖的术语也能对应上ChatModel对应对话补全EmbeddingModel对应文本向量化ImageModel对应文生图VectorStore对应向量数据库操作。这套抽象的最大价值在于模型厂商的 API 在快速迭代如果哪天你要把通义千问换成其他模型只需要改配置和依赖业务代码几乎不动。1.2 阿里云在 Spring AI 之上补了什么Spring AI 官方只做抽象框架具体的模型适配是各大厂商各自维护。阿里云开源的 Spring AI Alibaba 项目正是为了补齐 Spring AI 在阿里云百炼平台和通义千问上的适配同时也把国内企业用大模型时更关心的几个场景加进去了。从官方的模块划分来看它主要包含几个能力基于 Spring AI 的 ChatClient、Tool Calling、RAG 等自动化装配接入通义千问、通义万相、Embedding 等模型。可观测性管理提供一个 Admin 控制台用来管理模型配置、查看调用统计、调试 Prompt。企业级扩展比如 Multi-Agent 编排、工作流定义、以及适配阿里云百炼平台的一些高级能力。提供了spring-ai-alibaba-starter这样的快速启动依赖让 Spring Boot 项目不用写一堆Bean配置就能直接用。你可能会问直接只用 Spring AI 通义千问的官方 SDK 行不行行但你会很累。比如通义千问的流式输出用的是 SSE你需要自己处理text/event-stream格式对话历史要自己管理上下文 token 数量故障重试也是自己写。Spring AI Alibaba 把这些都藏起来了暴露给你的就是尽量符合 Spring 习惯的 API。前面说到的 Admin 控制台也是官方 Spring AI 没有的模块这是阿里云这边额外做的在模型落地运维的时候非常有用。2. 从零搭建5分钟跑通第一个对话请求2.1 环境准备先用最直接的路径把第一个对话请求跑起来。我用的开发环境是JDK 17Spring AI 官方的 baseline 要求就是 17不管你是 17 还是 21 都行Maven 3.9Spring Boot 3.3.x注意和 Spring AI 的版本匹配后面会讲坑一个阿里云百炼平台的 API Key如果还没有阿里云百炼的 API Key先去阿里云百炼控制台开通 DashScope 服务模型那边申请对应的通义千问版本。需要提醒一下不同时期百炼平台提供的模型名称会变比如你看到qwen-plus、qwen-turbo、qwen-max等等教程里推荐的当前可用的名称也会有差异。最稳妥的方式是去控制台模型广场看看或者在代码里配置成比较稳定的qwen-plus。API Key 申请之后先保存好别像某些同事一样把它写死在代码里提交到 Git。创建一个空的 Spring Boot 项目基础pom.xml先声明 parent版本我直接用 3.3.5parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.3.5/version relativePath/ /parent2.2 引入依赖和配置Spring AI Alibaba 的依赖不需要单独指定一堆 jar只需要集成官方的 BOM 和自己的 starter。在pom.xml里加上properties java.version17/java.version spring-ai.version1.0.0/spring-ai.version /properties dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-starter/artifactId version1.0.0/version /dependency /dependencies需要注意的是spring-ai-bom和spring-ai-alibaba-starter的版本要匹配。我当时第一次搭的时候一个用了 Spring AI 的 0.8.1 snapshot一个用了 Alibaba 的 1.0.0-M 开头版本结果启动时直接报ChatModel找不到 Bean。现在官方发布了稳定版本建议所有版本都优先选 Release 版。最新版本号可以去 Maven Central 搜spring-ai-alibaba-starter。在application.yml中配置模型信息spring: ai: dashscope: api-key: ${DASHSCOPE_API_KEY} # 如果不配置默认可能是 qwen-plus chat: options: model: qwen-plus这里的环境变量DASHSCOPE_API_KEY是阿里云 DashScope 的 API Key不要写在配置里我习惯在启动的时候通过--DASHSCOPE_API_KEYxxx注入或者放在本地环境变量。如果你不想用环境变量直接写api-key: sk-xxxx也能跑但就别上传公开仓库了。另外如果你有自己的代理配置可以设置spring.ai.dashscope.base-url指向代理地址一般开发环境不需要。2.3 写一个 Controller 完成对话调用配置好之后就可以写代码。Spring AI Alibaba 的用法和 Spring AI 官方一模一样核心入口是ChatClient。在 Spring Boot 的启动类或者配置类里注入然后写一个简单的 REST 接口RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder builder) { this.chatClient builder.build(); } GetMapping(/chat) public String chat(RequestParam String message) { return chatClient.prompt() .user(message) .call() .content(); } }启动项目后直接浏览器访问http://localhost:8080/chat?message你好就能看到通义千问的回复。这里有一个细节ChatClient.Builder是 Spring AI 自动装配好的只要 classpath 下存在spring-ai-alibaba-starter并且配置了 API Key就自动创建 ChatModel你不需要自己手动构建OpenAiChatModel。如果启动报错提示没有ChatClient.Builder多半是依赖没引入或者版本冲突。如果你想跑一个更贴近实际场景的测试而不是 REST 接口可以把CommandLineRunner作为启动时直接输出一段回复方便验证Component public class StartRunner implements CommandLineRunner { private final ChatModel chatModel; public StartRunner(ChatModel chatModel) { this.chatModel chatModel; } Override public void run(String... args) { String response chatModel.call(用一句话介绍一下 Spring AI Alibaba); System.out.println(模型回复: response); } }2.4 常见坑API Key、模型名和网络超时这个 5 分钟教程网上很多实际执行的时候会踩到几个非常隐蔽的坑我一个个说模型名称写错。百炼平台的模型名是有时效性的比如有些教程写qwen-v1现在已经废弃要用qwen-plus。如果配错控制台会返回类似InvalidParameter的错误你第一眼还以为是 API Key 的问题。网络超时。DashScope 的默认模型接口在部分网络环境下访问较慢Spring AI 默认超时时间比较短你可以在配置里调整spring: ai: dashscope: api-key: ${DASHSCOPE_API_KEY} timeout: 120s别忽略请求日志。在application.yml里开启 debug 日志能看到每次请求的 URL 和响应状态logging: level: org.springframework.ai: DEBUG开启后你会发现请求路径是类似https://dashscope.aliyuncs.com/api/v2/apps/text-generation这样的地址方便排查网络问题。3. 核心玩法拆解对话、函数调用和 RAG3.1 对话消息历史和流式输出最基础的call()方法是一次性同步调用适合简单测试。生产环境里我强烈建议使用流式输出大模型的一句话可能需要好几秒才能完全生成等全部生成完再返回会让用户疯掉。Spring AI 的流式调用和 WebFlux 的Flux结合得很好接口改成这样即可GetMapping(value /chat/stream, produces text/event-stream;charsetUTF-8) public FluxString chatStream(RequestParam String message) { return chatClient.prompt() .user(message) .stream() .content(); }注意这里的produces是text/event-stream前端用 EventSource 或者 fetch 的流式读取就能逐字拿到回复体验比同步好很多。真正的对话系统还需要记忆历史。Spring AI 提供了MessageChatMemory你可以简单地在获取ChatClient时加入一个默认系统 Prompt 和ChatMemoryBean ChatClient chatClient(ChatClient.Builder builder) { ChatMemory memory MessageWindowChatMemory.builder() .maxMessages(20) .build(); return builder.defaultAdvisors(new MessageChatMemoryAdvisor(memory)) .defaultSystem(你是一个乐于助人的Java助手回答尽量简洁) .build(); }这样同一个ChatClient实例在多次请求之间会维护上下文窗口不需要自己拼接历史字符串。这里的maxMessages(20)是限制最多保留多少条消息防止 token 超限。3.2 函数调用让大模型自己调你的业务方法函数调用是 Spring AI 里最有价值的特性之一。场景很简单模型不知道你数据库里的订单状态、天气、库存但你可以给模型一个“函数”当用户问“帮我查一下杭州今天的天气”时模型识别意图返回一个结构化调用请求框架帮你执行你的 Java 方法再把结果回传模型生成最终回复。Spring AI Alibaba 提供注解式工具定义。写一个方法加上Tool注解Component public class WeatherTools { Tool(description 查询指定城市的实时天气参数cityCode为城市编码例如杭州101210101) public String getWeather(String cityCode) { // 这里调用真实的天气服务本地先返回固定值 return 晴28度西南风3级; } }然后在调用时注册这个工具chatClient.prompt() .user(杭州今天天气怎么样) .tools(getWeather) .call() .content();tools(getWeather)里的字符串对应的是 Bean 名称默认是方法名。执行时模型会分析问题发现需要工具就自动发起调用整个过程对用户隐藏。这个能力我在实际项目里最常用的是查订单状态用户可以模糊地问“我的订单到哪一步了”我提供queryOrderStatus(orderId)工具模型会自动提取订单号参数调用业务方法最后用自然语言汇报结果。需要注意工具方法最好是无状态的放在独立Component里不要依赖请求上下文描述信息要写得足够详细模型才会在合适的时候选择它。3.3 RAG给你的模型灌私域知识RAGRetrieval-Augmented Generation是解决大模型幻觉问题最实用的方案。原理很简单先把企业文档切块、向量化存入向量库用户提问时先从向量库里检索出最相关的文本片段把这些片段拼接到 Prompt 里再让模型基于这些片段回答。Spring AI Alibaba 对 RAG 的支持比较完整包含文档加载器、文本分割器、向量 存储抽象。最小化实现只需要三步第一步引入向量数据库依赖我推荐先用简单的本地向量库SimpleVectorStore零部署成本适合学习和测试dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-commons-vector-store/artifactId /dependency第二步写一个初始化的 Service加载一个空运维的 Markdown 文件分割后存入向量库Service public class KnowledgeService { private final VectorStore vectorStore; private final EmbeddingModel embeddingModel; public KnowledgeService(VectorStore vectorStore, EmbeddingModel embeddingModel) { this.vectorStore vectorStore; this.embeddingModel embeddingModel; } PostConstruct public void loadData() throws IOException { // 读取 resources/data 下的文档 Resource resource new ClassPathResource(data/sop.md); // 使用 Spring AI 的默认文档解析器 DocumentReader reader new MarkdownDocumentReader(resource); ListDocument documents reader.read(); TextSplitter splitter TokenTextSplitter.builder() .defaultTokenPerChunk(500) .build(); ListDocument chunks splitter.apply(documents); vectorStore.write(chunks); } }第三步在提问时加入QuestionAnswerAdvisor框架会自动完成检索并拼接上下文Bean ChatClient chatClient(ChatClient.Builder builder, VectorStore vectorStore) { return builder.defaultAdvisors(new QuestionAnswerAdvisor(vectorStore)) .build(); }这样同一个接口就能回答文档里的内容了。比如你上传了公司请假制度用户问“请假三天以上需要谁审批”模型会检索文档并输出答案。当然真实场景你不会用SimpleVectorStore生产环境建议换成 Redis 向量库或阿里云的向量检索服务Spring AI Alibaba 也提供了对应的自动装配配置一下连接信息即可。4. 用 Docker 部署 Spring AI Alibaba Admin 控制台4.1 Admin 是什么它解决了什么问题前面讲的都是运行模型这个阶段你可能会遇到一个新的痛点好几个服务都在调通义千问想在网页上看每个服务的调用量、Token 消耗、Prompt 内容怎么办Spring AI Alibaba 给了一套很实际的可观测方案叫 Admin 控制台其实就是把模型调试和运维管理集中到一个 Web 页面里。它解决几个问题不用再 SSH 到服务器上翻日志看某次请求报错。可以在页面上管理多个模型 API Key切换模型、查看配置。能看到每次对话的完整上下文包括 Prompt、函数调用参数、Token 花费调试 Agent 的时候特别有用。Admin 既可以当作一个独立服务部署也可以嵌入到已有 Spring Boot 应用里。官方推荐以独立服务形式跑方便统一管理所有接入的服务。4.2 Docker 快速启动官方在 Docker Hub 上发布了spring-ai-alibaba-admin的镜像实际上是通过 Docker 安装spring-ai-alibaba-admin很方便省去自己编译源码的麻烦。直接用一行命令启动docker run -d \ --name spring-ai-alibaba-admin \ -p 9090:9090 \ -v /data/spring-ai-admin:/app/data \ -e JAVA_OPTS-Xms512m -Xmx1g \ springaidocker/spring-ai-alibaba-admin:latest这里我简单解释一下几个参数-p 9090:9090宿主机 9090 端口映射到容器内 9090这是 Admin 默认 Web 端口如果你的机器上 9090 被占了改成-p 18090:9090。-v /data/spring-ai-admin:/app/data把配置和日志目录挂载出来容器重建后数据不丢。-e JAVA_OPTSJVM 内存参数实测 512M 可以启动但建议 1G 以上因为页面加载和指标计算需要一定内存。启动之后浏览器访问http://服务器IP:9090。第一次进入会让你设置管理员账户设置完就能登录。4.3 接入本地 Spring AI Alibaba 服务Admin 启动后你需要让你的业务应用把调用记录上报给它。Spring AI Alibaba 项目里提供了上报依赖在你自己的应用pom.xml中加入dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-admin-client/artifactId version1.0.0/version /dependency然后在application.yml中指定 Admin 服务地址spring: ai: admin: endpoint: http://localhost:9090 enabled: true业务应用启动后会自动向 Admin 注册把 ChatClient 的每次调用写入 Admin。你可以在 Admin 页面看到“应用列表”里出现了你的服务名称、模型名称、请求次数、Token 消耗排行。值得注意的是上报是异步的不会阻塞业务请求对现有接口的延迟影响可以忽略。4.4 部署避坑时区、内存和网络模式把 Admin 部署到生产环境的时候有几个问题容易被忽略容器时区。官方镜像默认使用 UTC 时间你在页面上看到的调用时间会比北京时间慢 8 小时。解决办法是启动时挂载宿主机时区docker run -d \ --name spring-ai-alibaba-admin \ -p 9090:9090 \ -e TZAsia/Shanghai \ -v /etc/localtime:/etc/localtime:ro \ -v /data/spring-ai-admin:/app/data \ springaidocker/spring-ai-alibaba-admin:latest内存不足。如果你服务器内存只有 1G启动会频繁 OOM。建议至少 2G。同时注意容器的JAVA_OPTS环境变量镜像内默认可能有自己的设置你通过-e JAVA_OPTS覆盖时要包含-Xms、-Xmx。网络模式。如果业务应用和 Admin 不在同一台机器spring.ai.admin.endpoint要写 Admin 所在机器的内网 IP不要写localhost。如果容器化部署业务应用Docker 网络要用 user-defined 网络或 host 模式否则容器内访问不了宿主机端口。5. 实操中的常见问题与排查技巧5.1 版本不匹配是头号杀手这个项目目前迭代很快踩过最深的一个坑就是版本对应关系。Spring Boot 3.2.x 和 3.3.x 适配的 Spring AI 版本不一样Spring AI 的 1.0.0 版本对齐的是 Spring Boot 3.3。如果你项目用的是 3.2强行引入 Spring AI 1.0.0 会导致自动装配失败报错通常是NoSuchBeanDefinitionException或ClassNotFoundException。建议直接创建新项目时用 Spring Boot 3.3。如果公司老项目是 3.2可以先查一下官方版本映射表选择对应的 Spring AI 版本比如用 0.8.1 或等官方明确支持。5.2 工具调用的“不触发”问题很多人在Tool方法上卡很久模型明明看到了工具描述就是不调用总是闲聊式回答。排查思路可以先看请求日志确认是否真的把工具信息传到了模型。Spring AI 在日志中会打印tools参数。如果确认传了问题多半是工具描述写得太模糊模型不知道什么时候该用。比如你写“查订单”模型可能不知道参数是什么。一定要在Tool的description里把参数类型和含义写清楚甚至可以给示例。调通之后还有一个细节工具方法返回的结果会被模型二次加工再拼成回答所以返回的文本别搞成纯 JSON 代码格式尽量用容易读的中文描述模型回答会更自然。5.3 RAG 检索效果差问题出在哪我在初试 RAG 时最常见的现象是问问题时模型完全无视提供的文档还是凭训练知识乱说。这时候优先检查两件事一是文档是否真的分割并写入了向量库可以在 Admin 控制台或日志中查看向量库集合的文档数量二是是否在ChatClient里加了QuestionAnswerAdvisor。如果这两个都没问题再看看文档切分是否合理。粒度太大会导致检索到的片段包含大量无关信息粒度太小语义又不完整。经验值是中文文档每个 chunk 在 200~500 个 token 之间切分时最好按标题和段落边界切不要硬拆句子。5.4 流式输出时接口超时用FluxString返回流式内容时如果走的是 Nginx默认proxy_read_timeout可能只有 60s长文本生成超过 60s 就会被 Nginx 掐断。解决方法是调整网关的超时配置或者在前端直接通过 WebSocket/SSE 连接后端时不经过 Nginx。另外Spring Boot 内置服务器如果是 Tomcat也需要注意异步请求超时设置Tomcat 的async-supported在 Spring MVC 中是默认开启的但你若自定义了 Filter 或拦截器要确保它们也支持异步。5.5 Admin 页面看不到上报数据如果你按前面的方式配置了spring-ai-alibaba-admin-client页面还是看不到数据先检查客户端是否有admin-event相关的日志。如果没有很可能是你的业务应用里没有引入spring-ai-alibaba-starter导致自动装配不生效。还有一点Admin 客户端默认是采样上报不是每条都发你在测试时多调用几次对话等一两分钟再刷新页面。这个“采样率”如果也需要调整可以在配置里搜索admin.sampler支持百分比配置。最后再分享一个小技巧这个项目我试下来最顺手的用法是把 Spring AI Alibaba 当做一个桥梁让团队在切换模型时不用重写业务代码。具体做法是在项目里再包一层自己的AIService里面封装 ChatClient、工具调用和 RAG 逻辑业务层只依赖这个 Service。后来百炼平台升级过几次模型名称我只改了application.yml里的model和base-url业务代码一行没动。你也别迷信“底层全部用默认配置”Spring AI Alibaba 的官方示例里提供了不少很实用的配置项比如spring.ai.retry.on-http-codes、max-tokens、temperature等这些参数决定了实际生产效果建议照着官方文档逐个过一遍而不是只停留在能跑通请求的层面。
返回列表