之前我们聊过如何使用LangChain给LLM(大模型)装上记忆,里面提到对话链ConversationChainMessagesPlaceholder,可以简化安装记忆的流程。下文来拆解基于LangChain的大模型记忆方案。

1. 安装记忆的原理

1.1. 核心步骤

给LLM安装记忆的核心步骤就3个:

  1. 在对话之前调取之前的历史消息。
  2. 将历史消息填充到Prompt里。
  3. 对话结束后,继续将历史消息保存到到memory记忆中。

1.2. 常规使用方法的弊端

了解这3个核心步骤后,在开发过程中,就需要手动写代码实现这3步,这也比较麻烦,不仅代码冗余,而且容易遗漏这些模板代码。

为了让开发者聚焦于业务实现,LangChain贴心地封装了这一整套实现。使用方式如下。

2. 记忆的种类

记忆分为 短时记忆 和 长时记忆。

在LangChain中使用ConversationBufferMemory作为短时记忆的组件,实际上就是以键值对的方式将消息存在内存中。

如果碰到较长的对话,一般使用ConversationSummaryMemory对上下文进行总结,再交给大模型。或者使用ConversationTokenBufferMemory基于固定的token数量进行内存刷新。

如果想对记忆进行长时间的存储,则可以使用向量数据库进行存储(比如FAISS、Chroma等),或者存储到Redis、Elasticsearch中。

下面以ConversationBufferMemory为例,对如何快速安装记忆做个实践。

3. 给LLM安装记忆 — 非MessagesPlaceholder

3.1. ConversationBufferMemory使用示例

使用ConversationBufferMemory进行记住上下文:

memory = ConversationBufferMemory()
memory.save_context(
{"input": "你好,我的名字是半支烟,我是一个程序员"}, {"output": "你好,半支烟"}
)
memory.load_memory_variables({})

3.2. LLMChain+ConversationBufferMemory使用示例

# prompt模板
template = """
你是一个对话机器人,以下<history>标签中是AI与人类的历史对话记录,请你参考历史上下文,回答用户输入的问题。 历史对话:
<history>
{customize_chat_history}
</history> 人类:{human_input}
机器人: """ prompt = PromptTemplate(
template=template,
input_variables=["customize_chat_history", "human_input"],
)
memory = ConversationBufferMemory(
memory_key="customize_chat_history",
)
model = ChatOpenAI(
model="gpt-3.5-turbo",
) chain = LLMChain(
llm=model,
memory=memory,
prompt=prompt,
verbose=True,
) chain.predict(human_input="你知道我的名字吗?") # chain.predict(human_input="我叫半支烟,我是一名程序员") # chain.predict(human_input="你知道我的名字吗?")

此时,已经给LLM安装上记忆了,免去了我们写那3步核心的模板代码。

对于PromptTemplate使用以上方式,但ChatPromptTemplate因为有多角色,所以需要使用MessagesPlaceholder。具体使用方式如下。

4. 给LLM安装记忆 — MessagesPlaceholder

MessagesPlaceholder主要就是用于ChatPromptTemplate场景。ChatPromptTemplate模式下,需要有固定的格式。

4.1. PromptTemplate和ChatPromptTemplate区别

ChatPromptTemplate主要用于聊天场景。ChatPromptTemplate有多角色,第一个是System角色,后续的是Human与AI角色。因为需要有记忆,所以之前的历史消息要放在最新问题的上方。

4.2. 使用MessagesPlaceholder安装

最终的ChatPromptTemplate + MessagesPlaceholder代码如下:

chat_prompt = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的助手。"),
MessagesPlaceholder(variable_name="customize_chat_history"),
("human", "{human_input}"),
]
) memory = ConversationBufferMemory(
memory_key="customize_chat_history",
return_messages=True,
)
model = ChatOpenAI(
model="gpt-3.5-turbo",
) chain = LLMChain(
llm=model,
memory=memory,
prompt=chat_prompt,
verbose=True,
) chain.predict(human_input="你好,我叫半支烟,我是一名程序员。")

至此,我们使用了ChatPromptTemplate简化了构建prompt的过程。

5. 使用对话链ConversationChain

如果连ChatPromptTemplate都懒得写了,那直接使用对话链ConversationChain,让一切变得更简单。实践代码如下:

memory = ConversationBufferMemory(
memory_key="history", # 此处的占位符必须是history
return_messages=True,
)
model = ChatOpenAI(
model="gpt-3.5-turbo",
) chain = ConversationChain(
llm=model,
memory=memory,
verbose=True,
) chain.predict(input="你好,我叫半支烟,我是一名程序员。") # 此处的变量必须是input

ConversationChain提供了包含AI角色和人类角色的对话摘要格式。ConversationChain实际上是对Memory和LLMChain和ChatPrompt进行了封装,简化了初始化Memory和构建ChatPromptTemplate的步骤。

6. ConversationBufferMemory

6.1. memory_key

ConversationBufferMemory有一个入参是memory_key,表示内存中存储的本轮对话的,后续可以根据找到对应的值。

6.2. 使用"chat_history"还是"history"

ConversationBufferMemorymemory_key,有些资料里是设置是memory_key="history",有些资料里是"chat_history"

这里有2个规则,如下:

  • 在使用MessagesPlaceholderConversationBufferMemory时,MessagesPlaceholdervariable_nameConversationBufferMemorymemory_key可以自定义,只要相同就可以。比如这样:
chat_prompt = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的助手。"),
MessagesPlaceholder(variable_name="customize_chat_history"),
("human", "{input}"),
]
) memory = ConversationBufferMemory(
memory_key="customize_chat_history", # 此处的占位符可以是自定义
return_messages=True,
)
model = ChatOpenAI(
model="gpt-3.5-turbo",
) chain = ConversationChain(
llm=model,
memory=memory,
prompt=chat_prompt,
verbose=True,
) chain.predict(input="你好,我叫半支烟,我是一名程序员。") # 此处的变量必须是input
  • 如果只是使用ConversationChain又没有使用MessagesPlaceholder的场景下,ConversationBufferMemory的memory_key,必须用history

7. MessagesPlaceholder的使用场景

MessagesPlaceholder其实就是在与AI对话过程中的Prompt的一部分,它代表Prompt中的历史消息这部分。它提供了一种结构化和可配置的方式来处理这些消息列表,使得在构建复杂Prompt时更加灵活和高效。

说白了它就是个占位符,相当于把从memory读取的历史消息插入到这个占位符里了。

比如这样,就可以表示之前的历史对话消息:

chat_prompt = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的助手。"),
MessagesPlaceholder(variable_name="customize_chat_history"),
("human", "{human_input}"),
]
)

是否需要使用MessagesPlaceholder,记住2个原则:

  • PromptTemplate类型的模板,无需使用MessagesPlaceholder

  • ChatPromptTemplate 类型的聊天模板,需要使用MessagesPlaceholder。但是在使用ConversationChain时,可以省去创建ChatPromptTemplate的过程(也可以不省去)。省去和不省去在输出过程中有些区别,如下:

8. 总结

本文主要聊了安装记忆的基本原理、快速给LLM安装记忆、ConversationBufferMemoryMessagesPlaceholder的使用、对话链ConversationChain的使用和原理。希望对你有帮助!

=====>>>>>> 关于我 <<<<<<=====

本篇完结!欢迎点赞 关注 收藏!!!

原文链接:https://mp.weixin.qq.com/s/cRavfyu--AjBOO3-1aY0UA

拆解LangChain的大模型记忆方案的更多相关文章

  1. Sqlserver 高并发和大数据存储方案

    Sqlserver 高并发和大数据存储方案 随着用户的日益递增,日活和峰值的暴涨,数据库处理性能面临着巨大的挑战.下面分享下对实际10万+峰值的平台的数据库优化方案.与大家一起讨论,互相学习提高!   ...

  2. NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索

    矩形嵌套 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a& ...

  3. 千亿参数开源大模型 BLOOM 背后的技术

    假设你现在有了数据,也搞到了预算,一切就绪,准备开始训练一个大模型,一显身手了,"一朝看尽长安花"似乎近在眼前 -- 且慢!训练可不仅仅像这两个字的发音那么简单,看看 BLOOM ...

  4. 无插件的大模型浏览器Autodesk Viewer开发培训-武汉-2014年8月28日 9:00 – 12:00

    武汉附近的同学们有福了,这是全球第一次关于Autodesk viewer的教室培训. :) 你可能已经在各种场合听过或看过Autodesk最新推出的大模型浏览器,这是无需插件的浏览器模型,支持几十种数 ...

  5. tomcat中间件提交表单数据量过大警告处理方案

    http://www.bubuko.com/infodetail-976418.html http://www.cnblogs.com/yg_zhang/p/4248061.html tomcat中间 ...

  6. 优秀后端架构师必会知识:史上最全MySQL大表优化方案总结

    本文原作者“ manong”,原创发表于segmentfault,原文链接:segmentfault.com/a/1190000006158186 1.引言   MySQL作为开源技术的代表作之一,是 ...

  7. MySQL 大表优化方案(长文)

    当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.部署.运维的各种复杂度,一般以整型 ...

  8. PowerDesigner 学习:十大模型及五大分类

    个人认为PowerDesigner 最大的特点和优势就是1)提供了一整套的解决方案,面向了不同的人员提供不同的模型工具,比如有针对企业架构师的模型,有针对需求分析师的模型,有针对系统分析师和软件架构师 ...

  9. PowerDesigner 15学习笔记:十大模型及五大分类

    个人认为PowerDesigner 最大的特点和优势就是1)提供了一整套的解决方案,面向了不同的人员提供不同的模型工具,比如有针对企业架构师的模型,有针对需求分析师的模型,有针对系统分析师和软件架构师 ...

  10. 比赛:大奔的方案solution

    分析: 此题是小奔的方案的改进.小奔的方案思路:倒推,每次都从小到大排序并且保证小号在前,然后使每一个人分到的金币都是上一次加一,直到金币分完或者自己可以存活(投票率大于等于所需概率),如果不行就-1 ...

随机推荐

  1. 2D空间中比较两三角形相交与包含

    在处理UV重叠.CPU的ZFighting检测时会遇到2D空间中的三角形相交问题, 网上普遍是3D空间的相交解法,因此写本文研究下,不过虽然实现了需求, 但用的方法比较暴力. 效果如图: (鼠标拖动区 ...

  2. Linux上执行内存中的脚本和程序

    在Linux中可以不需要有脚本或者二进制程序的文件在文件系统上实际存在,只需要有对应的数据在内存中,就有办法执行这些脚本和程序. 原理其实很简单,Linux里有办法把某块内存映射成文件描述符,对于每一 ...

  3. 智能便捷_AIRIOT智慧充电桩管理解决方案

    现如今随着对可持续交通的需求不断增加,电动车市场正在迅速扩大,建设更多更智能的充电桩,并通过管理平台提高充电设施的可用性和效率成为一项重要任务.传统的充电桩管理平台在对充电设施进行管理过程中,存在如下 ...

  4. 数据驱动ddt安装3种方式_unittest_Python

    命令行安装   pip install ddt -i  管理员运行命令提示符 pycharm设置里安装 pycharm Python Packages里安装

  5. 牛逼:一张900w的数据表,17s执行的SQL优化到300ms?

    转载自   https://mp.weixin.qq.com/s/ru_B1aI0YrpXeSl-J01sHQ

  6. 你不知道的PageContext

    你不知道的PageContext 最近在文艺复兴,学习JSP和Servlet,此文为笔者学习记录. 本文分为以下几个部分: 前言 环境搭建 正文 总结 前言 在我们使用的项目中,存储数据最常用的非 S ...

  7. 用python字典统计CSV数据

    1.用python字典统计CSV数据的步骤和代码示例 为了使用Python字典来统计CSV数据,我们可以使用内置的csv模块来读取CSV文件,并使用字典来存储统计信息.以下是一个详细的步骤和完整的代码 ...

  8. OSG编译安装-MSVC

    OSG编译安装-MSVC 1.准备工作 1.1 环境 Windows10 Qt5.14.2 Microsoft Visual Studio2017 cmake-3.20.4-windows-x86_6 ...

  9. FLV 分析脚本

    一.需求 通过脚本,可以检查本地flv文件格式是否正确,可以打印每个Tag中的二进制内容 二.效果 可以看到VideoTag中开始处增加了一段SEI数据,并且可以看到部分字段,gameid.time. ...

  10. 微信iOS消息拦截插件教程-第一个tweak编译过程

    -安装好theos框架之后,下面用一个简单的例子进行说明编译过程 -新建一个代码目录 -进入terminal,cd到刚才的目录中 1.进入目录 2.执行/opt/theos/bin/nic.pl 3. ...