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个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
day26使用腾讯云,在云服务器上安装docker,git,nginx,大部分用agent自动完成。明天就能部署了本地部署了一遍,用docker desktop部署的。校招投了一些,毕竟是2026应届毕业生,与很多校招时间上不匹配,投了一个银行还有一些大厂这几天看了ai知识,下载ai工具,熟悉ai作业,windsurf额度用完了,trae额度还挺多的,Cursor还没使用,已经安装了。明天部署完项
3
Day 2✅ 今天做了:RAG基础剩余部分以及作业⏰ 明天计划:RAG进阶📚 今日感悟:通过云知识库可以简化开发流程
1
Day 6~7✅ 今天做了:这两天学习了[工具调用 学习进度100%,掌握进度60%] 工具调用进阶知识,注入工具上下文、立即返回等简单的设置,以及工具执行模式管理工具给client使用。[MCP协议 学习进度70%, 掌握进度40%] mcp与工具调用区别、mcp的sse和stdio的两种调用方式,学习了程序使用mcp⏰ 明天计划:mcp收尾,并实操mcp的代码编写。📚 今日感悟:学习并理解工
2
Day 114✅ 今天做了:练习sql查询⏰ 明天计划:继续学习mysql
1
Day 36✅ 今天做了:1、扇贝英语单词打卡2、微信阅读15分钟3、编程导航学习⏰ 明天计划:待定📚 今日感悟:Keep going!
1

