【AI】持久化聊天记忆(隔离对话)
当我们需要模型支持上下文对话时,就必须要有对应的聊天记忆来进行支撑,对此,我们可以将每次用户的提问和AI的回复存储在一个存储介质中,这个存储介质可以是MySQL、Redis等各种存储媒介,而我们这里使用的是MongoDB来进行存储,测试结果显示不同memoryId能正确区分上下文,数据成功持久化到MongoDB中。这种方法有效解决了多会话场景下的上下文混淆问题。
【AI】持久化聊天记忆(隔离对话)
文章目录
引子
当我们需要模型支持上下文对话时,就必须要有对应的聊天记忆来进行支撑,对此,我们可以 将每次用户的提问和AI的回复存储在一个存储介质中,这个存储介质可以是MySQL、Redis等各种存储媒介,而我们这里使用的是MongoDB来进行存储,MongoDB具体安装方式请自行搜索安装(官网链接)
同时安装好可视化界面Compass并完成连接,效果如下:

完成上述步骤后,接下来就可以通过代码来完成聊天记忆的保存了。
1. 引入MongoDB
我们需要先将mongodb引入到项目中:
1.1 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
1.2 配置远程连接
# 若库不存在后续在完成连接后也能自动创建
spring.data.mongodb.uri=mongodb://localhost:27017/chat_memory_test_db
2. 代码编写
2.1 创建实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document("chat_messages") // 文档名称,如果mongodb没有这个文档将会自动创建
public class ChatMessages {
// 唯一标识,映射到 MongoDB 文档的 _id 字段
@Id
private ObjectId messageId;
// 用来区分每个记忆,后续的操作都是通过操控memoryId来进行当前记忆的增删改查的
private String memoryId;
// 存储当前聊天记录列表的json字符串
private String content;
}
注:如果想要根据用户来区分对话,可以自行添加上userId属性,并修改持久化类
2.2 创建持久化类
通过这个持久化类,我们能够对聊天记忆进行对应的crud:
@Component
public class MongoChatMemoryStore implements ChatMemoryStore {
@Autowired
private MongoTemplate mongoTemplate;
@Override
public List<ChatMessage> getMessages(Object memoryId) {
Criteria criteria = Criteria.where("memoryId").is(memoryId);
Query query = new Query(criteria);
ChatMessages chatMessages = mongoTemplate.findOne(query, ChatMessages.class);
if(chatMessages == null)
return new LinkedList<>();
return ChatMessageDeserializer.messagesFromJson(chatMessages.getContent());
}
@Override
public void updateMessages(Object memoryId, List<ChatMessage> messages) {
Criteria criteria = Criteria.where("memoryId").is(memoryId);
Query query = new Query(criteria);
Update update = new Update();
update.set("content", ChatMessageSerializer.messagesToJson(messages));
//根据query条件能查询出文档,则修改文档;否则新增文档
mongoTemplate.upsert(query, update, ChatMessages.class) ;
}
@Override
public void deleteMessages(Object memoryId) {
Criteria criteria = Criteria.where("memoryId").is(memoryId);
Query query = new Query(criteria) ;
mongoTemplate.remove(query, ChatMessages.class);
}
}
2.3 创建持久化配置
@Configuration
public class SeparateChatAssistantConfig {
@Autowired
private MongoChatMemoryStore mongoChatMemoryStore;
@Bean // 将这个方法加入IOC容器
ChatMemoryProvider chatMemoryProvider() {
return memoryId -> MessageWindowChatMemory.builder()
.id(memoryId)
.maxMessages(10) // 限制最大的记忆存储数
.chatMemoryStore(mongoChatMemoryStore) // 指定持久化类(存储介质)
.build();
}
}
2.4 注入配置
使用@AiService注解中的chatMemoryProvider属性将持久化配置引入到对话中,这样我们只需进行对话就能自动完成持久化配置的调用了:
@AiService(
wiringMode = EXPLICIT ,
chatModel = "qwenChatModel",
chatMemoryProvider = "chatMemoryProvider")
public interface SeparateChatAssistant {
/**
* 分离聊天记录
* @param memoryId 聊天id
* @param userMessage 用户消息
* @return
*/
String chat(@MemoryId int memoryId, @UserMessage String userMessage);
}
注:当AIService由多个组件如大模型、聊天记忆等组成的时候,我们就可以称它为 智能体 了
2.5 测试代码
@SpringBootTest
public class ChatMemoryTest {
@Autowired
private SeparateChatAssistant separateChatAssistant;
@Test
public void testChatMemory() {
//调用service的接口
String answer1 = separateChatAssistant.chat(1, "我是Gray");
System.out.println(answer1);
String answer2 = separateChatAssistant.chat(1, "我是谁");
System.out.println(answer2);
String answer3 = separateChatAssistant.chat(2, "我是谁");
System.out.println(answer3);
}
}
这里我们通过传入不同的memoryId来区分不同的聊天记忆,这样ai在获取上下文内容的时候就不会冲突调用了,执行结果如下:

可以看到不同的memoryId会有不同的记忆组区分,同时从mongodb中存储的内容也能直接看出区别:


可以看到,memoryId为1的内容与我们设置需要存储的内容一致,这样我们持久化聊天记忆就能实现隔离对话了!!
以上便是对持久化聊天记忆(隔离对话)的介绍与使用了,如果上述内容对大家有帮助的话请给一个三连关注吧💕( •̀ ω •́ )✧✨
更多推荐


所有评论(0)