聊天信息记忆分离
现在我们再来想另一种情况: 如果不同的用户或者不同的对话肯定不能用同一个记忆,要不然对话肯定会混淆,此时就需要进行区分。
可以通过memoryId进行区分, 在AiConfig配置类中加入配置信息:
public interface AssistantUnique{
// 普通聊天方法(阻塞式,返回完整响应)
String chat(@MemoryId int memoryId,@UserMessage String message);
/**
* 流式聊天方法(实时返回token)
*
*@param memoryId 对话记忆ID(用于区分不同会话)
*@param userMessage 用户输入的消息
*@return TokenStream 流式响应对象
*/
TokenStream stream(@MemoryId int memoryId,@UserMessage String userMessage);
}
/**
* 创建AssistantUnique实例的方法
* @param chatLanguageModel 同步聊天模型(注入的依赖)
* @param streamingChatLanguageModel 流式聊天模型(注入的依赖)
* @return 配置好的AssistantUnique实例
*/
@Bean
public AssistantUnique getAssistantUnique(ChatLanguageModel chatLanguageModel,
StreamingChatLanguageModel streamingChatLanguageModel){
// 使用AiServices构建器创建接口实现
AssistantUnique assistantUnique = AiServices.builder(AssistantUnique.class)
// 设置同步聊天模型(用于chat方法)
.chatLanguageModel(chatLanguageModel)
// 设置流式聊天模型(用于stream方法)
.streamingChatLanguageModel(streamingChatLanguageModel)
// 配置对话记忆提供者(为每个memoryId创建独立的记忆窗口)
.chatMemoryProvider(memoryId->
MessageWindowChatMemory.builder().maxMessages(10) // 每个对话最多保存10条消息
.id(memoryId) // 设置记忆ID(区分不同会话)
.build())
.build();
return assistantUnique;
}
原理:
- 通过AiService创建的代理对象(AiServices.builder(Assistant.class))调用chat方法
- 代理对象会去ChatMemory中根据id去获取之前的对话记录(获取记忆)
- 将获取到的对话记录合并到当前对话中(此时大模型根据之前的聊天记录肯定就拥有了“记忆”)
- 将当前的对话内容根据id存入ChatMemory(保存记忆)
memoryId可以设置为用户Id, 或者对话Id 进行区分即可:
控制器接口实现:
@Autowired
AiConfig.AssistantUnique assistantUnique;
@RequestMapping("/memoryId_chat")
public String memoryChat(@RequestParam(defaultValue = "我是谁") String message,int userId){
return assistantUnique.chat(userId,message);
}
观察效果:
首先我们发起第一个聊天,然后告诉大模型我们是小红,并且传多一个参数userId=2
然后我们使用userId为3的情况去获取用户的信息:
再试试看使用userId为2的场景去获取这个聊天信息: