当前位置: 首页 > news >正文

(增强)基于sqlite、mysql、redis的消息存储

原文链接:(增强)基于sqlite、mysql、redis的消息存储

教程说明

说明:本教程将采用2025年5月20日正式的GA版,给出如下内容

  1. 核心功能模块的快速上手教程
  2. 核心功能模块的源码级解读
  3. Spring ai alibaba增强的快速上手教程 + 源码级解读

版本:JDK21 + SpringBoot3.4.5 + SpringAI 1.0.0 + SpringAI Alibaba最新

将陆续完成如下章节教程。本章是第二章(advisor)快速上手—sqlite、mysql、redis消息存储

代码开源如下:https://github.com/GTyingzi/spring-ai-tutorial

(增强)基于 sqlite、mysql、redis 的消息存储

[!TIP]
实现了基于 sqlite、mysql、redis 的消息存储

实战代码可见:https://github.com/GTyingzi/spring-ai-tutorial 下的 advisor/advisor-memory-sqlite、advisor-memory-mysql、advisor-memory-redis

代码已贡献至:https://github.com/springaialibaba/spring-ai-alibaba-examples/pull/238

pom 文件

<properties><sqlite.verson>3.49.1.0</sqlite.verson><mysql.version>8.0.32</mysql.version><jedis.version>5.2.0</jedis.version>
</properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-autoconfigure-model-openai</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-autoconfigure-model-chat-client</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-memory</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-memory-jdbc</artifactId></dependency><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-memory-redis</artifactId></dependency><dependency><groupId>org.xerial</groupId><artifactId>sqlite-jdbc</artifactId><version>${sqlite.verson}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>${jedis.version}</version></dependency></dependencies>

application.yml

server:port: 8080spring:application:name: advisor-memory-mysqlai:openai:api-key: ${DASHSCOPE_API_KEY}base-url: https://dashscope.aliyuncs.com/compatible-modechat:options:model: qwen-maxchat:memory:repository:jdbc:mysql:jdbc-url: jdbc:mysql://localhost:3306/spring_ai_alibaba_mysql?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&tinyInt1isBit=false&allowLoadLocalInfile=true&allowLocalInfile=true&allowUrlusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driverenabled: truememory:redis:host: localhostport: 6379timeout:  5000password:

Sqllite

SqliteMemoryConfig
package com.spring.ai.tutorial.advisor.memory.config;import com.alibaba.cloud.ai.memory.jdbc.SQLiteChatMemoryRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;@Configuration
public class SqliteMemoryConfig {@Beanpublic SQLiteChatMemoryRepository sqliteChatMemoryRepository() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("org.sqlite.JDBC");dataSource.setUrl("jdbc:sqlite:advisor/advisor-memory-sqlite/src/main/resources/chat-memory.db");JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);return SQLiteChatMemoryRepository._sqliteBuilder_().jdbcTemplate(jdbcTemplate).build();}
}
SqliteMemoryController
package com.spring.ai.tutorial.advisor.memory.controller;import com.alibaba.cloud.ai.memory.jdbc.SQLiteChatMemoryRepository;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;import static org.springframework.ai.chat.memory.ChatMemory._CONVERSATION_ID_;@RestController
@RequestMapping("/advisor/memory/sqlite")
public class SqliteMemoryController {private final ChatClient chatClient;private final int MAX_MESSAGES = 100;private final MessageWindowChatMemory messageWindowChatMemory;public SqliteMemoryController(ChatClient.Builder builder, SQLiteChatMemoryRepository sqliteChatMemoryRepository) {this.messageWindowChatMemory = MessageWindowChatMemory._builder_().chatMemoryRepository(sqliteChatMemoryRepository).maxMessages(MAX_MESSAGES).build();this.chatClient = builder.defaultAdvisors(MessageChatMemoryAdvisor._builder_(messageWindowChatMemory).build()).build();}@GetMapping("/call")public String call(@RequestParam(value = "query", defaultValue = "你好,我的外号是影子,请记住呀") String query,@RequestParam(value = "conversation_id", defaultValue = "yingzi") String conversationId) {return chatClient.prompt(query).advisors(a -> a.param(_CONVERSATION_ID_, conversationId)).call().content();}@GetMapping("/messages")public List<Message> messages(@RequestParam(value = "conversation_id", defaultValue = "yingzi") String conversationId) {return messageWindowChatMemory.get(conversationId);}
}
效果

以会话“yingzi”发送消息,此时消息存储至 sqllite

从 sqllite 获取会话“yingzi”对应的消息

Mysql

MysqlMemoryConfig
package com.spring.ai.tutorial.advisor.memory.config;import com.alibaba.cloud.ai.memory.jdbc.MysqlChatMemoryRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;@Configuration
public class MysqlMemoryConfig {@Value("${spring.ai.chat.memory.repository.jdbc.mysql.jdbc-url}")private String mysqlJdbcUrl;@Value("${spring.ai.chat.memory.repository.jdbc.mysql.username}")private String mysqlUsername;@Value("${spring.ai.chat.memory.repository.jdbc.mysql.password}")private String mysqlPassword;@Value("${spring.ai.chat.memory.repository.jdbc.mysql.driver-class-name}")private String mysqlDriverClassName;@Beanpublic MysqlChatMemoryRepository mysqlChatMemoryRepository() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(mysqlDriverClassName);dataSource.setUrl(mysqlJdbcUrl);dataSource.setUsername(mysqlUsername);dataSource.setPassword(mysqlPassword);JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);return MysqlChatMemoryRepository._mysqlBuilder_().jdbcTemplate(jdbcTemplate).build();}
}
MysqlMemoryController
package com.spring.ai.tutorial.advisor.memory.controller;import com.alibaba.cloud.ai.memory.jdbc.MysqlChatMemoryRepository;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;import static org.springframework.ai.chat.memory.ChatMemory._CONVERSATION_ID_;@RestController
@RequestMapping("/advisor/memory/mysql")
public class MysqlMemoryController {private final ChatClient chatClient;private final int MAX_MESSAGES = 100;private final MessageWindowChatMemory messageWindowChatMemory;public MysqlMemoryController(ChatClient.Builder builder, MysqlChatMemoryRepository mysqlChatMemoryRepository) {this.messageWindowChatMemory = MessageWindowChatMemory._builder_().chatMemoryRepository(mysqlChatMemoryRepository).maxMessages(MAX_MESSAGES).build();this.chatClient = builder.defaultAdvisors(MessageChatMemoryAdvisor._builder_(messageWindowChatMemory).build()).build();}@GetMapping("/call")public String call(@RequestParam(value = "query", defaultValue = "你好,我的外号是影子,请记住呀") String query,@RequestParam(value = "conversation_id", defaultValue = "yingzi") String conversationId) {return chatClient.prompt(query).advisors(a -> a.param(_CONVERSATION_ID_, conversationId)).call().content();}@GetMapping("/messages")public List<Message> messages(@RequestParam(value = "conversation_id", defaultValue = "yingzi") String conversationId) {return messageWindowChatMemory.get(conversationId);}
}
效果

以会话“yingzi”发送消息,此时消息存储至 mysql

消息被存储至 mysql 中

从 mysql 获取会话“yingzi”对应的消息

Redis

RedisMemoryConfig
package com.spring.ai.tutorial.advisor.memory.config;import com.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RedisMemoryConfig {@Value("${spring.ai.memory.redis.host}")private String redisHost;@Value("${spring.ai.memory.redis.port}")private int redisPort;@Value("${spring.ai.memory.redis.password}")private String redisPassword;@Value("${spring.ai.memory.redis.timeout}")private int redisTimeout;@Beanpublic RedisChatMemoryRepository redisChatMemoryRepository() {return RedisChatMemoryRepository._builder_().host(redisHost).port(redisPort)// 若没有设置密码则注释该项
//           .password(redisPassword).timeout(redisTimeout).build();}
}
RedisMemoryController
package com.spring.ai.tutorial.advisor.memory.controller;import com.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;import static org.springframework.ai.chat.memory.ChatMemory._CONVERSATION_ID_;@RestController
@RequestMapping("/advisor/memory/redis")
public class RedisMemoryController {private final ChatClient chatClient;private final int MAX_MESSAGES = 100;private final MessageWindowChatMemory messageWindowChatMemory;public RedisMemoryController(ChatClient.Builder builder, RedisChatMemoryRepository redisChatMemoryRepository) {this.messageWindowChatMemory = MessageWindowChatMemory._builder_().chatMemoryRepository(redisChatMemoryRepository).maxMessages(MAX_MESSAGES).build();this.chatClient = builder.defaultAdvisors(MessageChatMemoryAdvisor._builder_(messageWindowChatMemory).build()).build();}@GetMapping("/call")public String call(@RequestParam(value = "query", defaultValue = "你好,我的外号是影子,请记住呀") String query,@RequestParam(value = "conversation_id", defaultValue = "yingzi") String conversationId) {return chatClient.prompt(query).advisors(a -> a.param(_CONVERSATION_ID_, conversationId)).call().content();}@GetMapping("/messages")public List<Message> messages(@RequestParam(value = "conversation_id", defaultValue = "yingzi") String conversationId) {return messageWindowChatMemory.get(conversationId);}
}
效果

以会话“yingzi”发送消息,此时消息存储至 redis

消息被存储至 redis 中

从 redis 获取会话“yingzi”对应的消息

相关文章:

  • 打卡第38天
  • vue3+vite+amfe-flexible+postcss-pxtorem 实现全分辨率自适应
  • 文件上传绕过方法总结
  • 3分钟学会跨浏览器富文本编辑器开发:精准光标定位+内容插入(附完整代码)
  • 5.27 打卡
  • MySQL问题:MySQL中使用索引一定有效吗?如何排查索引效果
  • 《Python基础》第1期:人生苦短,我用Python
  • 第四十七篇-Tesla P40+Qwen3-30B-A3B部署与测试
  • SD07_NVM的安装及相关操作
  • qiankun 子应用怎样通过 props拿到子应用【注册之后挂载之前】主应用中发生变更的数据
  • 6个月Python学习计划 Day 6 - 综合实战:学生信息管理系统
  • 【系分】论文模版
  • 开源酷炫大数据可视化大屏html+eacher 100+套
  • 2025 海外短剧 CPS 系统开发:技术驱动下的全球化内容分销新范式
  • Spark、Hadoop对比
  • Day04
  • cursor-stats 实时监控 Cursor IDE 的使用情况和订阅状态
  • 体现物联网环境下安全防护的紧迫性 :物联网环境下的个人信息安全:隐忧与防护之道
  • Linux升级内核回退到旧内核启动
  • 2025上半年软考系统架构设计师选择题试题与答案
  • 织梦网站怎样做锚文本/游戏加盟
  • 网站做优化效果怎么样/百度推广代理商
  • 网络营销平台的类型/网店seo排名优化
  • 网站设计中超链接怎么做/网络销售就是忽悠人
  • 南宁公司官网建站/长春网站建设路
  • 公司哪家好点/中山seo关键词