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.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.yolo.keyborad.model.vo.ChatMessageHistoryVO;
|
import com.yolo.keyborad.model.vo.ChatMessageHistoryVO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @author: ziin
|
* @author: ziin
|
||||||
* @date: 2026/1/26 17:00
|
* @date: 2026/1/26 17:00
|
||||||
@@ -21,4 +23,14 @@ public interface KeyboardAiChatMessageService extends IService<KeyboardAiChatMes
|
|||||||
* @return 分页结果
|
* @return 分页结果
|
||||||
*/
|
*/
|
||||||
IPage<ChatMessageHistoryVO> pageHistory(Long userId, Long companionId, Integer pageNum, Integer pageSize);
|
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.FileInfo;
|
||||||
import org.dromara.x.file.storage.core.FileStorageService;
|
import org.dromara.x.file.storage.core.FileStorageService;
|
||||||
import org.springframework.ai.chat.client.ChatClient;
|
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.ai.openai.OpenAiChatOptions;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.http.codec.ServerSentEvent;
|
import org.springframework.http.codec.ServerSentEvent;
|
||||||
@@ -371,7 +374,12 @@ public class ChatServiceImpl implements ChatService {
|
|||||||
// 获取AI人设的系统提示词
|
// 获取AI人设的系统提示词
|
||||||
String systemPrompt = aiCompanionService.getSystemPromptById(companionId);
|
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;
|
long llmDuration = System.currentTimeMillis() - startTime;
|
||||||
log.info("LLM 完成, userId: {}, 耗时: {}ms, 响应长度: {}", userId, llmDuration, response.length());
|
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
|
return client
|
||||||
.prompt()
|
.prompt()
|
||||||
.system(systemPrompt)
|
.system(systemPrompt)
|
||||||
.user(content)
|
.messages(messages)
|
||||||
.call()
|
.call()
|
||||||
.content();
|
.content();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import com.yolo.keyborad.model.vo.ChatMessageHistoryVO;
|
|||||||
import com.yolo.keyborad.service.KeyboardAiChatMessageService;
|
import com.yolo.keyborad.service.KeyboardAiChatMessageService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @author: ziin
|
* @author: ziin
|
||||||
* @date: 2026/1/26 17:00
|
* @date: 2026/1/26 17:00
|
||||||
@@ -28,4 +31,17 @@ public class KeyboardAiChatMessageServiceImpl extends ServiceImpl<KeyboardAiChat
|
|||||||
IPage<KeyboardAiChatMessage> entityPage = this.page(page, queryWrapper);
|
IPage<KeyboardAiChatMessage> entityPage = this.page(page, queryWrapper);
|
||||||
return entityPage.convert(entity -> BeanUtil.copyProperties(entity, ChatMessageHistoryVO.class));
|
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