跳到主要内容
Open on GitHub

如何迁移到LangGraph记忆

自 LangChain v0.3 发布以来,我们建议 LangChain 用户利用 LangGraph 的持久化功能,将 memory 集成到其 LangChain 应用程序中。

  • 依赖 RunnableWithMessageHistoryBaseChatMessageHistory 的用户**不需要**进行任何更改,但我们鼓励他们在更复杂的用例中考虑使用 LangGraph。
  • 依赖 LangChain 0.0.x 中已弃用内存抽象的用户应遵循本指南,升级到 LangChain 0.3.x 中新的 LangGraph 持久化功能。

为什么使用 LangGraph 进行内存管理?

LangGraph 持久化的主要优势是

  • 内置支持多用户和多会话,这是真实世界对话式 AI 应用程序的典型要求。
  • 能够在任何时候保存和恢复复杂的会话。这有助于
    • 错误恢复
    • 允许人工干预 AI 工作流程
    • 探索不同的会话路径(“时间旅行”)
  • 与传统语言模型和现代聊天模型完全兼容。LangChain 中早期的内存实现并未针对较新的聊天模型 API 进行设计,导致了工具调用等功能的问题。LangGraph 内存可以持久化任何自定义状态。
  • 高度可定制,允许您完全控制内存的工作方式并使用不同的存储后端。

LangChain 中内存的演变

自首次发布以来,LangChain 中的内存概念已显著演变。

LangChain 0.0.x 内存

广义而言,LangChain 0.0.x 内存主要用于处理三种用例

用例示例
管理会话历史仅保留用户和 AI 之间会话的最后 n 轮。
提取结构化信息从会话历史中提取结构化信息,例如关于用户学习到的事实列表。
复合内存实现结合多个内存源,例如,关于用户的已知事实列表以及在给定会话中学习到的事实。

尽管 LangChain 0.0.x 内存抽象很有用,但它们的功能有限,不适用于真实世界的对话式 AI 应用程序。这些内存抽象缺乏对多用户、多会话场景的内置支持,而这些场景对于实用的对话式 AI 系统至关重要。

这些实现中的大多数已在 LangChain 0.3.x 中正式弃用,取而代之的是 LangGraph 持久化。

RunnableWithMessageHistory 和 BaseChatMessageHistory

注意

如果您想在 LangGraph 中使用 BaseChatMessageHistory(无论是否与 RunnableWithMessageHistory 结合),请参阅 如何在 LangGraph 中使用 BaseChatMessageHistory

自 LangChain v0.1 起,我们开始建议用户主要依赖 BaseChatMessageHistoryBaseChatMessageHistory 作为一种简单的持久化机制,用于存储和检索会话中的消息。

当时,编排 LangChain 链的唯一选择是通过 LCEL。为了将内存与 LCEL 集成,用户必须使用 RunnableWithMessageHistory 接口。虽然这对于基本的聊天应用程序来说已经足够,但许多用户发现该 API 不直观且难以使用。

自 LangChain v0.3 起,我们建议**新**代码利用 LangGraph 进行编排和持久化

  • 编排:在 LangGraph 中,用户定义来指定应用程序的流程。这使得用户在需要 LCEL 时可以在各个节点内继续使用 LCEL,同时更容易定义更具可读性和可维护性的复杂编排逻辑。
  • 持久化:用户可以依赖 LangGraph 的持久化功能来存储和检索数据。LangGraph 持久化功能非常灵活,可以支持比 RunnableWithMessageHistory 接口更广泛的用例。
重要

如果您一直在使用 RunnableWithMessageHistoryBaseChatMessageHistory,则无需进行任何更改。我们不打算在近期弃用这两种功能。此功能对于简单的聊天应用程序来说已足够,并且任何使用 RunnableWithMessageHistory 的代码都将继续按预期工作。

迁移

先决条件

这些指南假定您对以下概念有所了解

1. 管理会话历史

管理会话历史的目标是以最适合聊天模型使用的方式存储和检索历史。

这通常涉及修剪和/或总结会话历史,以保留会话中最相关的部分,同时将会话适配到聊天模型的上下文窗口内。

属于此类的内存类包括

内存类型如何迁移描述
ConversationBufferMemory迁移指南链接一个基本的内存实现,它简单地存储会话历史。
ConversationStringBufferMemory迁移指南链接ConversationBufferMemory 的一个特例,专为 LLM 设计,现已不再相关。
ConversationBufferWindowMemory迁移指南链接保留会话的最后 n 轮。当缓冲区满时,丢弃最旧的一轮。
ConversationTokenBufferMemory迁移指南链接在会话总 token 数不超过特定限制的约束下,仅保留会话中最新的消息。
ConversationSummaryMemory迁移指南链接持续总结会话历史。摘要在每次会话轮次后更新。该抽象返回会话历史的摘要。
ConversationSummaryBufferMemory迁移指南链接提供会话的运行摘要以及会话中最新的消息,同时受限于会话的总 token 数不超过特定限制。
VectorStoreRetrieverMemory参见相关的长期记忆代理教程将会话历史存储在向量存储中,并根据输入检索过去会话中最相关的部分。

2. 从会话历史中提取结构化信息

请参阅长期记忆代理教程,该教程实现了一个可以从会话历史中提取结构化信息的代理。

属于此类的内存类包括

内存类型描述
BaseEntityStore一个类似于键值存储的抽象接口。它用于存储在会话中学习到的结构化信息。这些信息必须表示为键值对的字典。
ConversationEntityMemory结合了总结会话的能力,同时从会话历史中提取结构化信息。

以及特定后端抽象实现

内存类型描述
InMemoryEntityStoreBaseEntityStore 的一个实现,它将信息存储在计算机的实际内存(RAM)中。
RedisEntityStoreBaseEntityStore 的一个特定实现,它使用 Redis 作为后端。
SQLiteEntityStoreBaseEntityStore 的一个特定实现,它使用 SQLite 作为后端。
UpstashRedisEntityStoreBaseEntityStore 的一个特定实现,它使用 Upstash 作为后端。

这些抽象自首次发布以来开发有限。这是因为它们通常需要针对特定应用程序进行大量定制才能有效,因此它们的使用范围不如会话历史管理抽象广泛。

因此,这些抽象没有迁移指南。如果您在迁移依赖这些抽象的应用程序时遇到困难,请

  1. 请查阅此长期记忆代理教程,它应该为您如何从会话历史中提取结构化信息提供一个很好的起点。
  2. 如果您仍然遇到困难,请在 LangChain GitHub 仓库上提出一个问题,说明您的用例,我们将尽力提供更多关于如何迁移这些抽象的指导。

从会话历史中提取结构化信息的通用策略是使用具有工具调用能力的聊天模型来提取会话历史中的结构化信息。然后,提取的信息可以保存到适当的数据结构中(例如,字典),并根据需要从中检索信息并添加到提示中。

3. 在一个或多个内存实现之上提供复合逻辑的实现

属于此类的内存类包括

内存类型描述
CombinedMemory此抽象接受 BaseMemory 列表,并根据输入从每个内存中获取相关内存信息。
SimpleMemory用于添加只读的硬编码上下文。用户可以直接将这些信息写入提示中。
ReadOnlySharedMemory提供了现有 BaseMemory 实现的只读视图。

这些实现似乎并未被广泛使用,也未提供显著价值。用户应该能够在自定义代码中不费太多力气地重新实现它们。

探索 LangGraph 的持久性

使用简单 LCEL 添加持久性(对于更复杂的用例,推荐使用 LangGraph)

使用消息历史记录