Langchain Memory组件深度剖析:从对话基础到高级链式应用

在这里插入图片描述



前言

    Langchain框架中的Memory组件是构建智能对话系统的基石,它们不仅存储和管理对话信息,还促进上下文理解和对话连续性。 本文深入探讨Memory组件的多样类型,如ChatMessageHistory记录对话历史,ConversationBufferMemory管理对话缓冲区,ConversationKGMemory通过知识图谱增强智能。同时,长时记忆机制在Langchain中占据重要地位,助力AI系统实现持续学习和记忆。进一步,文章聚焦链上(Chains)使用Memory的高级应用,如LLMChain和ConversationChain,展示如何通过组合多个Memory组件构建高效对话流程。本文将引领您领略Langchain Memory组件的无限潜力与灵活应用。


Langchain中文文档:http://www.aidoczh.com/langchain/v0.2/docs/introduction/

一、Langchain memory 记忆

    LangChain 中的Memory组件是一个至关重要的部分,它为大语言模型(LLM)提供了记忆能力,使得对话系统能够保留和引用过去的交互内容,从而实现更加个性化和连贯的对话体验。

    默认情况下,链式模型和代理模型都是无状态的,这意味着它们将每个传入的查询独立处理(就像底层的 LLMs 和聊天模型本身一样)。在某些应用程序中,比如聊天机器人,记住先前的交互是至关重要的。无论是短期还是长期,都要记住先前的交互。Memory 类正是做到了这一点。


1.Memory 组件基本介绍

Memory组件的作用

  • 保存上下文信息: Memory组件能够存储多种形式的信息,包括历史对话内容、实时交流信息以及外部文件资料等。这些信息在必要时可以被引用,使对话不仅基于当前的交流,而且建立在一个丰富的信息背景之上。
  • 检索相关信息: Memory组件不仅是一个简单的存储设备,还是一个高效的检索系统。它能够根据语义相关度找到与输入最相关的信息,即使这些信息在字面上并非完全匹配。这种能力提高了对话的质量和效率,使得AI在理解用户需求方面变得更加精准。
  • 增强对话连贯性: 通过Memory组件,AI对话系统能够更深入地理解用户的需求,并提供更加精准的反馈和帮助。它能够在适当的时候检索必要的信息,从而增强对话的连贯性和个性化。

Memory组件的运作机制

  • 读取记忆: 当用户的初始输入被接收后,LangChain在执行其核心逻辑之前,会首先向Memory组件发送查询请求,读取与当前话题相关的历史交互信息。这些信息被用来丰富和增强当前的用户输入,以便更全面地理解上下文。
  • 写入记忆: 在核心逻辑执行完毕后,LangChain会将这次交互的输入和输出保存到Memory组件中。这一步骤对于更新和维护对话历史至关重要,因为它保证了系统能够记住最新的交互信息,从而在未来的对话中提供更加准确的与历史的上下文相关的回应。

Memory组件的类型

LangChain提供了多种Memory组件类型,以满足不同的需求和应用场景。其中一些常见的类型包括:

  • ConversationBufferMemory: 如实地记录列表中记录的对话历史消息,并且是记录所有的历史消息。它适用于交互次数少、输入输出字符量不大的情况。
  • ConversationBufferWindowMemory: 持续记录对话历史,但只使用最近的k个交互。这种类型确保了缓存大小不会过大,运行速度比较稳定。
  • ConversationSummaryMemory: 为了解决tokens大小限制,在滑动窗口外的另一种方案。它会对历史对话进行总结,生成摘要,再交给prompt。这种方式可以减少对LLM的调用次数,提高系统的效率。
  • 等等,后续详细介绍…

Memory组件的集成与应用

    Memory组件可以单独使用,也可以无缝地集成到LangChain的Chain中。在与LLM进行交互时,Chain会与Memory组件进行两次交互:一次是读取记忆以增强用户输入,另一次是写入记忆以更新对话历史。这种集成方式使得开发者能够更高效地构建大模型应用,提升对话系统的性能和用户体验。

    综上所述,LangChain的Memory组件是一个强大的工具,它为大语言模型提供了记忆能力,使得对话系统能够更加个性化和连贯地与用户进行交互。通过不断地保存和检索上下文信息,Memory组件能够增强对话的连贯性和精准度,为用户提供更好的服务体验。


2.Memory 组件的类型

1.ChatMessageHistory

    ChatMessageHistoryLangchain框架中用于存储对话历史的一个类。它允许开发者以结构化的方式保存用户和AI之间的对话记录,包括用户输入的消息和AI生成的响应。通过ChatMessageHistory,对话系统能够引用先前在对话中介绍的信息,从而提供更加连贯和个性化的回复。

from langchain.memory import ChatMessageHistory
from langchain_community.llms import Tongyi
llm = Tongyi()

history = ChatMessageHistory()
history.add_user_message("你好")
history.add_ai_message("你好?")
history.add_user_message("请问丹麦的首都是哪里?")
history.add_ai_message("哥本哈根")
print(history.messages)

ret = llm.invoke(history.messages)
print(ret)

在这里插入图片描述

2.ConversationBufferMemory

    ConversationBufferMemoryLangchain框架中用于存储对话历史的一个内存组件。它类似于一个缓冲区,将对话中的所有消息(包括用户输入和AI响应)按照顺序存储起来。这种存储方式使得对话系统能够随时回顾之前的对话内容,从而在生成新的响应时考虑这些上下文信息。

# 内存记忆
from langchain.memory import  ConversationBufferMemory
from langchain_community.llms import Tongyi
llm = Tongyi()

memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("你好,我是人类!")
memory.chat_memory.add_ai_message("你好,我是AI,有什么可以帮助你的吗?")
memory.chat_memory.add_user_message("你可以帮我做什么?")

print(memory.buffer)

ret = llm.invoke(memory.buffer)
print(ret)

在这里插入图片描述


#使用 ConversationBufferMemory在 LangChain 中,
#通过 ConversationBufferMemory(缓冲记忆)可以实现最简单的记忆机制。
from langchain.chains.conversation.base import ConversationChain
from langchain_community.llms import Tongyi
llm = Tongyi()
from langchain.chains.conversation.memory import ConversationBufferMemory
conversation = ConversationChain(llm=llm,memory=ConversationBufferMemory())

#第一天的对话
#回合1
conversation.invoke("我姐姐明天要过生日,我需要一束生日花束。")
print("第一次对话后的记忆:", conversation.memory.buffer,"\n")

# 回合2
conversation.invoke("她喜欢粉色玫瑰,颜色是粉色的。")
print("第二次对话后的记忆:", conversation.memory.buffer,"\n")

# 回合3 (第二天的对话)
conversation.invoke("我又来了,还记得我昨天为什么要来买花吗?")
print("\n第三次对话后时提示:\n",conversation.prompt.template)
print("\n第三次对话后的记忆:\n", conversation.memory.buffer,"\n")

在这里插入图片描述
在这里插入图片描述

3.ConversationBufferWindowMemory

    ConversationBufferWindowMemory基于滑动窗口的概念,只保留对话历史中的最近几轮交互。这种机制类似于人类的短期记忆,能够高效地管理对话上下文,同时减少内存占用。

# 实现一个最近的对话窗口,超过窗口条数的对话将被删除
from langchain.memory import  ConversationBufferWindowMemory

memory = ConversationBufferWindowMemory(k=5)

memory.save_context({
    
    "input":"你好,我是人类!"},{
    
    "output":"你好,我是AI,有什么可以帮助你的吗?"})
memory.save_context({
    
    "input":"我想吃鸡肉"},{
    
    "output":"好的,我帮你找找鸡肉的做法"})
memory.save_context({
    
    "input":"我想吃鸭肉"},{
    
    "output":"好的,我帮你找找鸭肉的做法"})

print(memory.buffer)
>>> 输出:
>>> Human: 你好,我是人类!
>>> AI: 你好,我是AI,有什么可以帮助你的吗?
>>> Human: 我想吃鸡肉
>>> AI: 好的,我帮你找找鸡肉的做法
>>> Human: 我想吃鸭肉
>>> AI: 好的,我帮你找找鸭肉的做法

4.ConversationEntityMemory

    LangchainMemory组件中的ConversationEntityMemory是一种特殊的记忆组件,它专注于跟踪和存储对话中提及的实体信息。 它通过识别对话中的实体(如人名、地名、产品名等),并将这些实体及其相关信息存储在内存中。在后续的对话中,这些实体信息可以被检索和引用,以增强对话的连贯性和准确性。这种机制在构建需要处理实体关系的对话系统时非常有用,比如任务管理、客户服务或医疗咨询等领域。

构建记忆实体概念清单:

# 构建记忆实体概念清单
from langchain.memory import ConversationEntityMemory
from langchain_community.llms import Tongyi
llm = Tongyi()

memory = ConversationEntityMemory(llm=llm)

_input = {
    
    
    "input":"胡八一和王胖子雪莉杨经常在一起冒险,合称盗墓铁三角."
}
_input2 = {
    
    
    "input":"王小华和另外一个学生叫张大壮还有刘能都是我们班级的学生"
}

print(memory.load_memory_variables(_input))
print(memory.load_memory_variables(_input2))

memory.save_context(
    _input,
    {
    
    
        "output":"听起来很刺激,我也想加入他们!"
    }
)

print(memory.load_memory_variables({
    
    "input": "铁三角是谁?"}))

在这里插入图片描述

5.ConversationKGMemory

    LangchainMemory组件中的ConversationKGMemory是一个用于增强对话系统上下文理解和记忆能力的重要工具。它利用知识图谱(Knowledge Graph)来组织和管理对话历史中的实体、概念和关系,从而提供更加丰富和准确的上下文信息。

    ConversationKGMemoryLangchain中的一个内存组件,它将对话历史中的关键信息(如实体、概念等)映射到知识图谱中,建立对话上下文与知识库之间的联系。通过这种方式,ConversationKGMemory能够在对话过程中持续更新对话状态,并根据当前对话上下文从知识图谱中检索相关信息,从而提供更加智能和连贯的回复。

使用知识图谱构建记忆:

# 使用知识图谱构建记忆
# from langchain.memory import ConversationKGMemory
from langchain_community.memory.kg import ConversationKGMemory
from langchain_community.llms import Tongyi
llm = Tongyi()

memory = ConversationKGMemory(llm=llm)
memory.save_context({
    
    "input": "say hi to dahuang"}, {
    
    "output": "who is dahuang"})
memory.save_context({
    
    "input": "dahuang is a dog name"}, {
    
    "output": "okay"})

print(memory.load_memory_variables({
    
    "input": "who is xiaohei"}))
print(memory.load_memory_variables({
    
    "input": "who is dahuang"}))

print(memory.get_knowledge_triplets("her favorite color is red"))

print(memory.get_current_entities("what's Sams favorite color?"))
print(memory.get_current_entities("穿着蓝色衣服、手里拿着冰糖葫芦的小明与小花正在去爬山"))
print(memory.get_current_entities("大壮的职业一个消防员"))
>>> 输出:
>>> {
    
    'history': ''}
>>> {
    
    'history': 'On dahuang: dahuang is a dog name.'}
>>> [KnowledgeTriple(subject='dahuang', predicate='favorite color is', object_='red')]
>>> ['Sam']
>>> ['小明', '小花']
>>> ['大壮']

6.ConversationSummaryMemory

    Langchain的Memory组件中的ConversationSummaryMemory是一种用于存储和管理对话上下文的工具,它不同于简单地存储对话的原始文本,而是通过生成对话的摘要来记忆关键内容。这种方式有助于在后续的交互中快速获取对话的关键要点,而无需处理大量的原始文本。
    ConversationSummaryMemory通过对整个对话的内容进行总结,生成一个简洁的对话摘要,并记住这个摘要。这个摘要通常包含了对话中的关键信息和要点,能够帮助大语言模型(LLM)在后续的对话中保持上下文的连贯性和一致性。

# 总结摘要
from langchain.memory import ConversationSummaryMemory
from langchain_community.llms import Tongyi
llm = Tongyi()

memory = ConversationSummaryMemory(llm=llm)
memory.save_context(
    {
    
    "input":"帮我找一下张三"},
    {
    
    "output":"对不起请问谁是张三?"}
)
memory.save_context(
    {
    
    "input":"张三是一个米其林大厨"},
    {
    
    "output":"好的,我知道了。"}
)
print(memory.load_memory_variables({
    
    }))

messages = memory.chat_memory.messages
#print(messages)
print(memory.predict_new_summary(messages, ""))
>>> 输出:
>>> {
    
    'history': 'The human asks the AI to find someone named Zhang San and clarifies that he is a Michelin-starred chef. The AI acknowledges the information and understands the context better.'}
>>> The human asks the AI to find information about someone named Zhang San. The AI asks for clarification on who Zhang San is. The human explains that Zhang San is a Michelin-starred chef. The AI acknowledges this and indicates that it understands.

二、长时记忆

1.简单介绍

    通过向量数据库来存储之前的对话内容,有的向量数据库服务还提供自动摘要等,每次对话的时候,都会从向量数据库里查询最相关的文档或历史对话。

2.长时记忆案例

from langchain.memory import ConversationBufferMemory
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings.dashscope import DashScopeEmbeddings

memory = ConversationBufferMemory()
memory.save_context(
    {
    
    "input":"帮我找一下tomie"},
    {
    
    "output":"对不起请问什么是tomie?"}
)
memory.save_context(
    {
    
    "input":"tomie是一个人工智能讲师"},
    {
    
    "output":"好的,我知道了。"}
)
memory.save_context(
    {
    
    "input":"今天他要讲一门关于RAG的课程"},
    {
    
    "output":"好的,我知道了。需要RAG的资料吗?"}
)
memory.save_context(
    {
    
    "input":"不需要资料了,谢谢"},
    {
    
    "output":"好的,那我就不打扰你了。"}
)

print(memory.buffer)

vectorstore = FAISS.from_texts(
    memory.buffer.split("\n"),
    DashScopeEmbeddings()
)
FAISS.save_local(vectorstore,"test_faiss")

faiss = FAISS.load_local("test_faiss",DashScopeEmbeddings(),allow_dangerous_deserialization=True)

print(faiss.similarity_search("tomie是什么职业?"))
print(faiss.similarity_search("课程是关于什么内容的?"))

在这里插入图片描述


三、链上(Chains)使用记忆(Memory)

1. LLMChain

from langchain.chains.llm import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate

from langchain_community.llms import Tongyi
llm = Tongyi()

template = """你是一个机器人助理。
{chat_history}
user:{human_input}
AI:"""

prompt= PromptTemplate(
    template=template,
    input_variables=["chat_history", "human_input"],
)

memory = ConversationBufferMemory(
    memory_key="chat_history",
)

chain = LLMChain(
    llm=llm,
    memory=memory,
    prompt=prompt,
)

print(chain.invoke("中国的首都是哪里?"))
print(chain.invoke("推荐一个旅游景点"))
print(chain.invoke("怎么去?"))

在这里插入图片描述

2.ConversationChain

from langchain.chains.conversation.base import ConversationChain
from langchain.memory import ConversationBufferMemory
from langchain_community.llms import Tongyi
llm = Tongyi()

memory = ConversationBufferMemory(
    memory_key="history",
    return_messages=True,
)
chain = ConversationChain(
    llm=llm,
    memory=memory
)
tp = {
    
    
    "input": "给我讲一个笑话"
}

chain.invoke("给我讲一个笑话")
chain.invoke("这个不好笑")

print(memory.buffer)

在这里插入图片描述

3.同一个链合并使用多个memory

# from langchain.Langchain_Chains import ConversationChain
from langchain.chains.conversation.base import ConversationChain
# from langchain.llms import OpenAI
from langchain.memory import (
    ConversationBufferMemory,
    ConversationSummaryMemory,
    CombinedMemory
)
from langchain.prompts import PromptTemplate
from langchain_community.llms import Tongyi
llm = Tongyi()

#使用CoversationSummaryMemory对对话进行总结
summay = ConversationSummaryMemory(
    llm=llm,
    input_key="input"
)
#使用ConversationBufferMemory对对话进行缓存
cov_memory = ConversationBufferMemory(
    memory_key="history_now",
    input_key="input",
)

memory = CombinedMemory(
    memories=[summay, cov_memory],
)

TEMPLATE = """下面是一段AI与人类的对话,AI会针对人类问题,提供尽可能详细的回答,如果AI不知道答案,会直接回复'人类老爷,我真的不知道'.
之前的对话摘要:
{history}
当前对话:
{history_now}
Human:{input}
AI:"""

prompt = PromptTemplate(
    template=TEMPLATE,
    input_variables=["history", "history_now", "input"],
)

chain = ConversationChain(
    llm=llm,
    memory=memory,
    prompt=prompt
)

print(chain.run("2024年NBA冠军是谁"))
print(chain.run("介绍一下python语言"))

在这里插入图片描述

4.构建问答对话链

#构建问答对话链
from langchain.chains.question_answering import load_qa_chain
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate
from langchain_community.llms import Tongyi

from langchain_core.documents import Document

llm = Tongyi()

docs = [Document(page_content='这是一些无用的干扰项文本\n,这是一些无用的干扰项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本\n项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本\n项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本\n项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本\n项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本项文本,这是一些无用的干扰项文本\n在2025年NBA总决赛的最后一场比赛中,哈哈队在主场以94-89击败热火,以总比分4-1成功夺得NBA总冠军。这是球队历史上第一次获得总冠军,也是球队自1976年进入NBA以来的最佳成绩。哈哈队的成功主要归功于他们的领袖球员HAHA的出色表现。\n在总决赛的五场比赛中,HAHA展现出了惊人的统治力。他场均贡献30.2分、14个篮板和7.2次助攻,成为球队得分、篮板和助攻的核心。HAHA在进攻端展现出了全面的技术,他的得分能力和篮板能力让热火队无可奈何。同时,他还展现出了出色的组织能力,为球队创造了很多得分机会。\n在总决赛的最后一场比赛中,HAHA更是发挥出色。他在关键时刻承担责任,不仅在进攻端贡献了关键得分,还在防守端起到了重要作用。他的领导能力和稳定性为球队赢得了决胜的胜利。\nHAHA荣获总决赛最有价值球员(MVP)毫无悬念。他在总决赛中的出色表现让他成为了不可或缺的球队核心,也让他获得了职业生涯中的首个总冠军。这一荣誉不仅是对他个人努力的认可,也是对他带领球队取得成功的肯定。\n随着HAHA的崛起,哈哈队在过去几个赛季中逐渐崭露头角。他的全面发展和领导能力使他成为了球队的核心和灵魂人物。通过这次总决赛的胜利,孙健不仅实现了自己的篮球梦想,也为球队带来了无比的荣耀。\nHAHA带领哈哈队赢得2025年NBA总冠军,并凭借出色的表现获得总决赛最有价值球员(MVP)的荣誉。他在总决赛期间的统治力和全面能力使他成为球队的核心,同时也展现了他的领导才能。这次胜利不仅是HAHA个人职业生涯的里程碑,也是哈哈队迈向更高荣耀的关键一步。随着HAHA的领导,哈哈队有望在未来继续取得更多的成功。'),]

template = """下面是一段AI与人类的对话,AI会针对人类问题,提供尽可能详细的回答,如果AI不知道答案,会直接回复'人类老爷,我真的不知道',参考一下相关文档以及历史对话信息,AI会据此组织最终回答内容.
{context}
{chat_history}
Human:{human_input}
AI:"""

prompt = PromptTemplate(
    template=template,
    input_variables=["context", "chat_history", "human_input"],
)

#使用ConversationBufferMemory对对话进行缓存
memory = ConversationBufferMemory(
    memory_key="chat_history",
    input_key="human_input",
    return_messages=True,
)

#加载对话链
chain = load_qa_chain(
    llm=llm,
    memory=memory,
    prompt=prompt,
    chain_type="stuff"
)

# chain.run("2024年NBA冠军是谁")
# chain({"input_documents":docs,"human_input":"公司的营销策略是什么?"})
print(chain({
    
    "input_documents": docs, "human_input": "2025年NBA冠军是谁?"}))

在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_48173416/article/details/141267394