Langchain4j-2-ChatMemory

参考文档:聊天记忆

聊天记忆含义

LangChain4j 提供的聊天记忆的抽象容器,用于简化手动维护和管理聊天消息的繁琐工作。

记忆 vs 历史的区别
- 历史:保持用户和AI之间所有消息的完整记录,是用户在UI中看到的实际对话内容
- 记忆:保存部分信息呈现给LLM,使其表现得"记住"对话,可以通过淘汰、总结、修改消息等方式处理历史

主要功能特性

  • 淘汰策略:自动管理消息数量以适应LLM上下文窗口限制
    • MessageWindowChatMemory(消息计数):保留最近的N条消息
    • TokenWindowChatMemoryTokenizer 计数):保留最近的N个 Token
  • 持久化支持:可将聊天消息存储到持久化存储(ChatMemoryStore)中
  • SystemMessage特殊处理:系统消息的专门管理机制
  • 工具消息特殊处理:避免孤立工具执行结果消息导致的问题

代码示例

在创建 AiService 时,再添加一个 chatMemoryProvider 即可。

// LLMConfig.java
// MessageWindowChatMemory示例
@Bean(name = "chatMessageWindowChatMemory")  
public ChatMemoryAssistant chatMessageWindowChatMemory(ChatModel chatModel)  
{  
  
    return AiServices.builder(ChatMemoryAssistant.class)  
            .chatModel(chatModel)  
            //按照memoryId对应创建了一个chatMemory  
            .chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(100))  
            .build();  
}  
  
// TokenWindowChatMemory示例(需要Tokenizer计数)
@Bean(name = "chatTokenWindowChatMemory")  
public ChatMemoryAssistant chatTokenWindowChatMemory(ChatModel chatModel)  
{
    TokenCountEstimator openAiTokenCountEstimator = new OpenAiTokenCountEstimator("gpt-4");  
  
    return AiServices.builder(ChatMemoryAssistant.class)  
            .chatModel(chatModel)  
            .chatMemoryProvider(memoryId -> TokenWindowChatMemory.withMaxTokens(1000,openAiTokenCountEstimator))  
            .build();  
}

聊天记忆持久化

用 redis 为例。

  1. 实现 ChatMemoryStore 接口。注意需要用 messagesToJsonmessagesToJson 进行序列化和反序列化。
// RedisChatMemoryStore.java
@Component
public class RedisChatMemoryStore implements ChatMemoryStore
{
    public static final String CHAT_MEMORY_PREFIX = "CHAT_MEMORY:";

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    @Override
    public List<ChatMessage> getMessages(Object memoryId)
    {
        String retValue = redisTemplate.opsForValue().get(CHAT_MEMORY_PREFIX + memoryId);

        return  ChatMessageDeserializer.messagesFromJson(retValue);
    }

    @Override
    public void updateMessages(Object memoryId, List<ChatMessage> messages)
    {
        redisTemplate.opsForValue()
                .set(CHAT_MEMORY_PREFIX + memoryId, ChatMessageSerializer.messagesToJson(messages));
    }

    @Override
    public void deleteMessages(Object memoryId)
    {
        redisTemplate.delete(CHAT_MEMORY_PREFIX + memoryId);
    }
}
  1. 创建 ChatMemoryProvider,添加 ChatMemoryStore
// LLMConfig.java
// ...
@Bean  
public ChatPersistenceAssistant chatMemoryAssistant(ChatModel chatModel)  
{  

	ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder()  
			.id(memoryId)  
			.maxMessages(1000)  
			.chatMemoryStore(redisChatMemoryStore)  
			.build();  

//        TokenCountEstimator openAiTokenCountEstimator = new OpenAiTokenCountEstimator("gpt-4");  
//        ChatMemoryProvider chatMemoryProvider1 = memoryId -> TokenWindowChatMemory.builder()  
//                .id(memoryId)  
//                .maxTokens(1000, openAiTokenCountEstimator)  
//                .chatMemoryStore(redisChatMemoryStore)  
//                .build();  

	return AiServices.builder(ChatPersistenceAssistant.class)  
			.chatModel(chatModel)  
			.chatMemoryProvider(chatMemoryProvider)  
			.build();  
}
// ...
posted @ 2025-08-17 18:03  Miaops  阅读(114)  评论(0)    收藏  举报