《LangChain 中对话记忆机制总结》
一、引言
在构建聊天机器人时,记忆机制非常重要。默认情况下,无论是大语言模型(LLM)还是代理都是无状态的,每次模型的调用都是独立的。ChatGPT 能够记得之前说过的话,是因为它使用了记忆机制,记录了之前的对话上下文,并将其作为提示的一部分在最新的调用中传递给模型。
二、四种记忆机制介绍
| 记忆机制 | 优势 | 劣势 |
|---|---|---|
| ConversationBufferMemory | 简单直接存储所有内容,为 LLM 提供最大量信息 | 新输入包含更多 Token,响应时间变慢且成本更高;当达到 LLM 的令牌数限制时,太长的对话无法被记住 |
| ConversationBufferWindowMemory | 擅长限制使用的 Token 数量,适合只需要记住最近互动的场景 | 会完全遗忘掉k轮之前的对话内容,对于某些场景不是最佳选择 |
| ConversationSummaryMemory | 对于长对话可以减少使用的 Token 数量,记录更多轮的对话信息,直观易懂 | 对于较短的对话可能会导致更高的 Token 使用;对话历史的记忆完全依赖于中间汇总 LLM 的能力,增加了成本,且并不限制对话长度 |
| ConversationSummaryBufferMemory | 可以回忆起较早的互动,有缓冲区确保不会错过最近的互动信息;在节省 Token 数量方面具有竞争力 | 对于较短的对话会增加 Token 数量 |
(一)ConversationChain
-
特点:提供了包含 AI 前缀和人类前缀的对话摘要格式,与记忆机制结合紧密。
-
提示模板参数:
{history}:存储会话记忆,即人类和人工智能之间对话历史的信息。{input}:新输入的地方,可看成是和 ChatGPT 对话时文本框中的输入。
-
记忆原理:有了
{history}参数以及 Human 和 AI 这两个前缀,能够把历史对话信息存储在提示模板中,并作为新的提示内容在新一轮对话中传递给模型。
(二)ConversationBufferMemory(缓冲记忆)
-
实现方式:通过 LangChain 中的 ConversationBufferMemory 实现最简单的记忆机制。
-
示例:
-
第一天的对话:
- 回合 1:用户输入 “我姐姐明天要过生日,我需要一束生日花束。”,模型输出推荐花束的话语,并存储对话历史。
- 回合 2:用户输入 “她喜欢粉色玫瑰,颜色是粉色的。”,模型输出关于粉色玫瑰花束的问题,并存储对话历史。
-
-
优势:简单直接地存储所有内容,为 LLM 提供最大量的信息。
-
劣势:新输入中包含更多 Token,响应时间变慢且成本更高;当达到 LLM 的令牌数(上下文窗口)限制时,太长的对话无法被记住。
(三)ConversationBufferWindowMemory(缓冲窗口记忆)
-
思路:只保存最新最近的几次人类和 AI 的互动,在 “缓冲记忆” 基础上增加了一个窗口值
k,只保留一定数量的过去互动,“忘记” 之前的互动。 -
示例:
-
设置
k = 1,意味着窗口只会记住与 AI 之间的最新的互动。 -
第一天的对话:
- 回合 1:用户输入 “我姐姐明天要过生日,我需要一束生日花束。”,模型输出推荐花束的话语。
- 回合 2:用户输入 “她喜欢粉色玫瑰,颜色是粉色的。”,模型输出关于粉色玫瑰花束的问题。
-
第二天的对话:
- 回合 3:用户输入 “我又来了,还记得我昨天为什么要来买花吗?”,由于只保留了最近的互动(
k = 1),模型忘记了正确答案,只能模糊回答。
- 回合 3:用户输入 “我又来了,还记得我昨天为什么要来买花吗?”,由于只保留了最近的互动(
-
-
优势:擅长限制使用的 Token 数量,适合只需要记住最近互动的场景。
(四)ConversationSummaryMemory(对话总结记忆)
-
核心特点:
- 汇总对话:每次新的互动发生时对对话历史进行汇总,然后将其添加到之前所有互动的 “运行汇总” 中。
- 使用 LLM 进行汇总:该汇总功能由另一个 LLM 驱动,对话的汇总实际上是由 AI 自己进行的。
- 适合长对话:对于长对话优势明显,虽然最初使用的 Token 数量较多,但随着对话的进展,汇总方法的增长速度会减慢。
-
示例:
-
第一天的对话:
- 回合 1:用户输入 “我姐姐明天要过生日,我需要一束生日花束。”,模型输出建议并提供一些花束的选择。
- 回合 2:用户输入 “她喜欢粉色玫瑰,颜色是粉色的。”,模型输出为用户姐姐准备花束的建议。
-
第二天的对话:
- 回合 3:用户输入 “我又来了,还记得我昨天为什么要来买花吗?”,模型根据汇总的历史信息回答出用户昨天买花是为了给姐姐作为生日礼物。
-
-
优势:对于长对话,可以减少使用的 Token 数量,记录更多轮的对话信息,直观易懂。
-
劣势:对于较短的对话,可能会导致更高的 Token 使用;对话历史的记忆完全依赖于中间汇总 LLM 的能力,增加了成本,且并不限制对话长度。
(五)ConversationSummaryBufferMemory(对话总结缓冲记忆)
-
实现方式:结合了 ConversationSummaryMemory 和 ConversationBufferWindowMemory 的特点,通过
max_token_limit这个参数做到在对话中总结早期的互动,同时尽量保留最近互动中的原始内容。 -
示例:
-
第一天的对话:
- 回合 1:用户输入 “我姐姐明天要过生日,我需要一束生日花束。”,模型输出建议并提供一些花束的选择。
- 回合 2:用户输入 “她喜欢粉色玫瑰,颜色是粉色的。”,模型输出关于粉色玫瑰花束的建议。
-
第二天的对话:
- 回合 3:用户输入 “我又来了,还记得我昨天为什么要来买花吗?”,模型根据总结的早期对话和保留的最近互动信息回答出用户昨天买花是为了给姐姐的生日。
-
-
优势:通过总结可以回忆起较早的互动,有缓冲区确保不会错过最近的互动信息;在节省 Token 数量方面具有竞争力。
-
劣势:对于较短的对话,也会增加 Token 数量。
总结
选择记忆机制时,需要根据具体的应用场景和需求来进行权衡。如果需要简单直接的存储所有内容且不担心 Token 数量和响应时间,可以选择ConversationBufferMemory;如果只需要记住最近的互动,可以选择 ConversationBufferWindowMemory;如果预期会有多轮的、长时间对话,可以选择 ConversationSummaryMemory或ConversationSummaryBufferMemory