From ac9a352004dd3c5e6e6dc52b0e247b58e687c561 Mon Sep 17 00:00:00 2001 From: ziin Date: Mon, 26 Jan 2026 20:25:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(chat):=20=E4=B8=BAAI=E9=99=AA=E8=81=8A?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8E=86=E5=8F=B2=E6=B6=88=E6=81=AF=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChatServiceImpl#message 现在会读取最近20条聊天记录作为LLM上下文 - 新增 callLLMWithHistory 方法,使用 Spring AI Message 构造对话历史 - KeyboardAiChatMessageService 新增 getRecentMessages 接口及实现,按时间正序返回指定条数消息 - 保持原有分页查询接口不变,仅补充上下文所需方法 --- .../service/KeyboardAiChatMessageService.java | 12 ++++++++ .../service/impl/ChatServiceImpl.java | 30 ++++++++++++++++--- .../KeyboardAiChatMessageServiceImpl.java | 16 ++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/yolo/keyborad/service/KeyboardAiChatMessageService.java b/src/main/java/com/yolo/keyborad/service/KeyboardAiChatMessageService.java index 47b604b..fc9f443 100644 --- a/src/main/java/com/yolo/keyborad/service/KeyboardAiChatMessageService.java +++ b/src/main/java/com/yolo/keyborad/service/KeyboardAiChatMessageService.java @@ -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 pageHistory(Long userId, Long companionId, Integer pageNum, Integer pageSize); + + /** + * 获取最近的聊天记录(按时间正序,用于LLM上下文) + * + * @param userId 用户ID + * @param companionId AI陪聊角色ID + * @param limit 获取条数 + * @return 聊天记录列表(时间正序) + */ + List getRecentMessages(Long userId, Long companionId, int limit); } diff --git a/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java index c48dcb3..948c9da 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java @@ -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 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 historyMessages) { + // 构建历史消息列表 + List 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(); } diff --git a/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiChatMessageServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiChatMessageServiceImpl.java index 45e1b08..10ffe55 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiChatMessageServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/KeyboardAiChatMessageServiceImpl.java @@ -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 entityPage = this.page(page, queryWrapper); return entityPage.convert(entity -> BeanUtil.copyProperties(entity, ChatMessageHistoryVO.class)); } + + @Override + public List getRecentMessages(Long userId, Long companionId, int limit) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(KeyboardAiChatMessage::getUserId, userId) + .eq(KeyboardAiChatMessage::getCompanionId, companionId) + .orderByDesc(KeyboardAiChatMessage::getCreatedAt) + .last("LIMIT " + limit); + List messages = this.list(queryWrapper); + // 反转列表,使其按时间正序排列(旧消息在前) + Collections.reverse(messages); + return messages; + } }