08|记忆:通过Memory记住客户上次买花时的对话细节

无论是LLM还是代理都是无状态的,每次模型的调用都是独立于其他交互的。也就是说,我们每次通过API开始和大语言模型展开一次新的对话,它都不知道你其实昨天或者前天曾经和它聊过天了。

使用ConversationChain

from langchain import OpenAI
from langchain.chains import ConversationChain# 初始化大语言模型
llm = OpenAI(temperature=0.5,model_name="text-davinci-003"
)# 初始化对话链
conv_chain = ConversationChain(llm=llm)# 打印对话的模板
print(conv_chain.prompt.template)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:
{history}
Human: {input}
AI:
  • {history} 是存储会话记忆的地方,也就是人类和人工智能之间对话历史的信息。
  • {input} 是新输入的地方,你可以把它看成是和ChatGPT对话时,文本框中的输入

image.png

使用ConversationBufferMemory

在LangChain中,通过ConversationBufferMemory(缓冲记忆)可以实现最简单的记忆机制。

from langchain import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.conversation.memory import ConversationBufferMemory# 初始化大语言模型
llm = OpenAI(temperature=0.5,model_name="text-davinci-003")# 初始化对话链
conversation = ConversationChain(llm=llm,memory=ConversationBufferMemory()
)# 第一天的对话
# 回合1
conversation("我姐姐明天要过生日,我需要一束生日花束。")
print("第一次对话后的记忆:", conversation.memory.buffer)#输出:
第一次对话后的记忆: 
Human: 我姐姐明天要过生日,我需要一束生日花束。
AI:  哦,你姐姐明天要过生日,那太棒了!我可以帮你推荐一些生日花束,你想要什么样的?我知道有很多种,比如玫瑰、康乃馨、郁金香等等。
# 回合2
conversation("她喜欢粉色玫瑰,颜色是粉色的。")
print("第二次对话后的记忆:", conversation.memory.buffer)#输出
第二次对话后的记忆: 
Human: 我姐姐明天要过生日,我需要一束生日花束。
AI:  哦,你姐姐明天要过生日,那太棒了!我可以帮你推荐一些生日花束,你想要什么样的?我知道有很多种,比如玫瑰、康乃馨、郁金香等等。
Human: 她喜欢粉色玫瑰,颜色是粉色的。
AI:  好的,那我可以推荐一束粉色玫瑰的生日花束给你。你想要多少朵?我可以帮你定制一束,比如说十朵、二十朵或者更多?

实际上,这些聊天历史信息,都被传入了ConversationChain的提示模板中的 {history} 参数,构建出了包含聊天记录的新的提示输入。
有了记忆机制,LLM能够了解之前的对话内容,这样简单直接地存储所有内容为LLM提供了最大量的信息,但是新输入中也包含了更多的Token(所有的聊天历史记录),这意味着响应时间变慢和更高的成本。
但是token太长,也是需要解决。

使用ConversationBufferWindowMemory

ConversationBufferWindowMemory 是缓冲窗口记忆,它的思路就是只保存最新最近的几次人类和AI的互动。

from langchain import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.conversation.memory import ConversationBufferWindowMemory# 创建大语言模型实例
llm = OpenAI(temperature=0.5,model_name="text-davinci-003")# 初始化对话链
conversation = ConversationChain(llm=llm,memory=ConversationBufferWindowMemory(k=1)
)# 第一天的对话
# 回合1
result = conversation("我姐姐明天要过生日,我需要一束生日花束。")
print(result)
# 回合2
result = conversation("她喜欢粉色玫瑰,颜色是粉色的。")
# print("\n第二次对话后的记忆:\n", conversation.memory.buffer)
print(result)# 第二天的对话
# 回合3
result = conversation("我又来了,还记得我昨天为什么要来买花吗?")
print(result)第三回合的输出:
{'input': '我又来了,还记得我昨天为什么要来买花吗?', 
'history': 'Human: 她喜欢粉色玫瑰,颜色是粉色的。\nAI:  好的,那粉色玫瑰花束怎么样?我可以帮你找到一束非常漂亮的粉色玫瑰花束,你觉得怎么样?', 
'response': '  当然记得,你昨天来买花是为了给你喜欢的人送一束粉色玫瑰花束,表达你对TA的爱意。'}

如果设置 k=1,这意味着窗口只会记住与AI之间的最新的互动,即只保留上一次的人类回应和AI的回应。

使用ConversationSummaryMemory

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

  1. 汇总对话:此方法不是保存整个对话历史,而是每次新的互动发生时对其进行汇总,然后将其添加到之前所有互动的“运行汇总”中。
  2. 使用LLM进行汇总:该汇总功能由另一个LLM驱动,这意味着对话的汇总实际上是由AI自己进行的。
  3. 适合长对话:对于长对话,此方法的优势尤为明显。虽然最初使用的 Token 数量较多,但随着对话的进展,汇总方法的增长速度会减慢。与此同时,常规的缓冲内存模型会继续线性增长。
from langchain.chains.conversation.memory import ConversationSummaryMemory# 初始化对话链
conversation = ConversationChain(llm=llm,memory=ConversationSummaryMemory(llm=llm)
)第一回合的输出:
{'input': '我姐姐明天要过生日,我需要一束生日花束。', 
'history': '', 
'response': ' 我明白,你需要一束生日花束。我可以为你提供一些建议吗?我可以推荐一些花束给你,比如玫瑰,康乃馨,百合,仙客来,郁金香,满天星等等。挑选一束最适合你姐姐的生日花束吧!'}
第二回合的输出:
{'input': '她喜欢粉色玫瑰,颜色是粉色的。', 
'history': "\nThe human asked what the AI thinks of artificial intelligence. The AI thinks artificial intelligence is a force for good because it will help humans reach their full potential. The human then asked the AI for advice on what type of flower bouquet to get for their sister's birthday, to which the AI provided a variety of suggestions.", 
'response': ' 为了为你的姐姐的生日准备一束花,我建议你搭配粉色玫瑰和白色康乃馨。你可以在玫瑰花束中添加一些紫色的满天星,或者添加一些绿叶以增加颜色对比。这将是一束可爱的花束,让你姐姐的生日更加特别。'}
第三回合的输出:
{'input': '我又来了,还记得我昨天为什么要来买花吗?', 
'history': "\n\nThe human asked what the AI thinks of artificial intelligence. The AI thinks artificial intelligence is a force for good because it will help humans reach their full potential. The human then asked the AI for advice on what type of flower bouquet to get for their sister's birthday, to which the AI suggested pink roses and white carnations with the addition of purple aster flowers and green leaves for contrast. This would make a lovely bouquet to make the sister's birthday extra special.",
'response': ' 确实,我记得你昨天想买一束花给你的姐姐作为生日礼物。我建议你买粉红色的玫瑰花和白色的康乃馨花,再加上紫色的雏菊花和绿叶,这样可以让你的姐姐的生日更加特别。'}

这里,我们不仅仅利用了LLM来回答每轮问题,还利用LLM来对之前的对话进行总结性的陈述,以节约Token数量
通过对话历史的汇总来优化和管理 Token 的使用,ConversationSummaryMemory 为那些预期会有多轮的、长时间对话的场景提供了一种很好的方法。然而,这种方法仍然受到 Token 数量的限制。在一段时间后,我们仍然会超过大模型的上下文窗口限制

使用ConversationSummaryBufferMemory

对话总结缓冲记忆,它是一种混合记忆模型,结合了上述各种记忆机制,包括ConversationSummaryMemory 和 ConversationBufferWindowMemory的特点。这种模型旨在在对话中总结早期的互动,同时尽量保留最近互动中的原始内容。
它是通过max_token_limit这个参数做到这一点的。当最新的对话文字长度在300字之内的时候,LangChain会记忆原始对话内容;当对话文字超出了这个参数的长度,那么模型就会把所有超过预设长度的内容进行总结,以节省Token数量。

from langchain.chains.conversation.memory import ConversationSummaryBufferMemory# 初始化对话链
conversation = ConversationChain(llm=llm,memory=ConversationSummaryBufferMemory(llm=llm,max_token_limit=300))

image.png

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

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

相关文章

1.gradle编译和运行

1.在Windows 项目的根目录下使用.\gradlew.bat build命令进行编译。 如果出错的原因是连接超时: Exception in thread “main” java.io.IOException: Downloading from https://services.gradle.org/distributions/gradle-8.6-bin.zip failed: timeout (10000ms) a…

【华为OD机试】找座位【C卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 在一个大型体育场内举办了一场大型活动,由于疫情防控的需要, 要求每位观众的必须间隔至少一个空位才允许落座。 现在给出一排观众座位分布图,座位中存在已落座的观众,请计算出, 在不移…

嵌入式会越来越卷吗?

嵌入式会越来越卷吗? 当谈及嵌入式系统时,我们探究的不仅是一种科技,更是一个日益多元与普及的趋势。嵌入式系统,作为一种融入更大系统中的计算机硬件和软件,旨在执行特定功能或任务。但这个看似特定的系统概念,却在发…

黑马程序员——javase进阶——day09——线程安全,死锁,状态,通讯,线程池

目录: 线程安全 线程安全产生的原因线程的同步同步代码块同步方法Lock锁线程死锁 概述:产生条件:代码实践线程的状态线程通信线程池 线程使用存在的问题线程池的介绍线程池使用的大致流程线程池的好处Java提供好的线程池线程池处理Runnable任务线程池处理Callable任…

LeetCode刷题记录:(11)组合(初识回溯算法)

leetcode传送通道 暂时记录&#xff0c;这篇没啥营养&#xff0c;不用看了 class Solution {List<List<Integer>> result new ArrayList<>(); // 存所有组合List<Integer> path new LinkedList<>(); //存每一个组合public List<List<Int…

世界第一个AI软件工程师问世!

2024年3月13日&#xff0c;科技公司Cognition推出了世界上第一位人工智能软件工程师Devin AI。这项创新有望利用人工智能编码和机器学习的力量加快发展。Devin AI不仅仅是帮助&#xff1b;它是一个成熟的队友&#xff0c;发挥智能编码自动化和自主人工智能编码的魔力&#xff0…

SQL注入无回显,利用DNSlog构造方式

没有回显的情况下&#xff0c;一般编写脚本&#xff0c;进行自动化注入。但与此同时&#xff0c;由于 防火墙的存在&#xff0c;容易被封禁 IP&#xff0c;可以尝试调整请求频率&#xff0c;有条件的使用代理池进行请求。 此时也可以使用 DNSlog 注入&#xff0c;原理就是把服…

salesforce生产环境如何删除触发器

由于生产环境不能直接删除触发器&#xff0c;所以需要在sandbox中先让触发器inactive再部署到生产环境&#xff0c;就可以让触发器失效了。

C++基础6:面向对象程序设计思想和类(上)

此专栏为移动机器人知识体系下的编程语言中的 C {\rm C} C从入门到深入的专栏&#xff0c;参考书籍&#xff1a;《深入浅出 C {\rm C} C》(马晓锐)和《从 C {\rm C} C到 C {\rm C} C精通面向对象编程》(曾凡锋等)。 6.面向对象程序设计思想和类 6.1 程序设计思想 6.1.1 结构化…

春招第一面-京东

宝子们&#xff0c;卷起来吧&#xff01; 1、自我介绍 2、实习项目 3、实习项目分库分表怎么做的&#xff1f; 4、分布式主键用的是什么&#xff1f;雪花ID是怎么样的&#xff0c;有什么问题&#xff1f; 5、实习业务具体是干嘛 6、你们这个业务为啥不用es&#xff0c;如…

vscode中自动生成python的UML类图的插件

需求&#xff1a; 阅读一些源码时&#xff0c;想直观的看一下它的UML类关系图。 搜索发现已有相关的软件可以实现这个功能。 Linux系统&#xff1a; 安装pylint pip3 install pylint 使用pyreverse命令 pyreverse -ASmy -o png test.py 生成名为classes.png的UML类图 参考…

苍穹外卖-day08:导入地址簿功能代码(单表crud)、用户下单(业务逻辑)、订单支付(业务逻辑,cpolar软件)

苍穹外卖-day08 课程内容 导入地址簿功能代码用户下单订单支付 功能实现&#xff1a;用户下单、订单支付 用户下单效果图&#xff1a; 订单支付效果图&#xff1a; 1. 导入地址簿功能代码&#xff08;单表crud&#xff09; 1.1 需求分析和设计 1.1.1 产品原型&#xff08…

苍穹外卖-day04:项目实战-套餐管理(新增套餐,分页查询套餐,删除套餐,修改套餐,起售停售套餐)业务类似于菜品模块

苍穹外卖-day04 课程内容 新增套餐套餐分页查询删除套餐修改套餐起售停售套餐 要求&#xff1a; 根据产品原型进行需求分析&#xff0c;分析出业务规则设计接口梳理表之间的关系&#xff08;分类表、菜品表、套餐表、口味表、套餐菜品关系表&#xff09;根据接口设计进行代…

rocky9 编写一键安装mysql 的sh脚本

基本操作步骤 1、虚拟机最小化安装rocky9系统&#xff0c;安装后克隆一个系统&#xff1b;1个用来获取下载的rpm包&#xff0c;一个用来编写sh 测试脚本&#xff1b; 2、修改虚拟机的 yum配置文件&#xff0c;获取获取rpm程序 &#xff1a;启用缓存&#xff0c;并修改yum下载…

比特币,区块链及相关概念简介(二)

目录 什么是挖矿挖矿是否代表资源浪费为什么挖矿能维持比特币网络安全性&#xff1f;是怎么做到的呢&#xff1f;该系列文章链接 以下内容结合了chatgpt 3.5以及网络文章。 用于学习记录。 简介&#xff1a; 介绍了什么是挖矿&#xff0c;挖矿是否代表资源浪费&#xff0c;挖矿…

四个按键控制数码管分别显示6,8 ,A,F

#include<reg52.h> typedef unsigned int u16; //重新定义系统默认数据类型 typedef unsigned char u8; #define SMG_A_DP_PORT P0 //使用宏定义定义P0端口&#xff0c;数码管段码口 …

【数据结构与算法】:非递归实现快速排序、归并排序

&#x1f525;个人主页&#xff1a; Quitecoder &#x1f525;专栏&#xff1a;数据结构与算法 上篇文章我们详细讲解了递归版本的快速排序&#xff0c;本篇我们来探究非递归实现快速排序和归并排序 目录 1.非递归实现快速排序1.1 提取单趟排序1.2 用栈实现的具体思路1.3 代码…

Linux:git的基础操作

git的下载 版本控制系统一般分为两种&#xff0c;集中式版本控制系统&#xff0c;分布式版本控制系统 什么是集中式版本控制系统&#xff1a;版本库集中存放在中央服务器&#xff0c;工作时候使用自己的电脑&#xff0c;当工作时候在中央服务器上拉取最新版本的代码&#xff0c…

U盘变身“本地磁盘”?数据恢复与防范策略大揭秘

一、突发状况&#xff1a;U盘秒变“本地磁盘” 在日常工作生活中&#xff0c;U盘凭借其便携性和大容量&#xff0c;成为我们存储和传输数据的重要工具。然而&#xff0c;有时我们会遇到这样一个棘手的问题&#xff1a;原本应显示为可移动磁盘的U盘&#xff0c;在插入电脑后却突…

ModuleNotFoundError: No module named,(python跨文件导包)

方法一&#xff1a;在文件中开头加入&#xff1a; import os import sys REPO os.path.dirname(os.path.dirname(os.path.realpath(__file__))) sys.path.append(REPO) 方法二&#xff1a;直接添加环境变量&#xff08;比较好用&#xff09; # 添加环境变量export PYTHONPAT…