【langchain4j】会话记忆chatMemory(五)
·
用于记住用户之前的对话,保持上下文连贯。langchain4j提供了MessageWindowChatMemory来支持会话记忆。
自己实现对话消息
1.自己维护消息列表
2.用户信息隔离
3.消息过多淘汰
4.内存溢出
// 自己实现会话记忆
Map<String, List<Message>> conversationHistory = new HashMap<>();
public String chat(String message, String userId) {
// 获取用户历史记录
List<Message> history = conversationHistory.getOrDefault(userId, new ArrayList<>());
// 添加用户新消息
Message userMessage = new Message("user", message);
history.add(userMessage);
// 构建完整历史上下文
StringBuilder contextBuilder = new StringBuilder();
for (Message msg : history) {
contextBuilder.append(msg.getRole()).append(": ").append(msg.getContent()).append("\n");
}
// 调用 AI API
String response = callAiApi(contextBuilder.toString());
// 保存 AI 回复到历史
Message aiMessage = new Message("assistant", response);
history.add(aiMessage);
conversationHistory.put(userId, history);
return response;
}
MessageWindowChatMemory提供了这样一个会话记忆的功能
1.支持用户信息隔离(但需要配合memoryId)
2.支持存储最大信息条数设置
@Configuration
public class AiCodeServiceFactory {
@Resource
ChatModel qwenChatModel;
@Bean
public AiCodeService aiCodeService() {
// 每个用户保存10条消息
MessageWindowChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);
return AiServices.builder(AiCodeService.class)
.chatMemory(chatMemory)
.chatModel(qwenChatModel)
.build();
}
}

当前以上是基于缓存来存储,还有基于持久化存储的方式
持久化会话记忆
class PersistentChatMemoryStore implements ChatMemoryStore {
@Override
public List<ChatMessage> getMessages(Object memoryId) {
// TODO: Implement getting all messages from the persistent store by memory ID.
// ChatMessageDeserializer.messageFromJson(String) and
// ChatMessageDeserializer.messagesFromJson(String) helper methods can be used to
// easily deserialize chat messages from JSON.
return null;
}
@Override
public void updateMessages(Object memoryId, List<ChatMessage> messages) {
// TODO: Implement updating all messages in the persistent store by memory ID.
// ChatMessageSerializer.messageToJson(ChatMessage) and
// ChatMessageSerializer.messagesToJson(List<ChatMessage>) helper methods can be used to
// easily serialize chat messages into JSON.
}
@Override
public void deleteMessages(Object memoryId) {
// TODO: Implement deleting all messages in the persistent store by memory ID.
}
}
用户信息隔离
如果你不传 @MemoryId,MessageWindowChatMemory 根本做不到多用户隔离!它只会共用一个记忆,所有用户的聊天记录会串在一起!
MessageWindowChatMemory = 消息容器
ChatMemoryStore = 存储位置
@MemoryId = 找到对应容器的钥匙
public interface AiCodeService {
@SystemMessage(fromResource = "ai.txt")
String chatWithMemoryId(@MemoryId String memoryId, @UserMessage String userMessage);
}
@Configuration
public class AiCodeServiceFactory {
@Resource
ChatModel qwenChatModel;
@Bean
public AiCodeService aiCodeService() {
return AiServices.builder(AiCodeService.class)
.chatModel(qwenChatModel)
.chatMemoryProvider(memoryId->MessageWindowChatMemory.withMaxMessages(10))
.build();
}
}
@Test
void chatWithChatMemoryProvider() {
// 用户 1
String user1 = "user-001";
String chatUser1 = aiCodeService.chatWithMemoryId(user1, "你好,我是程序员吴彦祖");
System.out.println("user1 第一次:" + chatUser1);
String whoAmI1 = aiCodeService.chatWithMemoryId(user1, "我是谁");
System.out.println("user1 第二次:" + whoAmI1);
// 用户 2(记忆完全隔离)
String user2 = "user-002";
String chatUser2 = aiCodeService.chatWithMemoryId(user2, "你好,我是程序员彭于晏");
System.out.println("user2 第一次:" + chatUser2);
String whoAmI2 = aiCodeService.chatWithMemoryId(user2, "我是谁");
System.out.println("user2 第二次:" + whoAmI2);
}
✅ 规则
- chatMemory 和 chatMemoryProvider 绝对不能同时配置
- 配置了哪个,就用对应的调用方式
✅ 效果
-
chatMemory
- 所有对话共享同一个记忆
- 适合单用户、Demo、测试
-
chatMemoryProvider
- 每个
@MemoryId独立记忆 - 用户之间互不干扰
- 生产环境必须用这个
- 每个
LangChain4j 文档明确指出:
Either a
ChatMemoryor aChatMemoryProvidercan be configured, but not both simultaneously.
chatMemory(ChatMemory):配置单个共享记忆实例,所有用户 / 会话共用。chatMemoryProvider(ChatMemoryProvider):配置多用户隔离记忆,通过@MemoryId区分会话。
更多推荐


所有评论(0)