LangChain大型语言模型(LLM)应用开发(二):Conversation & Memory

LangChain是一个Python框架,用于构建基于大语言模型如ChatGPT的应用。文章介绍了如何使用LangChain中的不同内存组件,如ConversationBufferMemory、ConversationBufferWindowMemory、ConversationTokenBufferMemory和ConversationSummaryMemory,来管理和优化与LLM的交互,特别是处理对话记忆,减少不必要的复杂性和成本。例如,ConversationBufferMemory能记住所有历史对话,而ConversationBufferWindowMemory和ConversationTokenBufferMemory则按对话轮数或token数限制存储,ConversationSummaryMemory则保存对话摘要以节省资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

LangChain是一个基于大语言模型(如ChatGPT)用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,以便在不同的应用程序中使用。

今天我们来学习DeepLearning.AI的在线课程:LangChain for LLM Application Development的第二门课:Memory,该门课程主要讲解几种和LLM交互时的内存记忆方法。一般情况下我们通过api的方式来访问openai的语言模型时,LLM是没有记忆能力的,也就是说LLM不能记住之前与用户对话的内容,要解决这个问题,我们必须每次与LLM对话时都必须将之前的所有对话内容全部输入给LLM,但这样也会增加程序的复杂性,同时也会增加经济成本,因为像ChatGPT这样的LLM是根据用户提交的数据内容的token数量来收费的,如果我们每次和LLM交互时提交的内容越多也就意味着token越多,那么就会产生越多的费用。这里Langchain提供了几种内存记忆组件可以帮助我们使用更高效和经济的方法来与LLM交互。

大纲

  • ConversationBufferMemory
  • ConversationBufferWindowMemory
  • ConversationTokenBufferMemory
  • ConversationSummaryMemory

ConversationBufferMemory

ConversationBufferMemory是一种最简单的记忆力组件,它会记住每次与LLM对话内容,并在下一轮对话时将历史对话记录全部传给LLM,这样LLM就会记住之前的对话内容,下面我们看一个例子:

import os

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file

import warnings
warnings.filterwarnings('ignore')
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory


llm = ChatOpenAI(temperature=0.0)
#定义ConversationBufferMemory记忆力组件
memory = ConversationBufferMemory()
conversation = ConversationChain(
    llm=llm, 
    memory = memory,#加入ConversationBufferMemory组件
    verbose=True
)

这里我们定义了一个llm, 该llm默认使用的是openai的"gpt-3.5-turbo"模型,同时我们温度参数temperature设置为0.0,这个很重要,因为温度参数temperature代表了LLM回答问题时候的随机性,取值范围是0-1之间,如果temperature越大,则LLM回答问题的随机性就会越大,这里我们将temperature设置为0,其目的是让LLM每次只选择概率最高的答案,从而避免产生随机答案。

conversation.predict(input="你好,我的名字叫王老六")

 

 这里我们看到,在与LLM交互时Langchain会产生一个prompt其中除了用户的输入的内容外,还有一段英语的前缀信息,这里前缀信息+用户信息构成了一个完整的prompt,下面我们进行第二轮对话:

conversation.predict(input="1+1等于几?")

 在langchain产生的第二轮对话的prompt中,我们看到除了前缀信息以为,还增加了历史对话记录。下面我们看第三轮对话:

conversation.predict(input="你还记得我叫什么名字吗?")

 

 第三轮对话时用户询问了LLM是否还记得用户的名字,LLM给出了正确的答案,这是因为第三轮对话的prompt中包含了历史所有的对话记录,所以LLM能够记住用户的名字。这里记住所有历史对话记录的能力就是由ConversationBufferMemory组件来实现的。

下面我们可以查看ConversationBufferMemory的一些内置方法:

print(memory.buffer)

memory.load_memory_variables({})

 

memory = ConversationBufferMemory()

memory.save_context({"input": "你好"}, 
                    {"output": "有啥事吗?"})

print(memory.buffer)

 

memory.load_memory_variables({})

memory.save_context({"input": "想找你聊天,可以吗?"}, 
                    {"output": "好的,没问题!"})
memory.load_memory_variables({})

 

 ConversationBufferWindowMemory

ConversationBufferWindowMemory组件与ConversationBufferMemory组件功能类似,只是ConversationBufferWindowMemory组件增加了一个窗口参数k, 因为之前的ConversationBufferMemory组件会在prompt中记录历史所有的聊天对话内容,而ConversationBufferWindowMemory组件只会记住最近的k轮对话内容,更早之前的对话讲话被抛弃而不保存在prompt中,下面我们看一个例子:

from langchain.memory import ConversationBufferWindowMemory

llm = ChatOpenAI(temperature=0.0)

#定义内存组件
memory = ConversationBufferWindowMemory(k=1)#k=1,意味着只能记住最后1轮对话内容
conversation = ConversationChain(
    llm=llm, 
    memory = memory, #添加记忆力组件
    verbose=True #展示中间结果
)

 这里我们将ConversationBufferWindowMemory对象的参数K设置为1,这意味着在prompt中只保留最近一轮的历史对话记录。

conversation.predict(input="你好,我是王老六。")

 

conversation.predict(input="1+1等于几?")

conversation.predict(input="你还记得我叫什么名字吗?")

 

 由于在第三轮对话的时候,prompt中只保留了上一轮对话的历史记录,且没有包含首轮对话记录,因此LLM并不记得在首轮对话时用户告诉LLM关于用户名字的信息,因此此时LLM无法给出用户的名字。下面我们再做一些简单的测试:

memory = ConversationBufferWindowMemory(k=1)

memory.save_context({"input": "Hi"},
                    {"output": "What's up"})
memory.save_context({"input": "Not much, just hanging"},
                    {"output": "Cool"})

memory.load_memory_variables({})

 这里我们也可以看到,虽然我们给memory组件手动增加了两组对话记录,但是最终它只保存了一组对话记录,这是因为我们定义memory时设置了窗口参数k=1所导致的。

ConversationTokenBufferMemory

ConversationTokenBufferMemory组件的功能也是限制prompt中存储对话记录的数量,与ConversationBufferWindowMemory不同的是ConversationBufferWindowMemory组件是根据窗口参数K来限制对话条数,而ConversationTokenBufferMemory组件是根据token数量来限制prompt中的对话条数:

#!pip install tiktoken

from langchain.memory import ConversationTokenBufferMemory
from langchain.llms import OpenAI
llm = ChatOpenAI(temperature=0.0)


memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)
memory.save_context({"input": "AI is what?!"},
                    {"output": "Amazing!"})
memory.save_context({"input": "Backpropagation is what?"},
                    {"output": "Beautiful!"})
memory.save_context({"input": "Chatbots are what?"}, 
                    {"output": "Charming!"})

上面我们在定义ConversationTokenBufferMemory时设置了参数max_token_limit的值为30,这意味着prompt中的历史对话数据的token数量不能超过30个token,接着我们给ConversationTokenBufferMemory组件手动增加了3轮对话记录,下面我们看看ConversationTokenBufferMemory组件最终能保存多少轮对话记录:

memory.load_memory_variables({})

 这里我们看到ConversationTokenBufferMemory组件保存了最近的30个token左右的对话记录,更早之前的对话记录已被丢弃,关于计算token的方法,不在本篇博客中说明。用户可以执行查阅相关资料。

ConversationSummaryMemory

ConversationSummaryMemory顾名思义会在prompt中保存历史对话记录的摘要,而不是完整的对话记录,下面我们来看一个例子:

from langchain.memory import ConversationSummaryBufferMemory
from langchain.chat_models import ChatOpenAI

#定义llm
llm = ChatOpenAI(temperature=0.0)

schedule ="""
上午 8 点与您的产品团队召开会议。\
您需要准备好幻灯片演示文稿。\
上午 9 点到中午 12 点有时间处理你的 LangChain 项目,\
这会进展得很快,因为 Langchain 是一个非常强大的工具。\
中午,在意大利餐厅与开车的顾客共进午餐\
距您一个多小时的路程,与您见面,了解人工智能的最新动态。\
请务必携带您的笔记本电脑来展示最新的LLM演示。\
"""
#定义ConversationSummaryBufferMemory组件
memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)
memory.save_context({"input": "你好"}, {"output": "什么事?"})
memory.save_context({"input": "没啥事情, 有个小问题请教"},
                    {"output": "好的,请说"})
memory.save_context({"input": "今天的日程安排是什么?"}, 
                    {"output": f"{schedule}"})

memory.load_memory_variables({})

在上面我们定义了一个ConversationSummaryMemory组件,并且设置了max_token_limit为100,这意味着prompt中的历史对话摘要的长度不能超过100个token。然后我们模拟了一组聊天记录,从返回的结果上看,memory组件中保存的不再是完整的对话记录,而是一段原始对话的摘要。保留摘要的好处是即保存了原始对话的内容的主要含义,又节省了token。

conversation = ConversationChain(
    llm=llm, 
    memory = memory,
    verbose=True
)

conversation.predict(input="一个好的演示应该展示什么?")

 参考资料

https://learn.deeplearning.ai/langchain/lesson/3/memory

### LangChain对话模型的工作原理 LangChain设计用于简化与多种语言模型的交互过程,特别是针对对话类的应用程序。通过定义统一的标准接口,使得开发者可以方便地切换不同类型的底层语言模型而不必担心具体的实现差异[^1]。 对于对话模型而言,LangChain不仅支持传统的以纯文本形式输入输出的语言模型,还特别优化了处理聊天记录这种结构化数据的能力——允许将多轮次的消息序列作为整体传递给模型,并接收同样格式化的回复内容来维持连贯自然的人机交流体验[^2]。 ### 实现方式 为了达成上述目标,LangChain引入了一系列专门面向会话管理的功能模块: - **记忆(Memory)**:这一特性模拟人类的记忆系统,能够在连续性的交谈中保存上下文信息,无论是短期互动中的即时状态还是长期跟踪用户偏好等方面都能发挥作用。这有助于构建更加个性化且情境感知度更高的虚拟助手服务[^4]。 ```python from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory() conversation_history = memory.load_memory_variables({}) print(conversation_history) # 更新内存变量 memory.save_context({"input": "你好"}, {"output": "很高兴见到你"}) ``` - **链(Chains)** 和 **代理(Agents)** :这两个概念共同构成了复杂业务逻辑执行的基础框架。“链条”代表了一种有序的任务流水线安排;而“代理人”则赋予了系统一定的决策权去动态选择合适的动作或工具调用来响应外界请求。两者相结合能够有效应对诸如客服咨询解答、任务调度指挥等多种实际需求场景下的挑战。 ```python from langchain.chains import LLMChain, SimpleSequentialChain from langchain.prompts import PromptTemplate from langchain.llms import OpenAI llm = OpenAI(temperature=0.9) template = "根据{question}给出一个简短的回答" prompt_template = PromptTemplate(input_variables=["question"], template=template) qa_chain = LLMChain(llm=llm, prompt=prompt_template) overall_chain = SimpleSequentialChain(chains=[qa_chain], verbose=True) answer = overall_chain.run("什么是LangChain?") print(answer) ``` ### 应用场景 得益于这些精心设计的技术要素,LangChain非常适合应用于如下领域: - 构建智能客服平台,帮助企业自动化处理客户询问; - 开发教育辅导软件,利用AI技术提供个性化的学习指导方案; - 打造智能家居控制系统,增强设备间协作效率的同时改善用户体验; - 设计游戏内NPC行为脚本,创造更为逼真丰富的剧情发展可能性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-派神-

感谢您慷慨解囊,我会更加努力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值