用于记住用户之前的对话,保持上下文连贯。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 绝对不能同时配置
  • 配置了哪个,就用对应的调用方式

✅ 效果

  1. chatMemory

    • 所有对话共享同一个记忆
    • 适合单用户、Demo、测试
  2. chatMemoryProvider

    • 每个 @MemoryId 独立记忆
    • 用户之间互不干扰
    • 生产环境必须用这个

LangChain4j 文档明确指出:

Either a ChatMemory or a ChatMemoryProvider can be configured, but not both simultaneously.

  • chatMemory(ChatMemory):配置单个共享记忆实例,所有用户 / 会话共用。
  • chatMemoryProvider(ChatMemoryProvider):配置多用户隔离记忆,通过 @MemoryId 区分会话。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐