05 大模型记忆功能实现,让对话更连贯|豆包MarsCode AI刷题

783 阅读4分钟

在默认情况下,每次和大语言模型交互都是一次崭新的对话过程。但是实际上大模型是能记得之前说过的内容的,这是因为使用了记忆机制,记录了之前的对话上下文,并且把这个上下文作为提示的一部分,在最新的调用中传递给了模型。

ConversationChain的使用

conv_chain = ConversationChain(llm=llm)
print(conv_chain.prompt.template)

会出现{history}和{input}的字眼。模型可以从{history}存储的上下文提供大量的具体细节。

加入记忆功能

conversation = ConversationChain(
    llm=llm,
    memory=ConversationBufferMemory()
)

image.png 上述的聊天历史信息,都被传入了ConversationChain的提示模板中的{history}参数,构建出了包含聊天记录的新的提示输入。

但是简单直接的存储所有内容为LLM提供了大量的信息,但也会使得新输入有更多的token,响应会慢成本会更高。而且当达到LLM的令牌数(上下文窗口)限制时,太长的对话无法被记住。

ConversationBufferWindowMemory的使用

ConversationBufferWindowMemory 是缓冲窗口记忆,它的思路就是只保存最新最近的几次人类和AI的互动。因此,它在之前的“缓冲记忆”基础上增加了一个窗口值 k。这意味着我们只保留一定数量的过去互动,然后“忘记”之前的互动。

conversation = ConversationChain(
    llm=llm,
    memory=ConversationBufferWindowMemory(k=1)
)

image.png 设置k=1。意味着只保留上一次的对话过程,比如这里输出的第三回合她已经遗忘掉姐姐的关键信息,但是凭借上一回的信息,模型还是有可能推断昨天来买花人的真实意图。

ConversationSummaryMemory的使用

如果模型在第二轮回答的时候,能够说出“我可以帮你为你姐姐找到...”,那么在第三轮回答时,即使窗口大小 k=1,还是能够回答出正确答案。这是因为模型在回答新问题的时候,对之前的问题进行了总结性的重述。ConversationSummaryMemory(对话总结记忆)的思路就是将对话历史进行汇总,然后再传递给 {history} 参数。这种方法旨在通过对之前的对话进行汇总来避免过度使用 Token。

ConversationSummaryMemory有这么几个核心特点。

  1. 汇总对话:此方法不是保存整个对话历史,而是每次新的互动发生时对其进行汇总,然后将其添加到之前所有互动的“运行汇总”中。
  2. 使用LLM进行汇总:该汇总功能由另一个LLM驱动,这意味着对话的汇总实际上是由AI自己进行的。
  3. 适合长对话:对于长对话,此方法的优势尤为明显。虽然最初使用的 Token 数量较多,但随着对话的进展,汇总方法的增长速度会减慢。与此同时,常规的缓冲内存模型会继续线性增长。
# 初始化对话链
conversation = ConversationChain(
    llm=llm,
    memory=ConversationSummaryMemory(llm=llm)
)

image.png

他的缺点是对于较短的对话,可能会导致更高的 Token 使用。另外,对话历史的记忆完全依赖于中间汇总LLM的能力,还需要为汇总LLM使用 Token,这增加了成本,且并不限制对话长度。

ConversationSummaryMemory 为那些预期会有多轮的、长时间对话的场景提供了一种很好的方法。然而,这种方法仍然受到 Token 数量的限制。在一段时间后,我们仍然会超过大模型的上下文窗口限制。

总结的过程中并没有区分近期的对话和长期的对话(通常情况下近期的对话更重要),所以我们还要继续寻找新的记忆管理方法。

ConversationSummaryBufferMemory的使用

话总结缓冲记忆,它是一种混合记忆模型,结合了上述各种记忆机制,包括ConversationSummaryMemory 和 ConversationBufferWindowMemory的特点。这种模型旨在在对话中总结早期的互动,同时尽量保留最近互动中的原始内容。

它是通过max_token_limit这个参数做到这一点的。当最新的对话文字长度在300字之内的时候,LangChain会记忆原始对话内容;当对话文字超出了这个参数的长度,那么模型就会把所有超过预设长度的内容进行总结,以节省Token数量。

conversation = ConversationChain(
    llm=llm,
    memory=ConversationSummaryBufferMemory(
        llm=llm,
        max_token_limit=300))

image.png

总结

针对以上几种记忆机制进行总结

image.png