langchain4j实现聊天记忆默认是基于进程内存的方式,InMemoryChatMemoryStore是具体的实现了,是将聊天记录到一个map中,如果用户大的话,会造成内存溢出以及数据安全问题。位了解决这个问题 langchain4提供了ChatMemoryStore接口,让开发者可以灵活的选择存储策略,常用的可以使用mysql、redis、mongodb等,本文以redis为例,集成百炼平台通义千问实现大模型聊天记忆持久化。
一、引入依赖
具体详情可参考官网
https://docs.langchain4j.dev/integrations/language-models/dashscope
XML
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '3.4.0'
// langchain4j AiService整合spring boot
implementation group: 'dev.langchain4j', name: 'langchain4j-spring-boot-starter', version: '1.0.0-beta4'
// langchain4j整合千问dashscope
implementation group: 'dev.langchain4j', name: 'langchain4j-community-dashscope-spring-boot-starter', version: '1.0.0-beta4'
yaml配置
bash
langchain4j:
## https://docs.langchain4j.dev/integrations/language-models/dashscope
community:
dashscope:
chat-model:
api-key: 百炼平台申请
model-name: qwen-plus
spring:
data:
redis:
host: server200
port: 6379
database: 3
二、持久化配置
官网参考地址https://docs.langchain4j.dev/tutorials/chat-memory/
java
@Configuration
public class ChatMemoryConf {
/**
* 聊天记录持久化存储到redis中
* @param redisTemplate
* @return
*/
public ChatMemoryStore chatMemoryStore(RedisTemplate<String,String> redisTemplate){
return new ChatMemoryStore(){
@Override
public List<ChatMessage> getMessages(Object memoryId) {
String value = redisTemplate.opsForValue().get("chat:" + memoryId.toString());
if(value == null || value.isEmpty()){
return List.of();
}
return ChatMessageDeserializer.messagesFromJson(value);
}
@Override
public void updateMessages(Object memoryId, List<ChatMessage> list) {
String messages = ChatMessageSerializer.messagesToJson(list);
redisTemplate.opsForValue().set("chat:" + memoryId.toString(), messages);
}
@Override
public void deleteMessages(Object memoryId) {
redisTemplate.delete("chat:" + memoryId.toString());
}
};
}
@Bean
public ChatMemoryProvider chatMemoryProvider(RedisTemplate<String,String> redisTemplate){
return memoryId -> MessageWindowChatMemory.
builder().
maxMessages(10).
id(memoryId).
chatMemoryStore(chatMemoryStore(redisTemplate)).
build();
}
}
三、创建AiService代理
AiService的具体功能,可以看官网(https://docs.langchain4j.dev/tutorials/ai-services),上面有很详细的解释和示例
java
@AiService
public interface DashScopeAssistant {
@SystemMessage("Answer using slang")
String chat(@MemoryId String chatId, @UserMessage String userMessage);
}
java
@Service
public class DashScopeChatMemoryService {
private final static Logger LOGGER = LoggerFactory.getLogger(DashScopeChatMemoryService.class);
private final DashScopeAssistant dashScopeAssistant;
@Autowired
public DashScopeChatMemoryService(QwenChatModel qwenChatModel,ChatMemoryProvider chatMemoryProvider) {
dashScopeAssistant = AiServices
.builder(DashScopeAssistant.class)
.chatMemoryProvider(chatMemoryProvider)
.chatModel(qwenChatModel)
.build();
}
public String persistentChat(String chatId, String userMessage){
String chat = dashScopeAssistant.chat(chatId, userMessage);
LOGGER.info("persistent chat output : {}" ,chat);
return chat;
}
}
四、测试持久化
java
chatMemoryService.persistentChat("101", "我是赵光义");
chatMemoryService.persistentChat("101", "我是北宋的第二位皇帝,在高粱河被辽国打败了");
chatMemoryService.persistentChat("101", "你知道为为什么叫车神吗?");
通过断点观察,数据已经成功存入redis