Spring AI 2.0 GA 实战:从环境搭建到RAG与智能体落地 📅 发布时间:2026/8/30 18:49:01 👁 浏览次数: Spring AI 2.0 GA 正式发布了。对于 Java 后端开发者来说这是 AI 应用开发方式的一次集中收口对话、结构化输出、RAG 知识库、Tool Calling 智能体、向量数据库集成全部统一到 Spring 的编程模型里不需要再自己拼 HTTP 请求、手动维护对话上下文、来回调 embedding 接口。这篇文章按企业级项目落地的顺序来写环境搭建、模型接入、基础对话、RAG 问答、智能体设计、业务封装、API 接口与批量任务最后是资源占用观察和上线排查。篇幅不短但每一步都能照着跑。先给结论Spring AI 2.0 GA 仍然是 Java 后端接入大模型最稳的官方方案SDK 演进到 2.x 之后编程模型更统一RAG 和智能体的封装也更成熟。接入 OpenAI、通义千问、Ollama 本地模型只需要改配置知识库问答用 DocumentReader TextSplitter VectorStore 一条链路完成智能体通过Tool注解把业务方法暴露给模型调用。本文所有示例基于 ChatClient 编程模型具体 API 以你引入的 2.0 GA 实际版本为准。1. Spring AI 2.0 GA 核心能力速览能力项说明项目类型Spring 官方 AI 应用开发框架Java 生态当前版本2.0 GA版本号以 Maven Central 实际发布为准核心能力ChatClient 对话、结构化输出、流式输出、RAG 知识库、Tool Calling 智能体模型支持OpenAI、通义千问DashScope、Ollama 本地模型、Azure OpenAI、Anthropic、Google Gemini 等向量库支持Redis、Milvus、PGVector、Chroma、Qdrant、SimpleVectorStore推荐环境JDK 17建议 JDK 21Spring Boot 3.4 / 4.x以官方兼容矩阵为准启动方式Spring Boot 标准启动mvn spring-boot:run或java -jar接口能力可直接封装 RestController 对外提供 API也支持 SSE 流式返回批量任务支持配合Async线程池、Spring Batch 或消息队列本地部署模型 API 走云端时不需要 GPU接 Ollama 本地模型需要关注内存和显存对 Java 后端来说Spring AI 2.0 GA 最值得关注的三点一是 ChatClient 把对话、上下文、工具调用揉成了一个统一入口二是 RAG 链路从文档解析到向量检索都有官方组件不再需要自己组装三是模型 API 的切换成本很低换模型基本就是改配置和依赖。2. 适用场景与使用边界Spring AI 2.0 GA 适合这几类场景企业知识库问答合同、产品手册、内部 SOP、技术文档的检索问答。这是 RAG 最典型的落地场景。智能客服与业务智能体把订单查询、工单处理、库存查询这类已有业务方法通过 Tool Calling 暴露给模型让模型自主调用。内容生成与辅助写作商品描述、报表说明、代码注释、测试用例生成批量处理时用异步任务队列。多模型统一接入同一个业务代码切换 OpenAI、通义千问、Ollama 本地模型只需要换依赖和配置。使用边界也要说清楚不要把模型 API 当作安全边界。用户输入进入模型服务之前必须做身份认证、参数校验、敏感信息过滤。企业私有数据接入 RAG 前要确认数据是否有授权、是否包含个人敏感信息必要时做脱敏处理。模型输出可能出现幻觉尤其是法律、医疗、金融类场景上线前必须做人工复核或引用溯源。本地部署时Ollama 这类方案对内存和显存有要求7B 级模型建议按模型官方页面标注的资源要求准备生产环境优先 GPU 推理。3. 本地部署环境准备Spring AI 是标准 Java 工程环境准备比 Python 生态简单但有几项必须确认。3.1 JDK 版本Spring AI 2.0 GA 需要 JDK 17 起步建议直接用 JDK 21。JDK 17 能跑但 JDK 21 的虚拟线程和更完整的 GC 调优参数在生产环境更顺手。java -version # 需要看到 17、21 或更高版本如果本机有多个 JDK确认JAVA_HOME指向正确版本。Windows 用户在 IDEA 的 Project Structure 里也要同步设置 SDK 版本。3.2 Maven 或 Gradle项目构建使用 Maven 3.9 或 Gradle 8.x。确认本机 Maven 版本mvn -version如果使用 IDEA可以直接用内置 Maven但建议配置阿里云镜像或腾讯云镜像加速依赖下载。3.3 可选依赖Docker如果 RAG 方案选择 Redis、Milvus、PGVector 这类向量库推荐用 Docker 启动减少本机污染。# 以 Redis 为例后续 RAG 实战会用到 docker run -d --name redis-vector -p 6379:6379 redis:7.4如果测试阶段不想引入外部向量库Spring AI 的SimpleVectorStore是纯内存实现零依赖项目重启后数据丢失适合功能验证。3.4 模型 API Key按你实际选择的模型准备OpenAI在 OpenAI 平台创建 API Key配置环境变量OPENAI_API_KEY。通义千问在阿里云百炼平台创建 DashScope API Key配置DASHSCOPE_API_KEY。Ollama 本地模型先安装 Ollama然后拉取模型例如ollama pull qwen2.5:7b不需要 API Key。4. 创建 Spring Boot 工程与依赖配置推荐直接用 Spring Initializr 创建工程。可以在 start.spring.io 网页生成也可以直接在 IDEA 里新建 Spring Boot 项目。4.1 基础依赖Spring AI 依赖统一通过spring-ai-bom管理避免版本冲突parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.5.3/version relativePath/ /parent properties java.version17/java.version spring-ai.version2.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 groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai/artifactId /dependency /dependencies如果你使用国内模型Spring AI Alibaba 提供通义千问的官方 startergroupId 是com.alibaba.cloud.aiartifactId 是spring-ai-alibaba-starter同样有独立的 BOM 管理具体引入方式以 Spring AI Alibaba 官方文档为准。后面的配置示例会同时给到 OpenAI 和 DashScope 两种。4.2 Spring AI 仓库Spring AI 2.0 GA 版本已经发布到 Maven Central不再强制需要 milestone 仓库。如果某些中间版本还没进 Central需要在pom.xml里补充 Spring 官方仓库repositories repository idspring-milestones/id nameSpring Milestones/name urlhttps://repo.spring.io/milestone/url /repository /repositories稳定版可以不加但保留这一项不会影响构建。5. 模型接入配置Spring AI 的核心设计是“统一 API、可插拔模型”。下面给三套配置按实际需要选择。5.1 OpenAI 配置spring: ai: openai: base-url: https://api.openai.com api-key: ${OPENAI_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.7base-url保留默认值即可api-key一定要通过环境变量或配置中心注入不能硬编码到配置文件中。5.2 通义千问 DashScope 配置引入 Spring AI Alibaba starter 后spring: ai: dashscope: api-key: ${DASHSCOPE_API_KEY} chat: options: model: qwen-plus通义千问的模型名按百炼平台实际开通的模型填写qwen-plus是综合能力比较均衡的版本也可以换qwen-max。5.3 Ollama 本地模型配置spring: ai: ollama: base-url: http://localhost:11434 chat: options: model: qwen2.5:7b启动 Ollama 服务后先确认模型已拉取ollama list然后启动 Spring Boot 应用。本地模型的好处是数据不出内网但推理速度受硬件限制生产环境需要评估吞吐。6. 基础对话功能测试ChatClient 与结构化输出配置完成后先做一个最简单的对话测试确认整个链路通不通。6.1 ChatClient 基础对话创建一个 Service注入ChatClient.BuilderService public class ChatService { private final ChatClient chatClient; public ChatService(ChatClient.Builder builder) { this.chatClient builder.build(); } public String chat(String message) { return chatClient.prompt() .user(message) .call() .content(); } }新建一个测试接口调用RestController RequestMapping(/api/ai) public class AiController { private final ChatService chatService; public AiController(ChatService chatService) { this.chatService chatService; } PostMapping(/chat) public String chat(RequestBody String message) { return chatService.chat(message); } }启动应用后用 curl 验证curl -X POST http://localhost:8080/api/ai/chat \ -H Content-Type: text/plain \ -d 用一句话介绍 Spring AI如果返回一段正常的中文回答说明模型接入、Spring 自动配置、网络链路都正常。6.2 结构化输出这是 Spring AI 2.0 里非常实用的能力可以让模型直接返回 Java 对象。比如让模型从一段商品描述中提取字段public record ProductInfo(String name, String category, BigDecimal price) {}public ProductInfo extractProduct(String text) { return chatClient.prompt() .user(u - u.text(从下面的文本中提取商品信息{text}) .param(text, text)) .call() .entity(ProductInfo.class); }调用时传入String text 华为Mate 60 Pro512G版本售价6999元属于智能手机品类; ProductInfo info chatService.extractProduct(text); System.out.println(info);模型会返回 JSON 并自动反序列化成ProductInfo记录。这个能力在做信息抽取、表单填充、数据清洗时非常有用能省掉大量正则解析逻辑。如果解析失败先打印模型的原始返回确认是不是字段命名或输出格式问题。6.3 流式输出面向对话类场景流式返回能显著降低用户等待感。Spring AI 的 ChatClient 支持响应式流import reactor.core.publisher.Flux; public FluxString streamChat(String message) { return chatClient.prompt() .user(message) .stream() .content(); }Controller 层用text/event-stream暴露PostMapping(value /chat/stream, produces text/event-stream;charsetUTF-8) public FluxString streamChat(RequestBody String message) { return chatService.streamChat(message); }前端用 EventSource 或 fetch 流式读取即可。要注意SSE 接口在生产环境需要配置合理的超时时间避免长连接被网关提前断开。6.4 多轮对话与 ChatMemorySpring AI 2.0 的多轮对话不需要自己拼历史消息直接用MessageWindowChatMemory维护滑动窗口import org.springframework.ai.chat.memory.MessageWindowChatMemory; import org.springframework.ai.chat.client.advisor.MessageWindowChatMemoryAdvisor; ChatClient chatClient ChatClient.builder(chatModel) .defaultAdvisors(MessageWindowChatMemoryAdvisor.builder(MessageWindowChatMemory.builder() .maxMessages(20) .build()) .build()) .build();设置之后Spring AI 会自动把最近 20 条消息携带给模型。生产环境如果用户量较大可以把 ChatMemory 换成 Redis 实现按会话 ID 隔离记忆。7. RAG 知识库问答实战RAG 是 Spring AI 2.0 被问得最多的功能。核心链路是文档加载 - 文本切分 - 向量化 - 存入向量库 - 检索增强问答。7.1 文档加载Spring AI 提供多个 DocumentReader按文档类型选择TikaDocumentReader支持 PDF、Word、PPT、HTML 等格式适合通用场景。PagePdfDocumentReader逐页读取 PDF适合需要保留页码的场景。JsonReader读取 JSON 文件。TextReader读取纯文本文件。示例代码加载 classpath 下的 PDF 文档import org.springframework.ai.reader.tika.TikaDocumentReader; import org.springframework.ai.document.Document; import org.springframework.core.io.ClassPathResource; TikaDocumentReader reader new TikaDocumentReader( new ClassPathResource(docs/spring-ai-guide.pdf)); ListDocument documents reader.get();7.2 文本切分切分策略直接影响检索效果。常见做法是TokenTextSplitter按 Token 数切块并保留少量重叠import org.springframework.ai.transformer.splitter.TokenTextSplitter; TokenTextSplitter splitter TokenTextSplitter.builder() .defaultTokenChunkSize(500) .minChunkSizeChars(350) .build(); ListDocument chunks splitter.apply(documents);切块没有绝对最优参数需要根据文档类型和模型上下文窗口调整。如果文档是结构化合同条款按章节切分比按固定 Token 切分更合理如果是长文本可以在切块之间保留 50 到 100 Token 的重叠避免语义断裂。7.3 向量化与向量库Embedding 模型负责把文本转成向量。OpenAI、DashScope、Ollama 都提供对应的 EmbeddingModel 实现Spring AI 会自动装配。VectorStore 决定向量存储和检索方式。测试阶段可以直接用 SimpleVectorStoreimport org.springframework.ai.vectorstore.SimpleVectorStore; Bean public VectorStore vectorStore(EmbeddingModel embeddingModel) { return SimpleVectorStore.builder(embeddingModel).build(); }生产环境建议用 Redis 或 Milvus。Redis 配置import org.springframework.ai.vectorstore.RedisVectorStore; import org.springframework.data.redis.connection.RedisConnectionFactory; Bean public VectorStore vectorStore(RedisConnectionFactory connectionFactory, EmbeddingModel embeddingModel) { return RedisVectorStore.builder(connectionFactory, embeddingModel) .indexName(knowledge_base) .initializeSchema(true) .build(); }向量库选型参考向量库部署复杂度适合场景注意事项SimpleVectorStore无本地测试、Demo内存存储重启丢失Redis低中小规模生产已有 Redis 可直接复用需要 RediSearch 模块Milvus中海量文档、高并发检索需要独立部署运维成本高PGVector中已有 PostgreSQL 的团队业务数据和向量数据统一存储Chroma低轻量应用默认文件存储适合小团队7.4 向量库初始化与检索问答把切分后的文档写入向量库Service public class KnowledgeBaseService { private final VectorStore vectorStore; private final ChatClient chatClient; public KnowledgeBaseService(VectorStore vectorStore, ChatClient.Builder builder) { this.vectorStore vectorStore; this.chatClient builder.build(); } public void initKnowledgeBase() { TikaDocumentReader reader new TikaDocumentReader( new ClassPathResource(docs/spring-ai-guide.pdf)); ListDocument documents reader.get(); TokenTextSplitter splitter TokenTextSplitter.builder() .defaultTokenChunkSize(500) .minChunkSizeChars(350) .build(); ListDocument chunks splitter.apply(documents); vectorStore.add(chunks); } public String ask(String question) { return chatClient.prompt() .user(question) .advisors(QuestionAnswerAdvisor.builder(vectorStore) .retrievalTopK(5) .build()) .call() .content(); } }QuestionAnswerAdvisor会自动完成检索和组装先根据用户问题在向量库中检索最相关的 5 个片段再和原始问题一起发给大模型让模型基于检索内容回答。调用ask方法前先执行一次initKnowledgeBase确保向量库有数据。7.5 引用溯源企业级知识库问答一定要有引用溯源否则模型回答错了无法定位原因。通过 ChatResponse 拿到检索到的文档ChatResponse response chatClient.prompt() .user(question) .advisors(QuestionAnswerAdvisor.builder(vectorStore).build()) .call() .chatResponse(); ListDocument references response.getMetadata() .getDocuments();拿到Document列表后可以把来源文件名、页码、原文片段一并返回给前端展示这是知识库类产品的基本要求。8. 智能体设计与 Tool Calling 实战智能体的核心不是让模型“自己思考”而是让模型在对话过程中自动决定调用哪些业务方法。Spring AI 2.0 用Tool注解把普通方法暴露给模型。8.1 定义业务工具假设已有订单服务要做一个能查物流的智能客服import org.springframework.ai.tool.annotation.Tool; Component public class OrderTool { private final OrderService orderService; public OrderTool(OrderService orderService) { this.orderService orderService; } Tool(description 根据订单编号查询订单物流状态) public String queryLogistics(String orderId) { LogisticsInfo info orderService.queryLogistics(orderId); if (info null) { return 未查询到该订单的物流信息; } return 订单状态 info.getStatus() 最新节点 info.getLatestNode(); } }方法名、入参、返回逻辑都不需要改写业务代码只需要把已有的 Service 方法包一层加上Tool注解。模型会在需要的时候生成对应的工具调用请求Spring AI 负责执行并把结果返回给模型继续生成回答。8.2 构建智能体 ChatClientService public class AgentService { private final ChatClient chatClient; public AgentService(ChatClient.Builder builder, OrderTool orderTool) { this.chatClient builder .defaultSystem(你是企业智能客服助手。 用户查询订单物流时必须调用工具获取真实信息。 如果工具返回未查询到要如实告知不能编造。) .defaultAdvisors(MessageWindowChatMemoryAdvisor.builder( MessageWindowChatMemory.builder().maxMessages(30).build()).build()) .defaultTools(orderTool) .build(); } public String chat(String message) { return chatClient.prompt() .user(message) .call() .content(); } }关键点在于defaultTools(orderTool)这样 ChatClient 会自动把工具定义传给模型。验证时可以先问“帮我查下单号 2026 的物流”模型会判断需要调用queryLogistics方法返回真实订单数据。如果工具没有生效优先查看模型请求日志中是否有tools字段以及工具方法的参数类型是否太复杂。建议工具方法入参使用简单类型复杂对象先拆成多个简单参数减少模型生成参数时的失败概率。8.3 多智能体设计的工程思路单个智能体适合任务单一的对话场景。复杂业务通常需要多个智能体入口路由智能体负责理解用户意图把请求分发给客服智能体、售后智能体或数据分析智能体。Spring AI 2.0 本身没有强制约束多智能体的编排方式工程上常用做法是每个智能体使用独立的 ChatClient 实例配备不同的 System Prompt 和工具集。入口模块根据意图识别结果路由到对应智能体。会话级状态通过 Redis 或数据库共享避免多智能体之间记忆割裂。如果要做可视化编排可以参考 Dify 这类智能体平台的设计如果要做 Java 生态内的节点编排可以关注 Spring AI Alibaba 的 Graph 模型但接入时以官方文档为准。9. 业务封装API 接口与批量任务智能体和 RAG 跑通之后接下来要解决的是怎么接进现有业务系统。9.1 REST API 封装把对话、RAG、智能体统一封装成 REST 接口前端和后端服务都能直接调用RestController RequestMapping(/api/ai) public class AiController { private final ChatService chatService; private final KnowledgeBaseService ragService; private final AgentService agentService; public AiController(ChatService chatService, KnowledgeBaseService ragService, AgentService agentService) { this.chatService chatService; this.ragService ragService; this.agentService agentService; } PostMapping(/chat) public String chat(RequestBody ChatRequest request) { return chatService.chat(request.message()); } PostMapping(/rag/ask) public RAGResponse ask(RequestBody RAGRequest request) { ListDocument references ragService.askWithReferences(request.question()); return new RAGResponse(ragService.ask(request.question()), references); } PostMapping(/agent/chat) public String agentChat(RequestBody AgentChatRequest request) { return agentService.chat(request.message()); } }接口设计建议消息体使用 DTO不要直接把实体类暴露给前端接口层做参数校验和登录鉴权RAG 接口返回引用文档列表方便前端展示来源。9.2 批量任务场景批量任务在 AI 应用中很常见批量向量化大量文档、批量生成商品描述、批量做文章摘要。Spring AI 本身不包含任务队列但可以结合 Spring 的异步能力实现。先配置线程池避免批量任务挤占 Web 请求线程spring: task: execution: pool: core-size: 8 max-size: 16 queue-capacity: 200 thread-name-prefix: ai-task-批量生成商品描述Service public class BatchGenerateService { private final ChatClient chatClient; public BatchGenerateService(ChatClient.Builder builder) { this.chatClient builder.build(); } Async(applicationTaskExecutor) public CompletableFutureString generateDescription(String productName) { String content chatClient.prompt() .user(u - u.text(为商品「{productName}」生成一段30字以内的卖点描述) .param(productName, productName)) .call() .content(); return CompletableFuture.completedFuture(content); } }批量任务的工程化要点先小批量测试确认输出质量稳定后再放大并发。模型 API 都有 QPS 和 Token 限制批量并发不要超过限流阈值。任务结果要落库失败任务要有重试机制和幂等控制。大批量文档向量化建议离线执行用 Spring Batch 或消息队列异步消费。10. 资源占用与性能观察Spring AI 自身的资源占用主要不在 GPU而在 JVM 内存、线程、网络连接和向量库。10.1 JVM 内存RAG 场景中Document 对象和向量数据会占用堆内存。如果使用 SimpleVectorStore所有向量都存在内存里文档量大时需要对 JVM 堆做合理规划。生产环境更推荐 Redis 或 Milvus把向量数据放到 JVM 外。启动参数示例java -Xms512m -Xmx2g -jar app.jar10.2 线程与连接池高并发对话场景每个请求都会占用一个 HTTP 线程并等待模型 API 返回。流式接口会长时间占用连接要注意网关和负载均衡的超时配置。模型 API 是网络 IO 密集操作线程池核心数不宜太小建议结合压测结果调整。10.3 本地模型推理性能如果使用 Ollama 本地模型性能瓶颈在推理侧。CPU 推理速度很慢7B 级模型只适合低并发测试生产环境需要 GPU。模型大小、量化等级、上下文长度都会影响响应时间。更稳妥的做法是先跑 Ollama 自带的性能测试确认单次推理耗时后再估算并发能力。10.4 性能观察方式用 Spring Boot Actuator 暴露health、metrics端点观察 JVM 内存和线程状态。在 ChatClient 调用前后记录耗时日志按模型、场景、用户维度统计。观察模型 API 的 Token 消耗避免长上下文对话导致 Token 费用快速上涨。批量任务要加任务进度和失败率监控。11. 常见问题与排查方法问题现象可能原因排查方式解决方案启动报错找不到 ChatModel Bean未引入对应模型 starter或未配置 api-key检查 pom 依赖和 application.yml引入对应 starter配置正确的 api-key调用模型接口返回 401/403API Key 错误、账户余额不足、接口权限未开通用 curl 单独调用模型 API 验证检查 key、账户状态和模型权限模型返回内容乱码编码未设置 UTF-8检查响应头 Content-TypeController 添加produces application/json;charsetUTF-8RAG 检索不出内容向量库为空或切分后数据量太少打印 VectorStore 数据和文档数量重新执行文档导入检查切块参数模型回答与知识库无关检索召回文档不匹配或 topK 太小开启日志查看实际检索到的文档调大 topK优化切块策略增加元数据过滤结构化输出解析失败模型返回 JSON 与目标实体字段不一致打印模型原始返回明确输出格式增加解析重试逻辑智能体工具不生效工具类未注册或方法参数类型过复杂查看模型请求中的 tools 列表注册工具 Bean简化参数类型批量任务频繁失败并发超过模型 API 限流阈值查看模型服务返回的限流错误降低并发增加重试退避内存 OOM堆内存不足或文档加载过多查看 JVM 堆使用和 GC 日志调大堆内存改用外部向量库分批加载端口被占用8080 已被其他应用使用netstat -ano | findstr 8080启动参数加--server.port808112. 最佳实践与合规建议工程化落地的几个建议按优先级排列密钥管理API Key 统一放环境变量或配置中心禁止提交到 Git 仓库。配置文件中用${API_KEY}方式引用。模型版本固定测试环境和生产环境锁死模型版本避免模型服务端更新导致输出行为变化。输出校验结构化输出结果必须做业务校验不能直接落库或展示。模型输出格式不正确时要有重试或降级方案。熔断限流模型 API 是外部依赖必须接入 Resilience4j 或 Sentinel防止模型服务故障拖垮业务系统。日志脱敏不要打印完整用户输入和模型输出。业务日志只记录必要信息涉及个人信息时必须脱敏。版权合规企业知识库中的文档必须有合法来源和使用授权上传前进行敏感信息扫描。生成内容的对外发布前要做人工复核。数据安全涉及客户隐私或商业机密的场景优先使用本地模型或私有化部署避免敏感数据离开内网。Prompt 模板化System Prompt 不要散落在代码里统一放到配置中心或模板文件方便调整和版本管理。13. 总结与下一步Spring AI 2.0 GA 最值得尝试的点是统一编程模型对话、RAG、智能体都在 ChatClient 之上展开代码结构清晰模型切换成本低。建议第一次接触时先跑通 ChatClient 基础对话和结构化输出确认模型接入没问题后再做 RAG 和 Tool Calling。最容易踩的坑集中在依赖版本、API Key 配置、切块策略和工具注册这几个环节出现问题先看日志和模型原始返回定位速度会快很多。接下来可以往三个方向扩展一是把 RAG 的检索链路升级为混合检索配合元数据过滤提高准确率二是用 Spring AI Alibaba 的 Graph 模型做多智能体节点编排三是接入消息队列把批量生成任务改成异步可重试的完整任务体系。RAG 的引用溯源和智能体的工具调用是企业在生产环境最看重的两个能力建议优先做深。