ARTICLE DETAIL

资讯详情

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

Spring AI 2.0实战:Java后端构建企业级RAG问答与智能体应用

Spring AI 2.0实战:Java后端构建企业级RAG问答与智能体应用 最近两年关于“Java 后端要不要学 AI”的讨论一直没有停过。很多团队的真实状态是Demo 已经跑通了模型能返回一句话但如果要把这个能力放进订单查询、售后工单、知识库问答、经营分析这些真实业务链路里马上就会遇到一连串工程问题——模型返回不稳定怎么办私有数据怎么进上下文让大模型自己调工具到底靠不靠谱这些 API 不能在生产出问题。如果你是一名 Java 后端开发者正在从“调用模型 API”走向“把 AI 能力做成产品能力”那 Spring AI 就是当前技术栈里最值得关注的一条主线。它的价值不在于多了一个新框架而在于它把大模型接入这件事重新拉回到了 Java 工程师熟悉的领域依赖注入、统一抽象、结构化数据、事务性的工程流程。标题里提到的 Spring AI 2.0 GA具体版本号请以官方发布为准但不管大版本怎么变企业级落地的核心链路是相对稳定的环境搭建、RAG 问答、智能体设计、业务封装、上线运维一整套都跑通才叫真正会用。这篇文章会按照一条完整的企业级实战路径展开先讲清楚 Spring AI 到底解决了什么问题再给出一套可直接复制的最小示例然后逐步深入到 RAG、结构化输出、智能体设计、向量存储覆盖、生产环境排错。读完这篇文章你应该能独立把一个基于 Spring AI 的后端问答或助手服务设计出来并且知道哪些环节容易出大坑。1. 这篇文章真正要解决的问题先说一个常见的现象很多团队引入大模型以后第一版功能往往是“拿着用户问题拼一个 Prompt发给模型把回复展示在页面上”。这个方案确实能用但它有两个致命问题。第一个问题是不可控。模型返回的是自然语言而你的业务系统需要的是订单号、状态码、金额、布尔值。如果你让用户对着一个订单系统说“帮我查一下最近一笔订单到哪了”模型理解完用户意图还不够你还得从一大段自然语言回复里把“已发货”这种状态解析出来。做得多了就会发现一个好好的业务接口硬生生被模型输出格式拖垮了。第二个问题是数据进不去。企业里的核心资产是私有数据比如产品手册、运维文档、客服历史工单。直接把这些数据拼进 Prompt 既不安全也不现实因为你不可能把整个知识库塞进上下文里。这就是 RAG检索增强生成存在的意义先检索出和问题最相关的片段再把片段交给模型做总结和生成。Spring AI 解决的核心问题就是把这两件事标准化。它把“调用模型”这个动作封装成了 Spring 风格的 API把“模型输出变成 Java 对象”做成了类型安全的结构化输出把“知识库文档进向量库”做成了抽象化的 VectorStore 操作。换句话说你不再需要每次接入一个模型都重写一遍 HTTP 调用、JSON 解析和工具调用逻辑。这篇文章更适合谁如果你正在做或准备做企业级 AI 应用尤其是 Java 技术栈、Spring Boot 项目、并且涉及 RAG 问答、智能体、私有知识库这些场景那么这篇文章的内容可以直接落到你的项目里。2. Spring AI 的核心概念与整体架构2.1 为什么是 Spring AI而不是直接用 HTTP 调用模型没有 Spring AI 的时候一个 Java 后端要接入大模型通常要自己做这些事封装 HTTP 客户端处理连接、超时、重试构建 Prompt 模板拼接历史对话和系统指令解析模型返回的 JSON手动转换成 Java 对象自己实现工具调用的协议Function Calling把模型选择的参数传给真实方法对接向量库时每个向量库都要单独写一套 CRUD。这些问题本身不难但每个团队都重复做一遍就是巨大的资源浪费。Spring AI 做的事情就是把这些步骤变成 Spring 风格的 Starter、AutoConfiguration 和统一接口。一个典型的 Spring AI 调用链路是这样的Java 业务代码 - ChatClient - Model API - 模型响应 - 结构化转换 - 返回 Java 对象这套抽象带来的直接价值是切换模型供应商时你的业务代码基本不用改改配置即可新增一个功能时不需要从零开始搭链路。2.2 核心抽象ChatClient、Prompt、Document、VectorStore、Tool要理解 Spring AI先掌握下面这几个关键概念概念解决的问题类比ChatClient统一聊天/生成入口类似 RestTemplate只是它对话的对象是大模型Prompt封装系统指令、用户消息、历史上下文类似 HTTP 请求体只是结构更丰富Document一个可被向量化/检索的文本片段类似一条待入库的业务记录VectorStore向量存储与相似度检索类似 ES 或 MySQL但按语义相似度查询Tool让模型在需要时调用你的 Java 方法类似把后端接口注册给模型其中ChatClient是平时使用最多的入口。在较新的 Spring AI 版本里它的 API 风格已经非常接近链式写法String answer chatClient.prompt() .system(你是一个订单客服助手回答必须简洁。) .user(我的订单还没到帮我看看) .call() .content();这里真正值得关注的是Prompt 不再是一个简单的字符串而是一个结构化的对象。系统指令、用户输入、工具定义、历史消息都可以放到这个对象里。这意味着你在写一个 AI 功能时可以像组装请求参数一样组装上下文而不是做大量字符串拼接。2.3 Spring AI Alibaba国内企业落地的一个重要分支在国内企业环境里很多团队需要将 Spring AI 与国产模型、阿里云中间件配合使用。目前有一个专门的生态项目叫 Spring AI Alibaba它在 Spring AI 的基础上提供了更适配国内模型和云服务的模块比如通义千问模型的接入、相关向量库和网关的集成。如果你们的业务部署在国内云环境并且已经大量使用阿里云的产品体系可以优先关注这个分支。但不管用哪个生态分支核心的设计思想是一致的上层业务代码不要直接依赖某个模型的 SDK而是依赖统一抽象。这样后面换模型、加模型成本都可控。3. 企业级接入前的架构决策在动手写代码之前先想清楚三件事模型怎么选、数据怎么进、权限怎么控。这几件事如果方向错了代码写得再漂亮上线后也会很痛苦。3.1 模型选型远程 API 还是本地模型远程 API如 OpenAI、国内主流大模型 API的优势是省心、效果稳定、不需要太多推理资源适合大多数业务场景。本地模型如通过 llama.cpp、Ollama 部署的开源模型的价值在于数据不出内网、可控性强适合对数据安全要求极高的企业。Spring AI 对这两种方式都有对应的抽象。如果你接的是 OpenAI 兼容协议的服务通常只需要改base-url、api-key、model这几个配置项。如果你的团队选择本地部署推理服务通常也是独立进程Spring 应用通过 HTTP 进行调用。这里有一个容易被忽视的点不要把模型推理和 Spring Boot 应用放进同一个 JVM 进程。本地模型推理非常吃内存很容易触发java.lang.OutOfMemoryError导致整个业务服务挂掉。更稳妥的做法是模型服务独立部署Spring Boot 只做业务编排。3.2 数据链路业务数据如何进入模型企业级 AI 应用最大的难点不是模型能力而是数据链路的完整度。以 RAG 为例一条完整的数据链路至少包含文档来源PDF、Word、数据库记录、API 返回值文档解析把非结构化内容切成文本片段文本切分按段落、长度、语义边界切成适合检索的块向量化通过 Embedding 模型把文本转成向量存储写入向量库检索根据用户问题召回最相关的 TopK 片段增强把片段注入 Prompt生成模型基于增强后的上下文回答问题。很多人在第 3 步就踩坑了。文本切分不是随便按固定长度切就行而是要尽量保持语义完整。比如一个订单说明被切成两半检索到后半段时模型根本不知道它讲的是哪个订单流程。3.3 安全与权限边界模型本身不具备你的业务权限体系。一个很常见的错误是把所有知识库文档无差别地注入给模型然后模型把不该说的内容也说了。企业实践中应该在检索之前就做权限过滤也就是“行级权限过滤”。比如只允许检索当前用户所属部门可见的文档这个过滤逻辑应该放在 RAG 的检索阶段而不是放在 Prompt 里让模型去判断。让模型“自觉”不要泄露数据是不可靠的。4. 环境准备与前置条件下面进入实操环节。先说清楚本教程使用的环境基线具体版本以你实际项目为准JDK 17 或更高版本Spring Boot 3.x 项目Spring AI 需要 Spring Boot 3 生态Maven 或 Gradle一个可用的模型 API或本地模型服务如果需要 RAG还需要一个向量库如 Elasticsearch、Opensearch、Redis、PGVector 等。4.1 创建 Spring Boot 工程并引入依赖最简单的方式是通过 Spring Initializr 创建工程然后手动添加 Spring AI 的 BOM 和 Starter 依赖。!-- pom.xml -- 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.ai/groupId artifactIdspring-ai-starter-model-openai/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency /dependencies这里需要提醒Spring AI 的版本更新较快不同小版本之间的 API 可能有微调。如果编译时报方法找不到优先去官方文档对照当前版本的 API而不是复制旧博客代码。4.2 配置模型接入在application.yml里配置模型供应商和模型名称。为了安全api-key不要硬编码在配置文件里而是通过环境变量注入spring: ai: openai: base-url: ${AI_BASE_URL:https://api.openai.com} api-key: ${AI_API_KEY:} chat: options: model: ${AI_MODEL:gpt-4o-mini} temperature: 0.7如果你的团队使用的是 OpenAI 兼容协议的服务包括国内模型服务、自建网关、本地模型的 HTTP 接口通常只需要调整base-url和model即可。这样设计的好处是业务代码完全感知不到模型供应商的变化。4.3 第一个最小调用示例创建一个 Controller注入ChatClient.Builder// 文件路径src/main/java/com/example/ai/ChatController.java RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder chatClientBuilder) { this.chatClient chatClientBuilder.build(); } GetMapping(/chat) public String chat(RequestParam String message) { return chatClient.prompt() .user(message) .call() .content(); } }启动服务后访问http://localhost:8080/chat?message你好如果能正常拿到模型回复说明整条链路已经打通。这也是后续所有实战内容的最小骨架。5. 完整示例让 Spring AI 输出结构化的 Java 对象模型返回自然语言对业务系统来说就是一个“黑盒字符串”。假设你在做一个售后工单系统用户说“我上周买的耳机坏了想退款”你需要从这句话里提取出用户意图、商品类目、期望动作。这时候如果把模型回复直接返回给前端前端还得再做一层解析非常不可控。Spring AI 提供了结构化输出能力核心目标就是把模型输出直接转换成 Java 实体类。这一点对 Java 后端特别友好因为你的 Service、Mapper、Event 全都依赖类型而不是依赖字符串。5.1 定义输出实体类创建一个 Java Record 来表示从用户诉求里提取的结果// 文件路径src/main/java/com/example/ai/dto/UserIntentDTO.java public record UserIntentDTO( JsonSchema(description 用户意图例如售后、订单查询、咨询) String intent, JsonSchema(description 涉及的商品类目) String category, JsonSchema(description 用户期望的动作) String action, JsonSchema(description 是否包含联系方式) boolean contactProvided ) { }注意这里的JsonSchema注解它会在给模型的 Prompt 中加入 JSON Schema 提示帮助模型按照约定格式输出。这是一种非常实用的工程手段与其在 Prompt 里写大段“你必须输出 JSON”不如用 Schema 把输出结构明确约束好。5.2 使用 BeanOutputConverter 做转换下面这个例子演示了如何从一段用户消息里提取结构化字段// 文件路径src/main/java/com/example/ai/service/IntentService.java Service public class IntentService { private final ChatClient chatClient; public IntentService(ChatClient.Builder builder) { this.chatClient builder.build(); } public UserIntentDTO parseIntent(String userMessage) { BeanOutputConverterUserIntentDTO converter new BeanOutputConverter(UserIntentDTO.class); Prompt prompt new Prompt( 你是客服工单系统的意图识别助手。 请从用户消息中提取结构化信息。 用户消息%s 输出要求%s .formatted(userMessage, converter.getFormat()) ); String content chatClient.prompt(prompt).call().content(); return converter.convert(content); } }这段代码的关键逻辑是converter.getFormat()会生成模型的输出格式说明模型返回字符串后converter.convert()负责把字符串反序列化成UserIntentDTO。这样后续业务代码拿到的就是类型安全的 Java 对象而不是需要正则或手工切割的字符串。如果模型返回的 JSON 里出现多余字段或者字段名不符converter.convert()会抛出异常这时候你至少能明确感知到“模型输出不符合约定”而不是让脏数据悄悄流进业务层。6. RAG 问答实战让知识库真正能回答问题RAG 是企业级 AI 落地的重要场景。它的目的不是让模型“记住”你的私有数据而是让模型在回答时可以参考私有数据。RAG 的核心是先检索后生成模型只负责组织语言。6.1 文档导入与向量化在 Spring AI 中Document是一个统一的文档抽象。它包含文本内容和元数据。示例中我们会把一段产品说明写入向量库// 文件路径src/main/java/com/example/ai/service/KnowledgeService.java Service public class KnowledgeService { private final VectorStore vectorStore; private final EmbeddingModel embeddingModel; public KnowledgeService(VectorStore vectorStore, EmbeddingModel embeddingModel) { this.vectorStore vectorStore; this.embeddingModel embeddingModel; } public void addDocument(String businessDocId, String content) { Document doc new Document(content, Map.of( businessDocId, businessDocId, category, product-manual )); vectorStore.add(List.of(doc)); } }这里有一个需要特别强调的坑如果你多次调用addDocument而不做去重同一个业务文档的旧向量和新向量会同时存在于向量库中。这样检索时会出现重复内容甚至旧版本文档“污染”新版本答案。6.2 向量存储的覆盖与去重问题Spring AI 的VectorStore接口默认提供的是add、delete、similaritySearch等方法它没有一个统一的 upsert 语义。所以在企业实践里通常需要自己实现“先删后写”。实现思路是在文档元数据中维护一个唯一的业务文档 ID比如businessDocId写入前先根据这个 ID 删除旧向量再写入新向量。public void upsertDocument(String businessDocId, String content) { // 按业务文档 ID 删除旧向量 var filter new Filter.Expression( Filter.ExpressionType.EQ, businessDocId, businessDocId ); vectorStore.delete(filter); // 写入新向量 Document doc new Document(content, Map.of(businessDocId, businessDocId)); vectorStore.add(List.of(doc)); }这个“先删后写”的模式适用于绝大多数向量存储场景。如果你发现向量库里的文档越积越多先检查是不是没有做基于业务 ID 的去重。6.3 用 ChatClient 实现 RAG 问答RAG 问答的完整代码可以封装成一个 Service。它的职责是接收用户问题从向量库召回相关片段把片段拼进 Prompt交给模型生成答案。// 文件路径src/main/java/com/example/ai/service/RagChatService.java Service public class RagChatService { private final ChatClient chatClient; private final VectorStore vectorStore; public RagChatService(ChatClient.Builder builder, VectorStore vectorStore) { this.chatClient builder.build(); this.vectorStore vectorStore; } public String answer(String question) { // 1. 语义检索取最相关的 3 条片段 ListDocument docs vectorStore.similaritySearch( SearchRequest.builder() .query(question) .topK(3) .build() ); // 2. 拼接上下文 String context docs.stream() .map(Document::getContent) .reduce((a, b) - a \n b) .orElse(无相关资料); // 3. 增强生成 return chatClient.prompt() .system(你是企业知识库助手。请只根据提供的资料回答如果资料中没有相关信息请明确说明。) .user(资料\n context \n\n问题 question) .call() .content(); } }这里有一个检索数量控制的问题也就是大家常问的“如何指定关联的上下文的数量限制”。在SearchRequest里通过topK(3)就能限制召回的文档片段数量。片段数量不是越多越好因为每个片段都会占用模型上下文片段过多不仅会拉长响应时间还可能引入无关信息干扰模型判断。6.4 RAG 的四个常见误区把整篇 PDF 塞进向量库而不做切分。这会导致检索到的片段过大信息噪声高。不做权限过滤。不同角色看到的文档范围不同权限过滤应该在检索阶段做。不做元数据清理。文档更新后旧向量没有删除导致答案过时。把“不知道”强行回答成“知道”。系统 Prompt 必须明确告诉模型资料不足时可以说不知道。7. 智能体设计从“问答”到“自动完成任务”如果说 RAG 解决的是“回答得更准”那智能体Agent解决的是“直接帮用户把事情办了”。典型场景是用户说“帮我查一下订单 A10086 的物流信息”系统不仅返回一句“好的”而是真的调用订单查询接口把结果返回给用户。7.1 什么是 Agent一个带工具的执行器在 Spring AI 语境里Agent 不是一个神秘的独立进程而是一个带有工具调用能力的 ChatClient 工作流。模型负责理解用户意图、决定调用哪个工具你的 Java 方法负责实际执行。这种能力在底层依赖 Function Calling / Tool Calling。没有工具调用时你只能让模型“建议”用户去查询有了工具调用模型可以直接发起查询。这是智能体与普通聊天最大的区别。7.2 使用 Tool 定义业务工具Spring AI 支持通过注解将普通 Java Bean 方法暴露给大模型。// 文件路径src/main/java/com/example/ai/tool/OrderTools.java Component public class OrderTools { Tool(name queryOrderStatus, description 根据订单号查询订单物流状态) public String queryOrderStatus(String orderId) { // 实际项目中这里会调用订单服务 return 订单 orderId 当前状态已发货预计明天送达。; } }这里需要理解的关键点是Tool注解里的description非常重要。模型就是靠这个描述来决定“什么时候该调用这个工具”的。描述写得含糊模型就会在错误场景调用或者在正确场景不调用。7.3 让模型自己决定调用工具接下来把工具注册到 ChatClient 上// 文件路径src/main/java/com/example/ai/service/OrderAgentService.java Service public class OrderAgentService { private final ChatClient chatClient; public OrderAgentService(ChatClient.Builder builder) { this.chatClient builder.build(); } public String handleUserMessage(String userMessage) { return chatClient.prompt() .system(你是订单助手。当用户询问订单状态时必须使用 queryOrderStatus 工具查询。) .user(userMessage) .tools(new OrderTools()) .call() .content(); } }运行后输入“我的订单 A10086 到哪了”模型会自主决定调用queryOrderStatus工具拿到结果后再生成一段自然语言回复。7.4 Agent 循环设计的坑最简单的 Agent 模式是一次工具调用就结束。但真实场景往往需要多轮工具调用用户问“给我推荐一款适合我的手机”你不仅要查用户信息还要查商品库存、查价格最后综合结果给答案。如果你发现模型只调用了第一个工具然后就用不完整的信息开始回答通常是因为你没有设计“多步执行循环”。在 Spring AI 里这类需求通常需要你自己维护一个“工具调用结果回填”的循环也就是把模型返回的工具调用结果再次作为上下文传给模型让模型继续判断是否需要调用下一个工具。设计上的一个稳定建议是给 Agent 的任务加上“边界”。明确告诉模型哪些事情可以做哪些事情不能做。比如订单 Agent 只能查订单状态不能直接发起退款。这个边界不能只靠 Prompt 约束还要在工具方法内部做权限校验。8. 生产环境上线的关键注意点一个 AI 功能从“本地能跑”到“生产可用”中间有很多容易被忽视的细节。下面几条是我认为企业级项目最重要的事项。8.1 超时、重试与连接管理大模型接口的延迟通常是秒级而不是毫秒级。默认 HTTP 客户端很可能无法覆盖这种场景。你需要显式地配置连接超时和读取超时。在 Spring AI 中可以通过自定义RestClient.Builder或WebClient.Builder来实现更精细的控制。如果使用本地模型服务还要考虑模型服务可能过载。当并发请求集中进来时模型推理时间会明显上升。这时候要做连接池与队列设计并且对慢请求做超时熔断而不是无限等待。8.2 模型返回的稳定性模型输出天然具有随机性。同一个 Prompt这次返回 JSON下次可能在 JSON 前后附加解释文字。结构化输出能减少这个问题但不能完全消除。工程上更稳妥的做法是对模型返回内容做“兜底校验”。如果解析失败可以自动重试一次并强制要求“只输出 JSON不要解释”。如果重试仍然失败则走降级逻辑返回可读的提示信息而不是直接抛出 500。8.3 日志与可观测性AI 应用排错最大的难点是用户说答案不对但你不知道是检索错了、Prompt 错了还是模型本身输出错了。因此生产环境必须记录三个关键信息用户输入的原始问题RAG 检索到的文档内容和相关度模型最终返回的结果。建议把这几类日志结构化输出方便后续检索和分析。开销可控的团队还可以把这套链路接入统一的链路追踪系统把调用链串起来。8.4 成本控制模型调用是按 Token 计费的Prompt 越长成本越高。RAG 场景里有一个非常常见的浪费检索到 10 条片段全塞进 Prompt但模型真正用到的可能只有 2 条。在生产项目里建议通过实验确定最优的topK值同时把系统 Prompt 控制在合理长度。另一个思路是将历史对话做滑动窗口截断而不是把全部历史都发给模型。9. 常见问题与排查方法以下这些问题是 Spring AI 项目里出现频率较高的整理成排查表格方便遇到问题时快速定位。问题现象可能原因排查方式解决方案调用模型报 401/403API Key 缺失或权限不足检查环境变量是否正确注入查看模型平台返回的具体错误码正确配置 api-key确认模型白名单权限请求超时模型推理时间长HTTP 默认超时过短查看日志中耗时和超时时间配置调整连接/读取超时配置重试和队列结构化输出解析失败模型返回了多余文本或字段名与实体类不一致打印模型原始返回内容强制要求只输出 JSON重试一次或放宽解析规则向量库文档重复每次写入都调用 add没有按业务 ID 去重查询向量库中同一 businessDocId 的文档数量实现先删除后写入的 upsert 逻辑回答完全基于模型幻觉不参考知识库Prompt 中没有约束“只根据资料回答”检查系统 Prompt 和检索结果是否为空增强系统 Prompt并增加检索结果校验RAG 检索不到相关内容文档切分不合理、Embedding 模型不匹配检查切块长度和检索返回结果调整切块策略更换更合适的 Embedding 模型本地模型 Spring Boot 出现 OOM模型推理和业务服务共用 JVM 内存查看 JVM 内存监控将模型推理外置为独立服务编译报错找不到 APISpring AI 版本 API 有调整对照当前版本的官方文档和类路径升级/锁定版本按新 API 调整代码这里面最值得重视的是第一个和最后一个。HTTP 401/403 问题在模型平台更换时尤其常见排查时先确认 base-url 是否写对、api-key 是否属于当前平台。而 API 方法找不到的问题通常是因为从旧博客或旧项目复制了不兼容的代码解决方式是锁定版本并随手查阅官方文档。10. 最佳实践与工程建议到这里核心链路基本已经完整。下面这些工程建议是把我自己在 Spring AI 项目落地中的经验沉淀出来的比较适合架构设计阶段参考。10.1 将 Prompt 视为代码资产Prompt 不应散落在 Controller 或 Service 的字符串拼接里。更推荐的做法是把 Prompt 模板集中管理可以放在专用的常量类、配置文件中甚至做成数据库配置。每次 Prompt 变更都应该像代码变更一样走评审和测试流程。Spring AI 的 PromptTemplate 可以帮你做参数的格式化。这样你能把系统指令、用户输入、检索上下文清晰分开也更容易维护。10.2 封装一层 AI Service不要把所有 AI 逻辑直接写在 Controller 里。建议在业务层之上再封装一层 AIService专门负责构造 Prompt 参数、调用 ChatClient、解析结构化输出、处理异常和降级。这样做的最大好处是后续从 OpenAI 换到国内模型时业务代码不需要感知底层变化。同时AI Service 内部要对异常做分类。模型调用失败和业务校验失败应该走不同逻辑。比如模型超时走降级文案查询不到订单走业务提示两者不能混为一谈。10.3 敏感数据脱敏不要把手机号、身份证号、密钥等敏感信息直接塞进 Prompt。如果需要用真实数据做业务判断尽量在本地完成判断只把“判断结果摘要”传给模型。如果你的工具方法需要接收用户输入输入校验要按普通接口的标准来做不要因为它是 AI 应用就放松警惕。10.4 用最小闭环驱动功能迭代AI 应用最大的风险是过度设计。很多团队一开始就规划了复杂的多 Agent 架构结果发现连最基础的单轮问答都不稳定。先跑通一个最小闭环一个 Controller、一个 ChatClient、一个结构化输出、一个业务工具。确认链路稳定后再逐步引入 RAG、多工具、多轮循环。11. 总结Spring AI 给 Java 后端带来了什么回到开头的问题。Java 后端开发者学习 AI真正的切入点不应该是去训练模型而是把模型作为一项基础设施接入到自己的业务系统里。Spring AI 在这条路上提供了一个很务实的抽象层ChatClient 统一了模型调用结构化输出解决了类型安全VectorStore 屏蔽了向量库差异Tool 把工具调用机制简化成了普通 Bean 方法。从环境搭建到 RAG 问答、从智能体设计到业务封装再到生产环境的上线排错这条链路其实并没有想象中那么复杂。最关键的还是那几个朴素的问题数据怎么进、输出怎么控、权限怎么管、异常怎么兜底。只要把这些问题想清楚大模型在你的系统里就不再是一个不可控的黑盒而是一个可以被 Java 代码编排的组件。下一步建议你基于本文的最小示例先跑通一个 Spring Boot 项目然后把其中一个真实业务场景改成结构化输出再加上一个工具调用。等你把这三个动作做完再回头看那些更复杂的 Agent 编排思路会清晰很多。如果这篇文章对你有帮助建议收藏备用后续需要落地 RAG 或智能体项目时可以直接照着做。
返回列表