package com.ruoyi.system.task; import com.aliyuncs.CommonRequest; import com.aliyuncs.CommonResponse; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.http.MethodType; import com.aliyuncs.profile.DefaultProfile; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.ruoyi.system.config.AliyunChatbotConfig; import com.ruoyi.system.domain.SysFaq; import com.ruoyi.system.service.ISysFaqService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.util.*; /** * 阿里云聊天历史同步任务 * * @author ruoyi */ @Component public class AliyunChatHistorySyncTask { private static final Logger log = LoggerFactory.getLogger(AliyunChatHistorySyncTask.class); @Autowired private ISysFaqService sysFaqService; @Autowired private AliyunChatbotConfig config; /** * 每天凌晨2点执行同步任务 */ @Scheduled(cron = "0 0 2 * * ?") public void syncChatHistory() { log.info("开始同步阿里云聊天历史记录"); try { // 获取昨天的日期范围 Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_MONTH, -1); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String startTime = sdf.format(calendar.getTime()) + " 00:00:00"; calendar.add(Calendar.DAY_OF_MONTH, 1); String endTime = sdf.format(calendar.getTime()) + " 00:00:00"; // 调用阿里云API获取聊天历史 List historyList = fetchChatHistory(startTime, endTime); // 分析并导入高频问题 importFrequentQuestions(historyList); log.info("同步完成,共处理 {} 条聊天记录", historyList.size()); } catch (Exception e) { log.error("同步阿里云聊天历史失败", e); } } /** * 手动触发同步指定日期范围的数据 */ public void syncChatHistoryByDateRange(String startTime, String endTime) { log.info("手动同步聊天历史: {} 至 {}", startTime, endTime); try { List historyList = fetchChatHistory(startTime, endTime); importFrequentQuestions(historyList); log.info("手动同步完成"); } catch (Exception e) { log.error("手动同步失败", e); throw new RuntimeException("同步失败: " + e.getMessage()); } } /** * 从阿里云获取聊天历史 */ private List fetchChatHistory(String startTime, String endTime) throws ClientException { // 创建客户端 DefaultProfile profile = DefaultProfile.getProfile( config.getRegion(), config.getAccessKeyId(), config.getAccessKeySecret() ); IAcsClient client = new DefaultAcsClient(profile); // 构建通用请求 CommonRequest request = new CommonRequest(); request.setSysMethod(MethodType.POST); request.setSysDomain(config.getEndpoint()); request.setSysVersion("2022-04-08"); request.setSysAction("ListTongyiChatHistorys"); // 设置请求参数 request.putQueryParameter("RobotInstanceId", config.getRobotInstanceId()); request.putQueryParameter("StartTime", startTime); request.putQueryParameter("EndTime", endTime); request.putQueryParameter("Limit", "100"); // 发送请求 CommonResponse response = client.getCommonResponse(request); String responseData = response.getData(); log.info("API响应状态: {}, 数据: {}", response.getHttpStatus(), responseData); // 解析JSON响应 return parseResponse(responseData); } /** * 解析API响应 */ private List parseResponse(String responseData) { List historyList = new ArrayList<>(); try { Gson gson = new Gson(); JsonObject jsonObject = gson.fromJson(responseData, JsonObject.class); if (jsonObject.has("Datas")) { JsonArray datas = jsonObject.getAsJsonArray("Datas"); for (JsonElement element : datas) { JsonObject data = element.getAsJsonObject(); String question = data.has("Question") ? data.get("Question").getAsString() : null; String answer = data.has("Answer") ? data.get("Answer").getAsString() : null; String sessionId = data.has("SessionId") ? data.get("SessionId").getAsString() : null; String queryTime = data.has("QueryTime") ? data.get("QueryTime").getAsString() : null; // 过滤无效数据 if (question != null && !question.trim().isEmpty() && answer != null && !answer.trim().isEmpty()) { ChatHistory history = new ChatHistory(); history.setQuestion(question.trim()); history.setAnswer(answer.trim()); history.setSessionId(sessionId); // 解析时间 if (queryTime != null) { try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); history.setCreateTime(sdf.parse(queryTime)); } catch (Exception e) { log.warn("解析时间失败: {}", queryTime); } } historyList.add(history); } } log.info("成功解析 {} 条有效聊天记录", historyList.size()); } else { log.warn("响应中没有Datas字段"); } } catch (Exception e) { log.error("解析响应数据失败: {}", responseData, e); } return historyList; } /** * 分析高频问题并导入 */ private void importFrequentQuestions(List historyList) { // 统计问题频次 Map questionStatsMap = new HashMap<>(); for (ChatHistory history : historyList) { String question = history.getQuestion(); String answer = history.getAnswer(); QuestionStats stats = questionStatsMap.getOrDefault(question, new QuestionStats(question, answer)); stats.incrementCount(); questionStatsMap.put(question, stats); } // 过滤并导入高频问题 int minFrequency = config.getMinFrequency(); int importCount = 0; for (QuestionStats stats : questionStatsMap.values()) { if (stats.getCount() >= minFrequency) { // 检查是否已存在 if (!sysFaqService.isQuestionExists(stats.getQuestion())) { SysFaq faq = new SysFaq(); faq.setQuestion(stats.getQuestion()); faq.setAnswer(stats.getAnswer()); faq.setSortOrder(stats.getCount()); // 用频次作为排序 faq.setStatus("0"); // 默认正常状态 faq.setCreateBy("system"); sysFaqService.insertSysFaq(faq); importCount++; log.info("导入高频问题: {} (出现{}次)", stats.getQuestion(), stats.getCount()); } else { log.debug("问题已存在,跳过: {}", stats.getQuestion()); } } } log.info("共导入 {} 条新的高频问题(出现≥{}次)", importCount, minFrequency); } /** * 聊天历史记录 */ static class ChatHistory { private String question; private String answer; private String sessionId; private Date createTime; public String getQuestion() { return question; } public void setQuestion(String question) { this.question = question; } public String getAnswer() { return answer; } public void setAnswer(String answer) { this.answer = answer; } public String getSessionId() { return sessionId; } public void setSessionId(String sessionId) { this.sessionId = sessionId; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } } /** * 问题统计 */ static class QuestionStats { private String question; private String answer; private int count; public QuestionStats(String question, String answer) { this.question = question; this.answer = answer; this.count = 0; } public void incrementCount() { this.count++; } public String getQuestion() { return question; } public String getAnswer() { return answer; } public int getCount() { return count; } } }