feat(chat): 新增重置会话接口并优化主键策略
- ChatController 增加 /session/reset 端点,支持用户主动重置与 AI 角色的会话 - 会话重置逻辑:将当前活跃会话置为失效,并创建版本号递增的新会话 - 新增 SessionResetReq DTO 与 ChatSessionVO 返回视图 - KeyboardAiChatSession 主键生成策略由 AUTO 改为 ASSIGN_ID,适配分布式场景
This commit is contained in:
@@ -14,12 +14,15 @@ import com.yolo.keyborad.model.dto.chat.ChatMessageReq;
|
||||
import com.yolo.keyborad.model.dto.chat.ChatReq;
|
||||
import com.yolo.keyborad.model.dto.chat.ChatSaveReq;
|
||||
import com.yolo.keyborad.model.dto.chat.ChatStreamMessage;
|
||||
import com.yolo.keyborad.model.dto.chat.SessionResetReq;
|
||||
import com.yolo.keyborad.model.vo.AudioTaskVO;
|
||||
import com.yolo.keyborad.model.vo.ChatMessageHistoryVO;
|
||||
import com.yolo.keyborad.model.vo.ChatMessageVO;
|
||||
import com.yolo.keyborad.model.vo.ChatSessionVO;
|
||||
import com.yolo.keyborad.model.vo.ChatVoiceVO;
|
||||
import com.yolo.keyborad.service.ChatService;
|
||||
import com.yolo.keyborad.service.KeyboardAiChatMessageService;
|
||||
import com.yolo.keyborad.service.KeyboardAiChatSessionService;
|
||||
import com.yolo.keyborad.service.impl.QdrantVectorService;
|
||||
import io.qdrant.client.grpc.JsonWithInt;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -55,6 +58,9 @@ public class ChatController {
|
||||
@Resource
|
||||
private KeyboardAiChatMessageService aiChatMessageService;
|
||||
|
||||
@Resource
|
||||
private KeyboardAiChatSessionService aiChatSessionService;
|
||||
|
||||
|
||||
@PostMapping("/message")
|
||||
@Operation(summary = "同步对话", description = "发送消息给大模型,同步返回 AI 响应,异步生成音频")
|
||||
@@ -131,4 +137,24 @@ public class ChatController {
|
||||
userId, req.getCompanionId(), req.getPageNum(), req.getPageSize());
|
||||
return ResultUtils.success(result);
|
||||
}
|
||||
|
||||
@PostMapping("/session/reset")
|
||||
@Operation(summary = "重置会话", description = "重置与AI角色的聊天会话,将当前会话设为不活跃并创建新会话,后续聊天记录将绑定到新会话")
|
||||
public BaseResponse<ChatSessionVO> resetSession(@RequestBody SessionResetReq req) {
|
||||
if (req.getCompanionId() == null) {
|
||||
throw new BusinessException(ErrorCode.COMPANION_ID_EMPTY);
|
||||
}
|
||||
|
||||
Long userId = StpUtil.getLoginIdAsLong();
|
||||
var newSession = aiChatSessionService.resetSession(userId, req.getCompanionId());
|
||||
|
||||
ChatSessionVO vo = ChatSessionVO.builder()
|
||||
.sessionId(newSession.getId())
|
||||
.companionId(newSession.getCompanionId())
|
||||
.resetVersion(newSession.getResetVersion())
|
||||
.createdAt(newSession.getCreatedAt())
|
||||
.build();
|
||||
|
||||
return ResultUtils.success(vo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.yolo.keyborad.model.dto.chat;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/28
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "会话重置请求")
|
||||
public class SessionResetReq {
|
||||
|
||||
@Schema(description = "AI陪聊角色ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long companionId;
|
||||
}
|
||||
29
src/main/java/com/yolo/keyborad/model/vo/ChatSessionVO.java
Normal file
29
src/main/java/com/yolo/keyborad/model/vo/ChatSessionVO.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.yolo.keyborad.model.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/28
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@Schema(description = "会话信息VO")
|
||||
public class ChatSessionVO {
|
||||
|
||||
@Schema(description = "会话ID")
|
||||
private Long sessionId;
|
||||
|
||||
@Schema(description = "AI陪聊角色ID")
|
||||
private Long companionId;
|
||||
|
||||
@Schema(description = "会话版本号")
|
||||
private Integer resetVersion;
|
||||
|
||||
@Schema(description = "会话创建时间")
|
||||
private Date createdAt;
|
||||
}
|
||||
@@ -26,4 +26,13 @@ public interface KeyboardAiChatSessionService extends IService<KeyboardAiChatSes
|
||||
* @return 活跃会话ID
|
||||
*/
|
||||
Long getOrCreateActiveSessionId(Long userId, Long companionId);
|
||||
|
||||
/**
|
||||
* 重置会话:将当前活跃会话设为不活跃,并创建新的活跃会话
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param companionId AI角色ID
|
||||
* @return 新创建的活跃会话
|
||||
*/
|
||||
KeyboardAiChatSession resetSession(Long userId, Long companionId);
|
||||
}
|
||||
|
||||
@@ -55,4 +55,43 @@ public class KeyboardAiChatSessionServiceImpl extends ServiceImpl<KeyboardAiChat
|
||||
public Long getOrCreateActiveSessionId(Long userId, Long companionId) {
|
||||
return getOrCreateActiveSession(userId, companionId).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyboardAiChatSession resetSession(Long userId, Long companionId) {
|
||||
Date now = new Date();
|
||||
|
||||
// 查询当前活跃会话
|
||||
LambdaQueryWrapper<KeyboardAiChatSession> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(KeyboardAiChatSession::getUserId, userId)
|
||||
.eq(KeyboardAiChatSession::getCompanionId, companionId)
|
||||
.eq(KeyboardAiChatSession::getIsActive, true);
|
||||
KeyboardAiChatSession activeSession = this.getOne(queryWrapper);
|
||||
|
||||
// 如果存在活跃会话,将其设为不活跃
|
||||
if (activeSession != null) {
|
||||
activeSession.setIsActive(false);
|
||||
activeSession.setEndedAt(now);
|
||||
this.updateById(activeSession);
|
||||
}
|
||||
|
||||
// 查询该用户与该角色的最大版本号
|
||||
LambdaQueryWrapper<KeyboardAiChatSession> maxVersionWrapper = new LambdaQueryWrapper<>();
|
||||
maxVersionWrapper.eq(KeyboardAiChatSession::getUserId, userId)
|
||||
.eq(KeyboardAiChatSession::getCompanionId, companionId)
|
||||
.orderByDesc(KeyboardAiChatSession::getResetVersion)
|
||||
.last("LIMIT 1");
|
||||
KeyboardAiChatSession lastSession = this.getOne(maxVersionWrapper);
|
||||
int newVersion = lastSession != null ? lastSession.getResetVersion() + 1 : 1;
|
||||
|
||||
// 创建新的活跃会话
|
||||
KeyboardAiChatSession newSession = new KeyboardAiChatSession();
|
||||
newSession.setUserId(userId);
|
||||
newSession.setCompanionId(companionId);
|
||||
newSession.setResetVersion(newVersion);
|
||||
newSession.setIsActive(true);
|
||||
newSession.setCreatedAt(now);
|
||||
this.save(newSession);
|
||||
|
||||
return newSession;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user