目录
3.ConsultantService接口方法中添加参数memoryId
一.目前存在的问题
1.先看一个现象:会话没有实现隔离
我们通过上篇文章,实现了大模型的会话记忆功能,但是目前存在如下问题:
使用浏览器A,模拟用户1,打开前端页面进行对话:

先使用微软浏览器,问大模型"姚明多高?"
再使用浏览器B,模拟用户2,打开前端页面进行对话:

可见此时,用户2问的问题"艾弗森呢?",受到了用户1刚刚问的问题影响了,知道我们问的是身高。
2.原因
因为两个浏览器都请求一个后端,而我们后端又没有对会话进行隔离,说白了两个用户的会话记录此时存到了同一个存储对象(用于让大模型实现会话记忆功能,存储会话记录的容器)中。

可见此时两个用户的会话记录确实存到一起了,我们本篇文章的目标就是将其分开,即:分别存到两个存储对象(容器)中。说白了就是用户1的会话记录存到一个容器,用户2的会话记录存到另一个容器。
二.实现会话隔离的思路
后端应该有一个大的容器(蓝色部分),用于盛放所有存储对象(可以理解为小容器,用于存储会话记录)。
当用户1发送消息"aaa"(会话id为1),先去大容器中找memoryId=1的存储对象(小容器),没找到,所以要创建一个存储对象,后续再来会话id为1的消息,会先找memoryId=1的存储对象,找到就直接往里存,而不会创建重复的存储对象,因此后续所有memoryId=1的消息都往这个存储对象中存放。
当用户2发送消息"bbb"(会话id为2),先去大容器中找memoryId=2的存储对象(小容器),没找到,所以要再创建一个存储对象,后续再来会话id为2的消息,会先找memoryId=2的存储对象,找到就直接往里存,而不会创建重复的存储对象,因此后续所有memoryId=2的消息都往这个存储对象中存放。
后续以此类推,规律很明显了,无需多言......

三.具体实现步骤
1.定义会话记忆对象提供者
还在刚才的配置类中,添加下面的代码

java
// 使用 @Bean 注解声明这是一个 Spring Bean 定义方法
// Spring 容器会自动调用此方法并将返回值注册为 Bean
@Bean
public ChatMemoryProvider chatMemoryProvider() {
// 创建 ChatMemoryProvider 接口的匿名实现类
// ChatMemoryProvider 是用于提供聊天记忆管理的工厂接口
ChatMemoryProvider chatMemoryProvider = new ChatMemoryProvider() {
// 实现 get 方法,根据 memoryId 获取对应的 ChatMemory 实例
// memoryId 通常是会话标识符(如用户ID、会话ID等)
@Override
public ChatMemory get(Object memoryId) {
// 使用 MessageWindowChatMemory 构建器模式创建聊天记忆实例
// MessageWindowChatMemory 是一种基于滑动窗口的记忆实现
// 它只保留最近的一定数量的消息,避免内存无限增长
return MessageWindowChatMemory.builder()
// 设置记忆的唯一标识符,用于区分不同会话的记忆
.id(memoryId)
// 配置最大消息保留数量,这里设置为保留最近的20条消息
// 当消息超过20条时,最旧的消息会被自动移除
.maxMessages(20)
// 完成构建并返回 ChatMemory 实例
.build();
}
};
// 返回 ChatMemoryProvider 实例,Spring 会将其纳入容器管理
return chatMemoryProvider;
}
2.配置会话记忆对象提供者
注意:该配置的值(引号里的值),就是上面配置类中的方法名。

3.ConsultantService接口方法中添加参数memoryId
注意一个小细节:当我们在service新加一个参数后,message就不是第一个参数了,因此为了让系统识别这个变量代表用户消息(用户问的具体问题),需要加上@UserMessage注解。

4.Controller中chat接口接收memoryId
在controller中,也加一个memoryId参数,代表会话id。

5.前端页面请求时传递memoryId


四.验证效果
先在浏览器A,测试一下:
可见会话记忆功能完好,没有被破坏。

再去浏览器B,测试一下:
此时大模型没有意会到我们的具体问题,因此说明会话成功被隔离,所以我们的目的达到了。

五.补充:查看生成"新的对话"的逻辑
1.查看逻辑


这就说明新的对话,是和之前的对话隔离的。
2.验证
如下图所示,可见当点击"+"以后,会生成新的会话id传到后端,也就是和之前的会话记录就不是存放到同一个存储对象了,说白了就是互相隔离了。这也印证了我们的猜想!


说白了,这里实现了两种隔离:
①不同用户的会话记忆相互隔离
②同一用户的不同轮对话(按+就会新建一轮对话)的会话记忆相互隔离
以上就是本篇文章的全部内容,喜欢的话可以留个免费的关注呦~~~