基于Spring AI Alibaba构建Java AI Agent:集成多模态RAG与自定义Skill

📅 发布时间:2026/8/2 17:01:33
基于Spring AI Alibaba构建Java AI Agent:集成多模态RAG与自定义Skill 最近在尝试将大模型能力集成到Java后端项目中发现直接调用API虽然简单但想要构建一个能理解复杂意图、自主调用工具、并具备长期记忆的智能体Agent却面临架构设计、工具管理、状态维护等一系列挑战。Spring AI Alibaba Agent Framework的出现为Java开发者提供了一套开箱即用的Agent构建方案尤其与多模态RAG检索增强生成和自定义Skill结合后能轻松打造出强大的行业应用。本文将从零开始手把手带你基于Spring AI Alibaba Agent Framework构建一个集成了多模态RAG和自定义Skill的Java AI Agent。内容涵盖核心概念、环境搭建、框架集成、RAG构建、Skill开发以及工程实践提供完整可运行的代码示例。无论你是想快速入门AI Agent开发还是寻求在企业级Java项目中落地智能体应用都能从中获得可直接复用的解决方案。1. 背景与核心概念为什么需要AI Agent框架在深入代码之前我们有必要厘清几个关键概念理解Spring AI Alibaba Agent Framework究竟解决了什么问题。1.1 从大模型到AI Agent大模型LLM提供了强大的理解和生成能力但它本质是一个“对话者”。当面临“查询公司上周财报并总结风险点”这类复杂任务时仅靠单次对话无法完成。AI Agent智能体则是一个更高级的抽象它具备感知-规划-行动-反思的循环能力。它可以理解用户目标拆解为子任务如登录系统、查询数据、调用分析接口自主选择并执行合适的工具Skill最终整合结果返回给用户。1.2 Spring AI Alibaba Agent Framework 是什么它是Spring AI生态中由阿里云贡献的一个用于构建、管理和运行AI Agent的高层框架。它基于Spring Boot提供了声明式的编程模型让开发者能像定义Spring Bean一样定义Agent、Skill和工具链。其核心优势在于开箱即用内置了ReActReasoning Acting、Plan-and-Execute等经典Agent执行模式。技能Skill管理可以方便地注册、发现和组合不同的技能如数据库查询、API调用、文件处理。状态管理自动维护Agent的会话历史、执行状态和工具调用记录。多模型支持可轻松对接阿里云灵积、通义千问等国内模型也支持OpenAI、Ollama等。与Spring生态无缝集成享受依赖注入、配置管理、监控等Spring全家桶能力。1.3 多模态RAG检索增强生成传统RAG主要针对文本而多模态RAG能处理图像、音频、视频、表格等多种格式的数据。其流程为将非文本数据通过编码器如CLIP转换为向量与文本向量一同存入向量数据库。当用户提问时系统同时检索相关的文本和多媒体片段将其作为上下文提供给大模型从而生成更准确、信息更丰富的回答。这对于知识库问答、产品说明书解读等场景至关重要。1.4 Skill技能在Agent框架中Skill是一个可执行的最小功能单元通常对应一个具体的工具或API。例如WeatherSkill: 调用天气API。DBSearchSkill: 执行数据库查询。CalculatorSkill: 进行数学计算。 框架负责将用户的自然语言指令通过大模型“翻译”成对特定Skill的调用。技术栈全景图我们的目标架构如下用户通过自然语言与Java AI Agent交互Agent核心由Spring AI Alibaba Agent Framework驱动。Agent根据意图可以调用两类核心能力一是多模态RAG系统从向量库中检索图文并茂的上下文二是各类自定义Skill执行具体的业务逻辑。整个系统基于Spring Boot并可灵活配置底层的大模型。2. 环境准备与项目搭建我们使用Spring Boot 3.x 和 Java 17 进行开发。Spring AI Alibaba 相关组件版本需保持一致。2.1 基础环境JDK: 17 或 21 (推荐17)Maven: 3.6IDE: IntelliJ IDEA 或 VS Code向量数据库: 本文示例选用ChromaDB轻量易于本地启动生产环境可考虑Milvus、Weaviate等。2.2 初始化Spring Boot项目使用 Spring Initializr 生成项目选择Project: MavenLanguage: JavaSpring Boot: 3.2.xDependencies:Spring Web,Lombok,Spring AI Alibaba你也可以直接使用以下pom.xml核心依赖?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 !-- 使用稳定版本 -- relativePath/ /parent groupIdcom.example/groupId artifactIdjava-ai-agent-demo/artifactId version0.0.1-SNAPSHOT/version namejava-ai-agent-demo/name descriptionDemo project for Java AI Agent with Spring AI Alibaba/description properties java.version17/java.version spring-ai-alibaba.version0.1.0/spring-ai-alibaba.version !-- 请检查最新版本 -- /properties dependencies !-- Spring Boot 基础 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- Spring AI Alibaba 核心 -- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-bom/artifactId version${spring-ai-alibaba.version}/version typepom/type scopeimport/scope /dependency dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-ai-service/artifactId /dependency !-- Agent Framework 依赖 -- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-agent-framework/artifactId /dependency !-- 假设使用DashScope模型 -- dependency groupIdcom.alibaba.cloud.ai/groupId artifactIdspring-ai-alibaba-dashscope-spring-boot-starter/artifactId /dependency !-- 向量数据库连接 (以Chroma为例需根据实际选择) -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-chroma-store-spring-boot-starter/artifactId version0.8.1/version !-- Spring AI 版本 -- /dependency !-- 多模态处理图片向量化等 (示例) -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version0.8.1/version !-- 用于OpenAI的CLIP模型或选择其他提供商 -- scoperuntime/scope !-- 仅用于编码非必须 -- /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 及相关组件迭代较快请务必在 Alibaba Cloud Spring AI 官方仓库查看最新版本和依赖配置。2.3 配置文件在application.yml中配置大模型连接和向量数据库。这里以阿里云灵积DashScope和本地ChromaDB为例。# application.yml spring: application: name: java-ai-agent-demo # Spring AI Alibaba DashScope 配置 ai: alibaba: dashscope: # 从阿里云控制台获取https://dashscope.console.aliyun.com/ api-key: ${DASHSCOPE_API_KEY:your-api-key-here} # 选择模型如 qwen-max, qwen-plus chat: options: model: qwen-max temperature: 0.7 # 向量存储配置 (Chroma) vectorstore: chroma: # 本地ChromaDB地址 host: localhost port: 8000 # 集合名称 collection-name: multimodal_docs # 是否在启动时创建集合如果不存在 initialize-schema: true # 自定义配置 app: rag: # 多模态文档存储路径 doc-store-path: ./data/docs # 图片向量化模型如果使用OpenAI CLIP image-embedding-model: clip-vit-base-patch32确保已设置环境变量DASHSCOPE_API_KEY或直接在配置文件中填入不推荐提交至代码库。3. 核心组件一构建多模态RAG系统RAG系统是Agent的“外部大脑”为其提供精准的知识检索能力。我们构建一个支持文本和图片的多模态RAG服务。3.1 数据准备与向量化首先定义文档和图片的元数据结构。// 文件路径src/main/java/com/example/agent/rag/model/DocumentChunk.java package com.example.agent.rag.model; import lombok.Data; import java.util.List; import java.util.Map; Data public class DocumentChunk { private String id; private String text; // 文本内容 private String imagePath; // 图片本地路径或URL (可选) private ListFloat textEmbedding; // 文本向量 private ListFloat imageEmbedding; // 图片向量 (可选) private MapString, Object metadata; // 来源、页码等元数据 }接着创建服务来处理文档的加载、分块、向量化及存储。// 文件路径src/main/java/com/example/agent/rag/service/MultimodalRagService.java package com.example.agent.rag.service; import com.example.agent.rag.model.DocumentChunk; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.document.Document; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; Slf4j Service RequiredArgsConstructor public class MultimodalRagService { private final VectorStore vectorStore; // Spring AI 自动注入 private final ResourceLoader resourceLoader; private final TextEmbeddingService textEmbeddingService; // 文本向量化服务 private final ImageEmbeddingService imageEmbeddingService; // 图片向量化服务 (需实现) Value(${app.rag.doc-store-path}) private String docStorePath; /** * 初始化加载指定目录下的文档并存入向量库 */ PostConstruct public void initVectorStore() throws IOException { Path docsPath Paths.get(docStorePath); if (!Files.exists(docsPath) || !Files.isDirectory(docsPath)) { log.warn(文档目录不存在: {}, docStorePath); return; } ListDocument documents loadAndSplitDocuments(docsPath); if (!documents.isEmpty()) { vectorStore.add(documents); log.info(成功加载并向量化 {} 个文档片段, documents.size()); } } /** * 加载并分割文档简化版按文件类型处理 */ private ListDocument loadAndSplitDocuments(Path docsPath) throws IOException { ListDocument allChunks new ArrayList(); // 遍历目录 Files.list(docsPath).forEach(filePath - { try { if (filePath.toString().endsWith(.txt)) { allChunks.addAll(processTextFile(filePath)); } else if (filePath.toString().matches(.*\\.(jpg|png|jpeg)$)) { allChunks.addAll(processImageFile(filePath)); } else if (filePath.toString().endsWith(.pdf)) { // 处理PDF可使用Apache PDFBox等库 // allChunks.addAll(processPdfFile(filePath)); } } catch (Exception e) { log.error(处理文件失败: {}, filePath, e); } }); return allChunks; } private ListDocument processTextFile(Path filePath) throws IOException { String content Files.readString(filePath); // 简单按段落分割生产环境可用更复杂的分块策略 String[] paragraphs content.split(\\n\\s*\\n); ListDocument chunks new ArrayList(); for (int i 0; i paragraphs.length; i) { String paragraph paragraphs[i].trim(); if (!paragraph.isEmpty()) { // 生成文本向量 ListFloat embedding textEmbeddingService.embed(paragraph); // 构建Spring AI Document对象 Document doc new Document(paragraph, Map.of(source, filePath.getFileName().toString(), chunk_index, i, type, text)); // 注意Spring AI VectorStore 内部会调用EmbeddingClient重新生成向量。 // 这里仅为演示多模态向量存储逻辑。 chunks.add(doc); } } return chunks; } private ListDocument processImageFile(Path filePath) { // 处理图片生成图片描述和向量 // 1. 使用多模态模型如Qwen-VL生成图片描述文本 // String description imageCaptioningService.caption(filePath); // 2. 使用CLIP等模型生成图片向量 // ListFloat imageEmbedding imageEmbeddingService.embed(filePath); // 3. 将描述文本和图片向量关联存储 // 此处简化仅存储图片路径作为文本内容 Document doc new Document(图片文件: filePath.getFileName(), Map.of(source, filePath.getFileName().toString(), image_path, filePath.toAbsolutePath().toString(), type, image)); return List.of(doc); } /** * 混合检索根据查询文本同时检索相关的文本和图片片段 */ public ListDocument hybridSearch(String query, int topK) { // 1. 文本检索 ListDocument textResults vectorStore.similaritySearch( SearchRequest.query(query).withTopK(topK) ); // 2. 图片检索如果查询可能涉及图片内容 // 可以将查询文本向量化与预先存储的图片向量进行相似度搜索 // ListDocument imageResults searchImagesByText(query, topK); // 3. 结果合并与重排可根据分数、类型等 // ListDocument allResults mergeAndRerank(textResults, imageResults); // 此处简化仅返回文本结果 return textResults; } /** * 为Agent提供格式化后的上下文 */ public String getContextForAgent(String query) { ListDocument relevantDocs hybridSearch(query, 5); if (relevantDocs.isEmpty()) { return 未在知识库中找到相关信息。; } StringBuilder context new StringBuilder(以下是从知识库中检索到的相关信息\n); for (int i 0; i relevantDocs.size(); i) { Document doc relevantDocs.get(i); context.append(String.format([片段 %d, 来源: %s]\n, i 1, doc.getMetadata().get(source))); context.append(doc.getContent()).append(\n\n); } return context.toString(); } }3.2 向量化服务实现文本向量化服务可以直接使用Spring AI Alibaba提供的EmbeddingClient。// 文件路径src/main/java/com/example/agent/rag/service/TextEmbeddingService.java package com.example.agent.rag.service; import lombok.RequiredArgsConstructor; import org.springframework.ai.embedding.EmbeddingClient; import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.stereotype.Service; import java.util.List; Service RequiredArgsConstructor public class TextEmbeddingService { private final EmbeddingClient embeddingClient; public ListFloat embed(String text) { EmbeddingResponse response embeddingClient.embedForResponse(List.of(text)); // 通常返回第一个也是唯一一个输入的向量 return response.getResult().getOutput(); } }图片向量化服务需要接入多模态Embedding模型如OpenAI CLIP、阿里云通义千问VL实现类似。4. 核心组件二开发自定义SkillSkill是Agent执行具体动作的“手”和“脚”。我们开发两个示例Skill一个查询RAG知识库一个执行简单的计算。4.1 定义Skill基类与注解Spring AI Alibaba Agent Framework 提供了Skill注解和Tool接口来定义技能。// 文件路径src/main/java/com/example/agent/skill/WeatherSkill.java package com.example.agent.skill; import com.alibaba.cloud.ai.agent.framework.skill.annotation.Skill; import com.alibaba.cloud.ai.agent.framework.skill.annotation.Tool; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; Slf4j Component Skill(name 天气查询技能, description 根据城市名称查询实时天气情况) public class WeatherSkill { Tool(name get_weather, description 查询指定城市的天气参数city-城市名) public String getWeather(String city) { log.info(正在查询 {} 的天气..., city); // 模拟调用天气API // 实际项目中这里应调用如和风天气、OpenWeatherMap等API String mockWeather switch (city) { case 北京 - 晴15°C北风2级; case 上海 - 多云18°C东南风1级; case 深圳 - 阵雨22°C南风3级; default - 未知城市请提供正确的城市名称。; }; return String.format(%s的天气是%s, city, mockWeather); } }4.2 集成RAG的Skill创建一个Skill让Agent能够使用我们之前构建的RAG系统来回答问题。// 文件路径src/main/java/com/example/agent/skill/RagQuerySkill.java package com.example.agent.skill; import com.alibaba.cloud.ai.agent.framework.skill.annotation.Skill; import com.alibaba.cloud.ai.agent.framework.skill.annotation.Tool; import com.example.agent.rag.service.MultimodalRagService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; Slf4j Component Skill(name 知识库查询技能, description 从公司内部知识库中检索信息来回答问题) RequiredArgsConstructor public class RagQuerySkill { private final MultimodalRagService ragService; Tool(name query_knowledge_base, description 使用自然语言问题查询知识库参数question-你的问题) public String queryKnowledgeBase(String question) { log.info(Agent正在查询知识库问题{}, question); // 1. 从RAG系统获取相关上下文 String context ragService.getContextForAgent(question); // 2. 将上下文和问题组合准备交给LLM生成最终答案这一步通常在Agent框架内自动完成 // 这里我们直接返回上下文框架会将其作为工具调用的结果传递给LLM进行总结。 return context; } }4.3 更复杂的Skill示例数据分析Skill假设我们有一个简单的业务数据查询接口。// 文件路径src/main/java/com/example/agent/skill/DataAnalysisSkill.java package com.example.agent.skill; import com.alibaba.cloud.ai.agent.framework.skill.annotation.Skill; import com.alibaba.cloud.ai.agent.framework.skill.annotation.Tool; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.time.LocalDate; import java.util.Map; Slf4j Component Skill(name 数据分析技能, description 对业务数据进行简单的统计和查询) public class DataAnalysisSkill { Tool(name get_sales_summary, description 获取指定日期范围内的销售总额参数startDate-开始日期(YYYY-MM-DD), endDate-结束日期(YYYY-MM-DD)) public String getSalesSummary(String startDate, String endDate) { log.info(查询销售汇总日期范围{} 至 {}, startDate, endDate); // 模拟数据库查询 // 实际应调用Service层 double totalSales 150000.0; int orderCount 120; return String.format(在%s至%s期间总销售额为%.2f元订单数量为%d笔。, startDate, endDate, totalSales, orderCount); } Tool(name get_user_stats, description 获取用户活跃度统计) public MapString, Object getUserStats() { log.info(查询用户统计信息); return Map.of( total_users, 1000, active_today, 150, avg_session_duration, 12.5分钟 ); } }5. 组装与配置AI Agent有了RAG系统和Skill现在我们可以使用Spring AI Alibaba Agent Framework来组装一个功能完整的Agent。5.1 配置Agent执行器Executor框架提供了AgentExecutor我们需要配置它使用的模型、技能列表以及执行策略。// 文件路径src/main/java/com/example/agent/config/AgentConfig.java package com.example.agent.config; import com.alibaba.cloud.ai.agent.framework.AgentExecutor; import com.alibaba.cloud.ai.agent.framework.executor.impl.ReActAgentExecutor; import com.alibaba.cloud.ai.agent.framework.planner.impl.ReActPlanner; import com.alibaba.cloud.ai.agent.framework.skill.SkillRegistry; import com.alibaba.cloud.ai.dashscope.DashScopeChatModel; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class AgentConfig { /** * 注册Agent执行器使用ReAct模式。 * ReAct模式让Agent通过“思考(Reasoning)-行动(Acting)”循环来使用工具。 */ Bean public AgentExecutor agentExecutor(DashScopeChatModel chatModel, SkillRegistry skillRegistry) { // 1. 创建规划器Planner决定如何使用工具 ReActPlanner planner new ReActPlanner(chatModel, skillRegistry); // 2. 创建执行器绑定规划器和模型 return new ReActAgentExecutor(planner, chatModel); } }5.2 创建Agent服务层提供一个服务类作为与Agent交互的入口。// 文件路径src/main/java/com/example/agent/service/AgentService.java package com.example.agent.service; import com.alibaba.cloud.ai.agent.framework.AgentExecutor; import com.alibaba.cloud.ai.agent.framework.message.AgentMessage; import com.alibaba.cloud.ai.agent.framework.message.impl.StringAgentMessage; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; Slf4j Service RequiredArgsConstructor public class AgentService { private final AgentExecutor agentExecutor; /** * 与Agent进行单轮对话 * param userInput 用户输入 * return Agent的回复 */ public String chat(String userInput) { log.info(用户提问{}, userInput); try { AgentMessage message new StringAgentMessage(userInput); AgentMessage response agentExecutor.execute(message); String responseText response.getContent().toString(); log.info(Agent回复{}, responseText); return responseText; } catch (Exception e) { log.error(Agent执行出错, e); return 抱歉处理您的请求时出现了问题 e.getMessage(); } } /** * 带会话历史的对话示例 * 框架通常会自动管理会话状态这里展示扩展思路。 */ public String chatWithHistory(String sessionId, String userInput) { // 可以从缓存如Redis中根据sessionId获取历史消息列表 // ListAgentMessage history sessionCache.get(sessionId); // 将历史消息和当前输入一起传给AgentExecutor // 框架的AgentExecutor可能支持传入历史上下文 // 此处简化直接调用单轮对话 return chat(userInput); } }5.3 创建RESTful控制器暴露HTTP API供前端或其他服务调用。// 文件路径src/main/java/com/example/agent/controller/AgentController.java package com.example.agent.controller; import com.example.agent.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 chat(RequestBody ChatRequest request) { return agentService.chat(request.getMessage()); } // 支持带会话的聊天 PostMapping(/chat/{sessionId}) public String chatWithSession(PathVariable String sessionId, RequestBody ChatRequest request) { // 实际应实现会话管理 return agentService.chatWithHistory(sessionId, request.getMessage()); } // 简单的请求体 public record ChatRequest(String message) {} }6. 运行、测试与效果演示6.1 启动服务确保ChromaDB已启动例如通过Docker:docker run -p 8000:8000 chromadb/chroma。在./data/docs目录下放置一些.txt或图片文件作为知识库。运行Spring Boot主类JavaAiAgentDemoApplication。6.2 测试Agent能力使用curl或 Postman 测试接口。测试Skill调用天气查询curl -X POST http://localhost:8080/api/agent/chat \ -H Content-Type: application/json \ -d {message:今天北京天气怎么样}预期输出Agent会识别出需要调用get_weather工具并返回模拟的天气信息。回复可能类似“根据查询北京的天气是晴15°C北风2级。”测试RAG集成知识库问答curl -X POST http://localhost:8080/api/agent/chat \ -H Content-Type: application/json \ -d {message:我们公司的主要产品是什么}预期过程Agent识别出需要查询知识库调用query_knowledge_base工具。RagQuerySkill从向量库中检索出相关文档片段。检索到的上下文被返回给Agent。Agent将上下文和原始问题结合调用大模型生成最终答案。返回类似“根据知识库信息公司的主要产品是智能AI助手平台专注于为企业提供定制化的对话机器人解决方案...”。测试复杂任务分解curl -X POST http://localhost:8080/api/agent/chat \ -H Content-Type: application/json \ -d {message:帮我查一下上周的销售情况然后告诉我北京和上海的天气对比。}预期过程Agent会展示ReAct模式的威力思考用户需要两个信息销售情况和两地天气。行动1调用get_sales_summary技能传入上周的日期范围。观察获得销售汇总结果。思考还需要北京和上海的天气。行动2调用get_weather技能参数为“北京”。观察获得北京天气。行动3调用get_weather技能参数为“上海”。观察获得上海天气。最终回答整合所有工具调用的结果生成一段连贯的总结回复。6.3 查看日志观察控制台日志可以看到框架详细的思考链Chain-of-Thought和工具调用记录这对于调试和理解Agent行为非常有帮助。7. 常见问题与排查思路在开发和使用过程中你可能会遇到以下典型问题问题现象可能原因排查思路与解决方案启动报错BeanCreationException找不到ChatModel或EmbeddingClientBean1. 大模型依赖未正确引入。2.application.yml中API Key配置错误或缺失。3. 版本不兼容。1. 检查pom.xml中spring-ai-alibaba-dashscope-spring-boot-starter依赖是否存在。2. 确认DASHSCOPE_API_KEY环境变量或配置文件已正确设置。3. 检查Spring Boot、Spring AI Alibaba 和 DashScope Starter 的版本兼容性。Agent不调用Skill直接让大模型回答1. Skill的Tool注解描述不清晰LLM无法理解其用途。2. 提示词Prompt未优化未能有效激发Agent使用工具。3. Skill未成功注册到SkillRegistry。1. 优化Tool的description用清晰、具体的自然语言描述工具的功能和参数。2. 检查框架的默认提示词考虑自定义Planner的提示模板。3. 确保Skill类被Component或Service注解并被Spring容器管理。RAG检索结果不相关1. 文档分块策略不合理太大或太小。2. 向量模型与查询不匹配。3. 向量数据库相似度搜索参数如topK设置不当。1. 调整分块大小和重叠度尝试按句子、段落或固定字符数分割。2. 确保检索时的查询文本与文档存储时使用的嵌入模型一致。3. 调整topK参数并考虑使用混合检索Hybrid Search结合关键词匹配。工具调用参数解析错误1. LLM生成的参数格式与工具方法签名不匹配。2. 参数类型复杂如对象、数组。1. 在Tool的description中明确参数类型和格式如“日期格式为YYYY-MM-DD”。2. 尽量使用简单类型String, int, boolean作为工具参数。复杂参数可设计为JSON字符串在工具方法内解析。多模态RAG中图片处理失败1. 图片向量化服务未正确配置或模型不可用。2. 图片路径错误或权限问题。3. 多模态Embedding模型不支持特定图片格式。1. 检查图片向量化服务如OpenAI CLIP的API Key和连接。2. 确保app.rag.doc-store-path路径可访问图片文件存在。3. 确认模型支持的图片格式通常为jpg, png并进行预处理如调整大小。性能问题响应慢1. 大模型API调用延迟高。2. RAG检索耗时尤其是图片向量化。3. Agent进行了多轮不必要的工具调用。1. 考虑使用更快的模型或部署本地模型如通过Ollama。2. 对图片向量进行预计算并缓存。对文本检索使用索引优化。3. 优化Agent的规划策略设置工具调用的最大轮次max iterations。8. 最佳实践与工程建议将AI Agent投入生产环境需要考虑更多工程化因素。8.1 技能Skill设计原则单一职责每个Skill只做一件事并做好。避免在一个Skill中混杂多个不相关的功能。清晰描述Tool的name和description是LLM理解工具的“说明书”务必用自然语言精确描述功能、输入和输出。健壮性Skill内部要有完善的异常处理和日志记录。对外部API调用设置超时和重试机制。无状态性尽量将Skill设计为无状态的依赖注入所需服务。状态应由Agent框架或外部存储管理。8.2 RAG系统优化分块策略根据文档类型选择分块方式。技术文档可按章节对话记录可按轮次。适当重叠如50-100字符可避免上下文断裂。元数据丰富化在向量化时存储更多元数据如文档ID、章节标题、重要性标签便于后续过滤和重排。检索后重排Rerank初次向量检索后可以使用更精细的交叉编码器Cross-Encoder模型对结果进行重排提升精度。缓存机制对频繁的相同或相似查询结果进行缓存显著降低响应延迟和模型调用成本。8.3 Agent的提示工程与规划系统提示词System Prompt在配置AgentExecutor时可以注入强化的系统提示词明确Agent的角色、可用工具列表、输出格式要求和约束如“如果无法确定请说不知道”。限制工具调用轮次通过配置maxIterations或maxSteps防止Agent陷入无限循环。验证工具输出对于关键操作如数据修改、外部支付可以在Skill执行后设计一个验证步骤让Agent确认结果是否符合预期。8.4 可观测性与监控结构化日志记录完整的Agent执行链包括用户输入、LLM的“思考”过程、每次工具调用的输入输出、最终回复。这对于调试和效果分析至关重要。性能指标监控平均响应时间、工具调用成功率、各阶段耗时LLM推理、检索、工具执行、Token消耗量。评估与反馈建立人工评估或用户反馈机制持续收集Bad Case用于优化提示词、技能描述和RAG检索策略。8.5 安全与权限技能权限控制不是所有用户都能调用所有Skill。可以在Skill方法前加入Spring Security的PreAuthorize注解或自定义一个权限校验层。输入输出过滤对用户输入和Skill返回的内容进行必要的安全检查防止Prompt注入、敏感信息泄露。审计日志记录所有Agent交互的完整流水满足合规要求。通过以上步骤我们完成了一个集成了多模态RAG和自定义Skill的Java AI Agent。它不再是简单的聊天接口而是一个能自主利用知识、调用工具完成复杂任务的智能助手。Spring AI Alibaba Agent Framework极大地降低了开发门槛让Java后端团队也能快速拥抱Agent技术。你可以在此基础上继续扩展更多业务技能如订单查询、报表生成接入更丰富的知识源或优化Agent的决策逻辑构建出更强大的企业级智能应用。