优化
This commit is contained in:
@@ -55,7 +55,12 @@ public interface MessageService extends IService<Message> {
|
||||
* 根据用户ID和关键词搜索消息
|
||||
*/
|
||||
List<Message> searchByUserIdAndKeyword(String userId, String keyword, Integer limit);
|
||||
|
||||
|
||||
/**
|
||||
* 根据用户ID获取最近的消息
|
||||
*/
|
||||
List<Message> getRecentByUserId(String userId, Integer limit);
|
||||
|
||||
/**
|
||||
* 查询会话的最后一条消息
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.emotion.dto.websocket.ChatRequest;
|
||||
import com.emotion.dto.websocket.ConnectRequest;
|
||||
import com.emotion.dto.websocket.WebSocketMessage;
|
||||
import com.emotion.entity.Message;
|
||||
import com.emotion.entity.Conversation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
@@ -219,50 +220,84 @@ public class WebSocketService {
|
||||
// 使用线程池异步处理AI响应
|
||||
new Thread(() -> {
|
||||
try {
|
||||
String userId = request.getSenderId();
|
||||
String conversationId = request.getConversationId();
|
||||
|
||||
// 如果没有会话ID,创建新会话
|
||||
if (conversationId == null || conversationId.trim().isEmpty()) {
|
||||
conversationId = createNewConversation(userId, request);
|
||||
request.setConversationId(conversationId);
|
||||
}
|
||||
|
||||
// 确保会话存在并更新活跃时间
|
||||
ensureConversationExists(conversationId, userId, request);
|
||||
|
||||
// 保存用户消息到数据库
|
||||
Message userMessage = new Message();
|
||||
userMessage.setConversationId(request.getConversationId());
|
||||
userMessage.setCreateBy(request.getSenderId());
|
||||
userMessage.setConversationId(conversationId);
|
||||
userMessage.setUserId(userId);
|
||||
userMessage
|
||||
.setUserType(request.getSenderType() == ChatRequest.SenderType.USER ? "registered" : "guest");
|
||||
userMessage.setContent(request.getContent());
|
||||
userMessage.setType(request.getMessageType().name());
|
||||
userMessage.setSender(request.getSenderType().name());
|
||||
userMessage.setType("text");
|
||||
userMessage.setSender("user");
|
||||
userMessage.setCozeRole("user");
|
||||
userMessage.setCozeContentType("text");
|
||||
messageService.createMessage(userMessage);
|
||||
|
||||
// 调用AI服务
|
||||
String aiReply = aiChatService.sendChatMessage(
|
||||
request.getConversationId(),
|
||||
request.getContent(),
|
||||
request.getSenderId()
|
||||
conversationId,
|
||||
request.getContent(),
|
||||
userId
|
||||
);
|
||||
|
||||
// 构建AI回复消息
|
||||
WebSocketMessage aiMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.conversationId(request.getConversationId())
|
||||
.type(WebSocketMessage.MessageType.TEXT)
|
||||
.content(aiReply)
|
||||
.senderId("ai")
|
||||
.senderType(WebSocketMessage.SenderType.AI)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
// 保存AI回复到数据库
|
||||
Message aiDbMessage = new Message();
|
||||
aiDbMessage.setConversationId(request.getConversationId());
|
||||
aiDbMessage.setCreateBy("ai");
|
||||
aiDbMessage.setContent(aiReply);
|
||||
aiDbMessage.setType("text");
|
||||
aiDbMessage.setSender("ai");
|
||||
messageService.createMessage(aiDbMessage);
|
||||
|
||||
// 发送AI回复
|
||||
messagingTemplate.convertAndSendToUser(request.getSenderId(), "/queue/messages", aiMessage);
|
||||
// 如果AI回复包含换行符,分割成多条消息
|
||||
String[] replyParts = aiReply.split("\\n\\n|\\n");
|
||||
|
||||
if (request.getConversationId() != null) {
|
||||
messagingTemplate.convertAndSend("/topic/conversation/" + request.getConversationId(), aiMessage);
|
||||
for (String part : replyParts) {
|
||||
if (part.trim().isEmpty())
|
||||
continue;
|
||||
|
||||
// 构建AI回复消息
|
||||
WebSocketMessage aiMessage = WebSocketMessage.builder()
|
||||
.messageId(UUID.randomUUID().toString())
|
||||
.conversationId(conversationId)
|
||||
.type(WebSocketMessage.MessageType.TEXT)
|
||||
.content(part.trim())
|
||||
.senderId("ai")
|
||||
.senderType(WebSocketMessage.SenderType.AI)
|
||||
.status(WebSocketMessage.MessageStatus.SENT)
|
||||
.createTime(LocalDateTime.now())
|
||||
.build();
|
||||
|
||||
// 保存AI回复到数据库
|
||||
Message aiDbMessage = new Message();
|
||||
aiDbMessage.setConversationId(conversationId);
|
||||
aiDbMessage.setUserId(userId);
|
||||
aiDbMessage.setUserType(
|
||||
request.getSenderType() == ChatRequest.SenderType.USER ? "registered" : "guest");
|
||||
aiDbMessage.setContent(part.trim());
|
||||
aiDbMessage.setType("text");
|
||||
aiDbMessage.setSender("ai");
|
||||
aiDbMessage.setCozeRole("assistant");
|
||||
aiDbMessage.setCozeContentType("text");
|
||||
messageService.createMessage(aiDbMessage);
|
||||
|
||||
// 发送AI回复
|
||||
messagingTemplate.convertAndSendToUser(userId, "/queue/messages", aiMessage);
|
||||
|
||||
if (conversationId != null) {
|
||||
messagingTemplate.convertAndSend("/topic/conversation/" + conversationId, aiMessage);
|
||||
}
|
||||
|
||||
// 添加短暂延迟,模拟自然对话
|
||||
Thread.sleep(500);
|
||||
}
|
||||
|
||||
|
||||
// 更新会话的最后活跃时间和消息数量
|
||||
updateConversationActivity(conversationId);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("AI响应处理失败", e);
|
||||
sendErrorMessage(request.getSenderId(), "AI服务暂时不可用,请稍后重试");
|
||||
@@ -293,4 +328,85 @@ public class WebSocketService {
|
||||
public int getOnlineUserCount() {
|
||||
return onlineUsers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新会话
|
||||
*/
|
||||
private String createNewConversation(String userId, ChatRequest request) {
|
||||
try {
|
||||
String conversationId = "conv_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8);
|
||||
|
||||
Conversation conversation = Conversation.builder()
|
||||
.userId(userId)
|
||||
.userType(request.getSenderType() == ChatRequest.SenderType.USER ? "registered" : "guest")
|
||||
.title("新对话")
|
||||
.type("chat")
|
||||
.conversationStatus("active")
|
||||
.startTime(LocalDateTime.now())
|
||||
.lastActiveTime(LocalDateTime.now())
|
||||
.messageCount(0)
|
||||
.build();
|
||||
|
||||
// 设置ID
|
||||
conversation.setId(conversationId);
|
||||
|
||||
conversationService.save(conversation);
|
||||
log.info("创建新会话: conversationId={}, userId={}", conversationId, userId);
|
||||
|
||||
return conversationId;
|
||||
} catch (Exception e) {
|
||||
log.error("创建新会话失败: userId={}", userId, e);
|
||||
throw new RuntimeException("创建会话失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保会话存在并更新活跃时间
|
||||
*/
|
||||
private void ensureConversationExists(String conversationId, String userId, ChatRequest request) {
|
||||
try {
|
||||
Conversation conversation = conversationService.getById(conversationId);
|
||||
if (conversation == null) {
|
||||
// 如果会话不存在,创建一个
|
||||
conversation = Conversation.builder()
|
||||
.userId(userId)
|
||||
.userType(request.getSenderType() == ChatRequest.SenderType.USER ? "registered" : "guest")
|
||||
.title("对话")
|
||||
.type("chat")
|
||||
.conversationStatus("active")
|
||||
.startTime(LocalDateTime.now())
|
||||
.lastActiveTime(LocalDateTime.now())
|
||||
.messageCount(0)
|
||||
.build();
|
||||
|
||||
// 设置ID
|
||||
conversation.setId(conversationId);
|
||||
|
||||
conversationService.save(conversation);
|
||||
log.info("创建会话: conversationId={}, userId={}", conversationId, userId);
|
||||
} else {
|
||||
// 更新最后活跃时间
|
||||
conversation.setLastActiveTime(LocalDateTime.now());
|
||||
conversationService.updateById(conversation);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("确保会话存在失败: conversationId={}, userId={}", conversationId, userId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新会话活跃状态
|
||||
*/
|
||||
private void updateConversationActivity(String conversationId) {
|
||||
try {
|
||||
Conversation conversation = conversationService.getById(conversationId);
|
||||
if (conversation != null) {
|
||||
conversation.setLastActiveTime(LocalDateTime.now());
|
||||
conversation.setMessageCount((conversation.getMessageCount() != null ? conversation.getMessageCount() : 0) + 1);
|
||||
conversationService.updateById(conversation);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("更新会话活跃状态失败: conversationId={}", conversationId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@ import com.emotion.entity.Message;
|
||||
import com.emotion.entity.Conversation;
|
||||
import com.emotion.entity.CozeApiCall;
|
||||
import com.emotion.entity.EmotionRecord;
|
||||
import com.emotion.entity.EmotionAnalysis;
|
||||
import com.emotion.service.AIChatService;
|
||||
import com.emotion.service.MessageService;
|
||||
import com.emotion.service.ConversationService;
|
||||
import com.emotion.service.CozeApiCallService;
|
||||
import com.emotion.service.EmotionRecordService;
|
||||
import com.emotion.service.EmotionAnalysisService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -59,6 +61,9 @@ public class AiChatServiceImpl implements AIChatService {
|
||||
@Autowired
|
||||
private EmotionRecordService emotionRecordService;
|
||||
|
||||
@Autowired
|
||||
private EmotionAnalysisService emotionAnalysisService;
|
||||
|
||||
@Value("${emotion.coze.api.token:}")
|
||||
private String cozeApiToken;
|
||||
|
||||
@@ -941,7 +946,7 @@ public class AiChatServiceImpl implements AIChatService {
|
||||
log.info("情绪分析总结生成完成: {}", emotionSummary);
|
||||
|
||||
// 解析AI返回的情绪分析结果
|
||||
EmotionAnalysisResult analysisResult = parseEmotionSummary(emotionSummary);
|
||||
EmotionAnalysis analysisResult = parseEmotionSummary(emotionSummary);
|
||||
|
||||
// 创建情绪记录
|
||||
EmotionRecord emotionRecord = createEmotionRecord(userId, analysisResult, chatHistory);
|
||||
@@ -1011,37 +1016,39 @@ public class AiChatServiceImpl implements AIChatService {
|
||||
/**
|
||||
* 解析情绪分析总结结果
|
||||
*/
|
||||
private EmotionAnalysisResult parseEmotionSummary(String summary) {
|
||||
private EmotionAnalysis parseEmotionSummary(String summary) {
|
||||
try {
|
||||
// 尝试从AI回复中提取JSON
|
||||
String jsonStr = extractJsonFromSummary(summary);
|
||||
if (jsonStr != null) {
|
||||
JSONObject json = JSON.parseObject(jsonStr);
|
||||
|
||||
EmotionAnalysisResult result = new EmotionAnalysisResult();
|
||||
result.setPrimaryEmotion(json.getString("primaryEmotion"));
|
||||
result.setIntensity(json.getDoubleValue("intensity"));
|
||||
result.setTriggers(json.getString("triggers"));
|
||||
result.setEmotionTrend(json.getString("emotionTrend"));
|
||||
result.setSuggestions(json.getString("suggestions"));
|
||||
result.setSummary(json.getString("summary"));
|
||||
|
||||
return result;
|
||||
return EmotionAnalysis.builder()
|
||||
.primaryEmotion(json.getString("primaryEmotion"))
|
||||
.intensity(BigDecimal.valueOf(json.getDoubleValue("intensity")))
|
||||
.keywords(json.getString("triggers"))
|
||||
.suggestion(json.getString("suggestions"))
|
||||
.text(summary)
|
||||
.polarity(determinePolarity(json.getString("primaryEmotion")))
|
||||
.confidence(BigDecimal.valueOf(0.85))
|
||||
.analysisTime(LocalDateTime.now())
|
||||
.build();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析情绪分析结果失败,使用默认值: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// 如果解析失败,返回默认结果
|
||||
EmotionAnalysisResult defaultResult = new EmotionAnalysisResult();
|
||||
defaultResult.setPrimaryEmotion("平静");
|
||||
defaultResult.setIntensity(0.5);
|
||||
defaultResult.setTriggers("日常对话");
|
||||
defaultResult.setEmotionTrend("相对稳定");
|
||||
defaultResult.setSuggestions("保持当前的积极状态");
|
||||
defaultResult.setSummary(summary);
|
||||
|
||||
return defaultResult;
|
||||
return EmotionAnalysis.builder()
|
||||
.primaryEmotion("平静")
|
||||
.intensity(BigDecimal.valueOf(0.5))
|
||||
.keywords("日常对话")
|
||||
.suggestion("保持当前的积极状态")
|
||||
.text(summary)
|
||||
.polarity("neutral")
|
||||
.confidence(BigDecimal.valueOf(0.5))
|
||||
.analysisTime(LocalDateTime.now())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1063,14 +1070,14 @@ public class AiChatServiceImpl implements AIChatService {
|
||||
/**
|
||||
* 创建情绪记录
|
||||
*/
|
||||
private EmotionRecord createEmotionRecord(String userId, EmotionAnalysisResult analysisResult, String chatHistory) {
|
||||
private EmotionRecord createEmotionRecord(String userId, EmotionAnalysis analysisResult, String chatHistory) {
|
||||
EmotionRecord record = EmotionRecord.builder()
|
||||
.userId(userId)
|
||||
.recordDate(LocalDate.now())
|
||||
.emotionType(analysisResult.getPrimaryEmotion())
|
||||
.intensity(BigDecimal.valueOf(analysisResult.getIntensity()))
|
||||
.triggers(analysisResult.getTriggers())
|
||||
.description(analysisResult.getSummary())
|
||||
.intensity(analysisResult.getIntensity())
|
||||
.triggers(analysisResult.getKeywords())
|
||||
.description(analysisResult.getText())
|
||||
.notes("基于当天聊天记录自动生成的情绪分析")
|
||||
.tags("AI分析,聊天记录,情绪总结")
|
||||
.build();
|
||||
@@ -1078,37 +1085,14 @@ public class AiChatServiceImpl implements AIChatService {
|
||||
emotionRecordService.save(record);
|
||||
log.info("情绪记录创建成功: recordId={}", record.getId());
|
||||
|
||||
// 设置情绪分析记录的关联ID并保存
|
||||
analysisResult.setUserId(userId);
|
||||
analysisResult.setMessageId(record.getId()); // 关联到情绪记录ID
|
||||
|
||||
emotionAnalysisService.save(analysisResult);
|
||||
log.info("情绪分析记录创建成功: analysisId={}", analysisResult.getId());
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* 情绪分析结果内部类
|
||||
*/
|
||||
public static class EmotionAnalysisResult {
|
||||
private String primaryEmotion;
|
||||
private Double intensity;
|
||||
private String triggers;
|
||||
private String emotionTrend;
|
||||
private String suggestions;
|
||||
private String summary;
|
||||
|
||||
// Getters and Setters
|
||||
public String getPrimaryEmotion() { return primaryEmotion; }
|
||||
public void setPrimaryEmotion(String primaryEmotion) { this.primaryEmotion = primaryEmotion; }
|
||||
|
||||
public Double getIntensity() { return intensity; }
|
||||
public void setIntensity(Double intensity) { this.intensity = intensity; }
|
||||
|
||||
public String getTriggers() { return triggers; }
|
||||
public void setTriggers(String triggers) { this.triggers = triggers; }
|
||||
|
||||
public String getEmotionTrend() { return emotionTrend; }
|
||||
public void setEmotionTrend(String emotionTrend) { this.emotionTrend = emotionTrend; }
|
||||
|
||||
public String getSuggestions() { return suggestions; }
|
||||
public void setSuggestions(String suggestions) { this.suggestions = suggestions; }
|
||||
|
||||
public String getSummary() { return summary; }
|
||||
public void setSummary(String summary) { this.summary = summary; }
|
||||
}
|
||||
}
|
||||
@@ -195,4 +195,10 @@ public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> impl
|
||||
// 通过conversation表关联查询用户的消息,根据关键词搜索
|
||||
return this.baseMapper.searchByUserIdAndKeyword(userId, keyword, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Message> getRecentByUserId(String userId, Integer limit) {
|
||||
// 获取用户最近的消息,按时间倒序
|
||||
return this.baseMapper.getRecentByUserId(userId, limit);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user