ChatMemory连续对话保存和持久化
简单来说,大模型的对话记忆功能主要就是我们可以接连的进行问题回答,使得上下文之间的问题联系到一起,最终达到我们需要的记忆和对话功能。
Spring AI Alibaba中的聊天记忆应该维护AI聊天应用程序的对话上下文和历史机制。
首先我们需要解决内存的存储,大模型本身是不存储数据的,所以我们如果把历史对话信息存储到内存当中,如果重新进行启动的话,我们就会失去历史信息,所以最好的方法就是存储到可以持续化的插件里面,比方说mysql,redis,mongoDB,同样的我们还是需要进行对话窗口中的保存信息上线,也就是说当达到上线的时候我们就可以把之前的问题和对话记录给进行取消。
在官网的文档里面,我们可以使用以下方法
同样的只要我们是通过内存实现的,那么我们只要重启服务,那么我们就没有办法达到持续化的存储。
注意!
官网是没有对这一方式进行良好的解决。
所以我们通过以下的方式进行对话的长久存储。
首先我们需要引入依赖,必不可少的以下三个
<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-memory-redis</artifactId>
</dependency>
//根据阿里开发手册当中,规定我们使用jedis来进行redis的使用。
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>
</dependency>
然后我们进行redis的简单配置
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.password=123456
spring.data.redis.database=0
spring.data.redis.connect-timeout=3
spring.data.redis.timeout=2
配置完成之后,我们就可以写业务类了。
我们在官网可以看到,大型语言模型是无状态的,也就是说需要通过下面的三个接口来实现对话保存。
而其中的ChatMemoryRepository的接口实现就在内存和redis其中之一,所以我们就可以使用redis进行实现对话保存的功能:
而jedis也是我们的保存对话的时候使用的
我们通过推导可以知道RedisChatMemoryRepository的接口是实现于ChatMemoryRepository, 而ChatMemoryRepository接口的实现类有RedisChatMemoryRepository和MemoryChatMemoryRepository所有我们可以创建一个RedisMemoryConfig类,继承RedisChatMemoryRepository类,并添加@Configuration注解,使其生效。
package ai.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 {// RedisMemoryConfig 配置类@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private int port;@Beanpublic RedisChatMemoryRepository redisChatMemoryRepository() {return RedisChatMemoryRepository.builder().host(host).port(port).build();}
}
因为我们为了实现持久化,同时也有一个注意的地方就是消息窗口的聊天对话的上限。
通过官方的学习文档,我们可以看得出,最大的存储消息我们可以自己进行配置。我们为了实现这个功能,我们就需要使用Advisors通过顾问的形式,将我们需要实现的管理模式进行导入,可以让我们得大模型知晓我们使用的存储工具。官方地址:Advisors API :: Spring AI 参考
我们通过对官方文档的学习可以得到大模型功能的增强:
对于配置类,我们需要进行如下的改写:
@Bean(name = "deepseekChatClient")
public ChatClient deepseekChatClient(@Qualifier("deepseek") ChatModel deepseek, RedisChatMemoryRepository redisChatMemoryRepository) {MessageWindowChatMemory windowChatMemory = MessageWindowChatMemory.builder().chatMemoryRepository(redisChatMemoryRepository).maxMessages(10).build();return ChatClient.builder(deepseek).defaultAdvisors(MessageChatMemoryAdvisor.builder(windowChatMemory).build()).build();
}
@Bean(name = "qwenChatClient")
public ChatClient qwenChatClient(@Qualifier("qwen") ChatModel qwen,RedisChatMemoryRepository redisChatMemoryRepository) {MessageWindowChatMemory windowChatMemory = MessageWindowChatMemory.builder().chatMemoryRepository(redisChatMemoryRepository).maxMessages(10).build();return ChatClient.builder(qwen).defaultAdvisors(MessageChatMemoryAdvisor.builder(windowChatMemory).build()).build();
}
通过顾问的lambda表达式来实现对话记忆的打入功能。
@GetMapping("/chatmemory/deepseekChatClient")
public String deepseekChatClient(@RequestParam(name = "message", defaultValue = "你是谁?")String message,String userid) {return deepseekChatClient.prompt(message).advisors(advisorSpec -> advisorSpec.param(CONVERSATION_ID, userid)).call().content();
}
当我们对于以上的操作进行之后,我们就可以正常的使用对话记忆的功能了
同样的我们可以在redis的可视化界面上面看到我们的对话记录存储到redis里面去了。