#LLM入门|Prompt#3.3_存储_Memory

news2024/11/14 14:47:24

在与语言模型交互时,一个关键问题:记忆缺失使得对话缺乏真正的连续性。
因此,接下来介绍 LangChain 中的储存模块,即如何将先前的对话嵌入到语言模型中的,使其具有连续对话的能力。
当使用 LangChain 中的储存(Memory)模块时,它旨在保存、组织和跟踪整个对话的历史,从而为用户和模型之间的交互提供连续的上下文。
LangChain 提供了多种储存类型。缓冲区储存允许保留最近的聊天消息,摘要储存则提供了对整个对话的摘要。实体储存则允许在多轮对话中保留有关特定实体的信息。
这些记忆组件都是模块化的,可与其他组件组合使用,从而增强机器人的对话管理能力。
储存模块可以通过简单的 API 调用来访问和更新,允许开发人员更轻松地实现对话历史记录的管理和维护。
此次课程主要介绍其中四种储存模块,其他模块可查看文档学习。

  • 对话缓存储存 (ConversationBufferMemory)
  • 对话缓存窗口储存 (ConversationBufferWindowMemory)
  • 对话令牌缓存储存 (ConversationTokenBufferMemory)
  • 对话摘要缓存储存 (ConversationSummaryBufferMemory)

短期记忆在LangChain中的大语言模型(LLM)里的重要知识点包括:

  1. 长期记忆与短期记忆的区别:LLM通过训练获得长期记忆,而短期记忆是用户与模型互动时产生的。
  2. 参数不变性:LLM的长期参数在训练完成后不会因用户输入而改变。
  3. 对话中的信息处理:LLM在对话过程中会暂时记住用户的输入和自己的输出,以便进行下一步的预测和生成响应。
  4. 信息的临时性:一旦LLM完成输出,它会“遗忘”之前的用户输入和自己的输出,这些信息仅作为短期记忆存在。
  5. 短期记忆的作用:短期记忆帮助LLM在特定会话中维持上下文的连贯性和相关性。

为了延长 LLM 短期记忆的保留时间,则需要借助一些外部储存方式来进行记忆,以便在用户与 LLM 对话中,LLM 能够尽可能的知道用户与它所进行的历史对话信息。

一、对话缓存储存

1.1 初始化对话模型

让我们先来初始化对话模型。

from langchain.chains import ConversationChain
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory

# 这里我们将参数temperature设置为0.0,从而减少生成答案的随机性。
# 如果你想要每次得到不一样的有新意的答案,可以尝试增大该参数。
llm = ChatOpenAI(temperature=0.0)  
memory = ConversationBufferMemory()


# 新建一个 ConversationChain Class 实例
# verbose参数设置为True时,程序会输出更详细的信息,以提供更多的调试或运行时信息。
# 相反,当将verbose参数设置为False时,程序会以更简洁的方式运行,只输出关键的信息。
conversation = ConversationChain(llm=llm, memory = memory, verbose=True ) 

1.2 第一轮对话

当我们运行预测(predict)时,生成了一些提示,如下所见,他说“以下是人类和 AI 之间友好的对话,AI 健谈“等等,这实际上是 LangChain 生成的提示,以使系统进行希望和友好的对话,并且必须保存对话,并提示了当前已完成的模型链。
conversation.predict(input=“你好, 我叫皮皮鲁”)

> Entering new  chain...
Prompt after formatting:
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:

Human: 你好, 我叫皮皮鲁
AI:

> Finished chain.





'你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?' 

1.3 第二轮对话

当我们进行第二轮对话时,它会保留上面的提示
conversation.predict(input=“1+1等于多少?”)

> Entering new ConversationChain chain...
Prompt after formatting:
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:
Human: 你好, 我叫皮皮鲁
AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?
Human: 1+1等于多少?
AI:

> Finished chain.





'1+1等于2。' 

1.4 第三轮对话

为了验证他是否记忆了前面的对话内容,我们让他回答前面已经说过的内容(我的名字),可以看到他确实输出了正确的名字,因此这个对话链随着往下进行会越来越长。
conversation.predict(input=“我叫什么名字?”)

> Entering new ConversationChain chain...
Prompt after formatting:
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:
Human: 你好, 我叫皮皮鲁
AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?
Human: 1+1等于多少?
AI: 1+1等于2。
Human: 我叫什么名字?
AI:

> Finished chain.





'你叫皮皮鲁。' 

1.5 查看储存缓存

储存缓存(buffer),即储存了当前为止所有的对话信息
print(memory.buffer)

Human: 你好, 我叫皮皮鲁
AI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?
Human: 1+1等于多少?
AI: 1+1等于2。
Human: 我叫什么名字?
AI: 你叫皮皮鲁。 

也可以通过load_memory_variables({})打印缓存中的历史消息。这里的{}是一个空字典,有一些更高级的功能,使用户可以使用更复杂的输入,具体可以通过 LangChain 的官方文档查询更高级的用法。
print(memory.load_memory_variables({})) {‘history’: ‘Human: 你好, 我叫皮皮鲁\nAI: 你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?\nHuman: 1+1等于多少?\nAI: 1+1等于2。\nHuman: 我叫什么名字?\nAI: 你叫皮皮鲁。’}

1.6 直接添加内容到储存缓存

我们可以使用save_context来直接添加内容到buffer中。

memory = ConversationBufferMemory()
memory.save_context({"input": "你好,我叫皮皮鲁"}, {"output": "你好啊,我叫鲁西西"})
memory.load_memory_variables({}) 

{‘history’: ‘Human: 你好,我叫皮皮鲁\nAI: 你好啊,我叫鲁西西’}
继续添加新的内容

memory.save_context({"input": "很高兴和你成为朋友!"}, {"output": "是的,让我们一起去冒险吧!"})
memory.load_memory_variables({}) 

{‘history’: ‘Human: 你好,我叫皮皮鲁\nAI: 你好啊,我叫鲁西西\nHuman: 很高兴和你成为朋友!\nAI: 是的,让我们一起去冒险吧!’}
可以看到对话历史都保存下来了!
当我们在使用大型语言模型进行聊天对话时,大型语言模型本身实际上是无状态的。语言模型本身并不记得到目前为止的历史对话。每次调用API结点都是独立的。储存(Memory)可以储存到目前为止的所有术语或对话,并将其输入或附加上下文到LLM中用于生成输出。如此看起来就好像它在进行下一轮对话的时候,记得之前说过什么。

二、对话缓存窗口储存

随着对话变得越来越长,所需的内存量也变得非常长。将大量的tokens发送到LLM的成本,也会变得更加昂贵,这也就是为什么API的调用费用,通常是基于它需要处理的tokens数量而收费的。
针对以上问题,LangChain也提供了几种方便的储存方式来保存历史对话。其中,对话缓存窗口储存只保留一个窗口大小的对话。它只使用最近的n次交互。这可以用于保持最近交互的滑动窗口,以便缓冲区不会过大。

2.1 添加两轮对话到窗口储存

我们先来尝试一下使用ConversationBufferWindowMemory来实现交互的滑动窗口,并设置k=1,表示只保留一个对话记忆。接下来我们手动添加两轮对话到窗口储存中,然后查看储存的对话。

from langchain.memory import ConversationBufferWindowMemory

# k=1表明只保留一个对话记忆
memory = ConversationBufferWindowMemory(k=1)  
memory.save_context({"input": "你好,我叫皮皮鲁"}, {"output": "你好啊,我叫鲁西西"})
memory.save_context({"input": "很高兴和你成为朋友!"}, {"output": "是的,让我们一起去冒险吧!"})
memory.load_memory_variables({}) 

{‘history’: ‘Human: 很高兴和你成为朋友!\nAI: 是的,让我们一起去冒险吧!’}
通过结果,我们可以看到窗口储存中只有最后一轮的聊天记录。

2.2 在对话链中应用窗口储存

接下来,让我们来看看如何在ConversationChain中运用ConversationBufferWindowMemory吧!

llm = ChatOpenAI(temperature=0.0)
memory = ConversationBufferWindowMemory(k=1)
conversation = ConversationChain(llm=llm, memory=memory, verbose=False  )

print("第一轮对话:")
print(conversation.predict(input="你好, 我叫皮皮鲁"))

print("第二轮对话:")
print(conversation.predict(input="1+1等于多少?"))

print("第三轮对话:")
print(conversation.predict(input="我叫什么名字?")) 
第一轮对话:
你好,皮皮鲁!很高兴认识你。我是一个AI助手,可以回答你的问题和提供帮助。有什么我可以帮你的吗?
第二轮对话:
1+1等于2。
第三轮对话:
很抱歉,我无法知道您的名字。 

注意此处!由于这里用的是一个窗口的记忆,因此只能保存一轮的历史消息,因此AI并不能知道你第一轮对话中提到的名字,他最多只能记住上一轮(第二轮)的对话信息

三、对话字符缓存储存

使用对话字符缓存记忆,内存将限制保存的token数量。如果字符数量超出指定数目,它会切掉这个对话的早期部分 以保留与最近的交流相对应的字符数量,但不超过字符限制。
添加对话到Token缓存储存,限制token数量,进行测试

from langchain.llms import OpenAI
from langchain.memory import ConversationTokenBufferMemory
memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)
memory.save_context({"input": "朝辞白帝彩云间,"}, {"output": "千里江陵一日还。"})
memory.save_context({"input": "两岸猿声啼不住,"}, {"output": "轻舟已过万重山。"})
memory.load_memory_variables({}) 

{‘history’: ‘AI: 轻舟已过万重山。’}
ChatGPT 使用一种基于字节对编码(Byte Pair Encoding,BPE)的方法来进行 tokenization (将输入文本拆分为token)。BPE 是一种常见的 tokenization 技术,它将输入文本分割成较小的子词单元。 OpenAI 在其官方 GitHub 上公开了一个最新的开源 Python 库 tiktoken(https://github.com/openai/tiktoken),这个库主要是用来计算%EF%BC%8C%E8%BF%99%E4%B8%AA%E5%BA%93%E4%B8%BB%E8%A6%81%E6%98%AF%E7%94%A8%E6%9D%A5%E8%AE%A1%E7%AE%97) tokens 数量的。相比较 HuggingFace 的 tokenizer ,其速度提升了好几倍。 具体 token 计算方式,特别是汉字和英文单词的 token 区别,具体可参考知乎文章(https://www.zhihu.com/question/594159910)。%E3%80%82)

四、对话摘要缓存储存

对话摘要缓存储存,使用 LLM 对到目前为止历史对话自动总结摘要,并将其保存下来。

4.1 使用对话摘要缓存储存

我们创建了一个长字符串,其中包含某人的日程安排。

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

# 创建一个长字符串
schedule = "在八点你和你的产品团队有一个会议。 \
你需要做一个PPT。 \
上午9点到12点你需要忙于LangChain。\
Langchain是一个有用的工具,因此你的项目进展的非常快。\
中午,在意大利餐厅与一位开车来的顾客共进午餐 \
走了一个多小时的路程与你见面,只为了解最新的 AI。 \
确保你带了笔记本电脑可以展示最新的 LLM 样例."

llm = ChatOpenAI(temperature=0.0)
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}"})

print(memory.load_memory_variables({})['history']) 

System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o’clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.

4.2 基于对话摘要缓存储存的对话链

基于上面的对话摘要缓存储存,我们新建一个对话链。

conversation = ConversationChain(llm=llm, memory=memory, verbose=True)
conversation.predict(input="展示什么样的样例最好呢?")
> Entering new ConversationChain chain...
Prompt after formatting:
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:
System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o'clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples.
Human: 展示什么样的样例最好呢?
AI:

> Finished chain.





'展示一些具有多样性和创新性的样例可能是最好的选择。你可以展示一些不同领域的应用,比如自然语言处理、图像识别、语音合成等。另外,你也可以展示一些具有实际应用价值的样例,比如智能客服、智能推荐等。总之,选择那些能够展示出我们AI技术的强大和多样性的样例会给客户留下深刻的印象。'

print(memory.load_memory_variables({})) # 摘要记录更新了
{‘history’: “System: The human introduces themselves as Pipilu and the AI introduces themselves as Luxixi. They express happiness at becoming friends and decide to go on an adventure together. The human asks about the schedule for the day. The AI informs them that they have a meeting with their product team at 8 o’clock and need to prepare a PowerPoint presentation. From 9 am to 12 pm, they will be busy with LangChain, a useful tool that helps their project progress quickly. At noon, they will have lunch with a customer who has driven for over an hour just to learn about the latest AI. The AI advises the human to bring their laptop to showcase the latest LLM samples. The human asks what kind of samples would be best to showcase. The AI suggests that showcasing diverse and innovative samples would be the best choice. They recommend demonstrating applications in different fields such as natural language processing, image recognition, and speech synthesis. Additionally, they suggest showcasing practical examples like intelligent customer service and personalized recommendations to impress the customer with the power and versatility of their AI technology.”}
通过对比上一次输出,发现摘要记录更新了,添加了最新一次对话的内容总结。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1516194.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BI数据分析案例详解:零售人货场分析该怎么做?

在当今快节奏、高竞争的商业环境中,人货场分析已成为企业成功的关键因素之一。科技的进步和数据的日益丰富使得企业对人流、货物流和场地布局的深入洞察变得愈发重要。通过科学的人货场分析,企业能更好地理解顾客行为、优化供应链、提高运营效率&#xf…

wpscan专门针对wordpress的安全扫描工具

说明 WPScan是一款专门针对WordPress的漏洞扫描工具,它使用Ruby编程语言编写。WPScan能够扫描WordPress网站中的多种安全漏洞,包括WordPress本身的漏洞、插件漏洞和主题漏洞。此外,WPScan还能扫描类似robots.txt这样的敏感文件,并…

Python打印输出Linux中最常用的linux命令之示例

一、Linux中的~/.bash_history文件说明: 该文件保存了linux系统中运行过的命令的历史。使用该文件来获取命令的列表,并统计命令的执行次数。统计时,只统计命令的名称,以不同参数调用相同的命令也视为同一命令。 二、示例代码&am…

什么是token?token是用来干嘛的?

相信很多从事计算机行业的朋友都听说过token这么个东西,但是其他行业的人就很少了解到token,下面就给大家来详细介绍一下token是什么意思?token是用来干嘛的这一块的内容,希望能帮助到大家。 🏻 token是什么意思 作为…

matplotlib-散点图

日期:2024.03.14 内容:将matplotlib的常用方法做一个记录,方便后续查找。 # 引入需要使用的库 from matplotlib import pyplot as plt# 设置画布大小 plt.figure(figsize(20,8),dpi 300)# 全局设置中文字体 plt.rcParams[font.sans-serif]…

DHCP中继实验(思科)

华为设备参考:DHCP中继实验(华为) 一,技术简介 DHCP中继,可以实现在不同子网和物理网段之间处理和转发DHCP信息的功能。如果DHCP客户机与DHCP服务器在同一个物理网段,则客户机可以正确地获得动态分配的IP…

L2-009 抢红包(Java)

没有人没抢过红包吧…… 这里给出N个人之间互相发红包、抢红包的记录,请你统计一下他们抢红包的收获。 输入格式 输入第一行给出一个正整数N(≤104),即参与发红包和抢红包的总人数,则这些人从1到N编号。随后N行&…

决策树 | 分类树回归树:算法逻辑

目录 一. 决策树(Decision Tree)1. 决策树的构建1.1 信息熵(Entropy)1.1.1 信息量&信息熵 定义1.1.2 高信息熵&低信息熵 定义1.1.3 信息熵 公式 1.2 信息增益(Information Gain)1.2.1 信息增益的计算1.2.2 小节 2. 小节2.1 算法分类2.2 决策树算法分割选择2.3 决策树算…

【2024 R1 版本更新】Ansys Fluent(下)

Ansys2024R1来了,小宇赶紧将新功能给大家汇报一下。GPU求解器功能势头最强,pyFluent又开始迭代了,CPU模型中又更新了很多功能,fluent meshing中的thin volume mesh功能也来了。

【2024 R1 版本更新】Ansys Fluent(上)

​​Ansys2024R1来了,小宇赶紧将新功能给大家汇报一下。GPU求解器功能势头最强,pyFluent又开始迭代了,CPU模型中又更新了很多功能,fluent meshing中的thin volume mesh功能也来了。

C++函数 加括号与不加括号

很多时候,我们会看到一些在创建对象时有的加括号有的不加括号 那么,这是什么情况呢? 总结:函数需要加上括号,加上括号会对函数初始化,不加括号可能导致未知错误 我们来验证一下。 1.基本数据类型不带括…

Linux编程4.4 网络编程-通信架构

TCP客户端服务器编程模型 1、客户端调用序列 调用socket函数创建套接字调用connect连接服务器端调用I/O函数(read/write)与服务器端通讯调用close关闭套接字 2、服务器端调用序列 调用socket函数创建套接字调用bind绑定本地地址和端口调用listen启动…

阿里云国际放行DDoS高防回源IP

如果源站服务器上设置了IP白名单访问控制(如安全软件、安全组),由于设置了DDoS高防后,回源IP是高防回源IP段,您需要将DDoS高防的回源IP段的地址加入安全软件和安全组的白名单中,避免DDoS高防的回源流量被误…

ElasticSearch之Nested对象

写在前面 本文看下es的nested嵌套对象相关内容。 1:es用了啥范式? 在关系型数据库中定义了6大数据库范式,即1,2,3,BC,4,5的NF(normal form),分别如下: 1N…

每一位教师都应该学会的“夸夸术”

在教育领域,我们常常强调正面教育和激励教育的重要性。这其中,教师们的“夸夸术”——也就是赞美和表扬学生的技巧——无疑是极为关键的一环。掌握并运用好“夸夸术”,不仅可以激发学生的学习兴趣和自信心,还能培养他们积极向上的…

武汉星起航:秉承客户至上服务理念,为创业者打造坚实后盾

在跨境电商的激荡浪潮中,武汉星起航电子商务有限公司一直秉持着以客户为中心的发展理念,为跨境创业者提供了独特的支持和经验积累,公司通过多年的探索和实践,成功塑造了一个以卖家需求为导向的服务平台,为每一位创业者…

C#快速入门基础

本篇文章从最基础的C#编程开始学习,经过非常优秀的面向对象编程思想和方法的学习,为C#编程打下基础。 第 01 章 C#开发环境之VS使用和.NET平台基础 1.1 Visual Studio 开发环境 1.1.1 硬件环境 i5CPUi5CPU(建议 4核 4线程或以上 &#xff0…

如何在Windows系统安装Node.js环境并制作html页面发布公网远程访问?

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

Pygame教程06:Event事件的类型+处理方法+监听鼠标事件

------------★Pygame系列教程★------------ Pygame教程01:初识pygame游戏模块 Pygame教程02:图片的加载缩放旋转显示操作 Pygame教程03:文本显示字体加载transform方法 Pygame教程04:draw方法绘制矩形、多边形、圆、椭圆、弧…

Redis到底是单线程还是多线程!,【工作感悟】

无论你是做 Python,PHP,JAVA,Go 还是 C#,Ruby 开发的,都离不开使用 Redis。 大部分程序员同学工作中都有用到 Redis,但是只限于会简单的使用,对Redis缺乏整体的认知。 无论是在大厂还是在中小…