
如果你是一名Java开发者最近一定被“AI大模型”这个词刷屏了。从ChatGPT到各种国产大模型似乎一夜之间不会用AI的程序员就要被淘汰了。但当你真正想动手把AI能力集成到自己的Spring Boot项目里时却发现困难重重官方文档语焉不详Demo跑不通各种概念Agent、RAG、Function Calling看得人头晕更别提生产环境下的稳定性、成本和权限管控了。这恰恰是大多数Java开发者面对AI时的真实困境知道它很重要但不知道如何以自己熟悉的、工程化的方式去使用它。你需要的不是一个又一个零散的概念科普而是一条清晰的、从零到一的、能落地的技术路径。本文将为你梳理这条路径。我们不谈空泛的趋势只解决具体问题如何用你最熟悉的Java技术栈Spring Boot快速、可靠地将主流AI大模型能力集成到你的业务系统中。我们会聚焦于当前Java生态中最具代表性的三个框架Spring AI、Spring AI Alibaba以及LangChain4j并通过一个完整的智能客服Agent案例带你走通从环境搭建、模型接入、功能开发到生产实践的全过程。读完本文你将能清晰地回答以下几个问题Spring AI、Spring AI Alibaba、LangChain4j 这三个框架到底有什么区别我该选哪个如何用几行配置就接入OpenAI、DeepSeek或通义千问等模型什么是AI Agent在Java项目中如何构建一个具备工具调用能力的智能体开发一个AI应用时有哪些必须注意的“坑”如成本控制、异常处理、流式响应如何将AI能力与现有业务系统如数据库、Redis结合实现RAG等高级应用我们直接从最核心的选择难题开始。1. 框架选型Spring AI、Spring AI Alibaba 还是 LangChain4j面对三个名字相似的框架很多开发者第一反应是困惑。简单来说这是三种不同风格的“桥梁”连接你的Java应用和AI大模型。Spring AISpring官方出品可以理解为AI领域的“Spring Data”。它的目标是提供一套统一的、声明式的API让你像操作数据库JpaRepository一样操作大模型。你只需要定义ChatClient、EmbeddingClient等接口具体的模型提供商OpenAI, Azure, Ollama等通过配置切换。优点是背靠Spring生态与Spring Boot无缝集成配置简单理念统一。缺点是相对较新某些高级功能如复杂的Agent工作流还在快速发展中。Spring AI Alibaba阿里巴巴基于Spring AI理念的增强实现并深度融合了阿里云百炼平台等阿里系AI服务。它在提供通用AI能力的同时重点优化了对国产模型通义千问、千问VL等和阿里云生态的支持。如果你主要使用阿里云服务或国产模型它是更“接地气”的选择。LangChain4jJava版的LangChain。它是一个功能极其丰富的AI应用开发框架提供了从模型接入、提示词管理、记忆、索引到复杂Agent工作流的一整套工具链。优点是功能全面、设计灵活、社区活跃能实现非常复杂的AI应用逻辑。缺点是学习曲线较陡需要理解的概念更多与Spring的集成需要额外配置。为了更直观我们用一个表格对比特性维度Spring AISpring AI AlibabaLangChain4j出品方Spring官方阿里巴巴开源社区设计理念统一抽象声明式基于Spring AI增强阿里生态功能完备的工具链核心优势Spring生态集成简单易用对国产模型/阿里云支持好功能强大灵活Agent支持成熟学习成本低低中高适用场景快速集成AI对话/嵌入能力到Spring应用使用阿里云或国产模型的Spring项目需要构建复杂Agent、RAG或自定义工作流的项目与Spring集成原生支持原生支持需通过spring-boot-starter集成如何选择如果你是Spring Boot的忠实用户想最快速度体验AI能力无脑选Spring AI。如果你的项目部署在阿里云或主要使用通义千问等国产模型Spring AI Alibaba是更顺滑的选择。如果你需要构建功能复杂的AI智能体或对LangChain的Python生态很熟悉LangChain4j提供了最强大的武器库。本文将以Spring AI和LangChain4j为主线进行讲解因为它们分别代表了“开箱即用”和“深度定制”两种典型路径。理解了它们Spring AI Alibaba也就触类旁通了。2. 环境准备构建你的第一个AI Spring Boot项目理论说完我们动手搭建环境。假设你使用IntelliJ IDEA或VS Code并且已经安装了JDK 17或更高版本Spring AI 2.0 要求JDK 17。2.1 创建项目与核心依赖通过 Spring Initializr 创建一个标准的Spring Boot 3.x项目。这里以Spring Boot 3.2.5为例。关键依赖选择Spring Web提供Web接口。Spring AI核心AI依赖。Lombok简化代码可选但推荐。你的pom.xml核心依赖部分应该类似这样dependencies !-- Spring Boot 基础 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI 核心 (以OpenAI为例) -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId !-- 请查看Spring AI官网获取最新版本 -- /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- 测试 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies注意Spring AI的版本和Starter构件名可能会快速更新。请务必访问 Spring AI官方文档 查看最新的版本和依赖配置。例如你可能需要添加Spring AI的BOM物料清单来管理版本。如果你想使用LangChain4j则不需要spring-ai-openai-starter而是添加dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-spring-boot-starter/artifactId version0.31.0/version !-- 请使用最新版本 -- /dependency dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-open-ai/artifactId version0.31.0/version /dependency2.2 配置模型API密钥无论使用哪个框架你都需要一个AI模型的API Key。这里以OpenAI和DeepSeek性价比极高的国产模型为例。在application.yml或application.properties中配置使用Spring AI连接OpenAI# application.yml spring: ai: openai: api-key: ${OPENAI_API_KEY:sk-your-openai-key-here} # 从环境变量读取或直接填写 chat: options: model: gpt-3.5-turbo # 或 gpt-4 temperature: 0.7使用Spring AI连接DeepSeekDeepSeek兼容OpenAI API协议只需修改base URL。spring: ai: openai: base-url: https://api.deepseek.com api-key: ${DEEPSEEK_API_KEY:your-deepseek-key-here} chat: options: model: deepseek-chat使用LangChain4j连接OpenAI# application.yml langchain4j: open-ai: chat-model: api-key: ${OPENAI_API_KEY} model-name: gpt-3.5-turbo temperature: 0.7 timeout: 60s重要提醒永远不要将真实的API Key提交到代码仓库。务必使用环境变量${VAR_NAME}或在生产环境使用配置中心如Apollo、Nacos。temperature参数控制生成文本的随机性0-2。值越高越有创意值越低越确定。对于客服、代码生成等任务建议设置在0.1-0.7之间。首次使用建议从gpt-3.5-turbo或deepseek-chat开始成本低速度快。3. 核心概念速览Chat、Prompt、Embedding与Agent在写代码前花2分钟理解这四个核心概念能避免后续的很多困惑。Chat (聊天/对话): 最基础的功能你发送一段消息Message模型返回一段文本回复。对应ChatClient接口。Prompt (提示词): 你发给模型的指令或问题。一个好的Prompt直接决定模型输出的质量。它不仅仅是一句话可以包含角色设定、上下文、示例等。在代码中通常是一个字符串或Prompt对象。Embedding (向量嵌入): 将文本或图像、音频转换成一串有意义的数字向量。这个向量代表了文本的“语义”。相似含义的文本其向量在数学空间中也更接近。这是实现RAG检索增强生成的基石用于从知识库中查找相关信息。Agent (智能体): 一个能感知环境、进行决策、执行动作如调用工具/函数的AI程序。例如一个“订餐Agent”可以理解用户想吃什么然后调用“查询餐厅API”工具再调用“下单API”工具。它是构建复杂AI应用的关键。简单理解Chat是交互方式Prompt是输入内容Embedding是理解文本的手段Agent是能自主完成任务的智能单元。4. 实战第一步用Spring AI实现智能对话环境就绪概念清晰现在让我们用Spring AI实现一个最简单的聊天接口。4.1 创建ChatController// 文件路径src/main/java/com/example/aiassistant/controller/ChatController.java package com.example.aiassistant.controller; import lombok.RequiredArgsConstructor; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/api/chat) RequiredArgsConstructor // Lombok注解自动注入final字段 public class ChatController { private final ChatClient chatClient; // Spring AI会自动注入配置好的ChatClient PostMapping(/simple) public String chat(RequestBody String userMessage) { // 1. 构建Prompt Prompt prompt new Prompt(new UserMessage(userMessage)); // 2. 调用模型并获取响应 ChatResponse response chatClient.call(prompt); // 3. 返回生成的文本 return response.getResult().getOutput().getContent(); } PostMapping(/stream) public SseEmitter streamChat(RequestBody String userMessage) { SseEmitter emitter new SseEmitter(60_000L); // 超时时间60秒 // 流式响应适合生成较长内容提升用户体验 chatClient.stream(new Prompt(new UserMessage(userMessage))) .subscribe( chunk - { try { // 发送每一个流式片段 emitter.send(SseEmitter.event() .data(chunk.getResult().getOutput().getContent()) .id(String.valueOf(System.currentTimeMillis()))); } catch (IOException e) { emitter.completeWithError(e); } }, emitter::completeWithError, // 错误处理 emitter::complete // 完成处理 ); return emitter; } }4.2 代码解读与运行ChatClient是Spring AI的核心接口你无需关心背后是OpenAI还是DeepSeek框架已经帮你做好了适配。call()方法是同步调用会等待模型完全生成后返回结果。stream()方法是流式调用模型生成一个字就返回一个字通过Server-Sent Events (SSE) 推送给前端。这是现代AI应用的标配能极大改善用户等待长文本时的体验。使用RequestBody接收前端JSON格式的请求。运行与测试启动Spring Boot应用 (mvn spring-boot:run或运行Application类)。使用Postman或curl测试curl -X POST http://localhost:8080/api/chat/simple \ -H Content-Type: application/json \ -d 你好请用Java写一个Hello World程序你应该会收到模型生成的Java代码。5. 进阶用LangChain4j构建具备工具调用能力的Agent单纯的对话能力有限。真正的威力在于让AI能“动手操作”你的系统。下面我们用LangChain4j构建一个“智能客服Agent”它能查询订单状态模拟调用内部系统。5.1 定义Agent可用的“工具”Tool工具本质上是一个Java方法加上Tool注解LangChain4j就能让AI模型识别并调用它。// 文件路径src/main/java/com/example/aiassistant/tool/OrderTool.java package com.example.aiassistant.tool; import dev.langchain4j.agent.tool.Tool; import org.springframework.stereotype.Component; import java.time.LocalDate; import java.util.HashMap; import java.util.Map; Component // 注册为Spring Bean public class OrderTool { // 模拟一个订单数据库 private static final MapString, String ORDER_DB new HashMap(); static { ORDER_DB.put(ORDER-001, 状态已发货 | 商品《Spring实战第6版》 | 下单时间2024-01-15); ORDER_DB.put(ORDER-002, 状态配送中 | 商品无线鼠标 | 下单时间2024-01-18); ORDER_DB.put(ORDER-003, 状态已完成 | 商品Java视频课程 | 下单时间2024-01-10); } /** * 根据订单号查询订单状态 * Tool 注解让LangChain4j将此方法暴露给AI Agent * param orderNumber 订单号例如 ORDER-001 * return 订单状态的描述信息 */ Tool(根据提供的订单号查询订单的当前状态、商品信息和下单时间。) public String queryOrderStatus(final String orderNumber) { String orderInfo ORDER_DB.get(orderNumber); if (orderInfo ! null) { return String.format(订单 [%s] 的详细信息是%s, orderNumber, orderInfo); } else { return String.format(抱歉未找到订单号 [%s] 对应的信息请确认订单号是否正确。, orderNumber); } } /** * 查询当前用户的今日订单概览 (模拟) */ Tool(查询当前登录用户的今日所有订单的简要概览。) public String queryTodayOrders() { // 模拟逻辑 return 您今天 LocalDate.now() 共有2笔订单ORDER-004待支付ORDER-005已发货。; } }5.2 配置并创建AI Agent我们需要配置一个Agent它由一个大模型如GPT和一系列工具构成。// 文件路径src/main/java/com/example/aiassistant/config/AgentConfig.java package com.example.aiassistant.config; import dev.langchain4j.agent.tool.ToolSpecification; 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 lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.time.Duration; import java.util.List; Configuration RequiredArgsConstructor public class AgentConfig { // 注入我们刚才定义的OrderTool private final OrderTool orderTool; Bean public ChatLanguageModel chatLanguageModel() { // 创建OpenAI模型客户端配置从application.yml读取 return OpenAiChatModel.builder() .apiKey(System.getenv(OPENAI_API_KEY)) // 建议从环境变量读取 .modelName(gpt-3.5-turbo) .temperature(0.3) // Agent任务需要更确定性的输出 .timeout(Duration.ofSeconds(60)) .logRequests(true) // 开发时开启方便调试 .logResponses(true) .build(); } Bean public ChatMemory chatMemory() { // 给Agent一个记忆窗口保留最近10轮对话使其有上下文能力 return MessageWindowChatMemory.withMaxMessages(10); } Bean public CustomerServiceAgent customerServiceAgent(ChatLanguageModel model, ChatMemory memory) { // AiServices是LangChain4j的核心用于动态创建代理 return AiServices.builder(CustomerServiceAgent.class) .chatLanguageModel(model) .chatMemory(memory) .tools(orderTool) // 注册工具 .build(); } // 定义Agent的行为接口 public interface CustomerServiceAgent { String chat(String userMessage); } }5.3 创建Agent服务与控制器// 文件路径src/main/java/com/example/aiassistant/service/AgentService.java package com.example.aiassistant.service; import com.example.aiassistant.config.AgentConfig.CustomerServiceAgent; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; Service RequiredArgsConstructor public class AgentService { private final CustomerServiceAgent agent; // 注入我们配置的Agent public String chatWithAgent(String userMessage) { // 调用Agent进行对话Agent会自动判断是否需要以及如何调用工具 return agent.chat(userMessage); } }// 文件路径src/main/java/com/example/aiassistant/controller/AgentController.java package com.example.aiassistant.controller; import com.example.aiassistant.service.AgentService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/api/agent) RequiredArgsConstructor public class AgentController { private final AgentService agentService; PostMapping(/chat) public String agentChat(RequestBody String userMessage) { return agentService.chatWithAgent(userMessage); } }5.4 运行与测试Agent确保你的API Key已正确配置。启动应用。向Agent提问测试工具调用curl -X POST http://localhost:8080/api/agent/chat \ -H Content-Type: application/json \ -d 我的订单ORDER-001现在到哪里了预期结果Agent会理解你的意图是查询订单状态自动调用queryOrderStatus(ORDER-001)工具并将工具返回的结果整合成自然的语言回复给你例如“您好根据查询订单 [ORDER-001] 的详细信息是状态已发货 | 商品《Spring实战第6版》 | 下单时间2024-01-15。您的书已经在路上了”再测试一个需要推理的问题curl -X POST http://localhost:8080/api/agent/chat \ -H Content-Type: application/json \ -d 我今天下了哪些单预期结果Agent会调用queryTodayOrders()工具并告诉你结果。这就是Agent的魅力你不需要写复杂的逻辑去解析用户意图、匹配关键词、调用接口。你只需要定义好工具能力然后告诉Agent“这些工具你可以用”它就能自己决定什么时候用、怎么用。6. 效果验证与调试技巧开发过程中验证和调试至关重要。6.1 如何验证Agent是否调用了工具查看日志我们在AgentConfig中配置了logRequests(true)和logResponses(true)。在控制台你会看到LangChain4j与OpenAI API交互的详细日志包括模型决定调用哪个工具的“思考过程”。使用LangChain4j的调试工具更高级的做法是使用PromptTemplate和Observation来更精细地控制和分析。6.2 流式响应SSE前端对接示例前面我们实现了后端的流式接口这里给一个简单的前端HTML JavaScript示例展示如何接收流式数据。!DOCTYPE html html head titleAI助手流式对话/title /head body input typetext idinput placeholder输入你的问题... button onclicksendMessage()发送/button div idoutput stylewhite-space: pre-wrap; border:1px solid #ccc; min-height:200px;/div script function sendMessage() { const input document.getElementById(input).value; const outputDiv document.getElementById(output); outputDiv.innerHTML AI正在思考...br; const eventSource new EventSource(http://localhost:8080/api/chat/stream?message${encodeURIComponent(input)}); eventSource.onmessage function(event) { outputDiv.innerHTML event.data; // 自动滚动到底部 outputDiv.scrollTop outputDiv.scrollHeight; }; eventSource.onerror function(error) { console.error(EventSource failed:, error); eventSource.close(); outputDiv.innerHTML br[连接关闭]; }; // 简单处理实际应用应更完善 document.getElementById(input).value ; } /script /body /html注意这是一个极简示例。生产环境需要使用更健壮的SSE客户端库并处理连接重试、错误、多个请求等问题。7. 常见问题与排查思路避坑指南在实际集成中你几乎一定会遇到下面这些问题。问题现象可能原因排查方式解决方案启动报错No qualifying bean of type ChatClient1. Spring AI依赖未正确引入。2.application.yml中模型配置错误如api-key为空或格式不对。3. 使用了错误的Starter如想用OpenAI却配了Azure。1. 检查pom.xml依赖和版本。2. 检查application.yml配置项拼写和缩进。3. 查看启动日志是否有配置加载失败的警告。1. 确认依赖参考官方文档。2. 确保api-key有效可通过curl直接测试API。3. 核对spring.ai.openai.base-url等配置。调用接口超时Timeout1. 网络问题访问境外API慢。2. 模型响应慢如GPT-4。3. 请求的maxTokens设置过大。1. 使用curl或Postman直接调用API测试网络延迟。2. 查看服务器日志和监控。1. 调整timeout配置如LangChain4j的timeout(Duration.ofSeconds(120))。2. 考虑使用国内镜像或国产模型。3. 优化Prompt减少不必要的上下文。Agent不调用工具1. 工具方法没有被Spring管理缺少Component。2. 工具描述Tool注解中的字符串不清晰模型无法理解。3. 模型能力不足如用了gpt-3.5-turbo的旧版本。1. 检查工具类是否被Component标注并确认已注入到AgentConfig。2. 查看模型请求日志看模型是否生成了工具调用的请求。3. 简化工具描述用英文可能效果更好。1. 确保工具类是Spring Bean。2. 优化工具描述明确输入输出。3. 升级到更强的模型如gpt-3.5-turbo-1106或gpt-4或使用专门优化了函数调用能力的模型。API调用费用激增1. 被恶意刷接口。2. 循环调用或Prompt过长导致token消耗大。3. 流式响应未正确关闭连接。1. 检查服务器访问日志。2. 在OpenAI后台查看Usage分析。3. 监控应用内存和连接数。1.最重要设置API Key用量限制和告警。2. 实现用户认证和速率限制。3. 优化Prompt使用maxTokens限制生成长度。4. 确保SSE连接在客户端断开后能被服务器正确清理。国产模型如DeepSeek返回格式错误部分国产模型对OpenAI API的兼容性不是100%可能返回非标准JSON。查看完整的HTTP响应日志对比与OpenAI官方响应的差异。1. 尝试使用该模型官方的SDK如果有。2. 对于Spring AI可以尝试自定义RestClient或等待社区适配器。3. LangChain4j社区通常有第三方扩展模块。Java版本不兼容Spring AI 2.0 需要JDK 17。运行java -version确认版本。升级JDK到17或21LTS版本。8. 生产环境最佳实践与工程建议将AI能力用于生产远不止跑通Demo那么简单。以下是必须考虑的工程化要点。8.1 配置与密钥管理绝对禁止硬编码API Key必须通过环境变量、配置中心Nacos, Apollo或云厂商的密钥管理服务如AWS Secrets Manager, 阿里云KMS来获取。环境隔离为开发、测试、生产环境配置不同的API Key和模型端点如测试环境用gpt-3.5-turbo生产环境用gpt-4。配置模板使用application-dev.yml,application-prod.yml进行环境隔离。8.2 稳定性与容错重试机制网络波动或模型服务暂时不可用很常见。为AI客户端配置重试逻辑Spring Retry, Resilience4j。// 示例使用Spring Retry注解 Retryable(value {ResourceAccessException.class}, maxAttempts 3, backoff Backoff(delay 1000)) public String callAiWithRetry(String prompt) { return chatClient.call(new Prompt(prompt)).getResult().getOutput().getContent(); }降级策略当主要模型服务不可用时要有备选方案。例如可以配置多个ChatClientBean根据条件切换或直接返回缓存的标准话术。超时设置必须设置合理的连接超时和读取超时避免线程被长时间阻塞。8.3 成本控制与监控预算与限额在OpenAI、Azure OpenAI或国内模型平台后台严格设置每月使用预算和硬性限额。Token计数与估算在发送请求前估算Prompt的token数量可用tiktoken库或模型提供的估算API。对于长上下文如RAG成本会显著增加。日志与审计记录每一次AI调用的请求、响应、token使用量和成本如果平台提供。这有助于分析使用模式和优化Prompt。8.4 安全与合规输入输出过滤对用户输入进行严格的检查和过滤防止Prompt注入攻击。对模型输出也要进行敏感词过滤和内容安全审核避免产生有害内容。数据隐私明确告知用户数据的使用方式。如果涉及用户隐私数据考虑使用本地化部署的模型或进行数据脱敏。权限控制Agent工具调用必须与业务系统的权限体系结合。例如queryOrderStatus工具内部应校验当前用户是否有权查询该订单。8.5 性能优化异步与非阻塞AI调用通常是I/O密集型操作。使用Spring WebFlux或Async进行异步处理避免阻塞Web容器线程。缓存对频繁且结果不变的AI查询如“公司的产品介绍是什么”进行缓存。批处理对于Embedding等操作如果可能将多个文本合并为一个请求批量处理可以显著减少API调用次数和延迟。9. 下一步从Demo到真实系统至此你已经掌握了用Java集成AI大模型的核心技能。但要让AI真正创造业务价值还有更长的路要走。你的下一步可以是实现RAG检索增强生成结合向量数据库如Milvus, Pinecone, pgvector让AI能基于你私有的知识库产品文档、客服问答、代码库进行回答。这是当前企业级AI应用最热门的场景。构建复杂多Agent系统让多个具备不同技能的Agent协作完成一个任务。例如一个Agent分析需求一个Agent写代码一个Agent进行代码审查。深入Prompt工程学习Chain of Thought、Few-Shot Prompting等高级技巧大幅提升模型在复杂任务上的表现。模型微调Fine-tuning对于有大量高质量数据和对输出格式有严格要求的场景可以考虑对基础模型进行微调以获得更专、更可控的效果。探索本地模型部署出于成本、数据安全和网络延迟考虑可以研究在本地服务器部署开源模型如Qwen, Llama, DeepSeek Coder通过Ollama、LM Studio等工具进行集成。AI与Java的融合不是取代而是增强。它不会让你熟悉的Spring Boot、MyBatis、Redis失效而是为这些稳固的技术栈插上智能的翅膀。从今天这个能查订单的客服Agent开始一步步构建属于你自己的智能业务系统。