feat(chat): 为AI陪聊增加历史消息上下文支持
- ChatServiceImpl#message 现在会读取最近20条聊天记录作为LLM上下文 - 新增 callLLMWithHistory 方法,使用 Spring AI Message 构造对话历史 - KeyboardAiChatMessageService 新增 getRecentMessages 接口及实现,按时间正序返回指定条数消息 - 保持原有分页查询接口不变,仅补充上下文所需方法
This commit is contained in:
@@ -5,6 +5,8 @@ import com.yolo.keyborad.model.entity.KeyboardAiChatMessage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yolo.keyborad.model.vo.ChatMessageHistoryVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26 17:00
|
||||
@@ -21,4 +23,14 @@ public interface KeyboardAiChatMessageService extends IService<KeyboardAiChatMes
|
||||
* @return 分页结果
|
||||
*/
|
||||
IPage<ChatMessageHistoryVO> pageHistory(Long userId, Long companionId, Integer pageNum, Integer pageSize);
|
||||
|
||||
/**
|
||||
* 获取最近的聊天记录(按时间正序,用于LLM上下文)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param companionId AI陪聊角色ID
|
||||
* @param limit 获取条数
|
||||
* @return 聊天记录列表(时间正序)
|
||||
*/
|
||||
List<KeyboardAiChatMessage> getRecentMessages(Long userId, Long companionId, int limit);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.dromara.x.file.storage.core.FileStorageService;
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.messages.AssistantMessage;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.ai.chat.messages.UserMessage;
|
||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.http.codec.ServerSentEvent;
|
||||
@@ -371,7 +374,12 @@ public class ChatServiceImpl implements ChatService {
|
||||
// 获取AI人设的系统提示词
|
||||
String systemPrompt = aiCompanionService.getSystemPromptById(companionId);
|
||||
|
||||
String response = callLLM(content, systemPrompt);
|
||||
// 获取最近20条聊天记录作为上下文
|
||||
List<KeyboardAiChatMessage> historyMessages = aiChatMessageService.getRecentMessages(
|
||||
Long.parseLong(userId), companionId, 20);
|
||||
log.info("获取历史消息, userId: {}, companionId: {}, 数量: {}", userId, companionId, historyMessages.size());
|
||||
|
||||
String response = callLLMWithHistory(content, systemPrompt, historyMessages);
|
||||
|
||||
long llmDuration = System.currentTimeMillis() - startTime;
|
||||
log.info("LLM 完成, userId: {}, 耗时: {}ms, 响应长度: {}", userId, llmDuration, response.length());
|
||||
@@ -423,13 +431,27 @@ public class ChatServiceImpl implements ChatService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 LLM 生成响应
|
||||
* 调用 LLM 生成响应(带历史消息上下文)
|
||||
*/
|
||||
private String callLLM(String content, String systemPrompt) {
|
||||
private String callLLMWithHistory(String content, String systemPrompt, List<KeyboardAiChatMessage> historyMessages) {
|
||||
// 构建历史消息列表
|
||||
List<Message> messages = new ArrayList<>();
|
||||
for (KeyboardAiChatMessage msg : historyMessages) {
|
||||
if (msg.getSender() == 1) {
|
||||
// 用户消息
|
||||
messages.add(new UserMessage(msg.getContent()));
|
||||
} else {
|
||||
// AI消息
|
||||
messages.add(new AssistantMessage(msg.getContent()));
|
||||
}
|
||||
}
|
||||
// 添加当前用户消息
|
||||
messages.add(new UserMessage(content));
|
||||
|
||||
return client
|
||||
.prompt()
|
||||
.system(systemPrompt)
|
||||
.user(content)
|
||||
.messages(messages)
|
||||
.call()
|
||||
.content();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ import com.yolo.keyborad.model.vo.ChatMessageHistoryVO;
|
||||
import com.yolo.keyborad.service.KeyboardAiChatMessageService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @author: ziin
|
||||
* @date: 2026/1/26 17:00
|
||||
@@ -28,4 +31,17 @@ public class KeyboardAiChatMessageServiceImpl extends ServiceImpl<KeyboardAiChat
|
||||
IPage<KeyboardAiChatMessage> entityPage = this.page(page, queryWrapper);
|
||||
return entityPage.convert(entity -> BeanUtil.copyProperties(entity, ChatMessageHistoryVO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyboardAiChatMessage> getRecentMessages(Long userId, Long companionId, int limit) {
|
||||
LambdaQueryWrapper<KeyboardAiChatMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId)
|
||||
.eq(KeyboardAiChatMessage::getCompanionId, companionId)
|
||||
.orderByDesc(KeyboardAiChatMessage::getCreatedAt)
|
||||
.last("LIMIT " + limit);
|
||||
List<KeyboardAiChatMessage> messages = this.list(queryWrapper);
|
||||
// 反转列表,使其按时间正序排列(旧消息在前)
|
||||
Collections.reverse(messages);
|
||||
return messages;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user