基于Spring AI与Alibaba Agent Framework构建生产级Java AI Agent应用

发布时间:2026/8/2 2:59:49
基于Spring AI与Alibaba Agent Framework构建生产级Java AI Agent应用
在实际 Java 后端项目中集成大模型能力早已不是简单的 API 调用。当需求从“调用一次对话”升级为“构建一个能自主规划、使用工具、处理多模态信息的智能体AI Agent”时挑战才真正开始。你需要处理复杂的上下文管理、工具调用编排、状态持久化以及与大模型服务的高效交互。Spring AI 项目为 Java 生态带来了标准化的抽象而阿里巴巴开源的 Alibaba Agent Framework 则在其基础上为构建生产级 AI Agent 提供了更完整的脚手架和最佳实践。本文面向有一定 Spring Boot 和 Java 开发经验的工程师旨在带你从零开始基于 Spring AI 和 Alibaba Agent Framework构建一个具备多模态 RAG检索增强生成能力和自定义技能Skill的 AI Agent 应用。你将不仅学会如何让 Agent 调用代码解释器、查询数据库还能让它理解并处理图像、PDF等非文本信息。我们将从核心概念讲起逐步完成环境搭建、框架集成、核心功能开发并深入探讨生产环境中必须考虑的 Token 统计、内存管理、异常处理等实际问题。1. 理解 AI Agent 的核心组件与 Spring AI 生态在开始写代码之前必须厘清几个关键概念以及它们在 Spring AI 生态中的对应关系。这能避免后续配置时出现“张冠李戴”的混乱。1.1 AI Agent 是什么不仅仅是聊天机器人一个 AI Agent智能体是一个能够感知环境、进行决策并执行动作以实现目标的软件实体。与简单的聊天机器人Chatbot相比Agent 的核心特征在于其自主性和工具使用能力。自主性Agent 可以根据目标Goal或用户指令自主规划执行步骤Plan而无需用户逐步指导。工具使用Tool CallingAgent 可以调用外部工具如搜索引擎、数据库、代码执行器、API来获取信息或执行操作从而突破大模型本身的知识和实时性限制。在 Spring AI 的语境下Agent是一个高级抽象它封装了与大模型如 OpenAI GPT、通义千问、智谱 GLM的交互、工具调用的决策逻辑以及对话历史的管理。1.2 Spring AI 与 Alibaba Agent Framework 的关系Spring AI是 Spring 官方提供的项目旨在为 Java 应用集成人工智能功能提供一套统一的、抽象化的 API。它定义了ChatClient、EmbeddingClient、VectorStore等核心接口让开发者可以轻松切换不同的大模型供应商如 OpenAI、Azure OpenAI、Ollama 本地模型。它的Agent模块提供了构建智能体的基础能力。Alibaba Agent Framework是阿里巴巴基于 Spring AI 构建的一个增强框架。它不是一个替代品而是一个“脚手架”和“最佳实践套件”。它提供了更多开箱即用的功能例如更丰富的 Agent 类型预置了ReAct、PlanAndExecute等多种经典 Agent 实现。便捷的技能Skill开发模式提供了Tool注解等让开发者能以更 Spring 的方式类似Service定义工具。管理控制台Admin可选组件用于监控 Agent 的运行状态、查看对话历史、管理工具等。与阿里云模型服务的深度集成简化了通义千问等模型的配置。你可以把 Spring AI 看作“标准库”而 Alibaba Agent Framework 是建立在标准库之上的一个“功能丰富的框架”旨在降低企业级 AI Agent 的开发门槛。1.3 多模态 RAG检索增强生成与 Skill多模态 RAG传统的 RAG 主要处理文本。多模态 RAG 意味着系统能够处理和理解图像、音频、视频、PDF包含图文等多种格式的数据。其流程通常为1) 使用多模态模型将非文本数据转换为向量Embedding2) 存入向量数据库3) 用户提问时将问题也转换为向量进行相似性检索4) 将检索到的多模态上下文与大模型问题结合生成最终答案。这对于处理产品手册、设计图、医疗报告等场景至关重要。Skill技能在 Agent 框架中Skill 通常指一个封装好的、可被 Agent 调用的能力单元。一个 Skill 可以包含一个或多个Tool工具。例如一个“天气查询技能”可能封装了“根据城市名获取天气”这个工具。Skill 提供了更高层次的业务抽象。理解了这些我们就知道要构建的系统包含一个基于 Spring AI Alibaba Agent Framework 的 Agent 运行时它具备调用自定义 Skill/Tool 的能力并且后端连接着一个支持多模态数据的 RAG 管道。2. 环境准备与项目初始化我们将创建一个标准的 Spring Boot 3.x 项目并集成必要的依赖。生产环境建议使用 Java 17 或更高版本。2.1 创建 Spring Boot 项目使用 Spring Initializr 或 IDE 创建项目选择以下依赖Spring Web提供 RESTful API 接口。Spring AI核心 AI 抽象。Lombok简化代码可选但推荐。pom.xml中需要显式添加 Spring AI 的 BOM物料清单和具体模块依赖以及 Alibaba Agent Framework 的依赖。?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.5/version !-- 确保使用 Spring Boot 3.x -- relativePath/ /parent groupIdcom.example/groupId artifactIdai-agent-demo/artifactId version0.0.1-SNAPSHOT/version nameai-agent-demo/name descriptionDemo project for AI Agent with Spring AI/description properties java.version17/java.version spring-ai.version0.8.1/spring-ai.version !-- 使用稳定版本 -- alibaba-agent.version0.0.1/alibaba-agent.version !-- 请检查最新版本 -- /properties dependencyManagement dependencies !-- Spring AI BOM -- 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 !-- Spring AI OpenAI 模块 (以OpenAI为例可替换为 ollama, azure-openai 等) -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId /dependency !-- Spring AI Vector Store (以Redis为例用于RAG) -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-redis-store-spring-boot-starter/artifactId /dependency !-- Alibaba Agent Framework Core -- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-agent-framework-core/artifactId version${alibaba-agent.version}/version /dependency !-- 可选Alibaba Agent Framework Admin (Web管理界面) -- !-- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-agent-framework-admin/artifactId version${alibaba-agent.version}/version /dependency -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration excludes exclude groupIdorg.projectlombok/groupId artifactIdlombok/artifactId /exclude /excludes /configuration /plugin /plugins /build /project注意spring-ai-alibaba-agent-framework的版本可能更新较快请根据官方仓库如 GitHub - alibaba/spring-ai-alibaba获取最新版本号。如果使用阿里云通义千问模型还需要添加对应的 starter。2.2 配置大模型连接与向量数据库在application.yml中配置 OpenAI或其他模型的连接信息以及 Redis 作为向量数据库。这里以 OpenAI 和本地 Redis 为例。# application.yml spring: ai: openai: api-key: ${OPENAI_API_KEY:sk-your-openai-key-here} # 强烈建议使用环境变量 chat: options: model: gpt-4-turbo-preview # 或 gpt-3.5-turbo temperature: 0.7 vectorstore: redis: uri: redis://localhost:6379 # Redis 连接地址 index: ai_agent_docs # 向量索引名称 initialize-schema: true # 首次启动时初始化索引 # Alibaba Agent Framework 基础配置 (示例) alibaba: cloud: ai: agent: enabled: true # 可以配置默认使用的 Agent 类型如 react default-agent-type: react关键配置解释spring.ai.openai.api-key这是最重要的安全配置。绝对不要将密钥硬编码在代码或配置文件中提交到版本库。务必使用环境变量如OPENAI_API_KEY或配置中心来管理。model根据需求和成本选择。gpt-4-turbo在长上下文和复杂推理上更强gpt-3.5-turbo更经济。temperature控制输出的随机性0-2。值越高回答越多样、有创意值越低回答越确定、一致。对于工具调用类 Agent通常建议设置较低的值如 0.1-0.3以保证稳定性。spring.ai.vectorstore.redis这里配置了向量存储。Spring AI 支持多种向量数据库Redis, Pinecone, Chroma 等。initialize-schema在第一次运行时创建必要的索引结构。环境变量设置Linux/Mac:export OPENAI_API_KEYsk-...环境变量设置Windows PowerShell:$env:OPENAI_API_KEYsk-...3. 构建核心自定义 Skill 与 Tool 开发我们将创建两个典型的 Skill一个用于执行简单计算另一个用于查询系统信息。这展示了如何将业务逻辑封装成 Agent 可用的工具。3.1 定义计算器 Skill使用 Alibaba Agent Framework 提供的Tool注解来声明一个工具方法。框架会自动将其注册到 Agent 的上下文中。package com.example.agent.skill.calculator; import org.springframework.ai.alibaba.agent.framework.annotation.Tool; import org.springframework.stereotype.Component; Component public class CalculatorSkill { Tool(name Calculator, description 用于执行数学计算。输入一个数学表达式字符串如 1 2 * 3返回计算结果。) public String calculate(String expression) { try { // 警告此处为简化示例直接使用 JavaScript 引擎。生产环境务必进行严格的输入验证和安全沙箱处理 // 可以考虑使用像 exp4j 这样的安全表达式求值库。 javax.script.ScriptEngineManager mgr new javax.script.ScriptEngineManager(); javax.script.ScriptEngine engine mgr.getEngineByName(JavaScript); Object result engine.eval(expression); return String.format(表达式 %s 的计算结果是: %s, expression, result.toString()); } catch (Exception e) { return String.format(计算表达式 %s 时出错: %s, expression, e.getMessage()); } } }代码要点Component让 Spring 管理这个 Bean。Tool这是关键注解。name和description非常重要大模型如 GPT会根据这些描述来决定是否以及如何调用该工具。描述要清晰准确。安全警告示例中使用了ScriptEngine直接执行字符串这在生产环境中是极其危险的可能导致任意代码执行RCE。真实场景应使用安全的表达式解析库如exp4j或严格限制表达式的字符集和操作符。3.2 定义系统信息查询 Skill这个 Skill 展示如何返回结构化信息。package com.example.agent.skill.system; import org.springframework.ai.alibaba.agent.framework.annotation.Tool; import org.springframework.stereotype.Component; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; Component public class SystemInfoSkill { Tool(name GetSystemTime, description 获取当前的系统日期和时间。) public String getCurrentTime() { return LocalDateTime.now().format(DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss)); } Tool(name GetJVMUptime, description 获取 Java 虚拟机JVM自启动以来的运行时间毫秒。) public long getJvmUptime() { RuntimeMXBean rb ManagementFactory.getRuntimeMXBean(); return rb.getUptime(); } }3.3 配置并创建 Agent我们需要配置一个 Agent 实例它将使用我们定义的工具和指定的大模型。在 Alibaba Agent Framework 中可以方便地通过配置类或属性文件来定义 Agent。创建一个配置类AgentConfig.javapackage com.example.agent.config; import org.springframework.ai.alibaba.agent.framework.Agent; import org.springframework.ai.alibaba.agent.framework.AgentBuilder; import org.springframework.ai.alibaba.agent.framework.agent.ReActAgent; import org.springframework.ai.chat.client.ChatClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class AgentConfig { Bean public Agent myAssistantAgent(ChatClient.Builder chatClientBuilder) { // 使用 ReActAgent这是一种经典的推理行动Reasoning and Acting的 Agent 模式 return AgentBuilder.builder() .agentType(ReActAgent.TYPE) // 指定 Agent 类型 .chatClientBuilder(chatClientBuilder) // 注入 ChatClient 构建器 .name(MyAssistant) // Agent 名称 .description(一个乐于助人的助手可以回答问题并使用计算器和系统工具。) .build(); } }解释AgentBuilder提供了流畅的 API 来构建 Agent。ReActAgent是框架预置的一种 Agent它遵循“思考Reason- 行动Act- 观察Observe”的循环非常适合工具调用场景。ChatClient.Builder由 Spring AI 自动配置它已经包含了我们在application.yml中设置的模型参数。框架会自动扫描所有被Tool注解的方法并将它们注册到 Agent 的上下文中无需手动注入。4. 实现多模态 RAG 管道多模态 RAG 允许 Agent 基于图像、PDF 等文件内容进行回答。我们构建一个简单的管道将 PDF 文件内容包括文本和图片描述向量化并存储然后支持基于内容的检索。4.1 准备多模态模型与文本分割Spring AI 的ChatClient主要用于对话而多模态内容的处理如图像理解、文档解析通常需要专门的模型或库。对于 PDF 文本提取我们可以使用 Apache PDFBox。对于图像的向量化如果使用支持多模态的模型如 OpenAIgpt-4-vision-preview可以通过ChatClient发送图像但存储和检索仍需文本向量。这里我们以实现一个文本 PDF 的 RAG为例图像的多模态 RAG 原理类似但需要额外的图像特征提取步骤。首先添加 PDFBox 依赖dependency groupIdorg.apache.pdfbox/groupId artifactIdpdfbox/artifactId version2.0.27/version /dependency4.2 创建文档加载、分割与向量化服务package com.example.agent.service.rag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; import org.springframework.ai.document.Document; import org.springframework.ai.reader.ExtractedTextFormatter; import org.springframework.ai.reader.pdf.PagePdfDocumentReader; import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig; import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import java.io.IOException; import java.util.List; Service Slf4j RequiredArgsConstructor public class MultimodalRagService { private final VectorStore vectorStore; /** * 将 PDF 文件内容加载、分割并存储到向量数据库 */ public void ingestPdf(Resource pdfResource) { Assert.notNull(pdfResource, PDF 资源不能为空); log.info(开始处理 PDF 文件: {}, pdfResource.getFilename()); // 1. 使用 Spring AI 的 PDF 阅读器基于 PDFBox PagePdfDocumentReader pdfReader new PagePdfDocumentReader( pdfResource, PdfDocumentReaderConfig.builder() .withPageExtractedTextFormatter(ExtractedTextFormatter.builder() .withNumberOfBottomTextLinesToDelete(3) // 删除页脚 .withNumberOfTopTextLinesToDelete(1) // 删除页眉 .build()) .withPagesPerDocument(1) // 每页作为一个 Document .build() ); ListDocument documents pdfReader.get(); // 2. 文本分割防止超出模型上下文长度 TokenTextSplitter textSplitter new TokenTextSplitter(1000, 200, 10, 1000, true); // 参数chunkSize, chunkOverlap, ... ListDocument splitDocuments textSplitter.apply(documents); // 3. 为每个文档片段生成向量并存储 // Spring AI 的 VectorStore 接口会自动调用 EmbeddingClient 来生成向量 vectorStore.add(splitDocuments); log.info(PDF 文件处理完成共存储 {} 个文档片段。, splitDocuments.size()); } /** * 基于问题检索相关文档片段 */ public ListDocument retrieve(String query) { // 相似性搜索默认返回前4个最相关的结果 return vectorStore.similaritySearch(query, 4); } /** * 一个简单的 RAG 问答函数 */ public String ragQuery(String question) { ListDocument relevantDocs retrieve(question); // 构建增强的提示词 StringBuilder context new StringBuilder(请根据以下上下文回答问题\n); for (Document doc : relevantDocs) { context.append(doc.getContent()).append(\n---\n); } context.append(\n问题).append(question); context.append(\n如果上下文不包含相关信息请直接回答你不知道。); // 这里需要调用 ChatClient为了简化我们返回构造的上下文。 // 实际应用中应将 context.toString() 发送给大模型。 log.info(RAG 查询构造的上下文长度: {}, context.length()); return 检索到 relevantDocs.size() 个相关片段。待发送给大模型的上下文已就绪。; // 实际调用示例 (需注入 ChatClient): // String answer chatClient.prompt().user(context.toString()).call().content(); // return answer; } }关键参数解释TokenTextSplitterchunkSize: 每个文本块的最大 token 数。需要根据所用模型的上下文窗口来设置例如GPT-3.5 是 4096GPT-4 Turbo 是 128k。设置太小会丢失信息太大会影响检索精度和生成效果。1000 是一个常用起始值。chunkOverlap: 块之间的重叠 token 数。这有助于防止在分割点切断重要信息如一个句子中间。生产环境中分割策略可能需要根据文档类型技术文档、小说、对话记录进行优化。4.3 创建 RAG 管理接口创建一个 REST 控制器来上传 PDF 和进行问答。package com.example.agent.controller; import com.example.agent.service.rag.MultimodalRagService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; RestController RequestMapping(/api/rag) RequiredArgsConstructor public class RagController { private final MultimodalRagService ragService; PostMapping(/ingest-pdf) public ResponseEntityString ingestPdf(RequestParam(file) MultipartFile file) { if (file.isEmpty()) { return ResponseEntity.badRequest().body(文件为空); } try { // 创建临时文件 Path tempFile Files.createTempFile(upload-, .pdf); Files.copy(file.getInputStream(), tempFile, StandardCopyOption.REPLACE_EXISTING); ragService.ingestPdf(new org.springframework.core.io.UrlResource(tempFile.toUri())); Files.deleteIfExists(tempFile); // 清理临时文件 return ResponseEntity.ok(PDF 文件已成功摄入向量数据库。); } catch (IOException e) { return ResponseEntity.internalServerError().body(文件处理失败: e.getMessage()); } } GetMapping(/query) public ResponseEntityString query(RequestParam String question) { String answer ragService.ragQuery(question); return ResponseEntity.ok(answer); } }5. 创建 Agent 服务端点并验证功能现在我们将 Agent 和 RAG 服务结合起来提供一个统一的智能问答端点。5.1 创建 Agent 服务层package com.example.agent.service; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.alibaba.agent.framework.Agent; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.stereotype.Service; Service Slf4j RequiredArgsConstructor public class AgentService { private final Agent myAssistantAgent; // 注入我们配置的 Agent private final ChatClient chatClient; // 注入原始的 ChatClient用于直接调用或 RAG /** * 与 Agent 对话Agent 可以自主决定是否调用工具 */ public String chatWithAgent(String userMessage) { // 使用 Agent 进行对话 ChatResponse response myAssistantAgent.chat(userMessage); return response.getResult().getOutput().getContent(); } /** * 直接调用大模型不经过Agent工具决策用于对比或简单问答 */ public String directChat(String userMessage) { return chatClient.prompt() .user(userMessage) .call() .content(); } }5.2 创建统一的 REST 控制器package com.example.agent.controller; import com.example.agent.service.AgentService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/api/chat) RequiredArgsConstructor public class ChatController { private final AgentService agentService; PostMapping(/agent) public String chatWithAgent(RequestBody ChatRequest request) { return agentService.chatWithAgent(request.getMessage()); } PostMapping(/direct) public String directChat(RequestBody ChatRequest request) { return agentService.directChat(request.getMessage()); } // 简单的请求体 public record ChatRequest(String message) {} }5.3 运行与验证启动应用确保 Redis 服务已运行然后启动 Spring Boot 应用。验证 Agent 工具调用使用curl或 Postman 发送 POST 请求到http://localhost:8080/api/chat/agentBody 为 JSON{message: 请计算一下 15 的平方加上 28 等于多少}预期现象Agent 会识别出这是一个计算任务调用Calculator工具并返回类似表达式15*15 28的计算结果是: 253的结果。观察应用日志你会看到 Tool Calling 相关的日志。再问{message: 现在几点了}。Agent 应调用GetSystemTime工具并返回当前时间。验证 RAG 功能上传一个 PDF 文件到http://localhost:8080/api/rag/ingest-pdf(使用multipart/form-data字段名file)。调用http://localhost:8080/api/rag/query?questionPDF中某个关键词。你会收到检索到的文档片段信息。下一步你需要修改MultimodalRagService.ragQuery方法将检索到的上下文和问题真正发送给ChatClient来获得最终答案。这涉及到提示词工程Prompt Engineering例如使用ChatClient的system()方法来设定角色和指令。6. 生产环境关键问题排查与优化将 AI Agent 投入生产会面临一系列在开发环境不易察觉的问题。以下是必须关注的要点。6.1 Token 使用统计与成本控制大模型 API 按 Token 收费无限制的上下文和工具调用会导致成本激增。Alibaba Agent Framework 和 Spring AI 都提供了统计 Token 的接口。如何统计 Token Spring AI 的ChatClient返回的ChatResponse包含Metadata其中可能有 Token 使用信息取决于底层模型实现。对于 OpenAI你可以这样获取ChatResponse response chatClient.prompt().user(message).call(); MapString, Object metadata response.getMetadata(); // OpenAI 的元数据通常包含 promptTokens, completionTokens, totalTokens Integer promptTokens (Integer) metadata.get(openai.prompt.tokens); Integer completionTokens (Integer) metadata.get(openai.completion.tokens);在 Agent 调用前减少 Token 消耗的策略精简对话历史Agent 的上下文窗口包含整个对话历史。需要实现历史消息的摘要Summarization或选择性遗忘。可以配置MessageChatMemory的maxConversationSize来限制保留的消息条数。优化工具描述Tool注解中的description要简洁准确过长的描述会增加每次请求的 Token 数。压缩 RAG 检索结果从向量库检索到的文档可能很长。可以对检索结果进行摘要或提取最关键句子后再喂给模型。使用更经济的模型对于简单的工具调用或分类任务可以使用gpt-3.5-turbo而非gpt-4。6.2 处理内存与性能问题Java: OutOfMemoryError: Insufficient memory原因处理大文件如高清图片、长PDF、存储过长的对话历史、向量化大量文档时可能导致堆内存或本地内存不足。排查使用jcmd pid GC.heap_info或 VisualVM 监控堆内存使用。检查是否在循环中创建了大量未释放的大对象如Document列表。解决增加 JVM 堆内存启动参数-Xmx4g -Xms2g。流式处理文件避免将整个文件一次性读入内存。对于 PDF使用 PDFBox 的流式 API。分批次处理向量化大量文档时分批进行如每100个一批并及时清理中间集合。使用外部向量数据库确保向量数据存储在 Redis/Pinecone 等外部服务中而不是应用内存里。限制上下文长度严格控制对话历史和 RAG 上下文的 Token 总数。数组越界等运行时异常在工具方法如CalculatorSkill内部必须进行严格的输入验证和异常捕获返回友好的错误信息给 Agent而不是抛出未处理的异常导致整个 Agent 会话中断。6.3 配置与依赖问题警告: 源发行版 17 需要目标发行版 17这通常是因为 IDE 或 Maven 编译器的 Java 版本与pom.xml中设置的java.version不一致。解决检查 IDE 的 Project SDK 和 Language Level确保与pom.xml中的版本一致。在 Maven 中可以显式配置maven-compiler-plugin。依赖冲突Spring AI 和 Alibaba Agent Framework 可能引入大量传递依赖。排查使用mvn dependency:tree查看依赖树寻找冲突的库版本。解决在pom.xml中使用exclusions排除冲突的传递依赖或在dependencyManagement中统一指定版本。6.4 常见错误与排查表问题现象可能原因检查点解决方案Agent 不调用工具1. 工具描述不清晰。2. 模型能力不足如用了不支持 function calling 的模型。3. 提示词或系统指令冲突。1. 检查Tool的description。2. 确认模型是否支持工具调用如gpt-3.5-turbo-1106及以上。3. 查看 Agent 的初始系统提示如果有。1. 优化工具描述明确输入输出。2. 更换模型。3. 简化系统提示让模型专注于工具使用。RAG 检索结果不相关1. 文本分割策略不合理。2. Embedding 模型不适合领域。3. 查询问题表述不清。1. 检查分割后的 chunk 内容是否完整。2. 尝试不同的chunkSize和chunkOverlap。3. 对查询语句进行重写或扩展。1. 调整TokenTextSplitter参数。2. 考虑使用领域微调过的 Embedding 模型。3. 实现查询重写Query Rewriting步骤。应用启动失败连接 Redis/模型超时1. 网络问题。2. 配置错误地址、端口、密钥。3. 依赖缺失。1.telnet检查网络连通性。2. 检查application.yml配置特别是环境变量是否生效。3. 查看启动日志的ClassNotFoundException或NoSuchBeanDefinitionException。1. 配置正确的网络代理或检查防火墙。2. 使用ConfigurationProperties绑定配置并打印验证。3. 确保相关 starter 依赖已添加。Token 消耗异常高1. 对话历史未清理。2. RAG 返回上下文过长。3. 工具调用链过长。1. 检查ChatMemory配置。2. 打印每次请求的上下文长度。3. 监控日志中模型调用的输入长度。1. 实现对话历史摘要或轮转。2. 对 RAG 结果进行压缩或截断。3. 设置 Agent 的最大迭代次数限制。7. 最佳实践与扩展方向7.1 开发阶段最佳实践工具设计原子化每个Tool方法应只做一件事并且功能明确。这有助于模型准确理解和使用。例如将“查询用户信息”和“更新用户信息”拆分成两个工具。描述即契约Tool的description是模型理解工具的唯一依据。描述要像 API 文档一样清晰说明输入参数的含义、格式和返回值的意义。例如“根据城市名称查询实时天气。输入cityName (字符串如 ‘北京’)。返回包含温度、天气状况、湿度的 JSON 字符串。”实现健壮的错误处理工具方法内部必须处理所有可能的异常并返回结构化的错误信息而不是抛出异常。这能保证 Agent 在工具调用失败后仍能继续推理或告知用户。为 Agent 设定明确的系统角色在创建Agent时通过.system()方法提供一个清晰的系统指令界定其能力范围和回答风格。例如“你是一个专业的 IT 助手擅长使用计算工具和查询系统信息。如果用户问题超出你的工具范围请直接说明。”7.2 生产环境部署建议配置外部化与安全所有 API Key、数据库密码等敏感信息必须通过环境变量或配置中心如 Nacos, Apollo注入。为不同环境开发、测试、生产准备不同的配置文件。实施监控与告警监控关键指标API 调用延迟、Token 消耗速率、工具调用成功率、向量数据库连接状态。记录详细的审计日志包括用户的原始问题、Agent 的思考过程、调用的工具及参数、模型的最终回复。这对于调试和优化至关重要。集成 Spring Boot Actuator 和 Micrometer将指标发送到 Prometheus 和 Grafana。设计降级与熔断策略大模型 API 可能不稳定。使用 Resilience4j 或 Sentinel 为ChatClient的调用配置熔断器、重试和超时。当主要模型服务不可用时应有备选方案如切换到另一个模型供应商或返回缓存答案。管理对话状态对于 Web 应用需要将用户的ChatMemory与用户会话Session或数据库关联实现跨请求的持久化对话。7.3 后续扩展方向集成更复杂的多模态探索使用专门的视觉模型如 CLIP为图像生成向量与文本向量一起存入多模态向量数据库如 Qdrant实现真正的图文混合检索。实现 PlanAndExecute Agent对于需要多步骤复杂规划的任务可以尝试 Alibaba Framework 提供的PlanAndExecuteAgent。它先制定详细计划再逐步执行适合复杂问题拆解。接入工作流引擎将 Agent 作为决策节点嵌入到 Camunda、Flowable 等工作流中实现 AI 驱动的自动化业务流程。模型微调Fine-tuning如果领域性很强可以考虑使用少量标注数据对基础大模型进行微调或训练专用的 Embedding 模型以大幅提升在特定任务上的准确性和效率。构建技能市场将 Skill 设计成可插拔的模块通过配置文件动态加载实现业务能力的灵活组装。构建 AI Agent 应用是一个持续迭代的过程核心在于理解业务需求、设计清晰的工具契约、并建立完善的观测和运维体系。从本文的最小可行产品MVP出发你可以逐步融入上述高级特性和生产保障措施最终打造出稳定、可靠且智能的业务助手。