Agent AI 超级智能体企业级实战(26年必学) - 基于Redis存储持久化(SpringAI1.1.2版本)
这里我存在Redis缓存里面,避免数据库压力
- 引入依赖
▼plain复制代码<!--RedisChatMemory--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
- 配置Redis
▼plain复制代码spring: data: redis: host: localhost port: 6379 password: database: 2
- 自定义RedisChatMemoryRepository
注意咱们的Message在读取和存入的序列化问题(这里使用了Hutool工具)
▼plain复制代码@Repository public class RedisChatMemoryRepository implements ChatMemoryRepository { private final StringRedisTemplate redisTemplate; private static final String KEY_PREFIX = "chat:memory:"; private static final String CONVERSATIONS_KEY = "chat:memory:conversations"; private static final long TTL_HOURS = 24 * 7; // 会话保留7天 public RedisChatMemoryRepository(StringRedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } @Override public List<String> findConversationIds() { Set<String> members = redisTemplate.opsForSet().members(CONVERSATIONS_KEY); return members != null ? new ArrayList<>(members) : List.of(); } @Override public List<Message> findByConversationId(String conversationId) { Assert.hasText(conversationId, "Conversation ID must not be empty"); String key = KEY_PREFIX + conversationId; List<String> jsonMessages = redisTemplate.opsForList().range(key, 0, -1); if (jsonMessages == null || jsonMessages.isEmpty()) { return List.of(); } List<Message> messages = new ArrayList<>(); for (String json : jsonMessages) { Message message = deserializeMessage(json); if (message != null) { messages.add(message); } } return messages; } @Override public void saveAll(String conversationId, List<Message> messages) { Assert.hasText(conversationId, "Conversation ID must not be empty"); String key = KEY_PREFIX + conversationId; // 删除旧记录 redisTemplate.delete(key); if (messages != null && !messages.isEmpty()) { List<String> jsonMessages = new ArrayList<>(); for (Message message : messages) { String json = serializeMessage(message); if (json != null) { jsonMessages.add(json); } } // 批量存入Redis List redisTemplate.opsForList().rightPushAll(key, jsonMessages); // 设置过期时间 redisTemplate.expire(key, TTL_HOURS, TimeUnit.HOURS); // 记录会话ID到集合 redisTemplate.opsForSet().add(CONVERSATIONS_KEY, conversationId); } } @Override public void deleteByConversationId(String conversationId) { Assert.hasText(conversationId, "Conversation ID must not be empty"); String key = KEY_PREFIX + conversationId; redisTemplate.delete(key); redisTemplate.opsForSet().remove(CONVERSATIONS_KEY, conversationId); } /** * 序列化消息为JSON(用Hutool) */ private String serializeMessage(Message message) { JSONObject json = JSONUtil.createObj() .set("messageType", message.getMessageType().name()) .set("text", message.getText()); // 如果有其他属性可以继续添加 if (message.getMetadata() != null && !message.getMetadata().isEmpty()) { json.set("metadata", message.getMetadata()); } return json.toString(); } /** * 反序列化JSON为Message(用Hutool) */ private Message deserializeMessage(String json) { if (StrUtil.isBlank(json)) { return null; } JSONObject jsonObject = JSONUtil.parseObj(json); String messageType = jsonObject.getStr("messageType"); String text = jsonObject.getStr("text"); if (messageType == null || text == null) { return null; } // 根据消息类型创建具体的Message对象 return switch (messageType) { case "USER" -> new UserMessage(text); case "ASSISTANT" -> new AssistantMessage(text); case "SYSTEM" -> new SystemMessage(text); default -> null; }; } }
- 重写我们的对话记忆
▼plain复制代码/** * 初始化AI 客户端 * @param dashScopeChatModel */ public TravelApp(DashScopeChatModel dashScopeChatModel, RedisChatMemoryRepository redisChatMemoryRepository) { //基于内存的对话记忆 //现在不再存在内存,而进行持久化存储(Redis) ChatMemory chatMemory = MessageWindowChatMemory.builder() .chatMemoryRepository(redisChatMemoryRepository) .maxMessages(10) .build(); chatClient = ChatClient.builder(dashScopeChatModel) .defaultSystem(SYSTEM_PROMPT) .defaultAdvisors( MessageChatMemoryAdvisor.builder(chatMemory).build(), //自定义日志拦截器 new MyLoggerAdvisor() // 自定义推理增强Advisor,可以按需开启(需要烧token) //new ReReadingAdvisor() ) .build(); }


评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
AI 超级智能体 - 基于mysql的消息存储
4
SpringAl+RAG+MCP全栈|AI超级智能体企业级实战项目中:stdio连接方式调用MCP服务问题运行测试时解决:1. 先查看MCP server那的yml文件,文件名有没有写错2. 修改server端的"application-stdio.yml",把每一个报错发给deepseek再验证之后,得出结论:Server 的 stdout 完全被污染了:Spring Boot Banner 完
3
SpringAI + RAG + MCP 全栈 | AI 超级智能体企业级实战(26年必学) - 第三期:基础内容 笔记
3
AI超级智能体项目_踩坑记录_PGVector维度冲突
2
Code Log-AI超级智能体项目,开发日志。SpringAI + RAG + MCP 全栈 | AI 超级智能体企业级实战(26年必学)
2
作者分享
深航26信息技术春招(一二面汇总)
4
Day 2
✅ 今天做了:海投100家+面试题+LeetCode5道
⏰ 明天计划:早上继续海投来约面进行训练,八股背诵,项目优化实现然后做LeetCode
📚 今日感悟:今天的海投大部分已读不回,有十几家家要了简历,然后有一个离谱的一直问我能不能接受加班,说他们家一直996,长期加班出差,我答应了毕竟就是为了海投约面,反正最后也不去这种拿offer,哎,晚上跟家里人聊天,他们好像只认可央国企,我一说去找工作上班,他们就说我这个就是假公司迟早被裁员,我本来就很烦了,我也知道央国企的好处,但是说了好几次不想去,而且现在人家也不要我啊,一天天说这个,不管是什么企业,只要能给我一直发工资的企业就是好企业呀,服了
3
Day 1
✅ 今天做了:海投、八股、LeetCode 5道、Stream流和Lambda
⏰ 明天计划:早上海投、八股、LeetCode 5道、完善项目
📚 今日感悟:今天跟硕士同学交流了一下,发现大家都在焦虑,哎,今天进了三家人才库😭,做了两家测评,目前还没有一家面试,可能投的太少了(目前就投了20家),明天要提高效率了,想约小厂来试试自己的面试水平
3
Day 11
✅ 今天做了:Redis实战篇--短信验证学完了,整理了笔记,把途中遇到的bug总结了一下,顺便用ai帮助扩展了知识点
⏰ 明天计划:Redis实战篇--商户查询缓存学习,面试题看一会,SpringBoot知识点
📚 今日感悟:总体效率跟不上啊,有时候自己太过于对细节追究太深,导致许多没学过的知识涌过来的时候就吃不消,还是得慢慢来,今天对有些方法有了很深的体会,继续加油ヾ(◍°∇°◍)ノ゙
2
Day 10
✅ 今天做了:主要集中学习了Redis的基础篇,序列化和反序列化知识的学习
⏰ 明天计划:开始Redis的实战篇(~ ̄▽ ̄)~+面试题*2+SpirngBoot知识
📚 今日感悟:今天主要学习了Redis相关知识,发现自己的Redis版本太低了3.x安在windows上面的,然后黑马教程是6.2以上,这样里面有些命令是不一样的,在6.2可以进行,自己这边就一直报error,目前发现到的两个一个是LPOP users 1这种的操作,在3.x版本是不容许,一下子多个pop的,只能lpop users这样的,还有一个就是ZADD key member score 这个操作,在3.x版本也是不容许的,只能ZADD key score member [score member ...](这个方法是通用的,所有版本都可以)。
2

