mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-05 15:57:32 +00:00
refactor: 抽离特殊聊天模式处理逻辑
- 将工作流、人机交互恢复、思考模式处理逻辑抽离为独立方法 - 新增 handleSpecialChatModes 方法统一处理特殊模式 - 新增 handleThinkingMode 方法专门处理思考模式 - 简化 sseChat 方法结构,提高代码可读性 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
package org.ruoyi.agent;
|
||||
|
||||
import dev.langchain4j.agentic.Agent;
|
||||
import dev.langchain4j.service.SystemMessage;
|
||||
import dev.langchain4j.service.UserMessage;
|
||||
import dev.langchain4j.service.V;
|
||||
|
||||
/**
|
||||
* User Name Retrieval Agent
|
||||
* A simple assistant that retrieves user names using the get_name tool.
|
||||
*/
|
||||
public interface GetNameInfo {
|
||||
|
||||
@SystemMessage("""
|
||||
You are a user identity assistant. You MUST always use tools to get information.
|
||||
|
||||
MANDATORY REQUIREMENTS:
|
||||
- You MUST call the get_user_name_by_id tool for ANY question about names or identity
|
||||
- NEVER respond without calling the get_user_name_by_id tool first
|
||||
- Return ONLY the exact string returned by the get_user_name_by_id tool
|
||||
- Do not make up names like "John Doe" or any other default names
|
||||
- Do not use your knowledge to answer - ALWAYS use the tool
|
||||
|
||||
Your workflow:
|
||||
1. Extract userId from the query (if mentioned), or use "1" as default
|
||||
2. ALWAYS call the get_user_name_by_id tool with the userId parameter
|
||||
3. Return the exact result as plain text with no additions
|
||||
|
||||
CRITICAL: If you don't call the get_user_name_by_id tool, your response is wrong.
|
||||
""")
|
||||
@UserMessage("""
|
||||
Get the user name using the get_user_name_by_id tool. Query: {{query}}
|
||||
|
||||
IMPORTANT: Return only the exact result from the tool.
|
||||
""")
|
||||
@Agent("User identity assistant that returns user name from get_name tool")
|
||||
String search(@V("query") String query);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.ruoyi.agent;
|
||||
|
||||
import dev.langchain4j.agentic.Agent;
|
||||
import dev.langchain4j.service.SystemMessage;
|
||||
import dev.langchain4j.service.UserMessage;
|
||||
import dev.langchain4j.service.V;
|
||||
|
||||
public interface McpAgent extends Agent {
|
||||
|
||||
/**
|
||||
* 系统提示词:通用工具调用智能体
|
||||
* 不限定具体工具类型,让 LangChain4j 自动传递工具描述给 LLM
|
||||
*/
|
||||
@SystemMessage("""
|
||||
你是一个AI助手,可以通过调用各种工具来帮助用户完成不同的任务。
|
||||
|
||||
【工具使用规则】
|
||||
1. 根据用户的请求,判断需要使用哪些工具
|
||||
2. 仔细阅读每个工具的描述,确保理解工具的功能和参数要求
|
||||
3. 使用正确的参数调用工具
|
||||
4. 如果工具执行失败,向用户友好地说明错误原因,并尝试提供替代方案
|
||||
5. 对于复杂任务,可以分步骤使用多个工具完成
|
||||
6. 将工具执行结果以清晰易懂的方式呈现给用户
|
||||
|
||||
【响应格式】
|
||||
- 直接回答用户的问题
|
||||
- 如果使用了工具,说明使用了什么工具以及结果
|
||||
- 如果遇到错误,提供友好的错误信息和解决建议
|
||||
""")
|
||||
|
||||
@UserMessage("""
|
||||
{{query}}
|
||||
""")
|
||||
|
||||
@Agent("通用工具调用智能体")
|
||||
/**
|
||||
* 智能体对外调用入口
|
||||
* @param query 用户的自然语言请求
|
||||
* @return 处理结果
|
||||
*/
|
||||
String callMcpTool(@V("query") String query);
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
//package org.ruoyi.service.chat.handler;
|
||||
//
|
||||
//import dev.langchain4j.agentic.AgenticServices;
|
||||
//import dev.langchain4j.community.model.dashscope.QwenChatModel;
|
||||
//import dev.langchain4j.service.tool.ToolProvider;
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.ruoyi.agent.McpAgent;
|
||||
//import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
|
||||
//import org.ruoyi.common.chat.entity.chat.ChatContext;
|
||||
//import org.ruoyi.common.chat.service.chatMessage.IChatMessageService;
|
||||
//import org.ruoyi.common.sse.utils.SseMessageUtils;
|
||||
//import org.ruoyi.mcp.service.core.ToolProviderFactory;
|
||||
//import org.springframework.core.annotation.Order;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
//
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.List;
|
||||
//
|
||||
///**
|
||||
// * Agent 深度思考处理器
|
||||
// * <p>
|
||||
// * 处理 enableThinking=true 的场景,使用 Agent 进行深度思考和工具调用
|
||||
// *
|
||||
// * @author ageerle@163.com
|
||||
// * @date 2025/12/13
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//@Order(3)
|
||||
//@RequiredArgsConstructor
|
||||
//public class AgentChatHandler implements ChatHandler {
|
||||
//
|
||||
// private final ToolProviderFactory toolProviderFactory;
|
||||
//
|
||||
// @Override
|
||||
// public boolean supports(ChatContext context) {
|
||||
// Boolean enableThinking = context.getChatRequest().getEnableThinking();
|
||||
// return enableThinking != null && enableThinking;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public SseEmitter handle(ChatContext context) {
|
||||
// log.info("处理 Agent 深度思考,用户: {}", context.getUserId());
|
||||
//
|
||||
// Long userId = context.getUserId();
|
||||
// String tokenValue = context.getTokenValue();
|
||||
// ChatModelVo chatModelVo = context.getChatModelVo();
|
||||
//
|
||||
// try {
|
||||
// // 1. 保存用户消息
|
||||
// String content = extractUserContent(context);
|
||||
//// saveChatMessage(context.getChatRequest(), userId, content,
|
||||
//// RoleType.USER.getName(), chatModelVo);
|
||||
//
|
||||
// // 2. 执行 Agent 任务
|
||||
// String result = doAgent(content, chatModelVo);
|
||||
//
|
||||
// // 3. 发送结果并保存
|
||||
// SseMessageUtils.sendMessage(userId, result);
|
||||
// SseMessageUtils.completeConnection(userId, tokenValue);
|
||||
//
|
||||
//// saveChatMessage(context.getChatRequest(), userId, result,
|
||||
//// RoleType.ASSISTANT.getName(), chatModelVo);
|
||||
// // todo 保存消息
|
||||
// } catch (Exception e) {
|
||||
// log.error("Agent 执行失败: {}", e.getMessage(), e);
|
||||
// SseMessageUtils.sendMessage(userId, "Agent 执行失败:" + e.getMessage());
|
||||
// SseMessageUtils.completeConnection(userId, tokenValue);
|
||||
// }
|
||||
//
|
||||
// return context.getEmitter();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 执行 Agent 任务
|
||||
// */
|
||||
// private String doAgent(String userMessage, ChatModelVo chatModelVo) {
|
||||
// log.info("执行 Agent 任务,消息: {}", userMessage);
|
||||
//
|
||||
// try {
|
||||
// // 1. 加载 LLM 模型
|
||||
// QwenChatModel qwenChatModel = QwenChatModel.builder()
|
||||
// .apiKey(chatModelVo.getApiKey())
|
||||
// .modelName(chatModelVo.getModelName())
|
||||
// .build();
|
||||
//
|
||||
// // 2. 获取内置工具
|
||||
// List<Object> builtinTools = toolProviderFactory.getAllBuiltinToolObjects();
|
||||
// List<Object> allTools = new ArrayList<>(builtinTools);
|
||||
// log.debug("加载 {} 个内置工具", builtinTools.size());
|
||||
//
|
||||
// // 3. 获取 MCP 工具提供者
|
||||
// ToolProvider mcpToolProvider = toolProviderFactory.getAllEnabledMcpToolsProvider();
|
||||
//
|
||||
// // 4. 创建 MCP Agent
|
||||
// var agentBuilder = AgenticServices.agentBuilder(McpAgent.class)
|
||||
// .chatModel(qwenChatModel);
|
||||
//
|
||||
// if (!allTools.isEmpty()) {
|
||||
// agentBuilder.tools(allTools.toArray(new Object[0]));
|
||||
// }
|
||||
// if (mcpToolProvider != null) {
|
||||
// agentBuilder.toolProvider(mcpToolProvider);
|
||||
// }
|
||||
//
|
||||
// McpAgent mcpAgent = agentBuilder.build();
|
||||
//
|
||||
// // 5. 调用 Agent
|
||||
// String result = mcpAgent.callMcpTool(userMessage);
|
||||
// log.info("Agent 执行完成,结果长度: {}", result.length());
|
||||
// return result;
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// log.error("Agent 模式执行失败: {}", e.getMessage(), e);
|
||||
// return "Agent 执行失败: " + e.getMessage();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 提取用户消息内容
|
||||
// */
|
||||
// private String extractUserContent(ChatContext context) {
|
||||
// var messages = context.getChatRequest().getMessages();
|
||||
// if (messages != null && !messages.isEmpty()) {
|
||||
// return messages.get(0).getContent();
|
||||
// }
|
||||
// return "";
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@@ -1,53 +0,0 @@
|
||||
//package org.ruoyi.service.chat.handler;
|
||||
//
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.ruoyi.common.chat.domain.dto.request.ReSumeRunner;
|
||||
//import org.ruoyi.common.chat.entity.chat.ChatContext;
|
||||
//import org.ruoyi.common.chat.service.workFlow.IWorkFlowStarterService;
|
||||
//import org.ruoyi.common.core.utils.ObjectUtils;
|
||||
//import org.springframework.core.annotation.Order;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
//
|
||||
///**
|
||||
// * 人机交互恢复处理器
|
||||
// * <p>
|
||||
// * 处理 isResume=true 的场景,恢复工作流的人机交互
|
||||
// *
|
||||
// * @author ageerle@163.com
|
||||
// * @date 2025/12/13
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//@Order(1)
|
||||
//@RequiredArgsConstructor
|
||||
//public class ResumeChatHandler implements ChatHandler {
|
||||
//
|
||||
// private final IWorkFlowStarterService workFlowStarterService;
|
||||
//
|
||||
// @Override
|
||||
// public boolean supports(ChatContext context) {
|
||||
// Boolean isResume = context.getChatRequest().getIsResume();
|
||||
// return isResume != null && isResume;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public SseEmitter handle(ChatContext context) {
|
||||
// log.info("处理人机交互恢复,用户: {}", context.getUserId());
|
||||
//
|
||||
// ReSumeRunner reSumeRunner = context.getChatRequest().getReSumeRunner();
|
||||
// if (ObjectUtils.isEmpty(reSumeRunner)) {
|
||||
// log.warn("人机交互恢复参数为空");
|
||||
// return context.getEmitter();
|
||||
// }
|
||||
//
|
||||
// workFlowStarterService.resumeFlow(
|
||||
// reSumeRunner.getRuntimeUuid(),
|
||||
// reSumeRunner.getFeedbackContent(),
|
||||
// context.getEmitter()
|
||||
// );
|
||||
//
|
||||
// return context.getEmitter();
|
||||
// }
|
||||
//}
|
||||
@@ -1,54 +0,0 @@
|
||||
//package org.ruoyi.service.chat.handler;
|
||||
//
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.ruoyi.common.chat.base.ThreadContext;
|
||||
//import org.ruoyi.common.chat.domain.dto.request.WorkFlowRunner;
|
||||
//import org.ruoyi.common.chat.entity.chat.ChatContext;
|
||||
//import org.ruoyi.common.chat.service.workFlow.IWorkFlowStarterService;
|
||||
//import org.ruoyi.common.core.utils.ObjectUtils;
|
||||
//import org.springframework.core.annotation.Order;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
//
|
||||
///**
|
||||
// * 工作流对话处理器
|
||||
// * <p>
|
||||
// * 处理 enableWorkFlow=true 的场景,启动工作流对话
|
||||
// *
|
||||
// * @author ageerle@163.com
|
||||
// * @date 2025/12/13
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//@Order(2)
|
||||
//@RequiredArgsConstructor
|
||||
//public class WorkflowChatHandler implements ChatHandler {
|
||||
//
|
||||
// private final IWorkFlowStarterService workFlowStarterService;
|
||||
//
|
||||
// @Override
|
||||
// public boolean supports(ChatContext context) {
|
||||
// Boolean enableWorkFlow = context.getChatRequest().getEnableWorkFlow();
|
||||
// return enableWorkFlow != null && enableWorkFlow;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public SseEmitter handle(ChatContext context) {
|
||||
// log.info("处理工作流对话,用户: {}, 会话: {}",
|
||||
// context.getUserId(), context.getChatRequest().getSessionId());
|
||||
//
|
||||
// WorkFlowRunner runner = context.getChatRequest().getWorkFlowRunner();
|
||||
// if (ObjectUtils.isEmpty(runner)) {
|
||||
// log.warn("工作流参数为空");
|
||||
// return context.getEmitter();
|
||||
// }
|
||||
//
|
||||
// return workFlowStarterService.streaming(
|
||||
// ThreadContext.getCurrentUser(),
|
||||
// runner.getUuid(),
|
||||
// runner.getInputs(),
|
||||
// context.getChatRequest().getSessionId()
|
||||
// );
|
||||
// }
|
||||
//}
|
||||
@@ -1,25 +1,48 @@
|
||||
package org.ruoyi.service.chat.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import dev.langchain4j.agentic.AgenticServices;
|
||||
import dev.langchain4j.agentic.supervisor.SupervisorAgent;
|
||||
import dev.langchain4j.agentic.supervisor.SupervisorResponseStrategy;
|
||||
import dev.langchain4j.community.model.dashscope.QwenChatModel;
|
||||
import dev.langchain4j.data.message.*;
|
||||
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.stdio.StdioMcpTransport;
|
||||
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
|
||||
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||
import dev.langchain4j.model.chat.response.ChatResponse;
|
||||
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
|
||||
import dev.langchain4j.model.openai.OpenAiChatModel;
|
||||
import dev.langchain4j.service.tool.ToolProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ruoyi.agent.ChartGenerationAgent;
|
||||
import org.ruoyi.agent.SqlAgent;
|
||||
import org.ruoyi.agent.WebSearchAgent;
|
||||
import org.ruoyi.agent.tool.ExecuteSqlQueryTool;
|
||||
import org.ruoyi.agent.tool.QueryAllTablesTool;
|
||||
import org.ruoyi.agent.tool.QueryTableSchemaTool;
|
||||
import org.ruoyi.common.chat.base.ThreadContext;
|
||||
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
|
||||
import org.ruoyi.common.chat.domain.dto.request.ReSumeRunner;
|
||||
import org.ruoyi.common.chat.domain.dto.request.WorkFlowRunner;
|
||||
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
|
||||
import org.ruoyi.common.chat.enums.RoleType;
|
||||
import org.ruoyi.common.chat.service.chat.IChatModelService;
|
||||
import org.ruoyi.common.chat.service.chat.IChatService;
|
||||
import org.ruoyi.common.chat.service.workFlow.IWorkFlowStarterService;
|
||||
import org.ruoyi.common.core.utils.ObjectUtils;
|
||||
import org.ruoyi.common.satoken.utils.LoginHelper;
|
||||
import org.ruoyi.common.sse.core.SseEmitterManager;
|
||||
import org.ruoyi.common.sse.utils.SseMessageUtils;
|
||||
import org.ruoyi.domain.bo.vector.QueryVectorBo;
|
||||
import org.ruoyi.domain.vo.knowledge.KnowledgeInfoVo;
|
||||
import org.ruoyi.factory.ChatServiceFactory;
|
||||
import org.ruoyi.mcp.service.core.ToolProviderFactory;
|
||||
import org.ruoyi.service.chat.AbstractChatService;
|
||||
import org.ruoyi.service.chat.IChatMessageService;
|
||||
import org.ruoyi.service.chat.impl.memory.PersistentChatMemoryStore;
|
||||
@@ -62,12 +85,18 @@ public class ChatServiceFacade implements IChatService {
|
||||
|
||||
private final IChatMessageService chatMessageService;
|
||||
|
||||
private final IWorkFlowStarterService workFlowStarterService;
|
||||
|
||||
private final ToolProviderFactory toolProviderFactory;
|
||||
|
||||
/**
|
||||
* 内存实例缓存,避免同一会话重复创建
|
||||
* Key: sessionId, Value: MessageWindowChatMemory实例
|
||||
*/
|
||||
private static final Map<Object, MessageWindowChatMemory> memoryCache = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 统一聊天入口 - SSE流式响应
|
||||
*
|
||||
@@ -76,6 +105,11 @@ public class ChatServiceFacade implements IChatService {
|
||||
*/
|
||||
public SseEmitter sseChat(ChatRequest chatRequest) {
|
||||
|
||||
// 4. 具体的服务实现
|
||||
Long userId = LoginHelper.getUserId();
|
||||
String tokenValue = StpUtil.getTokenValue();
|
||||
SseEmitter emitter = sseEmitterManager.connect(userId, tokenValue);
|
||||
|
||||
// 1. 根据模型名称查询完整配置
|
||||
ChatModelVo chatModelVo = chatModelService.selectModelByName(chatRequest.getModel());
|
||||
if (chatModelVo == null) {
|
||||
@@ -85,14 +119,17 @@ public class ChatServiceFacade implements IChatService {
|
||||
// 2. 构建上下文消息列表
|
||||
List<ChatMessage> contextMessages = buildContextMessages(chatRequest);
|
||||
|
||||
// 3. 路由服务提供商
|
||||
// 3. 处理特殊聊天模式(工作流、人机交互恢复、思考模式)
|
||||
SseEmitter specialResult = handleSpecialChatModes(chatRequest, contextMessages, chatModelVo, emitter);
|
||||
if (specialResult != null) {
|
||||
return specialResult;
|
||||
}
|
||||
|
||||
// 4. 路由服务提供商
|
||||
String providerCode = chatModelVo.getProviderCode();
|
||||
log.info("路由到服务提供商: {}, 模型: {}", providerCode, chatRequest.getModel());
|
||||
AbstractChatService chatService = chatServiceFactory.getOriginalService(providerCode);
|
||||
// 4. 具体的服务实现
|
||||
Long userId = LoginHelper.getUserId();
|
||||
String tokenValue = StpUtil.getTokenValue();
|
||||
SseEmitter emitter = sseEmitterManager.connect(userId, tokenValue);
|
||||
|
||||
|
||||
StreamingChatResponseHandler handler = createResponseHandler(userId, tokenValue,chatRequest);
|
||||
|
||||
@@ -105,6 +142,131 @@ public class ChatServiceFacade implements IChatService {
|
||||
return emitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理特殊聊天模式(工作流、人机交互恢复、思考模式)
|
||||
*
|
||||
* @param chatRequest 聊天请求
|
||||
* @param contextMessages 上下文消息列表(可能被修改)
|
||||
* @param chatModelVo 聊天模型配置
|
||||
* @param emitter SSE发射器
|
||||
* @return 如果需要提前返回则返回SseEmitter,否则返回null
|
||||
*/
|
||||
private SseEmitter handleSpecialChatModes(ChatRequest chatRequest, List<ChatMessage> contextMessages,
|
||||
ChatModelVo chatModelVo, SseEmitter emitter) {
|
||||
// 处理工作流对话
|
||||
if (chatRequest.getEnableWorkFlow()) {
|
||||
log.info("处理工作流对话,会话: {}", chatRequest.getSessionId());
|
||||
|
||||
WorkFlowRunner runner = chatRequest.getWorkFlowRunner();
|
||||
if (ObjectUtils.isEmpty(runner)) {
|
||||
log.warn("工作流参数为空");
|
||||
}
|
||||
|
||||
return workFlowStarterService.streaming(
|
||||
ThreadContext.getCurrentUser(),
|
||||
runner.getUuid(),
|
||||
runner.getInputs(),
|
||||
chatRequest.getSessionId()
|
||||
);
|
||||
}
|
||||
|
||||
// 处理人机交互恢复
|
||||
if (chatRequest.getIsResume()) {
|
||||
log.info("处理人机交互恢复");
|
||||
|
||||
ReSumeRunner reSumeRunner = chatRequest.getReSumeRunner();
|
||||
if (ObjectUtils.isEmpty(reSumeRunner)) {
|
||||
log.warn("人机交互恢复参数为空");
|
||||
return emitter;
|
||||
}
|
||||
|
||||
workFlowStarterService.resumeFlow(
|
||||
reSumeRunner.getRuntimeUuid(),
|
||||
reSumeRunner.getFeedbackContent(),
|
||||
emitter
|
||||
);
|
||||
|
||||
return emitter;
|
||||
}
|
||||
|
||||
// 处理思考模式
|
||||
if (chatRequest.getEnableThinking()) {
|
||||
handleThinkingMode(chatRequest, contextMessages, chatModelVo);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理思考模式
|
||||
*
|
||||
* @param chatRequest 聊天请求
|
||||
* @param contextMessages 上下文消息列表
|
||||
* @param chatModelVo 聊天模型配置
|
||||
*/
|
||||
private void handleThinkingMode(ChatRequest chatRequest, List<ChatMessage> contextMessages, ChatModelVo chatModelVo) {
|
||||
// 步骤1: 配置MCP传输层 - 连接到bing-cn-mcp服务器
|
||||
McpTransport transport = new StdioMcpTransport.Builder()
|
||||
.command(List.of("C:\\Program Files\\nodejs\\npx.cmd", "-y", "bing-cn-mcp"))
|
||||
.logEvents(true)
|
||||
.build();
|
||||
|
||||
McpClient mcpClient = new DefaultMcpClient.Builder()
|
||||
.transport(transport)
|
||||
.build();
|
||||
|
||||
ToolProvider toolProvider = McpToolProvider.builder()
|
||||
.mcpClients(List.of(mcpClient))
|
||||
.build();
|
||||
|
||||
// 配置echarts MCP
|
||||
McpTransport transport1 = new StdioMcpTransport.Builder()
|
||||
.command(List.of("C:\\Program Files\\nodejs\\npx.cmd", "-y", "mcp-echarts"))
|
||||
.logEvents(true)
|
||||
.build();
|
||||
|
||||
McpClient mcpClient1 = new DefaultMcpClient.Builder()
|
||||
.transport(transport1)
|
||||
.build();
|
||||
|
||||
ToolProvider toolProvider1 = McpToolProvider.builder()
|
||||
.mcpClients(List.of(mcpClient1))
|
||||
.build();
|
||||
|
||||
// 配置模型
|
||||
OpenAiChatModel plannerModel = OpenAiChatModel.builder()
|
||||
.baseUrl(chatModelVo.getApiHost())
|
||||
.apiKey(chatModelVo.getApiKey())
|
||||
.modelName(chatModelVo.getModelName())
|
||||
.build();
|
||||
|
||||
// 构建各Agent
|
||||
SqlAgent sqlAgent = AgenticServices.agentBuilder(SqlAgent.class)
|
||||
.chatModel(plannerModel)
|
||||
.tools(new QueryAllTablesTool(), new QueryTableSchemaTool(), new ExecuteSqlQueryTool())
|
||||
.build();
|
||||
|
||||
WebSearchAgent searchAgent = AgenticServices.agentBuilder(WebSearchAgent.class)
|
||||
.chatModel(plannerModel)
|
||||
.toolProvider(toolProvider)
|
||||
.build();
|
||||
|
||||
ChartGenerationAgent chartGenerationAgent = AgenticServices.agentBuilder(ChartGenerationAgent.class)
|
||||
.chatModel(plannerModel)
|
||||
.toolProvider(toolProvider1)
|
||||
.build();
|
||||
|
||||
// 构建监督者Agent
|
||||
SupervisorAgent supervisor = AgenticServices.supervisorBuilder()
|
||||
.chatModel(plannerModel)
|
||||
.subAgents(sqlAgent, chartGenerationAgent)
|
||||
.responseStrategy(SupervisorResponseStrategy.LAST)
|
||||
.build();
|
||||
|
||||
String invoke = supervisor.invoke(chatRequest.getContent());
|
||||
contextMessages.add(AiMessage.from(invoke));
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持外部 handler 的对话接口(跨模块调用)
|
||||
* 同时发送到 SSE 和外部 handler
|
||||
|
||||
Reference in New Issue
Block a user