langchain4j-5 (Chat Memory 聊天记忆)

Chat Memory

手动维护和管理 ChatMessage 很麻烦。因此,LangChain4j 提供了一个 ChatMemory 抽象以及多个开箱即用的实现。
ChatMemory 可以用作独立的低级组件,也可以用作高级组件(如 AI 服务 )的一部分。
ChatMemory 充当 ChatMessage 的容器(由 List 支持),具有其他功能,例如:

  • Eviction policy 驱逐策略
  • Persistence 坚持
  • Special treatment of SystemMessage 系统消息的特殊处理
  • Special treatment of tool messages 工具消息的特殊处理

Memory vs History 内存与历史

请注意,“记忆”和“历史”是相似但不同的概念。

  • 历史记录使用户和 AI 之间的所有消息保持不变 。历史记录是用户在 UI 中看到的内容。它代表了实际所说的内容。
  • Memory 保留了一些信息 ,这些信息被呈现给 ,LLM 使其表现得好像它 “记住” 了对话一样。记忆与历史完全不同。根据所使用的内存算法,它可以以各种方式修改历史记录:驱逐一些消息、汇总多条消息、汇总单独的消息、从消息中删除不重要的细节、将额外信息(例如,用于 RAG)或指令(例如,用于结构化输出)注入消息,等等。

LangChain4j 目前只提供 “memory”,不提供 “history”。如果您需要保留整个历史记录,请手动执行此作。

Eviction policy 驱逐策略

驱逐策略是必要的,原因如下:

  • 以适应 LLM 的上下文窗口。一次可以处理的代币LLM数量有上限。在某些时候,对话可能会超过此限制。在这种情况下,应逐出某些消息。通常,最旧的消息会被逐出,但如果需要,可以实现更复杂的算法。
  • 为了控制成本。每个令牌都有成本,每次调用都会LLM逐渐增加成本。驱逐不必要的消息可以降低成本。
  • 控制延迟。发送到 的LLM令牌越多,处理它们所需的时间就越多。

目前,LangChain4j 提供了 2 种开箱即用的实现:

  • 更简单的 MessageWindowChatMemory 充当滑动窗口,保留 N 条最近的消息并驱逐不再适合的旧消息。 但是,由于每条消息可以包含不同数量的令牌, MessageWindowChatMemory 对于快速原型设计非常有用。
  • 更复杂的选项是 TokenWindowChatMemory,它也作为滑动窗口运行,但专注于保留 N 个最新的令牌 。 根据需要驱逐较旧的消息。 信息是不可分割的。如果消息不合适,则会将其完全逐出。 TokenWindowChatMemory 需要 Tokenizer 对每个 ChatMessage 中的令牌进行计数。

Persistence 坚持

默认情况下,ChatMemory 实现将 ChatMessage 存储在内存中。
如果需要持久性,则可以实现自定义 ChatMemoryStore 以将 ChatMessage 存储在您选择的任何持久性存储中:

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.
        }

        @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:实现通过内存 ID 删除持久存储中的所有消息。
        }
    }

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

每次将新的 ChatMessage 添加到 ChatMemory 时,都会调用 updateMessages() 方法。在与 LLM: 的每次交互期间,这通常发生两次,一次是在添加新的 UserMessage 时,另一次是在添加新的 AiMessage 时。updateMessages() 方法应更新与给定内存 ID 关联的所有消息。 ChatMessage 可以单独存储(例如,每条消息一条记录/行/对象),也可以一起存储(例如,整个 ChatMemory 的一条记录/行/对象)。

注意:请注意,从 ChatMemory 中逐出的消息也将从 ChatMemoryStore 中逐出。当消息被逐出时,将调用 updateMessages() 方法,其中包含不包含被逐出消息的消息列表。

每当 ChatMemory 的用户请求所有消息时,都会调用 getMessages() 方法。这通常在每次与 LLM.Object memoryId 参数的值对应于在创建 ChatMemory 期间指定的 ID。它可用于区分多个用户和/或对话。getMessages() 方法应返回与给定内存 ID 关联的所有消息。

每当调用 ChatMemory.clear() 时,都会调用 deleteMessages() 方法。如果不使用此功能,可以将此方法留空。

Special treatment of SystemMessage 系统消息的特殊处理

SystemMessage 是一种特殊类型的消息,因此它的处理方式与其他消息类型不同:

  • 添加后,将始终保留 SystemMessage。
  • 一次只能保留一个 SystemMessage。
  • 如果添加了具有相同内容的新 SystemMessage,则会忽略该 SystemMessage。
  • 如果添加了具有不同内容的新 SystemMessage,它将替换前一个 SystemMessage。

Special treatment of tool messages 工具消息的特殊处理

如果包含 ToolExecutionRequest 的 AiMessage 被逐出,则以下孤立的 ToolExecutionResultMessage 也会自动被逐出,以避免某些LLM提供程序(如 OpenAI)出现问题,这些提供程序禁止在请求中发送孤立的 ToolExecutionResultMessage。

Examples 例子

  • 使用 AiServices:
    • 聊天记忆:https://github.com/langchain4j/langchain4j-examples/blob/main/other-examples/src/main/java/ServiceWithMemoryExample.java
    • 为每个用户单独聊天:https://github.com/langchain4j/langchain4j-examples/blob/main/other-examples/src/main/java/ServiceWithMemoryForEachUserExample.java
    • 持久聊天记忆:https://github.com/langchain4j/langchain4j-examples/blob/main/other-examples/src/main/java/ServiceWithPersistentMemoryExample.java
    • 每个用户的持久聊天内存:https://github.com/langchain4j/langchain4j-examples/blob/main/other-examples/src/main/java/ServiceWithPersistentMemoryForEachUserExample.java
  • 使用旧版 Chains (PASS)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值