拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Spring AI 2.0实战:从环境搭建到RAG问答与智能体落地

当我第一次把一个Spring AI 2.0 GA版本集成到内部知识库项目时最深的感受不是“API变了”而是整个开发节奏变了。过去我们写AI功能通常是一次次拼HTTP请求、自己管理Prompt模板、自己处理JSON解析再手动处理各种异常和重试。而Spring AI 2.0把这些散落的问题收拢成了一个统一的开发抽象。这件事对Java后端开发者的意义比“多一个工具”要大得多。它意味着AI能力在Java服务端终于可以像写普通业务代码一样被设计、封装、测试、部署和替换。所以这篇文章不打算写成特性简历我会从环境搭建开始一步一步带你把Spring AI 2.0跑起来再依次实现RAG问答、智能体设计、业务封装以及项目上线。整个过程里我会穿插一些真实落地时的取舍和常见坑点希望帮你少走一些弯路。1. Spring AI 2.0到底改变了什么为什么值得你学先回答一个更底层的问题Spring AI 2.0到底解决了什么如果只是“多了一个调用大模型的SDK”那它并不值得你专门花时间。真正的原因在于它把你原本需要自己处理的那些繁琐细节全部收纳进了框架的骨架里。1.1 从“手工拼凑HTTP调用”到“统一抽象层”以前接入一个大模型服务类死代码大概长这样HttpClient client HttpClient.newHttpClient(); HttpRequest request HttpRequest.newBuilder() .uri(URI.create(https://api.example.com/v1/chat/completions)) .header(Content-Type, application/json) .header(Authorization, Bearer apiKey) .POST(HttpRequest.BodyPublishers.ofString(payload)) .build();然后你要自己处理流式响应、非流式响应、超时、重试、错误码、上下文拼接。更麻烦的是如果中途换一个模型供应商几乎整个调用层都要重写。Spring AI 2.0把这一层抽象掉了。你现在只需要定义ChatModel和EmbeddingModel这几个Bean框架统一处理请求、重试、模型切换和输出解析。这个变化直接把AI接入从“和外部系统死磕”变成了“配置与调用”。1.2 与LangChain等其他生态的差异讨论Spring AI时很难绕过LangChain或LangChain4j。我的体验是LangChain生态更适合需要高度自由编排和中转复杂流程的场景。但如果你本身就是一个Java后端团队项目里已经大量使用Spring BootSpring AI 2.0的吸引力就在于它不需要引入一套独立的生态而是直接借助Spring的自动配置、依赖注入、Actuator监控等能力。换句话说LangChain像是一个功能丰富的工具箱而Spring AI更像是一套“内嵌进常规开发流程的规范”。对于大多数企业级后端项目后者其实更容易落地因为你不用学习一套全新的编程模型只需要把AI相关的对象当作普通的Bean来管理。当然这里也要说清边界Spring AI 2.0并不适合所有场景。如果你需要深度控制每一步Prompt或复杂的Agent路由它可能不如一些专门框架灵活。但作为一个从零搭建企业级AI能力的起点它已经足够扎实。2. 环境搭建与项目初始化先把地基打好标题里写的是“2026最新版”但版本迭代很快我在写这篇文章时使用的版本是Spring AI 2.0 GA的某个release。你在实际搭建时一定要以Maven中央仓库里的最新GA版本为准不要直接用我这里的版本号。2.1 依赖引入与版本选择Spring AI 2.0不在Spring Boot的默认版本管理之内。你需要在pom.xml里显式引入依赖并且把版本号放到properties里统一管理。properties java.version17/java.version spring-boot.version3.3.5/spring-boot.version spring-ai.version1.0.0-M6/spring-ai.version /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-model-openai/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-model-ollama/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-vector-store-pinecone/artifactId /dependency /dependencies dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement这个例子同时引入了OpenAI和Ollama的starter目的是让你可以在本地环境用Ollama跑通流程再切到云端正式模型。如果你只使用阿里云、Azure等国内可访问的模型服务可以引入对应的starter。注意Spring AI的版本号一定要用GA正式版不要用Snapshot或M版本。毕竟AI模型的API变更频繁我们没必要在框架本身的边缘测试版本上浪费排错时间。2.2 核心配置模型、密钥、重试在application.yml里核心配置项是这样一组spring: ai: openai: base-url: https://api.example.com api-key: ${OPENAI_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.7 max-tokens: 800 embedding: options: model: text-embedding-3-small ollama: base-url: http://localhost:11434 chat: options: model: qwen2.5:7b temperature: 0.3这些配置并不难理解但从企业级工程角度我建议你把密钥放到环境变量或配置中心不要写死在代码仓库里。Spring AI本身支持通过Value注入但更常见的做法是用Spring Cloud Config或K8s Secret管理。2.3 最小化调用示例与验证写一个最小的Controller验证配置是否生效RestController public class ChatController { private final ChatModel chatModel; public ChatController(ChatModel chatModel) { this.chatModel chatModel; } GetMapping(/chat) public String chat(RequestParam String message) { return chatModel.call(message); } }启动应用后访问/chat?message你好如果返回结果正常说明基础链路已经通了。但是这里有一个易踩的坑你连通的只是模型调用还不是业务应用。很多人在这一步就开始欢呼其实后面的RAG和Agent才是真正复杂的地方。3. RAG问答从知识库到可回答的业务助手RAGRetrieval-Augmented Generation是目前把大模型接入企业私有知识库最靠谱的方式。它不是靠训练而是让模型在回答前先检索相关文档片段再把片段作为上下文组装进Prompt。3.1 RAG的工作流程与关键机制Spring AI 2.0提供了一个相对完整的RAG流程抽象核心组件包括DocumentReader读取PDF、Word、TXT等格式文档。DocumentTransformer做文档清洗、去重、分块。DocumentSplitter按一定策略切块。EmbeddingModel将文本块向量化。VectorStore存储和检索向量。RetrievalAugmentationAdvisor将检索结果与Prompt组装。一个最简单的RAG流程大概是读取本地文档。切块。Embedding后存入VectorStore。查询时先根据用户问题检索相似块。将检索到的文本块拼入Prompt再交给ChatModel生成回答。3.2 切块策略与向量化影响结果的最隐蔽因素很多人做RAG时把所有精力都放在模型选择上却忽略了切块策略。其实切块对最终效果的影响往往比模型选择更大。切得太小单个块丢失上下文检索结果可能是一些碎片信息切得太大嵌入时容易稀释主体的语义还会增加Token消耗。比较常见的做法是段落式切块按段落边界切适合文档结构清晰的内容。固定长度切块按字符数切适合结构不一致的文档。递归切块先按段落、再按句子、最后按固定长度Spring AI 2.0的TokenTextSplitter就支持类似策略。在实战中我建议先用默认的TokenTextSplitter然后人工挑几类典型的用户问题对比不同切块参数下的检索准确度。一次改一个参数不要同时改多个变量。3.3 检索增强与Prompt组装在Spring AI 2.0里你不需要手动拼接Prompt。你可以通过RetrievalAugmentationAdvisor来自动完成检索与增强。Bean RetrievalAugmentationAdvisor advisor(QueryTransformer queryTransformer, VectorStore vectorStore, DocumentRetriever retriever) { return RetrievalAugmentationAdvisor.builder() .queryTransformer(queryTransformer) .documentRetriever(retriever) .contextAugmenter(new DefaultContextAugmenter()) .build(); }这样你在业务代码里只需要调用ChatClientString answer chatClient.prompt() .user(请基于资料回答什么是Spring AI) .call() .content();底层会自动完成检索、拼上下文和回答。这让你在业务层几乎感觉不到RAG的存在也正是Spring AI 2.0这类框架的价值所在。3.4 效果排查链路如果你发现RAG效果不理想按照这个顺序排查先看检索结果把最终传给模型的上下文打出来。如果上下文不对回答再流畅也没用。再看切块粒度上下文是否正确覆盖了你希望模型看到的段落。再看检索方式是向量检索、关键词检索还是混合检索混合检索在小样本场景下通常更稳定。再看Prompt结构是否清楚告诉模型“只基于以下资料回答不要编造”。注意RAG并不是“把文档扔进去就完事”。你要持续维护知识库的更新、清理过期文档、观察用户问题的分布这些比单纯调模型重要得多。4. 智能体设计从“一问一答”到“多步行动”如果说RAG解决的是“模型怎么知道更多知识”智能体解决的则是“模型怎么完成更复杂的任务”。智能体不是简单的聊天机器人而是能根据用户目标自主决定调用哪些工具、按什么顺序执行、以及如何处理中间结果的系统。4.1 智能体核心机制不是“对话机器人”那么浅一个真正可用的智能体至少包含工具调用能力Function Calling任务记忆Memory步骤规划Planning结果校验ValidationSpring AI 2.0提供了比较完整的工具调用支持。你可以通过Tool注解把业务方法暴露给大模型。Component public class OrderTools { Tool(根据用户ID查询最近订单) public String getRecentOrder(ToolParam(用户ID) String userId) { // 调用你的业务Service return orderService.queryRecentOrder(userId); } }然后在大模型配置中把该工具注入给ChatClientChatClient chatClient ChatClient.builder(chatModel) .defaultTools(new OrderTools()) .build();用户问“我最近买了什么”模型会先判断需要调用getRecentOrder然后根据工具返回值生成最终回答。4.2 简单Agent的实现决策、工具调用、结果解析这里要强调一个认知智能体不是越多工具越好。工具越多模型选错工具的概率也越高。我建议从一个企业内部最常见的真实业务开始先实现一个只能调用两个工具的最小Agent。比如工具A查天气工具B查用户订单用户自然语言进Agent先根据意图选择工具拿到结果再生成回答。这个流程看起来简单但你已经把“模型自主决策”和“业务系统联动”打通了。4.3 多工具协同与安全边界当需要多个工具协同任务时Spring AI 2.0可以让你通过ChatClient的循环调用来实现但你需要特别注意三点工具执行必须有超时和重试限制不要让一次模型决策导致长时间等待。工具权限必须有边界对高风险操作比如删库、转账要设置人工审批。日志必须完整记录“模型为什么调用这个工具”否则很难排查。安全提醒Agent能访问的工具越多越要严格限制。我见过不少Demo能在本地跑得很好一旦把Agent接到生产系统就被工具乱调用给坑了。5. 业务封装把AI能力沉淀成可复用的服务对于企业级项目直接让Controller调用ChatClient虽然方便但业务耦合太紧。正确做法是把AI能力封装成Service供上层业务复用。5.1 设计一个面向业务层的Service接口假设你有一个“智能客服”需求可以先定义接口public interface CustomerServiceAiService { String answerQuestion(String customerId, String question); }实现类里再把RAG和Agent组合起来。这样上层业务不需要知道底层是用了OpenAI还是Ollama是RAG还是纯模型调用。以后切换模型供应商只需改实现类或配置不会波及业务层。5.2 异常处理、日志与幂等AI调用天然存在不确定性所以异常处理不能像普通接口那样一把catch。建议至少处理模型服务不可用超时、限流降级或返回固定文案。模型返回格式错误增加重试或解析校验。业务工具调用失败记录失败原因并让模型有机会尝试其他路径。同时避免重复调用。例如用户连续点击“提交”按钮你的AI服务需要做一个幂等措施比如基于用户ID问题内容生成请求ID短时间内重复请求只返回缓存结果。5.3 通用工具函数的封装策略在Agent场景里Tool注解是一个很直观的封装方式。但要注意不是所有公共方法都应该被暴露给模型。你应该单独封装一层“AI可调用工具集”而不是直接暴露整个Service。Component public class AiToolset { private final OrderService orderService; private final UserService userService; Tool(查询用户基本信息) public UserInfo getUserInfo(ToolParam(用户ID) String userId) { return userService.getById(userId); } Tool(查询订单状态) public String queryOrderStatus(ToolParam(订单号) String orderId) { return orderService.queryStatus(orderId); } }这样业务Service的变动不会直接影响到模型可用的工具契约。6. 项目上线从“本地能跑”到“生产可用”开发一段时间后你会意识到“本地能跑”和“生产可用”之间有一条巨大的鸿沟。Spring AI 2.0可以帮你降低开发门槛但上线仍然要走完工程化那几步。6.1 部署模式与资源规划Spring AI应用本身就是一个Spring Boot应用打包成JAR后用普通的容器部署方式即可。但需要特殊考虑的是模型API的代理地址国内直连某些海外模型的网络不稳定建议配置可用的API地址或使用国内云厂商提供的中转服务。向量数据库本地开发可以用内存版生产环境需要选一个持久化的向量库比如Milvus、Pinecone、Pgvector等。资源占用应用本身并不重但如果用本地模型如Ollama就需要给模型预留独立的GPU或CPU资源。6.2 性能、成本与稳定性控制AI调用的成本控制比普通接口复杂。我建议缓存结果对高频重复问题做结果缓存。限流按用户、按IP或按Token数量做限流。超时控制大模型调用通常比普通接口慢但也要设置上限比如10-30秒。监控指标记录每次调用的延迟、Token消耗、失败原因。Spring AI提供了对模型调用的Metrics接口可以集成到Micrometer。6.3 长期维护与迭代建议最后这条经验我想说得直接一点AI项目不是“上线即结束”而是一个持续迭代的过程。你需要建立一个反馈闭环——用户的问题、模型的回答、知识库的更新频率都要有对应的观察和改进机制。Spring AI 2.0把开发门槛降低了但真正决定项目长期价值的还是你对业务语义的理解和数据质量的控制。如果你现在正准备上手Spring AI 2.0我的建议是不要从一个庞大的“AI中台”开始而是先从一条最小的业务链路跑通比如先做一个内部文档问答再逐步扩展到Agent和工具调用。这样每前进一步你都能明确知道问题出在哪里也更容易把过程中踩坑的经验沉淀下来。AI能力在Java后端落地并不需要你变成一个算法专家。它需要的是把“提示词、检索、工具调用、异常处理、监控”这些工程组件像搭积木一样组合起来。Spring AI 2.0提供了一个可靠的地基至于上面的业务结构最终还是由你的设计能力决定。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门