181 lines
6.8 KiB
Java
181 lines
6.8 KiB
Java
package org.example.service;
|
|
|
|
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
|
|
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
|
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
|
|
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
|
|
import com.alibaba.cloud.ai.graph.exception.GraphRunnerException;
|
|
import org.example.agent.tool.DateTimeTools;
|
|
import org.example.agent.tool.InternalDocsTools;
|
|
import org.example.agent.tool.QueryLogsTools;
|
|
import org.example.agent.tool.QueryMetricsTools;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.ai.tool.ToolCallback;
|
|
import org.springframework.ai.tool.ToolCallbackProvider;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* 聊天服务
|
|
* 封装 ReactAgent 对话的公共逻辑,包括模型创建、系统提示词构建、Agent 配置等
|
|
*/
|
|
@Service
|
|
public class ChatService {
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(ChatService.class);
|
|
|
|
@Autowired
|
|
private InternalDocsTools internalDocsTools;
|
|
|
|
@Autowired
|
|
private DateTimeTools dateTimeTools;
|
|
|
|
@Autowired
|
|
private QueryMetricsTools queryMetricsTools;
|
|
|
|
@Autowired(required = false) // Mock 模式下才注册,所以设置为 optional,真实环境通过mcp配置注入
|
|
private QueryLogsTools queryLogsTools;
|
|
|
|
@Autowired
|
|
private ToolCallbackProvider tools;
|
|
|
|
@Value("${spring.ai.dashscope.api-key}")
|
|
private String dashScopeApiKey;
|
|
|
|
/**
|
|
* 创建 DashScope API 实例
|
|
*/
|
|
public DashScopeApi createDashScopeApi() {
|
|
return DashScopeApi.builder()
|
|
.apiKey(dashScopeApiKey)
|
|
.build();
|
|
}
|
|
|
|
/**
|
|
* 创建 ChatModel
|
|
* @param temperature 控制随机性 (0.0-1.0)
|
|
* @param maxToken 最大输出长度
|
|
* @param topP 核采样参数
|
|
*/
|
|
public DashScopeChatModel createChatModel(DashScopeApi dashScopeApi, double temperature, int maxToken, double topP) {
|
|
return DashScopeChatModel.builder()
|
|
.dashScopeApi(dashScopeApi)
|
|
.defaultOptions(DashScopeChatOptions.builder()
|
|
.withModel(DashScopeChatModel.DEFAULT_MODEL_NAME)
|
|
.withTemperature(temperature)
|
|
.withMaxToken(maxToken)
|
|
.withTopP(topP)
|
|
.build())
|
|
.build();
|
|
}
|
|
|
|
/**
|
|
* 创建标准对话 ChatModel(默认参数)
|
|
*/
|
|
public DashScopeChatModel createStandardChatModel(DashScopeApi dashScopeApi) {
|
|
return createChatModel(dashScopeApi, 0.7, 2000, 0.9);
|
|
}
|
|
|
|
/**
|
|
* 构建系统提示词(包含历史消息)
|
|
* @param history 历史消息列表
|
|
* @return 完整的系统提示词
|
|
*/
|
|
public String buildSystemPrompt(List<Map<String, String>> history) {
|
|
StringBuilder systemPromptBuilder = new StringBuilder();
|
|
|
|
// 基础系统提示
|
|
systemPromptBuilder.append("你是一个专业的智能助手,可以获取当前时间、查询天气信息、搜索内部文档知识库,以及查询 Prometheus 告警信息。\n");
|
|
systemPromptBuilder.append("当用户询问时间相关问题时,使用 getCurrentDateTime 工具。\n");
|
|
systemPromptBuilder.append("当用户需要查询公司内部文档、流程、最佳实践或技术指南时,使用 queryInternalDocs 工具。\n");
|
|
systemPromptBuilder.append("当用户需要查询 Prometheus 告警、监控指标或系统告警状态时,使用 queryPrometheusAlerts 工具。\n");
|
|
systemPromptBuilder.append("当用户需要查询腾讯云日志时,请调用腾讯云mcp服务查询,默认查询地域ap-guangzhou,查询时间范围为近一个月。\n\n");
|
|
|
|
// 添加历史消息
|
|
if (!history.isEmpty()) {
|
|
systemPromptBuilder.append("--- 对话历史 ---\n");
|
|
for (Map<String, String> msg : history) {
|
|
String role = msg.get("role");
|
|
String content = msg.get("content");
|
|
if ("user".equals(role)) {
|
|
systemPromptBuilder.append("用户: ").append(content).append("\n");
|
|
} else if ("assistant".equals(role)) {
|
|
systemPromptBuilder.append("助手: ").append(content).append("\n");
|
|
}
|
|
}
|
|
systemPromptBuilder.append("--- 对话历史结束 ---\n\n");
|
|
}
|
|
|
|
systemPromptBuilder.append("请基于以上对话历史,回答用户的新问题。");
|
|
|
|
return systemPromptBuilder.toString();
|
|
}
|
|
|
|
/**
|
|
* 动态构建方法工具数组
|
|
* 根据 cls.mock-enabled 决定是否包含 QueryLogsTools
|
|
*/
|
|
public Object[] buildMethodToolsArray() {
|
|
if (queryLogsTools != null) {
|
|
// Mock 模式:包含 QueryLogsTools
|
|
return new Object[]{dateTimeTools, internalDocsTools, queryMetricsTools, queryLogsTools};
|
|
} else {
|
|
// 真实模式:不包含 QueryLogsTools(由 MCP 提供日志查询功能)
|
|
return new Object[]{dateTimeTools, internalDocsTools, queryMetricsTools};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取工具回调列表,mcp服务提供的工具
|
|
*/
|
|
public ToolCallback[] getToolCallbacks() {
|
|
return tools.getToolCallbacks();
|
|
}
|
|
|
|
/**
|
|
* 记录可用工具列表:mcp服务提供的工具
|
|
*/
|
|
public void logAvailableTools() {
|
|
ToolCallback[] toolCallbacks = tools.getToolCallbacks();
|
|
logger.info("可用工具列表:");
|
|
for (ToolCallback toolCallback : toolCallbacks) {
|
|
logger.info(">>> {}", toolCallback.getToolDefinition().name());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 创建 ReactAgent
|
|
* @param chatModel 聊天模型
|
|
* @param systemPrompt 系统提示词
|
|
* @return 配置好的 ReactAgent
|
|
*/
|
|
public ReactAgent createReactAgent(DashScopeChatModel chatModel, String systemPrompt) {
|
|
return ReactAgent.builder()
|
|
.name("intelligent_assistant")
|
|
.model(chatModel)
|
|
.systemPrompt(systemPrompt)
|
|
.methodTools(buildMethodToolsArray())
|
|
.tools(getToolCallbacks())
|
|
.build();
|
|
}
|
|
|
|
/**
|
|
* 执行 ReactAgent 对话(非流式)
|
|
* @param agent ReactAgent 实例
|
|
* @param question 用户问题
|
|
* @return AI 回复
|
|
*/
|
|
public String executeChat(ReactAgent agent, String question) throws GraphRunnerException {
|
|
logger.info("执行 ReactAgent.call() - 自动处理工具调用");
|
|
var response = agent.call(question);
|
|
String answer = response.getText();
|
|
logger.info("ReactAgent 对话完成,答案长度: {}", answer.length());
|
|
return answer;
|
|
}
|
|
}
|