诺盾网站建设/爱用建站官网
最近两年,我们见识了“百模大战”,领略到了大型语言模型(LLM)的风采,但它们也存在一个显著的缺陷:没有记忆。
在对话中,无法记住上下文的 LLM 常常会让用户感到困扰。本文探讨如何利用 LangChain,快速为 LLM 添加记忆能力,提升对话体验。
LangChain 是 LLM 应用开发领域的最大社区和最重要的框架。
1. LLM 固有缺陷,没有记忆
当前的 LLM 非常智能,在理解和生成自然语言方面表现优异,但是有一个显著的缺陷:没有记忆。
LLM 的本质是基于统计和概率来生成文本,对于每次请求,它们都将上下文视为独立事件。这意味着当你与 LLM 进行对话时,它不会记住你之前说过的话,这就导致了 LLM 有时表现得不够智能。
这种“无记忆”属性使得 LLM 无法在长期对话中有效跟踪上下文,也无法积累历史信息。比如,当你在聊天过程中提到一个人名,后续再次提及该人时,LLM 可能会忘记你之前的描述。
本着发现问题解决问题
的原则,既然没有记忆,那就给 LLM 装上记忆吧。
2. 记忆组件的原理
2.1. 没有记忆的烦恼
当我们与 LLM 聊天时,它们无法记住上下文信息,比如下图的示例:
2.2. 原理
如果将已有信息放入到 memory 中,每次跟 LLM 对话时,把已有的信息丢给 LLM,那么 LLM 就能够正确回答,见如下示例:
目前业内解决 LLM 记忆问题就是采用了类似上图的方案,即:将每次的对话记录再次丢入到 Prompt 里,这样 LLM 每次对话时,就拥有了之前的历史对话信息。
但如果每次对话,都需要自己手动将本次对话信息继续加入到history
信息中,那未免太繁琐。有没有轻松一些的方式呢?有,LangChain!LangChain 对记忆组件做了高度封装,开箱即用。
2.3. 长期记忆和短期记忆
在解决 LLM 的记忆问题时,有两种记忆方案,长期记忆和短期记忆。
- 短期记忆:基于内存的存储,容量有限,用于存储临时对话内容。
- 长期记忆:基于硬盘或者外部数据库等方式,容量较大,用于存储需要持久的信息。
3. LangChain 让 LLM 记住上下文
LangChain 提供了灵活的内存组件工具来帮助开发者为 LLM 添加记忆能力。
3.1. 单独用 ConversationBufferMemory 做短期记忆
Langchain 提供了 ConversationBufferMemory
类,可以用来存储和管理对话。
ConversationBufferMemory
包含input
变量和output
变量,input
代表人类输入,output
代表 AI 输出。
每次往ConversationBufferMemory
组件里存入对话信息时,都会存储到history
的变量里。
3.2. 利用 MessagesPlaceholder 手动添加 history
python复制代码from langchain.memory import ConversationBufferMemorymemory = ConversationBufferMemory(return_messages=True)
memory.load_memory_variables({})memory.save_context({"input": "我的名字叫张三"}, {"output": "你好,张三"})
memory.load_memory_variables({})memory.save_context({"input": "我是一名 IT 程序员"}, {"output": "好的,我知道了"})
memory.load_memory_variables({})from langchain.prompts import ChatPromptTemplate
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholderprompt = ChatPromptTemplate.from_messages([("system", "你是一个乐于助人的助手。"),MessagesPlaceholder(variable_name="history"),("human", "{user_input}"),]
)
chain = prompt | modeluser_input = "你知道我的名字吗?"
history = memory.load_memory_variables({})["history"]chain.invoke({"user_input": user_input, "history": history})user_input = "中国最高的山是什么山?"
res = chain.invoke({"user_input": user_input, "history": history})
memory.save_context({"input": user_input}, {"output": res.content})res = chain.invoke({"user_input": "我们聊得最后一个问题是什么?", "history": history})
执行结果如下:
3.3. 利用 ConversationChain 自动添加 history
我们利用 LangChain 的ConversationChain
对话链,自动添加history
的方式添加临时记忆,无需手动添加。一个链
实际上就是将一部分繁琐的小功能做了高度封装,这样多个链就可以组合形成易用的强大功能。这里链
的优势一下子就体现出来了:
ini复制代码from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholdermemory = ConversationBufferMemory(return_messages=True)
chain = ConversationChain(llm=model, memory=memory)
res = chain.invoke({"input": "你好,我的名字是张三,我是一名程序员。"})
res['response']res = chain.invoke({"input":"南京是哪个省?"})
res['response']res = chain.invoke({"input":"我告诉过你我的名字,是什么?,我的职业是什么?"})
res['response']
执行结果如下,可以看到利用ConversationChain
对话链,可以让 LLM 快速拥有记忆:
3.4. 对话链结合 PromptTemplate 和 MessagesPlaceholder
在 Langchain 中,MessagesPlaceholder
是一个占位符,用于在对话模板中动态插入上下文信息。它可以帮助我们灵活地管理对话内容,确保 LLM 能够使用最上下文来生成响应。
采用ConversationChain
对话链结合PromptTemplate
和MessagesPlaceholder
,几行代码就可以轻松让 LLM 拥有短时记忆。
ini复制代码prompt = ChatPromptTemplate.from_messages([("system", "你是一个爱撒娇的女助手,喜欢用可爱的语气回答问题。"),MessagesPlaceholder(variable_name="history"),("human", "{input}"),]
)
memory = ConversationBufferMemory(return_messages=True)
chain = ConversationChain(llm=model, memory=memory, prompt=prompt)res = chain.invoke({"input": "今天你好,我的名字是张三,我是你的老板"})
res['response']res = chain.invoke({"input": "帮我安排一场今天晚上的高规格的晚饭"})
res['response']res = chain.invoke({"input": "你还记得我叫什么名字吗?"})
res['response']
4. 使用长期记忆
短期记忆在会话关闭或者服务器重启后,就会丢失。如果想长期记住对话信息,只能采用长期记忆组件。
LangChain 支持多种长期记忆组件,比如Elasticsearch
、MongoDB
、Redis
等,下面以Redis
为例,演示如何使用长期记忆。
ini复制代码from langchain_community.chat_message_histories import RedisChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAImodel = ChatOpenAI(model="gpt-3.5-turbo",openai_api_key="sk-xxxxxxxxxxxxxxxxxxx",openai_api_base="https://api.aigc369.com/v1",
)prompt = ChatPromptTemplate.from_messages([("system", "你是一个擅长{ability}的助手"),MessagesPlaceholder(variable_name="history"),("human", "{question}"),]
)chain = prompt | modelchain_with_history = RunnableWithMessageHistory(chain,# 使用redis存储聊天记录lambda session_id: RedisChatMessageHistory(session_id, url="redis://10.22.11.110:6379/3"),input_messages_key="question",history_messages_key="history",
)# 每次调用都会保存聊天记录,需要有对应的session_id
chain_with_history.invoke({"ability": "物理", "question": "地球到月球的距离是多少?"},config={"configurable": {"session_id": "baily_question"}},
)chain_with_history.invoke({"ability": "物理", "question": "地球到太阳的距离是多少?"},config={"configurable": {"session_id": "baily_question"}},
)chain_with_history.invoke({"ability": "物理", "question": "地球到他俩之间谁更近"},config={"configurable": {"session_id": "baily_question"}},
)
LLM 的回答如下,同时关闭 session 后,直接再次提问最后一个问题,LLM 仍然能给出正确答案。
只要configurable
配置的session_id
能对应上,LLM 就能给出正确答案。
然后,继续查看redis
存储的数据,可以看到数据在 redis
中是以 list
的数据结构存储的。
5. 总结
本文介绍了 LLM 缺乏记忆功能的固有缺陷,以及记忆组件的原理,还讨论了如何利用 LangChain 给 LLM 装上记忆组件,让 LLM 能够在对话中更好地保持上下文。希望对你有帮助!
读者福利:如果大家对大模型感兴趣,这套大模型学习资料一定对你有用
对于0基础小白入门:
如果你是零基础小白,想快速入门大模型是可以考虑的。
一方面是学习时间相对较短,学习内容更全面更集中。
二方面是可以根据这些资料规划好学习计划和方向。
资源分享
大模型AGI学习包
资料目录
- 成长路线图&学习规划
- 配套视频教程
- 实战LLM
- 人工智能比赛资料
- AI人工智能必读书单
- 面试题合集
《人工智能\大模型入门学习大礼包》,可以扫描下方二维码免费领取!

1.成长路线图&学习规划
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
2.视频教程
很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。
3.LLM
大家最喜欢也是最关心的LLM(大语言模型)
《人工智能\大模型入门学习大礼包》,可以扫描下方二维码免费领取!

相关文章:

LangChain让LLM带上记忆
最近两年,我们见识了“百模大战”,领略到了大型语言模型(LLM)的风采,但它们也存在一个显著的缺陷:没有记忆。 在对话中,无法记住上下文的 LLM 常常会让用户感到困扰。本文探讨如何利用 LangCha…...

Word恢复历史文档,记好4个方法就足够
“我正在准备一个重要的报告,但是电脑突然就崩溃了,导致我的文档还没保存就被关闭了,大家有什么方法可以恢复Word历史文档吗?快给我出出主意吧!” 在数字化时代,文档编辑和保存已经成为我们日常工作和学习中…...
收银系统源码-千呼新零售2.0【线上营销】
千呼新零售2.0系统是零售行业连锁店一体化收银系统,包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体,线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货等连锁店使用。 详细介绍请查看&a…...

OnlyOffice测评
官方链接: https://www.onlyoffice.com/zh/office-suite.aspx https://www.onlyoffice.com/zh/pdf-editor.aspx OnlyOffice:引领办公效率的新标杆 在数字化时代的浪潮中,办公软件已经成为我们日常工作中不可或缺的一部分。然而,…...

UDS - 8 Application layer protocol
8 应用层协议 来自:ISO 14229-1-2020.pdf 8.1 一般定义 应用层协议应始终是确认消息传输,这意味着对于从客户端发送的每个服务请求,服务器应发送一个或多个相应的响应。 此规则的唯一例外是使用功能寻址或请求/指示指定不生成响应/确认的少数情况。为了不给系统带来许多不…...

二叉树公共最近祖先
文章目录 1. **二叉搜索树(Binary Search Tree, BST)**2. **一般二叉树****递归方法**:**迭代方法**: 案例展示二叉搜索树(BST)中查找LCA一般二叉树中查找LCA1. **使用哈希表存储父节点信息**2. **处理多个查询**3. **异常处理**结…...

智慧运维系统指导规范
随着信息技术的迅猛发展,智慧运维系统在现代企业中扮演着越来越重要的角色。为了提高运维效率、保障系统稳定运行,并制定一套科学、合理的智慧运维系统指导规范至关重要。本规范旨在为企业提供一套全面、系统的智慧运维管理方法和操作准则,以…...

最新自助下单彩虹云商城系统源码,含小储云商城模板免授权
最新彩虹商城源码,含小储云商城模板免授权,试用了一下还行,具体的大家可以看看 源码下载:https://download.csdn.net/download/m0_66047725/89405387 更多资源下载:关注我。...

头条系统-05-延迟队列精准发布文章-概述添加任务(db和redis实现延迟任务)、取消拉取任务定时刷新(redis管道、分布式锁setNx)
文章目录 延迟任务精准发布文章1)文章定时发布2)延迟任务概述2.1)什么是延迟任务2.2)技术对比2.2.1)DelayQueue2.2.2)RabbitMQ实现延迟任务2.2.3)redis实现 3)redis实现延迟任务4)延迟任务服务实现4.1)搭建heima-leadnews-schedule模块4.2)数据库准备4.3)安装redis4.4)项目集成…...

.gitignore git添加忽略文件
在项目的根目录下创建一个名为 .gitignore 的文件。在这个文件中,列出您希望Git忽略的文件和文件夹的名称或模式。 下面是一些基本的步骤和规则: 创建 .gitignore 文件:在项目根目录下创建一个名为 .gitignore 的文件。如果没有这个文件&…...

面向遥感图像的多阶段特征融合目标检测方法
源自:电子学报 作者:陈立 张帆 郭威 黄赟 注:若出现无法显示完全的情况,可 V 搜索“人工智能技术与咨询”查看完整文章 摘 要 遥感图像目标具有多尺度、大横纵比、多角度等特性,给传统的目标检测方法带来了新的…...

操作系统面试篇一
很多读者抱怨计算操作系统的知识点比较繁杂,自己也没有多少耐心去看,但是面试的时候又经常会遇到。所以,我带着我整理好的操作系统的常见问题来啦!这篇文章总结了一些我觉得比较重要的操作系统相关的问题比如 用户态和内核态、系统…...

OPenFast软件中的NRELOffshrBsline5MW_Onshore_ServoDyn.dat文件详解
我先简单概括一下,后续我再详细总结:文件“NRELOffshrBsline5MW_Onshore_ServoDyn.dat”是用于NREL 5.0 MW基准风力发电机的ServoDyn模块的输入文件。它定义了仿真控制、变桨控制、发电机和扭矩控制、偏航控制以及输出设置等各种参数。以下是主要内容的总…...

搭建rtmp/rtsp流媒体服务器的步骤
很多文章介绍使用ffmpeg推送和拉流,执行推流命令: D:\software\ffmpeg-7.0.1-full_build\bin\ffmpeg.exe -re -stream_loop -1 -i "D:\Video\汪汪队立大功\S07\001.mp4" -vcodec h264 -acodec aac -f flv rtmp://127.0.0.1/live/test110 经常…...

vue自定义事件传递数据
页面应用一个组件,采用自定义事件来传递参数 $emit是Vue实例的一个方法,它用于触发自定义事件。这些事件可以被父组件监听到,从而实现子组件向父组件的通信。 这种方法的好处在于,它可以让数据的流动保持单向,有助于…...

TensorBoard 安装与启动
安装:pip install tensorboard启动:tensorboard --logdir<events_directory_name> events_directory_name 为运行 tensorboard 后,产生的 events 文件所在的路径 博客参考:TensorBoard最全使用教程...

云计算运维工程师的突发状况处理
云计算运维工程师在应对突发的故障和紧急情况时,需要采取一系列迅速而有效的措施来最小化服务中断的时间并恢复系统的稳定性。 以下是一些关键步骤和策略: 快速响应: 立即识别并确认故障的性质和范围。通知团队成员和相关的利益相关者,确保所有人了解当前情况。故障诊断:…...

【CSS in Depth 2 精译】1.6 本章小结
1.6 本章小结 浏览器遵循层叠规则来确定哪些样式在哪些元素上生效;选择器优先级由选择器中的 id 数、class 类的个数以及标签名的个数来共同确定。优先级更高的声明将覆盖较低声明;当某些属性没有层叠值时,它们会从父元素继承一个样式值。这…...

FFmpeg源码:ff_h2645_extract_rbsp函数分析
一、ff_h2645_extract_rbsp函数的声明 ff_h2645_extract_rbsp函数的声明放在FFmpeg源码(本文演示用的FFmpeg源码版本为5.0.3,该ffmpeg在CentOS 7.5上通过10.2.1版本的gcc编译)的头文件libavcodec/h2645_parse.h中。 /*** Extract the raw (u…...

关于 AD21导入电子元器件放置“3D体”STEP模型失去3D纹理贴图 的解决方法
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/139969415 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...

【JAVA】利用Redisson和Spring实现高效物联温度控制链路,确保温度调节的准确性和效率,定时链路执行使用案例,一环扣一环
主要功能和场景 柔性调温策略:这个类主要用于管理一个温度调节流程,通过不同的策略(如策略1和策略2)来调节温度,确保设备或环境中的温度达到预设的目标。 紧急停止机制:在流程执行过程中,如果需…...

yolov8部署资料
1.labelImg安装: labelImg的安装过程可以参照以下步骤进行,这里以Windows操作系统为例: 1. 检查Python环境 首先,需要确认你的电脑上是否已经安装了Python。你可以通过Win R打开windows“运行”对话框,输入cmd&#x…...

迅为RK3588开发板支持LVDS信号,标准 HDMI信号,IMIPI信号
性能强--iTOP-3588开发板采用瑞芯微RK3588处理器,是全新一代ALoT高端应用芯片,采用8nm LP制程,搭载八核64位CPU,四核Cortex-A76和四核Cortex-A55架构,主频高达2.4GHZ,8GB内存,32GB EMMC。 四核心…...

页面开发感想
页面开发 1、 前端预览 2、一些思路 2.1、首页自定义element-plus的走马灯 :deep(.el-carousel__arrow){border-radius: 0%;height: 10vh; }需要使用:deep(标签)才能修改样式 或者 ::v-deep 标签 2.2、整体设计思路 <template><div class"card" style&…...

TikTok达人合作ROI分析:品牌如何评估带货效果
在当今的数字营销时代,TikTok已经成为品牌推广和消费者互动的重要平台。通过与TikTok达人的合作,品牌可以有效地提升其市场影响力和销售额。其中,评估这些合作的投入产出比(ROI)对于品牌来说是至关重要的。本文Nox聚星…...

硬件实用技巧:电容精度和常用容值表
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/140009042 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...

Java面试题:内存管理、类加载机制、对象生命周期及性能优化
1. 说一下 JVM 的主要组成部分及其作用? JVM包含两个子系统和两个组件:Class loader(类装载)、Execution engine(执行引擎)、Runtime data area(运行时数据区)、Native Interface(本地接口)。 Class loader(类装载):根据给定的全限定名类名(如:java.lang.Object)装载class文…...

什么是 Payment Request API?
Payment Request API 是一个 Web API,允许网页和 Web 应用程序向用户展示一个标准化的支付界面,以便用户快速、方便地进行付款。这种 API 的设计目的是为了简化用户支付过程,提高支付转化率,并提供一种更加统一的支付体验。 支持…...

【杂记-浅谈EBGP外部边界网关协议、IBGP内部边界网关协议】
一、EBGP概述 EBGP,External Border Gateway Protocol,即外部边界网关协议,EBGP主要用于在不同自治系统(AS)之间交换路由信息,每个AS都有一个独特的AS号码,用于区分不同的自治系统。EBGP通过AS…...

基于Java的宠物领养管理系统【附源码】
摘 要 近些年来,随着科技的飞速发展,互联网的普及逐渐延伸到各行各业中,给人们生活带来了十分的便利,宠物管理系统利用计算机网络实现信息化管理,使整个宠物领养的发展和服务水平有显著提升。 本文拟采用IDEA开发工具…...