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<ChatHistory> 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<ChatHistory> historyList = fetchChatHistory(startTime, endTime);
|
importFrequentQuestions(historyList);
|
log.info("手动同步完成");
|
} catch (Exception e) {
|
log.error("手动同步失败", e);
|
throw new RuntimeException("同步失败: " + e.getMessage());
|
}
|
}
|
|
/**
|
* 从阿里云获取聊天历史
|
*/
|
private List<ChatHistory> 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<ChatHistory> parseResponse(String responseData) {
|
List<ChatHistory> 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<ChatHistory> historyList) {
|
// 统计问题频次
|
Map<String, QuestionStats> 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; }
|
}
|
}
|