Java后端转型AI应用开发实战:基于SpringAI与LangChain4j构建RAG与Agent

Java后端转型AI应用开发实战:基于SpringAI与LangChain4j构建RAG与Agent 如果你是一名Java后端开发者最近可能正被一种焦虑感包围身边的同事或朋友开始讨论AI应用开发谈论着RAG、Agent、LangChain这些新名词而你还在日复一日地写着CRUD接口。你或许会想AI开发是不是Python的天下Java开发者转型AI应用开发到底有没有一条清晰、可落地的路径答案是肯定的而且这条路径比你想象的要顺畅。SpringAI和LangChain4j的出现正在彻底改变Java生态在AI应用开发中的格局。它们不是简单的API封装而是将AI能力无缝集成到Spring Boot熟悉的开发范式里让你能用写Controller和Service的思维去构建智能应用。这意味着你积累多年的Java工程化经验、对高并发和分布式系统的理解不仅不会过时反而会成为你构建可靠、可维护AI产品的核心优势。本文不是一篇泛泛而谈的概念介绍而是一份为Java全栈尤其是后端开发者量身定制的“转型实战指南”。我们将彻底抛弃“调个API就算AI”的肤浅认知从零开始手把手带你交付一个完整的、具备生产级思考的AI智能产品。你将掌握的核心技术栈包括SpringAI官方钦定的AI集成框架、LangChain4jJava版的AI应用编排利器、向量数据库知识的大脑、RAG让AI“读懂”你私有资料的关键以及Agent让AI自主决策和行动的智能体。更重要的是我们会深入探讨这些技术如何与你熟悉的Spring Boot、MyBatis、Redis等后端技术栈协同工作构建出真正可用的系统。1. 为什么Java后端开发者必须关注AI应用开发在深入技术细节之前我们必须先回答一个根本问题为什么是现在为什么Java开发者需要投入精力学习AI应用开发首先市场需求的转变。企业级的AI应用核心诉求不再是炫技般的单点能力演示而是稳定、可靠、可集成、易维护的工程化解决方案。一个需要7x24小时稳定运行、能与现有ERP、CRM系统打通、具备完善权限和审计日志的智能客服或知识库系统其复杂性远超一个Jupyter Notebook脚本。这正是Java和Spring生态擅长解决的领域——工程化、标准化和规模化。其次技术栈的成熟。过去Java调用AI模型往往需要自己封装HTTP客户端处理复杂的JSON解析和异步调用繁琐且易错。现在SpringAI的诞生标志着Spring官方正式入场。它提供了统一的ChatClient、EmbeddingClient等抽象让切换OpenAI、Azure OpenAI、Ollama本地模型等后端就像更换一个数据库驱动一样简单。而LangChain4j则提供了更高层次的抽象用于编排复杂的AI工作流如RAG、Agent。这两者结合极大地降低了Java开发者进入AI应用开发的门槛。第三你的后端经验是宝贵资产。AI应用不仅仅是模型推理。它涉及数据预处理与管道这和你用Spring Batch处理ETL任务异曲同工。API设计与聚合和你设计Restful API供前端调用没有区别。异步与并发处理处理大量文档的向量化正是你熟悉的CompletableFuture或反应式编程的用武之地。缓存与性能优化向量检索结果缓存、Token消耗监控需要你已有的Redis、监控系统经验。安全与权限如何控制对AI能力的访问、如何审计AI的每一次调用这是企业级应用的基础。因此学习AI应用开发对你而言不是从零开始学Python而是将AI作为一种新的“数据源”或“业务逻辑组件”集成到你已有的、强大的Java工程体系之中。你的目标不是成为算法专家而是成为**“AI应用架构师”**——那个能连接AI能力与真实业务需求并确保其稳定落地的人。2. 核心概念全景图从CRUD到AI Stack的思维转变要构建AI应用我们需要先理解几个核心概念并建立与传统后端开发对应的思维模型。传统后端概念AI 应用对应概念核心差异与联系数据库 (MySQL)向量数据库 (Vector DB)传统DB按行和列存储结构化数据通过精确匹配或索引查询。向量DB存储文本、图片等生成的“向量”一组数字通过计算向量间的“距离”相似度进行模糊查询用于语义搜索。Service层业务逻辑AI Agent (智能体)Service包含固定的if-else规则。Agent则利用大语言模型(LLM)作为“推理引擎”根据目标、工具和上下文动态规划并执行步骤处理开放性问题。API网关/聚合层LangChain4j (编排框架)网关负责路由和聚合多个微服务。LangChain4j负责编排多个AI组件模型调用、工具使用、记忆管理成一个连贯的工作流如一个复杂的问答流程。外部服务调用 (FeignClient)AI Model Client (ChatClient)调用内部或第三方HTTP服务。通过ChatClient或EmbeddingClient统一调用本地或云端的AI模型服务。数据缓存 (Redis)向量缓存 / 对话记忆缓存数据库查询结果。缓存昂贵的向量嵌入结果或存储Agent的短期对话历史以节省成本并维持上下文。CRUD操作RAG (检索增强生成)流程CRUD是对数据库的直接增删改查。RAG是“检索(从向量库查) - 增强(将查到的资料作为上下文) - 生成(让AI基于上下文回答)”的复合操作是AI知识库的核心。通俗理解关键概念向量与嵌入(Embedding)把一段文本如一个句子、一个段落通过AI模型转换成一组有意义的数字比如768个浮点数。语义相近的文本其向量在数学空间里的“距离”也更近。这是让计算机“理解”语义的基础。RAG (检索增强生成)这是解决大模型“幻觉”胡编乱造和知识过时问题的关键技术。当用户提问时系统不是让模型凭空回忆而是先从你的向量知识库中检索出最相关的资料片段然后把这些资料作为“参考依据”连同问题一起交给模型让它生成答案。这就像考试时允许你开卷但只能翻指定的参考书。Agent (智能体)一个能自主理解目标、使用工具如搜索网络、执行代码、查询数据库、并逐步完成复杂任务的AI程序。你可以把它想象成一个拥有大语言模型作为“大脑”并能操作各种软件工具的虚拟员工。理解了这些对应关系你就会发现开发AI应用的思维模式是用向量数据库替代或补充传统数据库进行语义查询用AI模型作为核心“逻辑处理器”来处理非结构化问题和复杂决策并用编排框架来管理整个工作流的生命周期。3. 环境准备搭建你的Java AI开发沙箱在开始编码前我们需要一个干净、可复现的开发环境。这里我们选择最主流的组合。3.1 基础环境JDK 17 或 21Spring Boot 3.x 和 SpringAI 的推荐版本。确保环境变量配置正确。# 检查版本 java -versionMaven 3.6 或 Gradle本文以Maven为例。IDEIntelliJ IDEA推荐或 VS Code with Java插件。Docker Desktop用于快速启动本地向量数据库等基础设施。3.2 关键基础设施本地向量数据库为了快速实验我们使用ChromaDB它轻量、易用且支持内存模式。# 使用Docker快速启动一个Chroma服务 docker pull chromadb/chroma docker run -d -p 8000:8000 --name chroma-test chromadb/chroma启动后可以通过http://localhost:8000/api/v1/heartbeat验证服务是否正常。3.3 本地大语言模型可选但推荐完全依赖OpenAI等云服务会产生费用且受网络影响。为了学习和调试强烈建议在本地运行一个轻量级模型。Ollama是当前最佳选择。前往 ollama.com 下载并安装。拉取一个模型例如小巧但能力不错的qwen2.5:7b约4.3GBollama pull qwen2.5:7b运行模型服务ollama run qwen2.5:7b默认会在http://localhost:11434提供API。3.4 创建Spring Boot项目使用 start.spring.io 或IDE创建新项目。Project: MavenLanguage: JavaSpring Boot: 3.2.x (确保 3.2.0 SpringAI需要)Packaging: JarJava: 17Dependencies:Spring WebSpring AI(在添加依赖时搜索或手动添加坐标)Lombok(简化代码)Spring Boot DevTools(热部署)生成项目后关键的pom.xml依赖如下版本请使用最新稳定版dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI 核心依赖 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-core/artifactId version1.0.0-M5/version !-- 注意截至撰写时M5为最新请检查更新 -- /dependency !-- Spring AI 对接 OpenAI -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version1.0.0-M5/version /dependency !-- Spring AI 对接 Ollama (本地模型) -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-ollama-spring-boot-starter/artifactId version1.0.0-M5/version /dependency !-- LangChain4j 核心 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId version0.31.0/version /dependency !-- LangChain4j 与 Spring Boot 集成 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-spring-boot-starter/artifactId version0.31.0/version /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies注意SpringAI版本迭代较快请根据 Spring AI Project 官网更新版本号。4. 第一步用SpringAI实现最简单的AI对话让我们先忘记复杂的架构用最少的代码感受一下在Spring Boot里调用AI是多么简单。4.1 配置模型连接在application.yml中配置。我们先配置Ollama本地作为备选OpenAI作为主选需要API Key。spring: ai: # 配置OpenAI (需申请API KEY) openai: api-key: ${OPENAI_API_KEY:} # 建议使用环境变量 chat: options: model: gpt-3.5-turbo # 配置Ollama (本地) ollama: base-url: http://localhost:11434 chat: options: model: qwen2.5:7b # 指定默认使用的Chat模型。可选openai, ollama chat: client: type: ollama # 开发调试先用本地模型4.2 编写一个简单的对话Controller创建一个AiChatController。package com.example.aidemo.controller; import lombok.RequiredArgsConstructor; import org.springframework.ai.chat.client.ChatClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; RestController RequiredArgsConstructor public class AiChatController { // SpringAI 会自动注入一个配置好的 ChatClient private final ChatClient chatClient; GetMapping(/ai/chat) public String chat(RequestParam(defaultValue 你好介绍一下你自己) String message) { // 调用AI对话就是这么简单 String response chatClient.prompt() .user(message) .call() .content(); return response; } }启动应用访问http://localhost:8080/ai/chat?messageJava是什么你将立刻得到AI的回复。至此你已经完成了Java AI开发的第一步——将大模型作为一个“服务”注入到你的Spring上下文中并通过一个简单的REST接口暴露其能力。这和你注入一个UserService并调用其方法在工程思维上没有任何区别。5. 核心实战构建一个企业级RAG知识库系统单一对话能力价值有限。接下来我们构建一个真正的生产级核心——RAG知识库系统。它的功能是允许用户上传公司内部文档如产品手册、规章制度然后以自然语言提问系统从文档中查找相关信息并生成精准答案。5.1 系统架构设计一个健壮的RAG系统包含以下关键组件我们将用Java逐一实现文档加载与解析器处理PDF、Word、TXT、Markdown等格式。文本分割器将长文档切成适合模型处理的片段。嵌入模型客户端将文本片段转换为向量。向量数据库客户端存储和检索向量。检索器执行相似度搜索。提示词模板引擎构造包含上下文和问题的指令给大模型。对话链将以上组件串联成完整流程。5.2 实现文档处理与向量化存储首先我们需要将文档“喂”给系统即向量化并存入数据库。我们创建一个KnowledgeBaseService。package com.example.aidemo.service; import dev.langchain4j.data.document.Document; import dev.langchain4j.data.document.DocumentParser; import dev.langchain4j.data.document.parser.apache.pdfbox.ApachePdfBoxDocumentParser; import dev.langchain4j.data.document.parser.apache.poi.ApachePoiDocumentParser; import dev.langchain4j.data.document.splitter.DocumentSplitters; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.EmbeddingStoreIngestor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.reader.ExtractedTextFormatter; import org.springframework.ai.reader.pdf.PagePdfDocumentReader; import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig; import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.nio.file.Path; import java.util.List; Service Slf4j RequiredArgsConstructor public class KnowledgeBaseService { // LangChain4j 的嵌入模型底层会使用SpringAI配置的模型 private final EmbeddingModel embeddingModel; // 向量存储这里以内存存储为例生产环境需换为Chroma/Pinecone等 private final EmbeddingStoreTextSegment embeddingStore; /** * 上传并处理文档将其向量化后存入知识库 */ public void ingestDocument(MultipartFile file) throws IOException { // 1. 根据文件类型选择解析器 DocumentParser parser getDocumentParser(file.getOriginalFilename()); // 2. 将文件解析为Document对象 // 这里简化处理实际应将文件保存到临时目录 Path tempFile java.nio.file.Files.createTempFile(upload, getFileExtension(file.getOriginalFilename())); file.transferTo(tempFile); Document document parser.parse(tempFile.toFile()); // 3. 创建文档摄取器负责分割、嵌入、存储 EmbeddingStoreIngestor ingestor EmbeddingStoreIngestor.builder() .documentSplitter(DocumentSplitters.recursive(500, 100)) // 递归分割最大500字符重叠100字符 .embeddingModel(embeddingModel) .embeddingStore(embeddingStore) .build(); // 4. 执行摄取 ingestor.ingest(document); log.info(文档 {} 已成功向量化并存入知识库。, file.getOriginalFilename()); // 5. 清理临时文件 java.nio.file.Files.deleteIfExists(tempFile); } private DocumentParser getDocumentParser(String fileName) { if (fileName.toLowerCase().endsWith(.pdf)) { return new ApachePdfBoxDocumentParser(); } else if (fileName.toLowerCase().endsWith(.docx) || fileName.toLowerCase().endsWith(.doc)) { return new ApachePoiDocumentParser(); } else { // 默认为文本文件 return DocumentParser.ofText(); } } private String getFileExtension(String fileName) { return fileName.substring(fileName.lastIndexOf(.)); } }代码解释EmbeddingStoreIngestor是LangChain4j提供的“一站式”摄取管道它内部完成了分割 - 向量化 - 存储的完整流程。DocumentSplitters.recursive(500, 100)是关键的文本分割策略。它尝试按语义如段落、句子递归分割确保每个片段不超过500字符且相邻片段有100字符的重叠以避免信息在分割点丢失。这里为了简化EmbeddingStoreTextSegment使用了内存实现。在生产中我们需要将其替换为连接真实向量数据库的Bean。5.3 配置向量数据库连接以Chroma为例我们需要将内存存储替换为连接我们Docker中ChromaDB的存储。 首先添加ChromaDB的依赖LangChain4j扩展dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-store-embedding-chroma/artifactId version0.31.0/version /dependency然后配置一个ChromaDB的EmbeddingStoreBeanpackage com.example.aidemo.config; import dev.langchain4j.store.embedding.chroma.ChromaEmbeddingStore; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class VectorStoreConfig { Bean public ChromaEmbeddingStore chromaEmbeddingStore() { // 连接到本地运行的ChromaDB return ChromaEmbeddingStore.builder() .baseUrl(http://localhost:8000) .collectionName(company_knowledge) // 集合名称类似于数据库的表 .build(); } }修改KnowledgeBaseService将EmbeddingStoreTextSegment的注入来源改为ChromaEmbeddingStore。5.4 实现RAG检索与问答链这是最核心的部分。我们创建一个RagQueryService。package com.example.aidemo.service; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever; import dev.langchain4j.service.AiServices; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; Service RequiredArgsConstructor public class RagQueryService { private final ChatLanguageModel chatModel; // SpringAI或LangChain4j的聊天模型 private final EmbeddingStoreTextSegment embeddingStore; private final EmbeddingModel embeddingModel; // 定义AI服务的接口 interface Assistant { String answer(String question); } public String query(String question) { // 1. 构建检索器从向量库中查找与问题相关的内容 EmbeddingStoreContentRetriever retriever EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) .embeddingModel(embeddingModel) .maxResults(3) // 返回最相关的3个片段 .build(); // 2. 使用AiServices动态创建代理并注入检索器 Assistant assistant AiServices.builder(Assistant.class) .chatLanguageModel(chatModel) .contentRetriever(retriever) // 关键注入RAG能力 .build(); // 3. 提问。LangChain4j会自动完成“检索-增强-生成”的流程。 return assistant.answer(question); } }这段代码的精妙之处我们定义了一个纯接口Assistant其中只有一个answer方法。我们并没有实现它。AiServices.builder(...).build()动态生成了这个接口的实现类。这个过程被称为“AI服务动态代理”。通过.contentRetriever(retriever)我们告诉这个代理在回答任何问题之前先去向量库中检索相关内容并将内容作为上下文附加到问题中再交给大模型生成答案。开发者无需手动编写“检索-拼接-提问”的模板代码。这就是框架的价值。5.5 创建REST API端点最后我们创建控制器将上传和问答能力暴露为HTTP接口。package com.example.aidemo.controller; import com.example.aidemo.service.KnowledgeBaseService; import com.example.aidemo.service.RagQueryService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; RestController RequestMapping(/api/kb) RequiredArgsConstructor public class KnowledgeBaseController { private final KnowledgeBaseService knowledgeBaseService; private final RagQueryService ragQueryService; PostMapping(/upload) public ResponseEntityString uploadDocument(RequestParam(file) MultipartFile file) { try { knowledgeBaseService.ingestDocument(file); return ResponseEntity.ok(文档上传并处理成功); } catch (IOException e) { return ResponseEntity.internalServerError().body(文件处理失败: e.getMessage()); } } GetMapping(/query) public ResponseEntityString query(RequestParam String q) { String answer ragQueryService.query(q); return ResponseEntity.ok(answer); } }6. 进阶打造具备自主行动能力的AI AgentRAG让AI有了“知识”而Agent让AI有了“手脚”。Agent能理解复杂目标并自主调用工具函数来完成任务。例如“帮我查一下北京明天天气然后根据天气推荐室内活动最后把推荐结果总结成邮件草稿。”6.1 定义工具Tools工具就是Agent可以调用的Java方法。我们定义两个简单的工具。package com.example.aidemo.tools; import dev.langchain4j.agent.tool.Tool; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; Component // 必须声明为Spring Bean public class CompanyTools { Tool(根据员工姓名查询其所在部门和邮箱) // Tool注解是关键 public String getEmployeeInfo(String name) { // 这里应该是查询数据库或HR系统我们模拟返回 // 真实项目中这里可以注入你的UserService或MyBatis Mapper if (张三.equals(name)) { return 姓名张三部门研发部邮箱zhangsancompany.com; } else if (李四.equals(name)) { return 姓名李四部门市场部邮箱lisicompany.com; } else { return 未找到员工: name; } } Tool(获取当前服务器时间) public String getCurrentTime() { return LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)); } }6.2 创建并运行Agent我们创建一个AgentService将工具赋予AI。package com.example.aidemo.service; import com.example.aidemo.tools.CompanyTools; import dev.langchain4j.agent.tool.ToolExecutionRequest; import dev.langchain4j.agent.tool.ToolSpecification; import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.memory.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.service.AiServices; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; Service Slf4j public class AgentService { private final ChatLanguageModel chatModel; private final CompanyTools companyTools; private Assistant assistant; // 定义AI助手接口 interface Assistant { String chat(String userMessage); } public AgentService(ChatLanguageModel chatModel, CompanyTools companyTools) { this.chatModel chatModel; this.companyTools companyTools; } PostConstruct public void init() { // 创建具有对话记忆和工具的AI服务 ChatMemory chatMemory MessageWindowChatMemory.withMaxMessages(20); this.assistant AiServices.builder(Assistant.class) .chatLanguageModel(chatModel) .chatMemory(chatMemory) // 使Agent能记住上下文 .tools(companyTools) // 注入工具 .build(); } public String executeTask(String task) { log.info(用户任务: {}, task); String response assistant.chat(task); log.info(Agent回复: {}, response); return response; } }6.3 测试Agent创建一个简单的测试端点。GetMapping(/agent) public String agentTask(RequestParam String task) { return agentService.executeTask(task); }访问http://localhost:8080/api/agent?task请先查询员工张三的信息然后告诉我现在的服务器时间。你会看到类似以下的日志和结果用户任务: 请先查询员工张三的信息然后告诉我现在的服务器时间。 [Agent思考] 我需要调用两个工具。先调用 getEmployeeInfo再调用 getCurrentTime。 [工具调用] getEmployeeInfo with arguments: {name: 张三} [工具结果] 姓名张三部门研发部邮箱zhangsancompany.com [工具调用] getCurrentTime with arguments: {} [工具结果] 2024-05-27 14:30:25 Agent回复: 员工张三的信息是姓名张三部门研发部邮箱zhangsancompany.com。当前的服务器时间是2024-05-27 14:30:25。这就是Agent的力量它自动规划了步骤依次调用了两个工具并将结果整合成了一段通顺的回复。你可以将工具替换为任何Java方法调用内部API、执行数据库查询、发送邮件、调用第三方服务等等。7. 生产环境关键考量与最佳实践将上述Demo变为生产可用的系统还需要解决一系列工程问题。7.1 向量数据库选型与优化选型Chroma适合原型和中小项目。生产环境可考虑Milvus功能丰富性能强劲适合大规模向量检索。PgVectorPostgreSQL插件如果你的技术栈以PG为主这是最自然的选择。Qdrant/Weaviate云原生设计API友好。索引优化生产数据量大时必须创建向量索引如HNSW、IVF。这能极大提升检索速度。元数据过滤除了向量相似度还应支持按来源、日期、部门等元数据过滤这需要向量数据库支持。7.2 RAG流程的增强与调优查询重写用户问题可能模糊可以先让LLM对问题进行重写或扩展再用于检索。多路检索与重排序使用不同分割策略或检索器进行多次检索然后用一个更小的模型对结果进行重排序选出最相关的。引用与溯源在回复中明确标注答案来源于哪些文档的哪几页这是企业级应用的基本要求。缓存策略对常见问题的向量和检索结果进行缓存显著降低成本和延迟。7.3 提示词工程与系统指令不要将系统指令硬编码在代码中。将其外部化配置。# application.yml app: prompt: system: | 你是一个专业、严谨的公司内部知识库助手。 你必须严格根据提供的上下文信息回答问题。 如果上下文信息不足以回答问题请明确告知“根据现有资料我无法回答这个问题”。 请用中文回复并保持友好。在服务中读取并使用String systemPrompt env.getProperty(app.prompt.system); PromptTemplate promptTemplate new PromptTemplate(systemPrompt \n\n上下文{{context}}\n\n问题{{question}});7.4 监控、日志与成本控制Token消耗监控记录每次调用的输入/输出Token数关联用户和部门用于成本分摊和预算控制。性能监控监控向量检索延迟、模型响应时间、API调用成功率。审计日志记录所有用户提问、AI回复、引用的文档来源满足合规要求。限流与降级为AI服务配置限流并在OpenAI等服务不可用时优雅降级到本地模型或返回缓存。7.5 安全与权限输入输出过滤对用户输入和AI输出进行内容安全过滤防止注入攻击和不当内容。数据访问权限在向量检索层加入权限过滤确保用户只能检索到自己有权访问的文档向量。API密钥管理使用Vault或云厂商的密钥管理服务切勿将API密钥硬编码在代码或配置文件中。8. 常见问题与排查指南在开发过程中你几乎一定会遇到以下问题。问题现象可能原因排查步骤解决方案启动报错No qualifying bean of type ChatClientSpringAI自动配置未生效或依赖冲突。1. 检查pom.xml中SpringAI依赖是否正确。2. 检查Spring Boot版本是否3.2.0。3. 运行mvn dependency:tree查看冲突。统一SpringAI相关依赖版本确保Spring Boot版本兼容。调用AI接口超时或失败1. 网络问题。2. 本地Ollama未启动或模型未加载。3. OpenAI API Key无效或额度不足。1.curl http://localhost:11434/api/tags测试Ollama。2. 检查控制台或日志中的错误信息。3. 在OpenAI平台检查额度。1. 确保网络通畅服务可达。2. 正确配置spring.ai.*.base-url和api-key。3. 考虑增加超时配置spring.ai.openai.chat.options.timeout60s。RAG回答与文档无关幻觉1. 检索到的上下文不相关。2. 系统指令未强调“基于上下文”。3. 上下文在Prompt中位置不对或被截断。1. 检查向量检索结果的相关性可打印检索到的文本。2. 检查构建的最终Prompt格式。3. 检查模型上下文长度是否足够。1. 调整文本分割策略和检索数量。2. 强化系统指令使用更明确的模板。3. 使用LangChain4j的ContentInjector确保上下文被正确注入。向量数据库连接失败1. 数据库服务未启动。2. 网络或端口错误。3. 集合Collection不存在。1. 使用docker ps检查容器状态。2. 用telnet或curl测试端口连通性。3. 查看向量数据库的日志。1. 确保向量数据库服务正常运行。2. 检查配置中的baseUrl和collectionName。3. 某些向量库需要先显式创建集合。Agent不调用工具1. 工具类不是Spring Bean。2. 工具方法未加Tool注解。3. 模型能力不足无法理解工具用途。1. 检查工具类是否有Component注解。2. 检查Tool注解的name或description是否清晰。3. 尝试在Prompt中更详细描述任务。1. 确保工具Bean被正确扫描。2. 为工具编写清晰、具体的描述。3. 换用更强大的模型如GPT-4进行测试。内存溢出 (OOM)1. 一次性加载或处理超大文件。2. 向量模型在本地运行占用大量内存。1. 检查文件处理逻辑是否将整个文件读入内存。2. 使用jcmd或VisualVM监控堆内存。1. 使用流式方式处理大文件。2. 增加JVM堆内存-Xmx4g。3. 考虑使用云端的嵌入模型API。9. 总结从CRUD到AI全栈的升级路径通过以上近万字的实践我们完成了一次从传统Java后端到AI应用开发者的思维升级和技能跨越。回顾整个旅程技术栈层面你掌握了SpringAI作为AI能力接入的标准化入口统一了模型调用。LangChain4j作为AI应用编排框架优雅地实现了RAG、Agent等复杂模式。向量数据库理解了其作为“语义记忆”的核心作用并完成了集成。RAG全流程从文档解析、向量化、存储到检索增强生成的完整实现。AI Agent学会了如何将Java方法转化为AI可用的工具构建自主智能体。工程思维层面你实现了AI能力服务化将大模型、向量检索等封装成标准的Spring Bean和Service。复杂流程编排用声明式的方式AiServices替代了手动的流程控制代码。生产级考量开始思考监控、安全、权限、缓存等非功能性需求。这绝不仅仅是学会了几个新框架。其本质是你将自己强大的Java工程化能力扩展到了AI这个新的领域。你不再是一个被动的API调用者而是一个能够设计并实现完整AI产品架构的工程师。接下来的学习方向深入LangChain4j探索其Memory、OutputParser、Evaluation等高级模块。探索多模态尝试使用SpringAI处理图片和音频。模型微调了解如何用自有数据微调开源模型以获得更专业的领域表现。流式响应实现类似ChatGPT的打字机效果提升用户体验。加入业务上下文将Agent与你现有的业务系统订单、用户、库存深度集成创造真正的业务价值。AI应用开发的世界刚刚开启而Java开发者凭借其深厚的工程化底蕴在这里大有可为。现在你可以自信地将“SpringAI”、“LangChain4j”、“RAG”、“Agent”这些关键词写入你的简历并开始用这套技术栈去解决真实的业务问题了。建议收藏本文在构建你的第一个AI功能时随时回来查阅。