Memory的添加方式

from operator import itemgetterfrom langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_openai import ChatOpenAI
from pydantic import SecretStr
import os
from dotenv import load_dotenvload_dotenv()model = ChatOpenAI(api_key=SecretStr(os.environ.get("HUNYUAN_API_KEY", "")),  # 混元 APIKeybase_url="https://api.hunyuan.cloud.tencent.com/v1",  # 混元 endpointmodel="hunyuan-lite",  # 模型名称temperature=0
)
prompt = ChatPromptTemplate.from_messages([("system", "你是一个可以帮助人类的机器人"),MessagesPlaceholder(variable_name="history"),("human", "{input}"),]
)

MessagesPlaceholder 是 LangChain 中用于在聊天提示模板中插入消息列表的占位符。它主要用于处理对话历史和动态消息内容。

  • variable_name: 指定占位符的变量名,用于在运行时匹配对应的消息列表
  • 这个变量名需要与 Memory 组件的 memory_key 或 history_messages_key 保持一致
memory = ConversationBufferMemory(return_messages=True)

ConversationBufferMemory 是 LangChain 中最基础、最常用的记忆组件,用于存储对话历史。它将所有的对话消息按顺序保存在内存中,形成一个完整的对话缓冲区。
return_message参数:

  • True:返回消息对象列表(HumanMessage, AIMessage)
  • False:返回格式化的字符串
memory.load_memory_variables({})

load_memory_variables 是 LangChain 中所有 Memory 组件的核心方法,用于从记忆组件中加载记忆变量。它返回一个字典,包含当前存储的记忆内容。
示例:基于当前输入查询相关记忆
variables = memory.load_memory_variables({"input": "Where is Lisa?"})

# 增加一条链
chain = (RunnablePassthrough.assign(history=RunnableLambda(memory.load_memory_variables) | itemgetter("history"))| prompt| model
)

RunnablePassthrough 是一个特殊的可运行组件,用于在链中传递数据。它可以:

  • 直接传递输入数据
  • 使用assign方法添加新的键值对到输入字典中
  • 作为数据流的"桥梁"

RunnableLambda 是 LangChain LCEL 中用于将任意 Python 函数包装成可运行组件的工具。它允许您在链中插入自定义函数逻辑。
itemgetter 是 Python 标准库 operator 模块中的一个函数,用于从字典、列表等可索引对象中提取特定位置的元素。在 LangChain LCEL 中,它常用于数据流处理中提取特定的键值。

  • 这里 itemgetter(“history”) 从 memory.load_memory_variables() 返回的字典中提取 “history” 键对应的值。

这段代码构建了一个带记忆功能的对话链。RunnablePassthrough.assign() 在保持原始输入的同时,通过 RunnableLambda(memory.load_memory_variables) 从记忆组件中加载历史对话,然后用 itemgetter(“history”) 提取出对话历史列表,将其作为 history 字段添加到输入数据中。这样,当数据流经 prompt 模板时,历史对话会被注入到提示词中,最终让 model 能够基于完整的对话上下文生成回复,实现连续对话的记忆功能。

inputs = {"input": "你好,我是小明,很高兴认识你。"}
response = chain.invoke(inputs)
response

输出:

AIMessage(content='你好,小明!我也很高兴认识你,希望我们能成为好朋友😄 无论是聊天、玩耍还是其他方面,都可以随时找我哦。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 34, 'prompt_tokens': 18, 'total_tokens': 52, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'hunyuan-lite', 'system_fingerprint': '', 'id': '202f461322c14a2b37232dcb3e72cd56', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--e16a133a-6c92-46d0-a6a0-32deff6d2d7a-0', usage_metadata={'input_tokens': 18, 'output_tokens': 34, 'total_tokens': 52, 'input_token_details': {}, 'output_token_details': {}})
#保存记忆
memory.save_context(inputs, {"output": str(response.content)})
memory.load_memory_variables({})

输出:

{'history': [HumanMessage(content='你好,我是小明,很高兴认识你。', additional_kwargs={}, response_metadata={}),AIMessage(content='你好,小明!我也很高兴认识你,希望我们能成为好朋友😄 无论是聊天、玩耍还是其他方面,都可以随时找我哦。', additional_kwargs={}, response_metadata={})]}
inputs = {"input": "我是谁?"}
response = chain.invoke(inputs)
response
AIMessage(content='你是小明呀,我记得你。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 9, 'prompt_tokens': 57, 'total_tokens': 66, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'hunyuan-lite', 'system_fingerprint': '', 'id': '021589cde3e5617bedeacaeff5363d11', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--20559b8d-df04-447a-ad7f-a66524eabb0d-0', usage_metadata={'input_tokens': 57, 'output_tokens': 9, 'total_tokens': 66, 'input_token_details': {}, 'output_token_details': {}})

这个 AIMessage 显示模型回答"你是小明呀,我记得你",说明记忆功能正常工作。记忆的实现原理是:

  • 历史注入:通过 RunnablePassthrough.assign() 将 memory.load_memory_variables() 返回的历史对话作为 history 字段添加到输入中
  • 提示词构建:prompt 模板中的 MessagesPlaceholder(variable_name=“history”) 会将历史对话插入到提示词中,形成完整的上下文
  • 上下文感知:模型接收到包含历史对话的完整提示词,能够理解之前的对话内容,因此能够记住用户之前介绍过自己叫"小明"

使用Redis来实现长时记忆

先确保本地安装了redis sever并启动:

brew install redis
brew services start redis
pip install redis
from typing import Optionalfrom langchain_community.chat_message_histories import RedisChatMessageHistory
from langchain_openai import ChatOpenAI
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from pydantic import SecretStr
import os
from dotenv import load_dotenvload_dotenv()prompt = ChatPromptTemplate.from_messages([("system", "你是一个擅长{ability}的助手"),MessagesPlaceholder(variable_name="history"),("human", "{question}"),]
)chain = prompt | ChatOpenAI(api_key=SecretStr(os.environ.get("HUNYUAN_API_KEY", "")),  # 混元 APIKeybase_url="https://api.hunyuan.cloud.tencent.com/v1",  # 混元 endpointmodel="hunyuan-lite",  # 模型名称temperature=0
)chain_with_history = RunnableWithMessageHistory(chain,# 使用redis存储聊天记录lambda session_id: RedisChatMessageHistory(session_id, url="redis://localhost:6379/0"),input_messages_key="question",history_messages_key="history",
)# 每次调用都会保存聊天记录,需要有对应的session_id
chain_with_history.invoke({"ability": "历史", "question": "中国建都时间最长的城市是哪个?"},config={"configurable": {"session_id": "alex"}},
)

结果:

AIMessage(content='中国建都时间最长的城市是北京。北京作为中国的首都,有着悠久的历史和丰富的文化底蕴。早在西周时期,北京就是诸侯国的都城之一,称为“燕京”。在漫长的历史进程中,北京曾多次成为中国的都城,包括金朝的燕京、元朝的大都(今北京)、明朝的首都以及清朝的京师。经过这些朝代的统治,北京成为了中国政治、经济、文化的中心,至今已有超过800年的建都历史。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 105, 'prompt_tokens': 18, 'total_tokens': 123, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'hunyuan-lite', 'system_fingerprint': '', 'id': '51335c0cd7911a579bb1db283adb907b', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--64edee75-ae46-49de-9802-9f6a9ed21f53-0', usage_metadata={'input_tokens': 18, 'output_tokens': 105, 'total_tokens': 123, 'input_token_details': {}, 'output_token_details': {}})

RunnableWithMessageHistory 是 LangChain 中用于为任何可运行组件(Runnable)自动添加消息历史管理功能的包装器。它简化了记忆功能的实现,特别适合需要持久化对话历史的场景。
RedisChatMessageHistory 是 LangChain 中基于 Redis 数据库实现的消息历史存储类,用于持久化存储聊天对话历史。它继承自 BaseChatMessageHistory,提供了高性能、可扩展的对话历史管理功能。

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

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

相关文章

向Coze学习,我们把这些工作流也开源了

要说现在最火的工作流是什么,那非视频工作流莫属了。我每天也都能接到不少咨询短视频工作流的需求。 这大半年来我们团队也制作和整理了超过 100 工作流,其中很大一部分都是现在最火的视频工作流。 为了向Coze开源致敬,这次我们斑码团队也决…

Git 从零开始:完整项目上传指南

一、准备工作 1. 安装 Git Windows:下载安装包macOS:在终端运行 brew install gitLinux: # Ubuntu/Debian sudo apt update && sudo apt install git# CentOS/Fedora sudo yum install git2. 配置用户信息(首次使用&am…

【AI】入门级提示词模板:适用于ChatGPT、文心一言等主流模型

入门级提示词模板:适用于 ChatGPT、文心一言等主流模型**在当下这个人工智能飞速发展的时代,ChatGPT、文心一言等主流大模型已经广泛地融入到我们的工作与生活当中。不管是创作文章、生成代码,还是进行数据分析、获取创意灵感,这些…

如何解决 undetected_chromedriver 启动慢问题

要解决 undetected_chromedriver 启动慢的问题,可以从以下几个方面优化配置和代码: 1. 指定本地 Chrome 二进制路径 避免自动搜索 Chrome 路径,直接指定位置: driver uc.Chrome(browser_executable_pathrC:\Program Files\Google…

Python 程序设计讲义(42):组合数据类型——元组类型:创建元组

Python 程序设计讲义(42):组合数据类型——元组类型:创建元组 目录Python 程序设计讲义(42):组合数据类型——元组类型:创建元组一、元组的特征二、创建元组1、使用圆括号&#xff0…

windows 设置 vscode 免密远程

我们可以使用 vscode ssh 进行远程编辑文件项目。也可以使用 ssh 密匙 来实现免密登录。 本人在本地windows系统有多个密匙,使用 D:\SPB_Data\.ssh\id_rsa_local 进行本地设备进行登录。 在 vscode ssh 配置文件中添加 IdentityFile 配置 Host 本地设备ipHostName …

ubuntu自动搭建Android平台NDK编译环境

sh setup_ndk_env.sh自动下载NDK并解压 提取Android平台工具链 验证Android工具链 设置工具链变量 export CROSS_TRIPLE=aarch64_linux_android export CROSS_ROOT=/home/ubuntu/${CROSS_TRIPLE} export ANDROID_NDK=${CROSS_ROOT} export AS=${CROSS_ROOT}/bin/llvm-as exp…

添加捕捉吸附标识(使用QT+OpenGL开发三维CAD)

捕捉吸附标识怎么画出来?在点吸附的时候能够展示吸附标识可以让用户更直观的看到当前捕捉点,从而更准确的进行设计和绘制。 效果视频见原文:添加捕捉吸附标识(使用QTOpenGL开发三维CAD) 16.Add snap label 鼠标捕捉吸…

元宇宙中的“虫洞“:技术实现、应用场景与未来挑战

一、技术定义与核心架构1.1 虫洞的元宇宙隐喻概念来源:虫洞在物理学中是连接不同时空的通道,而在元宇宙中,这一概念被引申为连接不同虚拟世界的跨平台协议。英伟达Omniverse平台通过USD(通用场景描述)实现了这一隐喻&a…

使用GIS中基于森林的分类与回归模型来估算房屋价值

“基于森林的分类与回归”,它可以帮助分析师有效地设计、测试和部署预测模型。 基于森林的分类与回归应用了 Leo Breiman 的随机森林算法,这是一种用于分类和预测的流行监督机器学习方法。该工具允许分析师轻松整合表格属性、基于距离的要素和解释栅格来…

《 java 随想录》| LeetCode链表高频考题

前言:这是专门针对java语言讲解的算法解析(题目顺序大致参考《代码随想录》)思维导图操作链表删除节点删除链表中 D 节点时,只需将其前驱节点 C 的 next 指针指向 D 的下一个节点 E。添加节点​先让 新节点 F 的 next 指针 指向 C…

学习嵌入式的第三十一天-数据结构-(2025.7.23)网络协议封装

今天的内容主要是网络协议以及常用工具的介绍。协议头与数据封包/拆包数据封包示例:MAC|IP|TCP|hello| ———————————— IP数据报IP头信息默认20字节常用网络测试工具telnetnetstatpingarpwiresharktcpdumpssh2secure crt工具安装命令sudo ufw disable sud…

STL学习(十、常用排序、拷贝、替换算法)

目录 一、常用排序算法 1.sort (1) 内置数据类型 (2)自定义数据类型 2. random_shuffle(iterator beg, iterator end) 3.merge 4.reverse 二、常用的拷贝和替换算法 1.copy(起始不如直接赋值) 2.replace 3.replace_if 4.swap 一、常用排序算法 1.sort 函数原型 s…

【Datawhale AI夏令营】科大讯飞AI大赛(大模型技术)/夏令营:让AI理解列车排期表(Task3)

我没招了jpgimport pandas as pd import requests import re import json from tqdm import tqdm from datetime import datetime, timedeltadef calculate_stop_duration(arrival_time_str, departure_time_str):"""计算列车停留时长,处理跨天和异常…

【前后端】node mock.js+json-server

JSON-Server 一个在前端本地运行,可以存储json数据的server。前端开发可以模拟服务端接口数据,在本地搭建一个JSON服务,自己产生测试数据。 使用npm全局安装json-server :npm install -g json-server可以通过查看版本号&#xff0…

疏老师-python训练营-Day30模块和库的导入

浙大疏锦行 知识点回顾: 导入官方库的三种手段导入自定义库/模块的方式导入库/模块的核心逻辑:找到根目录(python解释器的目录和终端的目录不一致) 作业:自己新建几个不同路径文件尝试下如何导入 一.学习知识点 DAY30 …

神经网络知识讨论

AI 核心任务与数据类型:特征提取核心:AI 的核心是从原始输入数据中提取特征,CV 是将图像数据转换为计算机可识别的特征,NLP 是将文本数据转换为特征,数据挖掘是将结构化数据转换为特征。数据类型特点:图像数…

kotlin类型可为空,进行空安全的区别

定义一个可为空的变量b(String?),默认没有?是不可以为空的 var b: String? "Kotlin" b null print(b) // 输出 null默认不可为空 var a: String "Kotlin" a null // 编译器报错,null 不能被赋给不为空的变量空安全调用&#x…

Mysql事务基础

事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行 事务的特点 A(Atomicity&#…

FastAPI入门:安装、Pydantic、并发和并行

本系列参考FastAPI官方文档:https://fastapi.tiangolo.com/zh/python-types/安装 使用pip安装: pip install fastapi此外还需要 ASGI 服务器,生产环境可以使用 Uvicorn 或者 Hypercorn。 ASGI服务器:异步服务网关接口,…