一、引言
在默认情况下,无论是LLM(大语言模型)还是代理都是无状态的,每次模型的调用都是独立于其他交互的。然而,ChatGPT等聊天机器人能够记得之前的对话内容,这得益于其使用的记忆(Memory)机制。本文将介绍LangChain中几种不同的记忆机制,并探讨它们在实际应用中的效果。
二、ConversationChain
ConversationChain是LangChain中用于管理对话记忆的重要工具。它提供了包含AI前缀和人类前缀的对话摘要格式,与记忆机制结合紧密。
示例代码:
from langchain import OpenAI
from langchain.chains import ConversationChain
llm = OpenAI(temperature=0.5, model_name="gpt-3.5-turbo-instruct")
conv_chain = ConversationChain(llm=llm)
print(conv_chain.prompt.template)
输出:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
Current conversation:
{history}
Human: {input}
AI:
这里的{history}和{input}参数用于存储和传递对话历史和新输入内容。
三、使用ConversationBufferMemory
ConversationBufferMemory是LangChain中最简单的记忆机制,通过缓冲对话历史来实现记忆功能。
示例代码:
from langchain import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.conversation.memory import ConversationBufferMemory
llm = OpenAI(temperature=0.5, model_name="gpt-3.5-turbo-instruct")
conversation = ConversationChain(llm=llm, memory=ConversationBufferMemory())
# 第一天的对话
conversation("我姐姐明天要过生日,我需要一束生日花束。")
print("第一次对话后的记忆:", conversation.memory.buffer)
# 第二次对话
conversation("她喜欢粉色玫瑰,颜色是粉色的。")
print("第二次对话后的记忆:", conversation.memory.buffer)
# 第三次对话(第二天的对话)
conversation("我又来了,还记得我昨天为什么要来买花吗?")
print("\n第三次对话后时提示:\n", conversation.prompt.template)
print("\n第三次对话后的记忆:\n", conversation.memory.buffer)
输出:
第一次对话后的记忆:
Human: 我姐姐明天要过生日,我需要一束生日花束。
AI: 哦,你姐姐明天要过生日,那太棒了!我可以帮你推荐一些生日花束,你想要什么样的?我知道有很多种,比如玫瑰、康乃馨、郁金香等等。
...(后续对话内容)
这种机制简单直观,但可能会因为较长的对话历史而增加Token的使用。
四、使用ConversationSummaryMemory和ConversationSummaryBufferMemory
ConversationSummaryMemory和ConversationSummaryBufferMemory是更高级的记忆机制,旨在优化Token的使用并保留重要的对话内容。
- ConversationSummaryMemory:总结早期的互动,适用于多轮、长时间的对话场景。但无法区分近期和长期的对话。
- ConversationSummaryBufferMemory:结合了上述两种机制的特点,通过
max_token_limit参数控制总结的详细程度。当对话内容超过预设长度时,会进行总结以节省Token。
示例代码:
from langchain.chains.conversation.memory import ConversationSummaryBufferMemory
llm = OpenAI(temperature=0.5, model_name="gpt-3.5-turbo-instruct")
conversation = ConversationChain(llm=llm, memory=ConversationSummaryBufferMemory(llm=llm, max_token_limit=300))
# 初始化对话并观察输出内容的变化(略)...
这种机制在节省Token的同时,能够较好地保留重要的对话信息。但需要注意的是,对于较短的对话,也可能会增加Token的使用。
五、总结与比较
通过表格总结了四种记忆机制的优缺点:
| 记忆机制 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| ConversationBufferMemory | 简单直观,易于实现 | 对话历史较长时增加Token使用 | 简短、单次对话 |
| ConversationSummaryMemory | 节省Token,适用于多轮对话 | 无法区分近期和长期对话 | 多轮、长时间对话 |
| ConversationBufferWindowMemory | 直接节省Token,不依赖LLM的汇总能力 | 完全遗忘K轮之前的对话内容 | 需要频繁更新的场景 |
| ConversationSummaryBufferMemory | 结合了上述机制的特点,灵活性强 | 对于较短的对话也可能增加Token使用 | 多轮、需要节省Token的场景 |