AI 超级智能体 - 基于mysql的消息存储
▼java复制代码package com.cestbon.aiagent.chatmemory; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.cestbon.aiagent.entity.ChatConversation; import com.cestbon.aiagent.entity.ChatMessage; import com.cestbon.aiagent.mapper.ChatConversationMapper; import com.cestbon.aiagent.mapper.ChatMessageMapper; import jakarta.annotation.Resource; import org.springframework.ai.chat.memory.ChatMemoryRepository; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @Component public class InMySqlChatMemoryRepository implements ChatMemoryRepository { @Resource private ChatConversationMapper chatConversationMapper; @Resource private ChatMessageMapper chatMessageMapper; @Override public List<String> findConversationIds() { return chatConversationMapper.selectList(null) .stream() .map(ChatConversation::getConversationId) .collect(Collectors.toList()); } @Override public List<Message> findByConversationId(String conversationId) { Assert.hasText(conversationId, "conversationId must not be empty"); QueryWrapper<ChatMessage> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("conversation_id", conversationId).orderByAsc("message_index") .in("role", "USER", "ASSISTANT"); List<ChatMessage> records = chatMessageMapper.selectList(queryWrapper); if (records == null || records.isEmpty()) { return List.of(); } return records.stream().map(this::convertToMessage) .filter(Objects::nonNull) .collect(Collectors.toList()); } private Message convertToMessage(ChatMessage chatMessage) { String role = chatMessage.getRole(); String content = chatMessage.getContent(); if ("USER".equals(role)) { return new UserMessage(content); } else if ("ASSISTANT".equals(role)) { return new AssistantMessage(content); } return null; } @Override @Transactional public void saveAll(String conversationId, List<Message> messages) { Assert.hasText(conversationId, "conversationId must not be empty"); Assert.notNull(messages, "messages must not be null"); // 查询当前对话,检查是否已存在 QueryWrapper<ChatConversation> conversationWrapper = new QueryWrapper<>(); conversationWrapper.eq("conversation_id", conversationId); ChatConversation existingConversation = chatConversationMapper.selectOne(conversationWrapper); // 如果对话不存在,则新建 if (existingConversation == null) { ChatConversation newConversation = new ChatConversation(); newConversation.setConversationId(conversationId); newConversation.setTitle(messages.getFirst().getText()); chatConversationMapper.insert(newConversation); } else { // 更新对话的updateTime existingConversation.setUpdateTime(new Date()); chatConversationMapper.updateById(existingConversation); } // TODO 当会话消息超过当前窗口时,应该调用llm总结当前会话的内容为一条消息,然后再维护当前窗口,而不是直接删除清空窗口 chatMessageMapper.delete(new QueryWrapper<ChatMessage>().eq("conversation_id", conversationId)); for (int i = 0; i < messages.size(); i++) { Message message = messages.get(i); ChatMessage chatMessage = new ChatMessage(); chatMessage.setConversationId(conversationId); chatMessage.setMessageIndex(i); chatMessage.setContent(message.getText()); chatMessage.setRole(message.getMessageType().name()); chatMessage.setMetadata(JSONUtil.toJsonStr(message.getMetadata())); chatMessage.setCreateTime(new Date()); chatMessageMapper.insert(chatMessage); } } @Override public void deleteByConversationId(String conversationId) { Assert.hasText(conversationId, "conversationId must not be empty"); chatMessageMapper.delete(new QueryWrapper<ChatMessage>().eq("conversation_id", conversationId)); chatConversationMapper.delete(new QueryWrapper<ChatConversation>().eq("conversation_id", conversationId)); } }
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
Day1今天学习了java中if的使用
2
day 61今天来学校上课了,和教授谈了,可以接下RA工作,不过一周只能charge 10h, 工资很少,不过一个月600刀也勉强比没有好。今天的工作还没做完,最近在做知识库构造,Ui/UX上周就设计完,现在在做底座的建设今天也让Claude直接帮我把Neetcode150 题目+解题思路+代码给我整理了,我发现我真的只有找碎片化时间才能做题,我还不如先背先回忆(之前都做过)祝祖国母亲节日快乐,也
2
Day 1✅ 今天做了:⏰ 明天计划:📚 今日感悟:
0
企业级代码不是人写的,合并了升序降序的排序方法
3
开始写继承代码,准备翻越山丘,跨过继承、抽象、接口的分水岭
2

