LangChain4j -- ChatMemory

ChatMemory 和持久化存储

管理并手动维护ChatMessages

管理和手动维护ChatMessages是繁琐的工作,因此LangChain4j提供了一个名为ChatMemory的抽象层,以及多个开箱即用的实现。ChatMemory可以用作独立的底层组件,也可以作为高层次组件如AI服务的一部分使用。

ChatMemory的主要功能

  • 驱逐策略:为了适应LLM的上下文窗口限制、控制成本和延迟。
  • 持久化:支持将聊天记录保存到持久化存储中。
  • 对SystemMessage的特殊处理:确保系统消息被正确处理。
  • 对工具消息的特殊处理:避免发送孤立的执行结果消息。

记忆 vs 历史

“记忆”与“历史”虽然相似但在概念上有所不同:

  • 历史保持用户与AI之间的所有消息不变。它代表了实际所说的话。
  • 记忆则保存一些信息,使LLM表现得像它记住了对话一样。它可以以各种方式修改历史,例如驱逐某些消息或删除不重要的细节。

目前,LangChain4j仅提供“记忆”,并不提供“历史”。如果需要保留完整的历史记录,请手动进行。

驱逐策略

需要驱逐策略的原因

  1. 适应LLM的上下文窗口限制:存在LLM一次能处理的token数量上限。
  2. 控制成本:每个token都有成本,减少不必要的token可以降低成本。
  3. 控制延迟:发送到LLM的token越多,处理所需的时间就越长。

LangChain4j提供的两种实现

  • MessageWindowChatMemory:类似于滑动窗口,保留最近的N条消息。主要用于快速原型设计。
  • TokenWindowChatMemory:专注于保留最近的N个tokens,必要时驱逐较旧的消息。需要一个Tokenizer来计算每个ChatMessage中的tokens。

持久化

默认情况下,ChatMemory实现将ChatMessages存储在内存中。如果需要持久化,可以实现自定义的ChatMemoryStore来将ChatMessages存储在任何你选择的持久化存储中。

示例代码

class PersistentChatMemoryStore implements ChatMemoryStore {
    @Override
    public List<ChatMessage> getMessages(Object memoryId) {
        // 实现从持久化存储中通过memoryId获取所有消息的方法。
    }

    @Override
    public void updateMessages(Object memoryId, List<ChatMessage> messages) {
        // 实现更新持久化存储中所有消息的方法,通过memoryId。
    }

    @Override
    public void deleteMessages(Object memoryId) {
        // 实现通过memoryId从持久化存储中删除所有消息的方法。
    }
}

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .id("12345")
    .maxMessages(10)
    .chatMemoryStore(new PersistentChatMemoryStore())
    .build();

你可能感兴趣的:(java,ai)