mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-11 10:37:20 +00:00
feat-恢复mcp模块
This commit is contained in:
@@ -8,28 +8,22 @@ import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
|
||||
import dev.langchain4j.data.message.ChatMessage;
|
||||
import dev.langchain4j.data.message.SystemMessage;
|
||||
import dev.langchain4j.data.message.UserMessage;
|
||||
import dev.langchain4j.mcp.McpToolProvider;
|
||||
import dev.langchain4j.mcp.client.DefaultMcpClient;
|
||||
import dev.langchain4j.mcp.client.McpClient;
|
||||
import dev.langchain4j.mcp.client.transport.McpTransport;
|
||||
import dev.langchain4j.mcp.client.transport.http.StreamableHttpMcpTransport;
|
||||
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
|
||||
import dev.langchain4j.service.tool.ToolProvider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ruoyi.agent.McpAgent;
|
||||
import org.ruoyi.config.McpSseConfig;
|
||||
import org.ruoyi.enums.ChatModeType;
|
||||
import org.ruoyi.service.chat.impl.AbstractStreamingChatService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
|
||||
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
|
||||
import org.ruoyi.common.core.utils.SpringUtils;
|
||||
import org.ruoyi.enums.ChatModeType;
|
||||
import org.ruoyi.mcp.service.core.ToolProviderFactory;
|
||||
import org.ruoyi.service.chat.impl.AbstractStreamingChatService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
@@ -42,20 +36,9 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
@Slf4j
|
||||
public class QianWenChatServiceImpl extends AbstractStreamingChatService {
|
||||
|
||||
@Autowired
|
||||
private McpSseConfig mcpSseConfig;
|
||||
|
||||
// 添加文档解析的前缀字段
|
||||
private static final String UPLOAD_FILE_API_PREFIX = "fileid";
|
||||
|
||||
// 缓存不同API Key和模型的MCP智能体实例
|
||||
private final ConcurrentHashMap<String, SupervisorAgent> supervisorCache = new ConcurrentHashMap<>();
|
||||
|
||||
// 缓存不同API Key和模型的MCP客户端实例
|
||||
private final ConcurrentHashMap<String, McpClient> mcpClientCache = new ConcurrentHashMap<>();
|
||||
|
||||
// 缓存不同API Key和模型的MCP工具提供者实例
|
||||
private final ConcurrentHashMap<String, ToolProvider> toolProviderCache = new ConcurrentHashMap<>();
|
||||
// 用于线程安全的锁
|
||||
private final ReentrantLock cacheLock = new ReentrantLock();
|
||||
|
||||
@@ -108,77 +91,55 @@ public class QianWenChatServiceImpl extends AbstractStreamingChatService {
|
||||
}).orElse(messagesWithMemory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存键
|
||||
*/
|
||||
private String getCacheKey(ChatModelVo chatModelVo) {
|
||||
return chatModelVo.getApiKey() + ":" + chatModelVo.getModelName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化MCP客户端连接
|
||||
*/
|
||||
private McpClient initializeMcpClient() {
|
||||
// 步骤1:根据SSE对外暴露端点连接
|
||||
McpTransport httpMcpTransport = new StreamableHttpMcpTransport.Builder().
|
||||
url(mcpSseConfig.getUrl()).
|
||||
logRequests(true).
|
||||
build();
|
||||
|
||||
// 步骤2:开启客户端连接
|
||||
return new DefaultMcpClient.Builder()
|
||||
.transport(httpMcpTransport)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用MCP服务(智能体)
|
||||
* 使用统一的ToolProviderFactory获取所有已配置的工具(BUILTIN + MCP)
|
||||
*
|
||||
* @param userMessage 用户信息
|
||||
* @param chatModelVo 模型信息
|
||||
* @return 返回LLM信息
|
||||
*/
|
||||
protected String doAgent(String userMessage, ChatModelVo chatModelVo) {
|
||||
// 判断是否开启MCP服务
|
||||
if (!mcpSseConfig.isEnabled()) {
|
||||
return "";
|
||||
}
|
||||
// 生成缓存键
|
||||
String cacheKey = getCacheKey(chatModelVo);
|
||||
// 尝试从缓存获取监督智能体
|
||||
SupervisorAgent cachedSupervisor = supervisorCache.get(cacheKey);
|
||||
if (cachedSupervisor != null) {
|
||||
// 如果已存在缓存的监督智能体,直接使用
|
||||
return cachedSupervisor.invoke(userMessage);
|
||||
}
|
||||
cacheLock.lock();
|
||||
try {
|
||||
// 双重检查,防止并发情况下的重复初始化
|
||||
cachedSupervisor = supervisorCache.get(cacheKey);
|
||||
if (cachedSupervisor != null) {
|
||||
return cachedSupervisor.invoke(userMessage);
|
||||
}
|
||||
// 步骤1: 获取统一工具提供工厂
|
||||
ToolProviderFactory toolProviderFactory = SpringUtils.getBean(ToolProviderFactory.class);
|
||||
|
||||
// 获取或初始化MCP客户端
|
||||
McpClient mcpClient = mcpClientCache.computeIfAbsent(cacheKey, k -> initializeMcpClient());
|
||||
// 步骤2: 获取 BUILTIN 工具对象
|
||||
List<Object> builtinTools = toolProviderFactory.getAllBuiltinToolObjects();
|
||||
|
||||
// 步骤3:将mcp对象包装
|
||||
ToolProvider toolProvider = toolProviderCache.computeIfAbsent(cacheKey, k -> McpToolProvider.builder()
|
||||
.mcpClients(List.of(mcpClient))
|
||||
.build());
|
||||
// 步骤3: 获取 MCP 工具提供者
|
||||
ToolProvider mcpToolProvider = toolProviderFactory.getAllEnabledMcpToolsProvider();
|
||||
|
||||
// 步骤4:加载LLM模型对话
|
||||
log.info("doAgent: BUILTIN tools count = {}, MCP tools enabled = {}",
|
||||
builtinTools.size(), mcpToolProvider != null);
|
||||
|
||||
// 步骤4: 加载LLM模型
|
||||
QwenChatModel qwenChatModel = QwenChatModel.builder()
|
||||
.apiKey(chatModelVo.getApiKey())
|
||||
.modelName(chatModelVo.getModelName())
|
||||
.build();
|
||||
|
||||
// 步骤5:将MCP对象由智能体Agent管控
|
||||
McpAgent mcpAgent = AgenticServices.agentBuilder(McpAgent.class)
|
||||
.chatModel(qwenChatModel)
|
||||
.toolProvider(toolProvider)
|
||||
.build();
|
||||
// 步骤5: 创建MCP Agent,使用所有已配置的工具
|
||||
// 使用 .tools() 传入 BUILTIN 工具对象(Java 对象,带 @Tool 注解的方法)
|
||||
// 使用 .toolProvider() 传入 MCP 工具提供者(MCP 协议工具)
|
||||
var agentBuilder = AgenticServices.agentBuilder(McpAgent.class)
|
||||
.chatModel(qwenChatModel);
|
||||
|
||||
// 步骤6:将所有MCP对象由超级智能体管控
|
||||
// 添加 BUILTIN 工具(如果有)
|
||||
if (!builtinTools.isEmpty()) {
|
||||
agentBuilder.tools(builtinTools.toArray(new Object[0]));
|
||||
log.debug("Added {} BUILTIN tools to agent", builtinTools.size());
|
||||
}
|
||||
|
||||
// 添加 MCP 工具(如果有)
|
||||
if (mcpToolProvider != null) {
|
||||
agentBuilder.toolProvider(mcpToolProvider);
|
||||
log.debug("Added MCP tool provider to agent");
|
||||
}
|
||||
|
||||
McpAgent mcpAgent = agentBuilder.build();
|
||||
|
||||
// 步骤6: 创建超级智能体协调MCP Agent
|
||||
SupervisorAgent supervisor = AgenticServices
|
||||
.supervisorBuilder()
|
||||
.chatModel(qwenChatModel)
|
||||
@@ -186,10 +147,7 @@ public class QianWenChatServiceImpl extends AbstractStreamingChatService {
|
||||
.responseStrategy(SupervisorResponseStrategy.LAST)
|
||||
.build();
|
||||
|
||||
// 缓存监督智能体
|
||||
supervisorCache.put(cacheKey, supervisor);
|
||||
|
||||
// 步骤7:调用大模型LLM
|
||||
// 步骤7: 调用大模型LLM
|
||||
return supervisor.invoke(userMessage);
|
||||
} finally {
|
||||
cacheLock.unlock();
|
||||
|
||||
Reference in New Issue
Block a user