如何迁移到 LangGraph 内存
在 LangChain 的 v0.3 版本中,我们建议 LangChain 用户利用 LangGraph 持久化 将 memory
集成到他们的 LangChain 应用程序中。
- 依赖
RunnableWithMessageHistory
或BaseChatMessageHistory
的用户无需进行任何更改,但我们鼓励他们考虑在更复杂的用例中使用 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 开始,我们开始建议用户主要依赖 BaseChatMessageHistory。BaseChatMessageHistory
用作存储和检索对话中消息的简单持久化。
当时,编排 LangChain 链的唯一方法是通过 LCEL。为了将记忆与 LCEL
集成,用户必须使用 RunnableWithMessageHistory 接口。虽然对于基本的聊天应用程序来说足够了,但许多用户发现该 API 不直观且难以使用。
从 LangChain v0.3 开始,我们建议新代码利用 LangGraph 进行编排和持久化
- 编排:在 LangGraph 中,用户定义 图,指定应用程序的流程。这允许用户在需要
LCEL
时继续在各个节点中使用LCEL
,同时可以轻松定义更具可读性和可维护性的复杂编排逻辑。 - 持久化:用户可以依赖 LangGraph 的 持久化来存储和检索数据。LangGraph 持久化非常灵活,可以支持比
RunnableWithMessageHistory
接口更广泛的用例。
如果您一直在使用 RunnableWithMessageHistory
或 BaseChatMessageHistory
,则无需进行任何更改。我们不打算在近期弃用任何功能。此功能对于简单的聊天应用程序来说已经足够,并且任何使用 RunnableWithMessageHistory
的代码都将继续按预期工作。
迁移
这些指南假设您熟悉以下概念:
1. 管理对话历史
管理对话历史的目标是以一种最适合聊天模型使用的方式存储和检索历史。
通常,这涉及到修剪和/或总结对话历史,以保留对话中最相关的部分,同时使对话适合聊天模型的上下文窗口。
属于此类别的记忆类包括:
记忆类型 | 如何迁移 | 描述 |
---|---|---|
ConversationBufferMemory | 迁移指南链接 | 一种简单的记忆实现,仅存储对话历史。 |
ConversationStringBufferMemory | 迁移指南链接 | ConversationBufferMemory 的特例,专为 LLM 设计,现已不再相关。 |
ConversationBufferWindowMemory | 迁移指南链接 | 保留对话的最后 n 轮。当缓冲区已满时,删除最旧的一轮。 |
ConversationTokenBufferMemory | 迁移指南链接 | 仅保留对话中最近的消息,前提是对话中的令牌总数不超过某个限制。 |
ConversationSummaryMemory | 迁移指南链接 | 持续总结对话历史。每次对话轮次后都会更新摘要。该抽象返回对话历史的摘要。 |
ConversationSummaryBufferMemory | 迁移指南链接 | 在对话中提供运行摘要,并包含对话中最近的消息,前提是对话中的令牌总数不超过某个限制。 |
VectorStoreRetrieverMemory | 请参阅相关的长期记忆代理教程 | 将对话历史存储在向量存储中,并根据输入检索过去对话中最相关的部分。 |
2. 从对话历史中提取结构化信息
请参阅长期记忆代理教程,它实现了一个可以从对话历史中提取结构化信息的代理。
属于此类别的记忆类包括:
记忆类型 | 描述 |
---|---|
BaseEntityStore | 一个类似于键值存储的抽象接口。它用于存储在对话期间学习到的结构化信息。信息必须表示为键值对的字典。 |
ConversationEntityMemory | 结合了总结对话和从对话历史中提取结构化信息的能力。 |
以及抽象的特定后端实现:
记忆类型 | 描述 |
---|---|
InMemoryEntityStore | BaseEntityStore 的一个实现,将信息存储在计算机的实际内存 (RAM) 中。 |
RedisEntityStore | BaseEntityStore 的一个特定实现,使用 Redis 作为后端。 |
SQLiteEntityStore | BaseEntityStore 的一个特定实现,使用 SQLite 作为后端。 |
UpstashRedisEntityStore | BaseEntityStore 的一个特定实现,使用 Upstash 作为后端。 |
自最初发布以来,这些抽象的开发有限。这是因为它们通常需要针对特定应用程序进行大量自定义才能有效,这使得它们不如对话历史管理抽象广泛使用。
因此,这些抽象没有迁移指南。如果您在迁移依赖这些抽象的应用程序时遇到困难,请
- 请查看此长期记忆代理教程,它应该为如何从对话历史中提取结构化信息提供一个良好的起点。
- 如果您仍然遇到困难,请在 LangChain GitHub 存储库上打开一个 issue,解释您的用例,我们将尝试提供更多关于如何迁移这些抽象的指导。
从对话历史中提取结构化信息的通用策略是使用具有工具调用功能的聊天模型从对话历史中提取结构化信息。然后,可以将提取的信息保存到适当的数据结构(例如,字典)中,并且可以根据需要检索其中的信息并将其添加到提示中。
3. 在一个或多个记忆实现之上提供复合逻辑的实现
属于此类别的记忆类包括:
记忆类型 | 描述 |
---|---|
CombinedMemory | 此抽象接受 BaseMemory 列表,并根据输入从每个列表中获取相关的记忆信息。 |
SimpleMemory | 用于添加只读的硬编码上下文。用户可以直接将此信息写入提示中。 |
ReadOnlySharedMemory | 提供现有 BaseMemory 实现的只读视图。 |
这些实现似乎没有被广泛使用或提供显著的价值。用户应该能够在自定义代码中轻松地重新实现这些。
相关资源
使用 LangGraph 探索持久化
使用简单的 LCEL 添加持久化(对于更复杂的使用案例,倾向于使用 LangGraph)
处理消息历史