自定义MySQL对话存储
实现步骤: 1.引入依赖 2.配置并连接数据库 3.创表结构、实体类 4.插件生成代码 ,给启动类加上mapper扫描 **5.自定义mysql对话存储 ** 6.使用mysql对话存储
1:
注意:官方MP说要用4版本,但是经过我的测试,4不行

2....... 3.表结构:
▼--复制代码CREATE TABLE chat_memory_message ( id BIGINT PRIMARY KEY AUTO_INCREMENT, conversation_id VARCHAR(128) NOT NULL, message_index BIGINT NOT NULL, message_type VARCHAR(32) NOT NULL, message_text TEXT NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_conversation_id (conversation_id), INDEX idx_conversation_id_idx (conversation_id, message_index) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
实体类:
▼/**复制代码* MySQL对话存储实体类 */ @Data @NoArgsConstructor @AllArgsConstructor @TableName("chat_memory_message") public class ChatMemoryMessage { @TableId(type = IdType.AUTO) private Long id; /** * 对话id */ private String conversationId; /** * 对话序号 */ private Long messageIndex; /** * 对话类型 */ private String messageType; /** * 具体文本 */ private String messageText; /** * 创建时间 */ private LocalDateTime createTime; }
4....... 5.
▼/**复制代码* 基于MySQL的对话存储(MP) */ @Component public class MySQLChatMemory implements ChatMemory { private final ChatMemoryMessageMapper mapper; public MySQLChatMemory(ChatMemoryMessageMapper mapper) { this.mapper = mapper; } @Override @Transactional public void add(String conversationId, List<Message> messages) { if(messages==null || messages.isEmpty()){ return; } //查询当前下一条对话的位置 Long nextIndex=getNextIndex(conversationId); //批量插入message for(Message message:messages){ ChatMemoryMessage entity = toEntity(conversationId, message, nextIndex++); mapper.insert(entity); } } @Override public List<Message> get(String conversationId, int lastN) { if(lastN<=0){ return List.of(); } //返回最后N个 List<ChatMemoryMessage> all = mapper.selectList( new LambdaQueryWrapper<ChatMemoryMessage>() .eq(ChatMemoryMessage::getConversationId, conversationId) .orderByAsc(ChatMemoryMessage::getMessageIndex) ); if (all == null || all.isEmpty()) { return List.of(); } return all.stream() .skip(Math.max(0, all.size() - lastN)) .map(this::toMessage) .toList(); } @Override public void clear(String conversationId) { mapper.delete( new LambdaQueryWrapper<ChatMemoryMessage>() .eq(ChatMemoryMessage::getConversationId, conversationId) ); } //计算下一条消息的序号 private Long getNextIndex(String conversationId) { //查询到最新一条消息 LambdaQueryWrapper<ChatMemoryMessage> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ChatMemoryMessage::getConversationId, conversationId) .orderByDesc(ChatMemoryMessage::getMessageIndex) .last("LIMIT 1"); ChatMemoryMessage lastMessage = mapper.selectOne(queryWrapper); //返回下条消息的序号 return lastMessage == null ? 0L : lastMessage.getMessageIndex() + 1; } //Spring AI的message-->>ChatMemoryMessage private ChatMemoryMessage toEntity(String conservationId, Message message, long index) { ChatMemoryMessage chatMemoryMessage = new ChatMemoryMessage(); chatMemoryMessage.setConversationId(conservationId); chatMemoryMessage.setMessageIndex(index); chatMemoryMessage.setMessageType(message.getMessageType().getValue()); chatMemoryMessage.setMessageText(message.getText()); return chatMemoryMessage; } //ChatMemoeyMessage--->>Spring AI的message private Message toMessage(ChatMemoryMessage chatMemoryMessage){ MessageType messageType = MessageType.valueOf(chatMemoryMessage.getMessageType().toUpperCase()); //根据消息类型返回具体子类对象 return switch (messageType) { case SYSTEM -> new SystemMessage(chatMemoryMessage.getMessageText()); case USER -> new UserMessage(chatMemoryMessage.getMessageText()); case ASSISTANT -> new AssistantMessage(chatMemoryMessage.getMessageText()); default -> throw new IllegalArgumentException("未知的消息类型: " + chatMemoryMessage.getMessageType()); }; } }
6.注意:
因为@ Resource注解生效在构造方法之后,而我们是用构造方法构建的客户端,所以我们不能用注解来注入MySQLChatMemory,我们只能在构造方法上加一个参数,然后调用。
▼@Component复制代码public class RockKindomApp { private final ChatClient chatClient; private final String SYSTEM_PROMPT = "XXXXXXXXXXXXXXXXXXXXX; public RockKindomApp(ChatModel dashscopeModel,MySQLChatMemory chatMemory) { //创建基于内存的记忆 // InMemoryChatMemory chatMemory = new InMemoryChatMemory(); //创建基于文件的记忆 // String fileDir = System.getProperty("user.dir") + "/chat-memory"; // FileBasedChatMemory chatMemory = new FileBasedChatMemory(fileDir); chatClient = ChatClient.builder(dashscopeModel) .defaultSystem(SYSTEM_PROMPT) .defaultAdvisors( new MessageChatMemoryAdvisor(chatMemory), new MyAdvisor() )//内存记忆顾问 .build(); }
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
