# AI PaaS 平台架构设计文档 ## 1. 整体架构 AI PaaS 平台采用分层架构设计,主要包含以下层次: 1. **接口层**:RESTful API 接口,处理客户端请求 2. **服务层**:业务逻辑处理,包括 Agent 服务、RAG 服务等 3. **核心层**:Agent 核心实现,包括 BaseAgent、ReActAgent、ToolCallAgent 等 4. **存储层**:对话记忆存储,包括内存存储和 Redis 存储 5. **客户端层**:外部服务集成,包括 MCP 客户端和 RAG 客户端 ## 2. 记忆层设计与实现 ### 2.1 记忆存储方案 系统支持两种记忆存储方式: - **内存存储**:适用于临时对话,重启后数据丢失 - **Redis 存储**:适用于持久化对话,支持跨会话保持 ### 2.2 Kryo 序列化实现 **核心实现文件**:`RedisBasedChatMemory.java` **序列化流程**: 1. **Kryo 初始化**:在静态代码块中初始化 Kryo 实例,设置实例化策略 2. **消息序列化**:将 Message 列表转换为字节数组 3. **存储到 Redis**:使用 RedisTemplate 将序列化后的数据存储到 Redis 4. **反序列化**:从 Redis 读取字节数组,反序列化为 Message 列表 **关键代码**: ```java // 序列化消息列表 private byte[] serialize(List messages) { } // 反序列化消息列表 private List deserialize(byte[] data) { } ``` ### 2.3 对话历史查找 **实现方式**: 1. **键值设计**:使用 `chat:memory:{conversationId}` 作为 Redis 键 2. **获取历史**:通过 `get` 方法获取指定对话的历史消息 3. **限制数量**:支持返回最近 N 轮对话历史 4. **过期时间**:默认设置 7 天过期时间,避免内存占用过大 ## 3. RAG 核心流程 ### 3.1 RAG 流程设计 **核心实现文件**:`RagService.java` **流程步骤**: 1. **查询词生成**:使用本地模型将用户问题转换为精准的检索查询词 2. **向量检索**:调用 RAG 客户端进行向量检索 3. **结果处理**:对检索结果进行排序和数量限制 4. **上下文构建**:将检索结果拼接为上下文 5. **关键信息提取**:从上下文中提取关键信息 6. **信息保存**:判断是否需要保存提取的关键信息 ### 3.2 查询词生成 **实现方式**:使用本地 Ollama 模型生成精准的检索查询词,考虑历史对话上下文 **关键代码**: ```java public String generateRetrievalQuery(String userCurrentMsg, List historyDialog) { log.info("[RAG-Query] 开始生成检索查询词"); log.info("[RAG-Query] 用户原始消息:{}", userCurrentMsg); // 构建提示词 StringBuilder promptBuilder = new StringBuilder(); promptBuilder.append("你是一个检索查询优化助手。请根据用户当前问题和历史对话,生成一个精准的检索查询词。\n"); promptBuilder.append("要求:\n"); promptBuilder.append("1. 提取核心关键词\n"); promptBuilder.append("2. 去除无关词汇\n"); promptBuilder.append("3. 保持简洁\n"); promptBuilder.append("4. 只返回查询词,不要有其他内容\n\n"); if (historyDialog != null && !historyDialog.isEmpty()) { promptBuilder.append("历史对话:\n"); for (Message msg : historyDialog) { if (msg instanceof UserMessage) { promptBuilder.append("用户:").append(msg.getText()).append("\n"); } } promptBuilder.append("\n"); } promptBuilder.append("当前问题:").append(userCurrentMsg).append("\n"); promptBuilder.append("生成的检索查询词:"); String prompt = promptBuilder.toString(); log.debug("[RAG-Query] 提示词:\n{}", prompt); try { // 使用本地模型生成查询词 ChatResponse response = ollamaChatModel.call(new Prompt(prompt)); String query = response.getResult().getOutput().getText().trim(); log.info("[RAG-Query] 生成的检索查询词:{}", query); return query; } catch (Exception e) { log.error("[RAG-Query] 生成检索查询词失败,使用原始问题", e); return userCurrentMsg; } } ``` ### 3.3 检索与结果处理 **实现方式**:调用 RAG 客户端进行检索,对结果进行排序和限制 **关键代码**: ```java public Mono retrieve(String query, AgentConfiguration.RagConfig ragConfig) { if (ragConfig == null || !Boolean.TRUE.equals(ragConfig.getEnabled())) { log.debug("RAG 未启用,跳过检索"); return Mono.empty(); } // 转换为 RAG 客户端请求 List vectorStores = ragConfig.getVectorStores().stream() .map(config -> RagRetrieveRequest.VectorStoreConfig.builder() .vectorStoreId(config.getVectorStoreId()) .topK(config.getTopK()) .scoreThreshold(config.getScoreThreshold()) .build()) .collect(Collectors.toList()); RagRetrieveRequest request = RagRetrieveRequest.builder() .query(query) .vectorStores(vectorStores) .build(); return ragClient.retrieve(request); } public List sortAndLimitResults( RagRetrieveResponse response, Integer maxResults) { if (response == null || response.getResults() == null) { log.warn("[RAG-Sort] 响应或结果为空"); return List.of(); } log.info("[RAG-Sort] 开始排序,原始结果数:{},最大结果数:{}", response.getResults().size(), maxResults); List sorted = response.getResults().stream() .sorted(Comparator.comparing(RagRetrieveResponse.Result::getScore).reversed()) .limit(maxResults) .collect(Collectors.toList()); log.info("[RAG-Sort] 排序完成,保留结果数:{}", sorted.size()); return sorted; } ``` ## 4. ReAct 实现 ### 4.1 ReAct 架构设计 **核心实现文件**:`ReActAgent.java` **设计理念**: - **Think 阶段**:分析当前情况,决定是否需要调用工具 - **Act 阶段**:执行工具调用并处理结果 - **状态管理**:跟踪 Agent 的执行状态 - **步数限制**:防止无限循环 ### 4.2 核心实现 **关键代码**: ```java /** * 运行 Agent * * @param userPrompt 用户输入 * @return 执行结果 */ public String run(String userPrompt) { if (this.state != AgentState.IDLE) { throw new RuntimeException("Cannot run agent from state: " + this.state); } if (userPrompt == null || userPrompt.trim().isEmpty()) { throw new RuntimeException("Cannot run agent with empty user prompt"); } state = AgentState.RUNNING; messageList.add(new UserMessage(userPrompt)); List results = new ArrayList<>(); try { for (int i = 0; i < maxSteps && state != AgentState.FINISHED; i++) { currentStep = i + 1; log.info("[{}] 执行第 {} 步", name, currentStep); String stepResult = step(); results.add("Step " + currentStep + ": " + stepResult); } if (currentStep >= maxSteps) { state = AgentState.FINISHED; results.add("Terminated: Reached max steps (" + maxSteps + ")"); } return String.join("\n", results); } catch (Exception e) { state = AgentState.ERROR; log.error("[{}] 执行错误: {}", name, e.getMessage(), e); return "执行错误: " + e.getMessage(); } finally { this.cleanup(); } } /** * 单步执行 * 将 think() 和 act() 组合在一起 * * @return 步骤执行结果 */ public String step() { try { // 思考阶段:决定是否需要调用工具 boolean shouldAct = think(); if (!shouldAct) { return "思考完成 - 无需行动"; } // 行动阶段:执行工具调用 return act(); } catch (Exception e) { log.error("[{}] 步骤执行失败: {}", name, e.getMessage(), e); return "步骤执行失败: " + e.getMessage(); } } /** * 思考阶段 * 分析当前情况,决定是否需要调用工具 * * @return true - 需要调用工具,false - 无需调用工具 */ public abstract boolean think(); /** * 行动阶段 * 执行工具调用并处理结果 * * @return 行动结果 */ public abstract String act(); ``` ## 5. 配置管理架构 ### 5.1 配置管理设计 **核心实现文件**: - `AgentConfigRegistry.java`:Agent 配置注册表 - `AgentConfiguration.java`:Agent 配置类 - `ConfigMapWatcher.java`:配置监视器 **设计理念**: - **集中管理**:所有 Agent 配置集中在注册表中管理 - **动态更新**:支持配置的动态刷新和监听 - **结构化配置**:使用 YAML 配置文件,支持结构化配置 ### 5.2 配置结构 配置文件支持以下结构: - **Agent 基本配置**:名称、描述、类型等 - **ReAct 配置**:是否启用 ReAct 模式 - **RAG 配置**:向量存储、TopK、分数阈值等 - **记忆配置**:存储类型、过期时间等 - **MCP 配置**:MCP Hub 地址、鉴权信息等 ## 6. MCP 功能集成 ### 6.1 MCP 架构设计 **核心实现文件**: - `McpClientService.java`:MCP 客户端服务,负责与 MCP Hub 通信 - `McpTool.java`:MCP 工具封装,将 MCP 工具转换为 Spring AI 工具 - `McpServerConfig.java`:MCP 服务器配置 **设计理念**: - **模块化设计**:独立的 MCP 客户端模块,与其他模块解耦 - **会话管理**:支持多会话管理,每个会话对应一个 MCP 连接 - **智能路由**:支持智能路由模式,提供更智能的工具搜索和执行 ### 6.2 MCP 核心功能 **功能列表**: 1. **连接管理**:建立和管理与 MCP Hub 的 SSE 连接 2. **工具列表**:获取 MCP Hub 提供的工具列表 3. **工具调用**:调用 MCP Hub 中的工具 4. **智能路由**:使用智能路由搜索和执行工具 **关键代码**: ```java // MCP 连接管理 public synchronized String connect(String group) { // 如果已有连接,先关闭 if (sessions.containsKey(group)) { closeSession(sessions.get(group)); } SessionInfo sessionInfo = new SessionInfo(); sessionInfo.setGroup(group); sessionInfo.setSessionId(UUID.randomUUID().toString()); // 临时ID,会被覆盖 try { // 获取 sessionId String sessionId = getMCPSessionId(); sessionInfo.setSessionId(sessionId); sessions.put(group, sessionInfo); log.info("MCP 连接成功 [group={}, sessionId={}]", group, sessionId); return sessionId; } catch (Exception e) { log.error("MCP 连接失败 [group={}]: {}", group, e.getMessage()); throw new RuntimeException("无法建立 MCP 连接: " + e.getMessage(), e); } } // 工具调用 public ToolCallResult callTool(String group, String toolName, Map arguments) { SessionInfo session = getOrCreateSession(group); ToolCallParams params = ToolCallParams.builder() .name(toolName) .arguments(arguments) .build(); JsonRpcRequest request = JsonRpcRequest.builder() .jsonrpc("2.0") .id(requestIdGenerator.incrementAndGet()) .method("tools/call") .params(objectMapper.valueToTree(params)) .build(); JsonNode response = sendRequest(session, request); return parseToolCallResult(response); } // 智能路由搜索工具 public ToolCallResult searchTools(String group, String query, int limit) { SessionInfo session = getOrCreateSession(group); if (!"intelligence".equals(session.getMode())) { // 如果不是智能路由模式,先切换到智能路由 connectIntelligence(group); session = sessions.get(group); } Map arguments = Map.of( "query", query, "limit", limit ); ToolCallParams params = ToolCallParams.builder() .name("search_tools") .arguments(arguments) .build(); JsonRpcRequest request = JsonRpcRequest.builder() .jsonrpc("2.0") .id(requestIdGenerator.incrementAndGet()) .method("tools/call") .params(objectMapper.valueToTree(params)) .build(); JsonNode response = sendRequest(session, request); return parseToolCallResult(response); } ``` ### 6.3 MCP 工具集成 **McpTool 实现**: ```java public class McpTool implements ToolCallback { private final String name; private final String description; private final String group; private final McpClientService mcpClientService; @Override public ToolDefinition getToolDefinition() { return ToolDefinition.builder() .name(name) .description(description) // MCP 工具的参数 schema 由 MCP Hub 提供 // 这里使用一个通用的 object schema .inputSchema(""" { "type": "object", "properties": { "args": { "type": "object", "description": "工具参数,由 MCP Hub 定义" } } } """) .build(); } @Override public String call(String toolInput) { log.info("执行 MCP 工具 [name={}, group={}, input={}]", name, group, toolInput); try { // 解析输入参数 Map args = parseInput(toolInput); // 调用 MCP Hub ToolCallResult result; // 这里简化处理,实际应该根据会话的模式来选择调用方法 // 暂时使用普通的 callTool 方法 result = mcpClientService.callTool(group, name, args); if (result.isError()) { log.error("MCP 工具执行失败 [name={}]: {}", name, result.getContent()); return "工具执行失败: " + result.getContent(); } // 返回结果内容 String content = result.getContent(); log.info("MCP 工具执行成功 [name={}], 结果长度: {}", name, content != null ? content.length() : 0); return content != null ? content : "工具执行成功,但无返回内容"; } catch (Exception e) { log.error("MCP 工具执行异常 [name={}]: {}", name, e.getMessage(), e); return "工具执行异常: " + e.getMessage(); } } } ``` ### 6.4 MCP 配置 **配置项**: ```java @Data @Configuration @ConfigurationProperties(prefix = "mcp.hub") public class McpServerConfig { /** * MCP Hub 基础 URL */ private String baseUrl = "https://ai-paas-mcp-endpoint.njuu.top"; /** * 鉴权 token */ private String authorization = "sqGYuMvKgdxmzmTM5lNBgLdVpl6XNnPX"; /** * 连接超时(秒) */ private int connectTimeout = 10; /** * 请求超时(秒) */ private int requestTimeout = 60; /** * 是否自动重连 */ private boolean autoReconnect = true; } ``` ## 7. 系统工作流程 ### 7.1 典型流程 1. **客户端请求**:客户端发送聊天请求 2. **配置加载**:加载对应 Agent 的配置 3. **记忆检索**:获取对话历史 4. **RAG 处理**:执行 RAG 检索,获取相关知识 5. **ReAct 处理**:执行 ReAct 思考和行动 - **工具调用**:如需调用工具,可选择本地工具或 MCP 工具 - **MCP 工具调用**:通过 McpClientService 调用 MCP Hub 中的工具 6. **响应生成**:生成响应并返回给客户端 7. **记忆更新**:更新对话记忆 ### 7.2 MCP 集成流程 1. **MCP 连接**:建立与 MCP Hub 的 SSE 连接 2. **工具发现**:获取 MCP Hub 提供的工具列表 3. **工具注册**:将 MCP 工具注册为 Spring AI 工具 4. **工具调用**:在 ReAct 过程中调用 MCP 工具 5. **结果处理**:处理 MCP 工具返回的结果 ### 7.3 异步处理 系统使用 Spring 的异步处理能力,将保全信息等耗时操作异步解耦,提高系统响应速度。 ## 8. 技术选型 | 技术 | 版本 | 用途 | |------|------|------| | Spring Boot | 3.x | 后端框架 | | Spring AI | 1.x | AI 集成框架 | | Redis | 7.x | 持久化存储 | | Kryo | 5.x | 高效序列化 | | Ollama | 0.1.x | 本地模型 | | Maven | 3.x | 构建工具 | | MCP Hub | - | 工具服务平台 | ## 9. 未来扩展 ### 9.1 存储扩展 - **MySQL 存储**:实现多一级别的 MySQL 存储,支持更复杂的查询和分析 ### 9.2 模型扩展 - **模型列表**:补充更多模型支持 - **多模态调用**:实现完整的多模态调用功能 ### 9.3 客户端集成 - **MCP 功能增强**:扩展 MCP 客户端功能,支持更多 MCP Hub 特性 - **A2A 集成**:实现 A2A 相关功能 ### 9.4 工具完善 - **工具连接**:完善工具连接和使用 - **辅助工具**:补充更多辅助工具 - **工具管理**:实现工具的动态注册和管理 ### 9.5 智能路由优化 - **智能路由增强**:优化智能路由算法,提高工具匹配准确性 - **多模态工具**:支持多模态工具的智能路由 ## 10. 总结 AI PaaS 平台采用分层架构设计,实现了配置管理、Agent 核心、记忆系统、RAG 功能和 MCP 集成。系统架构清晰,代码组织合理,功能完整。 - **记忆层**:使用 Kryo 序列化和 Redis 存储,实现了高效的对话记忆管理 - **RAG**:实现了完整的 RAG 流程,包括查询词生成、向量检索、结果处理和关键信息提取 - **ReAct**:实现了 ReAct 模式,包含思考和行动两个阶段,支持工具调用 - **MCP 集成**:实现了与 MCP Hub 的完整集成,支持工具发现、调用和智能路由 系统已经具备了 AI PaaS 平台的核心功能,为未来的扩展和优化奠定了基础。MCP 功能的集成使得系统能够利用外部工具服务,大大扩展了 Agent 的能力范围。