ChatMemory聊天记忆自定义持久化实现
本文探讨了对话系统中ChatMemory持久化的重要性及实现方案。针对默认内存实现的局限性(数据易丢失、扩展性差等),提出基于MapDB的自定义持久化方法。MapDB作为轻量级Java嵌入式数据库,具有高性能、ACID事务支持等特点。文章详细介绍了实现流程:1) 创建PersistentChatMemoryStore类实现数据持久存储;2) 配置StreamingChatLanguageModel
在现代对话系统和聊天机器人应用中,保持连贯的对话记忆至关重要。ChatMemory 作为对话系统的记忆核心,负责维护和检索历史对话信息。然而,默认的内存实现往往无法满足生产环境的需求,特别是在持久化、扩展性和性能方面。本文将深入探讨如何实现 ChatMemory 的自定义持久化方案。
什么是 ChatMemory?
ChatMemory 是对话系统中的关键组件,它承担着以下职责:
-
存储对话历史和上下文信息
-
维护用户偏好和个性化设置
-
跟踪对话状态和流程
-
支持长期记忆和短期记忆的分离
为什么需要自定义持久化?
默认实现的局限性
大多数对话框架提供的默认内存实现存在以下问题:
-
内存限制:基于 RAM 的存储,重启后数据丢失
-
扩展性差:单机存储,无法分布式部署
-
性能瓶颈:大量对话数据时响应变慢
-
缺乏备份:数据丢失风险高
自定义持久化的优势
-
数据持久性:确保对话历史不丢失
-
可扩展性:支持水平扩展
-
性能优化:根据业务需求定制存储策略
-
数据安全:完善的备份和恢复机制
本文将基于 MapDB 的 ChatMemory 聊天记忆持久化实现
MapDB简介
MapDB是一个轻量级的Java嵌入式数据库引擎,它支持在JVM中直接运行,无需外部服务器。MapDB提供了基于磁盘或堆外存储的并发的Maps、Sets、Lists、Queues等数据结构,使得开发者可以像使用Java集合一样轻松地使用MapDB。此外,MapDB还支持ACID事务、MVCC(多版本并发控制)等特性,确保数据的完整性和一致性。
MapDB的特点
高性能:MapDB经过优化和重写,性能出色,可以在多核环境中实现线性扩展。
轻量级:MapDB的jar包体积较小,且没有其他依赖项,非常适合嵌入式系统或内存数据库的应用场景。
易用性:MapDB提供了基于Java集合的API,使得开发者可以轻松地进行数据存储和检索操作。
ACID事务支持:MapDB支持ACID事务,确保数据的一致性和隔离性。
模块化设计:MapDB采用模块化的架构设计,易于扩展和定制。
如何引入 MapDB
要开始使用 MapDB,首先需要将其添加到你的项目中。如果你使用的是 Maven,可以在项目的 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
<version>3.0.9</version>
</dependency>
实现自定义的聊天记忆存储器
package com.springai.config;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import java.util.List;
import java.util.Map;
import static dev.langchain4j.data.message.ChatMessageDeserializer.messagesFromJson;
import static dev.langchain4j.data.message.ChatMessageSerializer.messageToJson;
import static dev.langchain4j.data.message.ChatMessageSerializer.messagesToJson;
import static org.mapdb.Serializer.INTEGER;
import static org.mapdb.Serializer.STRING;
/**
* 自定义的持久化聊天存储器
*/
public class PersistentChatMemoryStore implements ChatMemoryStore {
// 创建一个MapDB数据库实例
private final DB db = DBMaker.fileDB("./chat-memory1.db").transactionEnable().make();
// 创建一个MapDB的HashMap,用于存储聊天消息
private final Map<Integer, String> map = db.hashMap("messages", INTEGER, STRING).createOrOpen();
// 根据指定的 memoryId 从存储中获取对应的聊天消息
//返回指定记忆ID对应的聊天消息列表
public List<ChatMessage> getMessages(Object memoryId) {
String json = map.get((Integer) memoryId);
return messagesFromJson(json);
}
// 更新指定memoryId的聊天消息
public void updateMessages(Object memoryId, List<ChatMessage> messages) {
// 将聊天消息列表转换为JSON字符串
String json = messagesToJson(messages);
// 将JSON字符串存储到指定的memoryId对应的键中
map.put((Integer) memoryId, json);
//通过 db.commit() 确保数据被写入磁盘,实现持久化存储
db.commit();
}
// 从存储中移除指定 memoryId 对应的所有聊天消息
public void deleteMessages(Object memoryId) {
map.remove((int) memoryId);
db.commit();
}
}
模型创建并实现记忆持久化
service接口
package com.springai.service;
import dev.langchain4j.service.MemoryId;
import dev.langchain4j.service.UserMessage;
import reactor.core.publisher.Flux;
public interface ChatAssistant {
/*
* @Param userId 用户id
* @Param message 用户消息
* */
Flux<String> chat(@MemoryId Integer userId, @UserMessage String message);
}
配置类实现模型信息
package com.springai.config;
import com.springai.config.PersistentChatMemoryStore;
import com.springai.service.ChatAssistant;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class LLMConfig {
// 创建一个流式模型
@Bean
public StreamingChatLanguageModel streamingChatLanguageModel() {
return OpenAiStreamingChatModel.builder()
.apiKey("sk-3dbcd881d8db42ddb24e1b095539f72e")
.modelName("qwen-max")
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.logRequests(true)
.logResponses(true)
.build();
}
//创建一个持久化聊天存储器容器
@Bean
public ChatMemoryStore chatMemoryStore() {
return new PersistentChatMemoryStore();
}
//创建一个聊天存储器提供者
@Bean
public ChatMemoryProvider chatMemoryProvider(ChatMemoryStore chatMemoryStore) {
return memoryId -> MessageWindowChatMemory.builder()
.id(memoryId)
.maxMessages(10)
.chatMemoryStore(chatMemoryStore)
.build();
}
//创建一个聊天助手
@Bean
public ChatAssistant chatAssistant(StreamingChatLanguageModel streamingChatLanguageModel,
ChatMemoryProvider chatMemoryProvider) {
return AiServices.builder(ChatAssistant.class)
// 使用注入的流式模型
.streamingChatLanguageModel(streamingChatLanguageModel)
// 使用注入的 chatMemoryProvider
.chatMemoryProvider(chatMemoryProvider)
.build();
}
}
接口实现
package com.springai.controller;
import com.springai.service.ChatAssistant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController
public class ChatContrnller {
@Autowired
ChatAssistant chatAssistant;
@GetMapping("/chat")
public Flux<String> chat(Integer userId, String message) {
Flux<String> chat = chatAssistant.chat(userId, message);
return chat;
}
}
本文使用的流式输出模型,也可以换为普通模型
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)