掘金 人工智能 05月08日 10:13
深入浅出:LangChain "记忆"能力
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了大语言模型(LLM)的“记忆”概念,指出其基础设计的局限性——“无状态”,即每次交互都是独立的,模型无法记住之前的对话内容。文章介绍了LangChain的Memory模块,旨在解决LLM缺乏“记忆”能力的问题,通过存储、管理和检索过去的交互信息,赋予LLM应用“记忆”的能力。通过构建一个简单的“智能客服”实战案例,逐步学习如何利用LangChain的不同Memory类型来存储和管理对话历史、用户偏好等信息,并观察这些记忆能力如何提升客服的交互体验。

🔑大语言模型(LLM)在基础设计上是“无状态”的,这意味着每次与LLM的交互都是独立的,模型本身不会记住之前的对话内容,这在构建需要多轮交互的应用时是一个显著的局限性。

🧰LangChain的Memory模块旨在解决LLM的“记忆”问题,通过提供一系列工具和方法,使得大语言模型应用能够存储、管理和检索过去的交互信息,从而赋予应用“记忆”的能力。

🤖通过构建一个简单的“智能客服”案例,展示了如何利用LangChain的不同Memory类型(如ConversationBufferMemory、ConversationBufferWindowMemory、ConversationSummaryMemory、ConversationSummaryBufferMemory和ConversationKGMemory)来存储和管理对话历史、用户偏好等信息,提升客服的交互体验。

📚LangChain Memory 模块的核心功能是存储和管理信息,这些信息通常是过去的对话回合,但也可能是从对话中提取出的关键信息、用户偏好、实体关系等等。Memory 的作用不仅仅是简单地记录一切,更重要的是以一种结构化的方式存储信息,以便在需要时能够有效地检索和利用。

🔄Memory 模块通常与 LangChain 的 Chain(链)一起使用。Chain 负责组织和执行一系列操作,例如接收用户输入、调用 LLM、处理输出等。Memory 模块则作为 Chain 的一个组成部分,在 Chain 执行过程中发挥作用。在 Chain 处理用户输入之前,它可以从 Memory 中读取历史信息。这些历史信息会被添加到当前的用户输入中,一起送入 LLM 的上下文。在 Chain 接收到 LLM 的输出并将其返回给用户之前,它可以将当前的输入和输出(即一个完整的对话回合)写入 Memory。

什么是大语言模型的“记忆”?

大语言模型(LLM)在基础设计上有一个显著的局限性:它们是“无状态”的。这意味着,每一次与 LLM 的交互都是独立的,模型本身并不会记住之前的对话内容。当你问它一个问题,然后紧接着问一个与前一个问题相关的问题时,LLM 可能会表现得像第一次听到这个话题一样,因为它没有保留之前的上下文信息。

这就好比你和一个人对话,但这个人每说一句话就会立刻忘记你之前说过的一切。这样的交流显然是低效且令人沮丧的。在构建需要进行多轮交互的应用时,例如聊天机器人、智能助手或个性化推荐系统,缺乏“记忆”能力是致命的。

大型语言模型虽然在单次交互中能处理一定长度的上下文,但这受限于其“上下文窗口”(context window)的大小。上下文窗口是指模型在生成当前输出时能够考虑的输入文本的最大长度。一旦对话内容超出这个窗口,早期信息就会被“遗忘”。对于需要长时间、深入交流的应用来说,仅仅依赖 LLM 原生的上下文窗口是远远不够的。我们需要一种机制来有效地管理和利用历史信息,以便模型能够理解对话的来龙去脉,提供连贯、个性化的回应。

LangChain 的 Memory 模块正是为了解决这个问题而设计的。它提供了一系列工具和方法,使得大语言模型应用能够存储、管理和检索过去的交互信息,从而赋予应用“记忆”的能力。通过集成 Memory 模块,我们可以构建出更加智能、更加符合人类交流习惯的应用。

简单的“智能客服”实战案例

为了更好地理解 LangChain Memory 的实际应用,我们将贯穿本文,围绕一个具体的案例来学习:构建一个简单的“智能客服”。

案例目标:  我们的目标是创建一个能够记住用户偏好和之前问题的智能客服,以便在用户咨询过程中提供更个性化和连贯的服务。

场景描述:  设想一个在线商城的智能客服场景。用户可能会多次前来咨询关于不同产品的信息、询问订单状态、或者寻求售后帮助。一个优秀的智能客服不仅应该能回答当前的问题,还应该能记住用户之前问过什么产品,是否表达过对某个类别的偏好,甚至记住用户的姓名(如果用户提供过)。例如,如果用户之前问过关于“笔记本电脑”的问题,当用户再次咨询时,客服应该能联想到用户可能对电子产品感兴趣,并提供更相关的帮助。如果用户提到了自己的订单号,客服应该能记住这个订单号,并在后续的交流中方便地引用。

通过实现这个“智能客服”案例,我们将逐步学习如何利用 LangChain 的不同 Memory 类型来存储和管理对话历史、用户偏好等信息,并观察这些记忆能力如何提升客服的交互体验。这将帮助我们更直观地理解各种 Memory 模块的原理和适用场景。

LangChain Memory 核心概念

在深入探讨各种具体的 Memory 类型之前,理解 LangChain Memory 模块的一些核心概念是至关重要的。这些概念构成了 Memory 模块的基础,并解释了它如何与 LangChain 的其他组件(特别是 Chain)协同工作。

Memory 的本质:存储和管理对话历史或相关信息

Memory 模块的核心功能是存储和管理信息,这些信息通常是过去的对话回合,但也可能是从对话中提取出的关键信息、用户偏好、实体关系等等。Memory 的作用不仅仅是简单地记录一切,更重要的是以一种结构化的方式存储信息,以便在需要时能够有效地检索和利用。

可以把 Memory 看作是 LLM 应用的“短期”或“长期”记忆库。短期记忆可能只保留最近的几轮对话,而长期记忆则可能存储更持久的用户信息或对话总结。不同的 Memory 类型采用了不同的策略来存储和管理这些信息,以适应不同的应用需求和资源限制。

Memory 的输入/输出:如何与 Chain 交互

Memory 模块通常与 LangChain 的 Chain(链)一起使用。Chain 负责组织和执行一系列操作,例如接收用户输入、调用 LLM、处理输出等。Memory 模块则作为 Chain 的一个组成部分,在 Chain 执行过程中发挥作用。

这种输入/输出机制使得 Chain 能够在每次运行时都“记住”之前发生的事情,从而实现连贯的多轮对话。

Memory Variables:记忆存储的数据名称

Memory 模块存储的信息是通过“Memory Variables”来访问的。Memory Variables 是 Memory 内部用来存储特定类型数据的变量名。例如,一个常见的 Memory Variable 是 chat_history,它用来存储对话的文本历史。不同的 Memory 类型可能会使用不同的 Memory Variables 来存储它们管理的信息。

当我们将 Memory 模块集成到 Chain 中时,需要确保 Chain 能够识别和使用 Memory Variables。Chain 会根据 Memory Variables 的名称从 Memory 中读取数据,并将这些数据添加到发送给 LLM 的 Prompt 中。同样,Chain 也会将新的对话回合写入 Memory 中对应的 Memory Variables。

Memory 与 LLM 上下文的区别与联系

理解 Memory 与 LLM 上下文的区别与联系是掌握 LangChain Memory 的关键。

联系:  Memory 的最终目标是有效地利用 LLM 的上下文窗口。它通过智能地管理历史信息,确保送入 LLM 上下文的内容既包含必要的历史背景,又不会超出上下文窗口的限制。Memory 模块充当了历史信息和 LLM 上下文之间的“协调者”或“过滤器”。

区别:  LLM 上下文是临时的,每次调用后就会“清空”。而 Memory 则是持久的(至少在一个对话会话期间),它可以跨越多次 LLM 调用来维护状态。Memory 提供了比原生 LLM 上下文更灵活和强大的历史信息管理能力。

通过理解这些核心概念,我们就为后续深入学习各种具体的 Memory 类型打下了基础。在下一部分,我们将结合“智能客服”案例,详细探讨 LangChain 中常见的 Memory 类型及其实现。

常见的 LangChain Memory 类型详解与实践(结合案例)

现在我们来深入了解 LangChain 中几种常见的 Memory 类型,并通过构建我们的 ai_customer_bot 智能客服来实际操作。在开始之前,请确保你已经设置好了开发环境,包括安装 uv 和必要的库。

首先,创建一个新的项目目录并使用 uv 初始化:

mkdir ai_customer_botcd ai_customer_botuv init

然后,安装 LangChain、DeepSeek SDK 以及用于运行的库:

uv pip install langchain langchain-deepseek python-dotenv

为了使用 DeepSeek 模型,你需要设置 DEEPSEEK_API_KEY 环境变量。新建 .env 文件,添加 DEEPSEEK_API_KEY

# .envDEEPSEEK_API_KEY='YOUR_DEEPSEEK_API_KEY'

现在,我们可以在 main.py 文件中编写代码, LangChain 内置的支持 Memory 的 ConversationChain 来使用不同的 memory 模拟对话。

1. ConversationBufferMemory:简单粗暴的记忆

让我们在 ai_customer_bot/main.py 中使用 ConversationBufferMemory 来构建一个基础的智能客服。

# ai_customer_bot/main.pyimport osfrom langchain_deepseek import ChatDeepSeekfrom langchain.chains import ConversationChainfrom langchain.memory import ConversationBufferMemoryfrom langchain_core.prompts import PromptTemplatefrom dotenv import load_dotenvload_dotenv()# 初始化 DeepSeek 模型llm = ChatDeepSeek(model="deepseek-chat")# 定义 Prompt 模板# {chat_history} 是 Memory 将要插入对话历史的地方template = """你是一个智能客服,请根据对话历史和用户的问题提供帮助。对话历史:{chat_history}用户: {input}智能客服:"""prompt = PromptTemplate(    input_variables=["chat_history", "input"],    template=template)# 初始化 ConversationBufferMemorymemory = ConversationBufferMemory(memory_key="chat_history")# 初始化 ConversationChain# verbose=True 可以看到 Chain 的详细执行过程,包括送给 LLM 的 Promptconversation = ConversationChain(    llm=llm,    memory=memory,    prompt=prompt,    verbose=True)# 模拟对话print("智能客服:您好,有什么可以帮您的?")while True:    user_input = input("用户:")    if user_input.lower() == '退出':        break    response = conversation.predict(input=user_input)    print(f"智能客服:{response}")

运行这段代码:uv run main.py。你会发现,随着你和客服的对话轮数增加,verbose=True 输出的 Prompt 中 chat_history 部分会越来越长,包含了之前所有的对话。这在短对话中没问题,但长对话就会遇到问题。

2. ConversationBufferWindowMemory:只记住最近的对话

修改 ai_customer_bot/main.py,将 ConversationBufferMemory 替换为 ConversationBufferWindowMemory

# ... (前面的导入和 DeepSeek 初始化代码不变)# 初始化 ConversationBufferWindowMemory,只记住最近 3 轮对话memory = ConversationBufferWindowMemory(memory_key="chat_history", k=3)# 初始化 ConversationChain (其他部分不变)conversation = ConversationChain(    llm=llm,    memory=memory,    prompt=prompt,    verbose=True)# ... (后面的对话模拟代码不变)

运行修改后的代码。观察 verbose=True 的输出,你会发现 chat_history 中只保留了最近的几轮对话(这里是 3 轮)。当你进行超过 3 轮对话后,最早的对话就会从 chat_history 中消失。这对于需要关注近期交互的场景很有用,但对于需要长期记忆的应用则不够理想。

3. ConversationSummaryMemory:用总结压缩记忆

修改 ai_customer_bot/main.py,使用 ConversationSummaryMemory。注意,ConversationSummaryMemory 需要一个 LLM 来进行总结。

# ... (前面的导入和 DeepSeek 初始化代码不变)# 初始化 ConversationSummaryMemory# 需要传入一个用于总结的 LLM 实例memory = ConversationSummaryMemory(llm=llm, memory_key="chat_history")# 初始化 ConversationChain (其他部分不变)conversation = ConversationChain(    llm=llm,    memory=memory,    prompt=prompt,    verbose=True)# ... (后面的对话模拟代码不变)

运行代码。你会看到 chat_history 部分不再是原始对话,而是一段由 DeepSeek 模型生成的对话总结。随着对话进行,这段总结会不断更新。这种方式在保持一定上下文的同时,显著控制了 Prompt 的长度。

4. ConversationSummaryBufferMemory:平衡细节与长度

修改 ai_customer_bot/main.py,使用 ConversationSummaryBufferMemory。我们需要设置一个 max_token_limit 来控制何时触发总结。

# ... (前面的导入和 DeepSeek 初始化代码不变)# 初始化 ConversationSummaryBufferMemory# max_token_limit 设置触发总结的 token 阈值memory = ConversationSummaryBufferMemory(llm=llm, memory_key="chat_history", max_token_limit=200) # 示例阈值# 初始化 ConversationChain (其他部分不变)conversation = ConversationChain(    llm=llm,    memory=memory,    prompt=prompt,    verbose=True)# ... (后面的对话模拟代码不变)

运行代码。在对话初期,chat_history 会显示完整的对话。当你输入足够多的内容,使得对话 token 数超过 max_token_limit 时,Memory 会调用 DeepSeek 模型对之前的对话进行总结,并将总结作为 chat_history 的一部分,同时继续缓冲最新的对话。这是一种非常实用的 Memory 类型,在智能客服场景中能够很好地平衡记忆的细节和长度。

5. ConversationKGMemory (Knowledge Graph Memory):构建结构化记忆

ConversationKGMemory 的使用相对复杂,需要安装额外的依赖(如 networkx 和用于实体提取的 LLM)。这里我们先简要介绍其用法和在智能客服案例中的设想应用,具体的代码实现可以作为进阶内容。

首先,安装必要的库:

uv pip install networkx

然后,在代码中:

# ... (前面的导入和 DeepSeek 初始化代码不变)from langchain.memory import ConversationKGMemory# 初始化 ConversationKGMemory# 需要传入一个用于提取实体和关系的 LLM 实例memory = ConversationKGMemory(llm=llm, memory_key="chat_history")# 初始化 ConversationChain (其他部分不变)conversation = ConversationChain(    llm=llm,    memory=memory,    prompt=prompt, # 注意:使用 KGMemory 时,Prompt 模板可能需要调整以利用知识图谱信息    verbose=True)# ... (后面的对话模拟代码不变)

在智能客服案例中,使用 ConversationKGMemory 可以实现更高级的功能。例如,当用户说“我叫张三”时,KGMemory 可以提取“用户”和“张三”这两个实体,并建立“用户”的“姓名”是“张三”的关系。当用户之后询问“我的订单”时,客服可以通过查询知识图谱,找到与“张三”相关的订单信息。这种结构化的记忆方式为构建更智能、更具推理能力的客服奠定了基础。然而,如何有效地将知识图谱信息融入到送给 DeepSeek 模型的 Prompt 中,以及如何处理复杂的实体和关系提取,是使用 KGMemory 需要深入研究的问题。

通过以上实践,我们了解了 LangChain 中几种 Memory 类型的特点和用法,并结合 ai_customer_bot 智能客服案例,初步体验了它们在实际应用中的效果。

进阶话题与思考

掌握了 LangChain 内置的几种常见 Memory 类型及其与 Chain 的集成方法后,我们可以进一步思考一些更高级的应用场景和技术。这些进阶话题能够帮助我们构建更复杂、更强大的 LLM 应用。

自定义 Memory:如何实现自己的记忆逻辑

LangChain 提供了灵活的接口,允许开发者实现自定义的 Memory 逻辑。这在内置 Memory 类型无法满足特定需求时非常有用。例如,在我们的 ai_customer_bot 案例中,我们可能希望实现一个专门用于存储和管理用户偏好的 Memory,比如用户喜欢的颜色、品牌、价格区间等。这些信息可能不是直接从对话历史中提取的,而是通过特定的交互或用户配置获取的。

要实现自定义 Memory,通常需要继承 LangChain 的 BaseMemory 类,并实现其核心方法:

通过实现这些方法,你可以完全控制 Memory 的存储、加载和更新逻辑。例如,你可以将用户偏好存储在一个字典中,并在 save_context 中从对话中尝试提取偏好信息进行更新,在 load_memory_variables 中将存储的偏好信息格式化后返回。

自定义 Memory 为构建高度定制化的有状态应用提供了无限可能。

Memory 的持久化:将记忆存储到数据库等

到目前为止,我们讨论的 Memory 类型都是“内存中”的,即它们的状态只存在于当前的程序运行期间。一旦程序结束,所有的记忆都会丢失。在实际应用中,我们通常需要将用户的对话历史或重要信息进行持久化存储,以便用户下次回来时能够恢复之前的对话或状态。

LangChain 提供了一些内置的持久化机制,或者你可以结合外部数据库来实现 Memory 的持久化。常见的持久化方式包括:

在 ai_customer_bot 案例中,如果希望用户下次访问时客服还能记住他们是谁以及之前的咨询内容,就需要将 Memory 进行持久化。例如,可以将用户的对话历史和提取出的用户偏好存储到数据库中,使用用户 ID 作为 key。当用户再次登录时,根据用户 ID 从数据库加载对应的 Memory 状态。

Memory 在复杂应用中的应用(如 Agent)

Memory 不仅可以用于简单的对话 Chain,在更复杂的 LangChain 应用(如 Agent)中也扮演着至关重要的角色。Agent 能够根据用户的输入和可用的工具(Tools)自主地决定下一步行动。在 Agent 的决策过程中,理解之前的对话历史和上下文信息是必不可少的。

Agent 通常会使用 Memory 来存储对话历史,以便在规划(Planning)和执行(Execution)步骤中参考。例如,一个 Agent 可能需要记住用户之前提到的文件路径,以便在后续步骤中使用文件读取工具。或者,一个 Agent 可能需要记住用户之前查询过的股票代码,以便在用户询问相关问题时直接提供信息。

在构建复杂的 Agent 时,选择合适的 Memory 类型以及如何有效地将 Memory 信息融入到 Agent 的思考过程(Thought)和行动(Action)中,是设计 Agent 的关键考虑因素之一。

通过掌握自定义 Memory、Memory 持久化以及 Memory 在 Agent 中的应用,我们可以构建出更加智能、灵活和实用的 LLM 应用,满足更广泛的业务需求。

如何选择合适的 Memory 策略

Langchain 提供几个 Memory 类型的比较

在我们的 ai_customer_bot 智能客服案例中,用户咨询的长度不确定,既可能有简短的问答,也可能有详细的产品咨询。同时,保留一定的对话历史对于提供连贯服务很重要,但完整的历史又可能超出 DeepSeek 模型的上下文窗口。因此,ConversationSummaryBufferMemory 是一个非常合适的选择,它能够在对话初期保留细节,在对话变长时进行总结,有效地平衡了记忆的细节和长度,并控制了送入 LLM 的上下文大小。

Memory 是构建智能对话应用的关键一环

Memory 模块是构建真正智能、有状态的 LLM 应用不可或缺的一部分。它赋予了应用“记住”过去的能力,使得应用能够理解上下文、提供个性化服务、进行多轮推理。无论是简单的聊天机器人,还是复杂的 Agent,有效的 Memory 管理都是提升用户体验和应用性能的关键。

通过学习和实践 LangChain 的 Memory 模块,你已经掌握了为你的 LLM 应用添加记忆能力的方法。结合不同的 Memory 类型和 Chain,你可以构建出能够进行连贯、智能对话的应用程序,就像我们的 ai_customer_bot 一样。

希望这篇教程能帮助你深入浅出地掌握 LangChain 的 Memory 能力,并在你的 LLM 应用开发中发挥作用!

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

大语言模型 LangChain Memory模块 智能客服
相关文章