【LangChain】存储与管理对话历史
0. 代码演示
from langchain_community.chat_message_histories import SQLChatMessageHistorydef get_session_history(session_id):# 通过 session_id 区分对话历史,并存储在 sqlite 数据库中return SQLChatMessageHistory(session_id, "sqlite:///memory.db")
from langchain_core.messages import HumanMessage
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI
from langchain.schema.output_parser import StrOutputParsermodel = ChatOpenAI(model="gpt-4o-mini", temperature=0)runnable = model | StrOutputParser()runnable_with_history = RunnableWithMessageHistory(runnable, # 指定 runnableget_session_history, # 指定自定义的历史管理方法
)runnable_with_history.invoke([HumanMessage(content="你好,我叫麦酷")],config={"configurable": {"session_id": "wzr"}},
)'你好,麦酷!很高兴再次见到你。有什么想聊的或者需要帮助的呢?'runnable_with_history.invoke([HumanMessage(content="你知道我叫什么名字")],config={"configurable": {"session_id": "wzr"}},
)'是的,你叫麦酷。有什么我可以帮助你的吗?'runnable_with_history.invoke([HumanMessage(content="你知道我叫什么名字")],config={"configurable": {"session_id": "test"}},
)'抱歉,我无法知道你的名字。你可以告诉我你的名字,或者如果你有其他问题,我也很乐意帮助你!'
代码功能解析
这段代码实现了一个带持久化历史记忆的对话系统,通过 session_id 区分不同用户的对话历史,并存储到 SQLite 数据库中。以下是核心模块的解析:
1. 对话历史管理模块
from langchain_community.chat_message_histories import SQLChatMessageHistorydef get_session_history(session_id):# 每个 session_id 对应独立的数据库记录return SQLChatMessageHistory(session_id=session_id, connection_string="sqlite:///memory.db" # SQLite 数据库路径)
- 核心作用: 为每个用户/会话创建独立的历史存储
- 技术细节:
- 使用 SQLite 数据库存储对话记录(文件名为
memory.db) session_id作为主键区分不同对话(如用户ID、设备ID等)- 实际表结构包含
id,session_id,message,timestamp等字段
- 使用 SQLite 数据库存储对话记录(文件名为
- 扩展性:可替换为其他存储后端(如PostgreSQL、Redis)
2. 对话链构建模块
from langchain_core.runnables.history import RunnableWithMessageHistorymodel = ChatOpenAI(model="gpt-4o-mini", temperature=0)
runnable = model | StrOutputParser() # 基础问答链runnable_with_history = RunnableWithMessageHistory(runnable=runnable, # 原始链get_session_history=get_session_history, # 历史管理方法input_messages_key="input", # 输入消息字段名(默认)history_messages_key="history" # 历史消息字段名(默认)
)
- 组件连接:
- 关键参数:
input_messages_key: 输入消息在上下文中的键名history_messages_key: 历史消息的键名(模型需支持上下文窗口)
3. 对话调用示例
response = runnable_with_history.invoke([HumanMessage(content="你好,我叫麦酷")], # 当前消息config={"configurable": {"session_id": "wzr"}} # 指定会话
)
- 执行流程:
- 根据
session_id="wzr"从数据库加载历史消息 - 将当前消息
"你好,我叫麦酷"添加到历史记录 - 组合历史消息 + 当前输入 → 发送给 GPT-4
- 解析模型输出 → 返回最终响应
- 将新消息对(用户输入 + 模型回复)保存到数据库
- 根据
4. 数据库操作示例
假设进行三次连续对话:
| 调用顺序 | 用户输入 | 数据库存储内容(session_id=“wzr”) |
|---|---|---|
| 第一次 | “你好,我叫麦酷” | [Human: 你好,我叫麦酷, AI: 回复1] |
| 第二次 | “记住我的名字了吗?” | 添加 [Human: 记住我的名字了吗?, AI: 回复2] |
| 第三次 | “我是谁?” | 添加 [Human: 我是谁?, AI: 回复3] |
模型在第三次调用时,实际接收的上下文包含前两次对话历史,因此能正确回答姓名。
5. 关键技术点
5.1 历史注入机制
# 伪代码展示实际发送给模型的内容
full_context = [{"role": "user", "content": "你好,我叫麦酷"},{"role": "assistant", "content": "回复1"},{"role": "user", "content": "记住我的名字了吗?"},{"role": "assistant", "content": "回复2"},{"role": "user", "content": "我是谁?"}
]
response = model.generate(full_context)
5.2 自动历史管理
- 自动追加:每次调用自动添加新消息到历史
- 上下文截断:当历史超过模型窗口时需处理(此示例未展示)
6. 优化建议
6.1 历史长度控制
from langchain.memory import ConversationBufferWindowMemory# 仅保留最近3轮对话
memory = ConversationBufferWindowMemory(k=3)
runnable_with_history.memory = memory
6.2 自定义历史格式
def custom_history_formatter(history):return "\n".join([f"{msg.type}: {msg.content}" for msg in history])chain = runnable_with_history.configure(history_formatter=custom_history_formatter
)
6.3 多模态历史支持
from langchain_core.messages import ImageMessage# 支持图片消息存储
history.add_message(ImageMessage(content="path/to/image.png"))
7. 常见问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 数据库无写入 | 文件权限问题 | 检查 memory.db 可写权限 |
| 历史消息未生效 | session_id 不一致 | 确认每次调用使用相同 session_id |
| 响应时间越来越长 | 历史消息过多未截断 | 添加窗口记忆或摘要记忆 |
| 中文内容存储乱码 | 数据库编码问题 | 使用 sqlite:///memory.db?charset=utf8 |
8. 典型应用场景
-
客服系统
# 根据用户手机号保持对话连续性 session_id = user.phone_number -
教育机器人
# 为每个学生保存学习进度 session_id = f"{student_id}-{course_id}" -
多设备同步
# 通过用户账户实现跨设备同步 session_id = user.account_id
该代码展示了如何快速构建具备长期记忆能力的对话系统,通过简洁的接口实现复杂的状态管理,是开发智能对话应用的基石。
通过 LCEL,还可以实现
- 配置运行时变量:https://python.langchain.com/v0.2/docs/how_to/configure/
- 故障回退:https://python.langchain.com/v0.2/docs/how_to/fallbacks
- 并行调用:https://python.langchain.com/v0.2/docs/how_to/parallel/
- 逻辑分支:https://python.langchain.com/v0.2/docs/how_to/routing/
- 动态创建 Chain: https://python.langchain.com/v0.2/docs/how_to/dynamic_chain/
更多例子:https://python.langchain.com/v0.2/docs/how_to/lcel_cheatsheet/
相关文章:
【LangChain】存储与管理对话历史
0. 代码演示 from langchain_community.chat_message_histories import SQLChatMessageHistorydef get_session_history(session_id):# 通过 session_id 区分对话历史,并存储在 sqlite 数据库中return SQLChatMessageHistory(session_id, "sqlite:///memory.d…...
[machine learning] MACS、MACs、FLOPS、FLOPs
本文介绍机器学习中衡量一个模型计算复杂度的四个指标:MACS、MACs、FLOPS、FLOPs。 首先从含义上讲,可以分类两类:MACS/FLOPS和MACs/FLOPs。MACs/FLOPs表示总的操作数(后缀s可以看成是表示复数),MACS/FLOPS表示每秒可以执行的操作…...
学习笔记-AMD CPU 命名
AMD的AI处理器主要分为锐龙AI 1代(基于Zen4架构XDNA 1 NPU)和锐龙AI 2代(基于Zen5架构XDNA 2 NPU),以下是两代的详细说明: 一、锐龙AI 1代(2024年发布) 1. 命名规则 结构…...
【Javascript】计算器(Calculator)网页设计案例
代码如下: <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>计算器</title…...
Stable Diffusion模型高清算法模型类详解
Stable Diffusion模型高清算法模型类详细对比表 模型名称核心原理适用场景参数建议显存消耗细节增强度优缺点4x-UltraSharp残差密集块(RDB)结构优化纹理生成真实人像/建筑摄影重绘幅度0.3-0.4,分块尺寸768px★★★★★☆皮肤纹理细腻,但高对比场景易出现…...
十大经典排序算法简介
一 概述 本文对十大经典排序算法做简要的总结(按常用分类方式排列),包含核心思想、时间/空间复杂度及特点。 二、比较类排序 1. 冒泡排序 (BUBBLE SORT) 思想:重复交换相邻逆序元素,像气泡上浮 复杂度: 时间:O(n^2)(最好情况O(n)) 空间:O(1) 特点:简单但效率低,稳…...
迷你世界脚本玩家接口:Player
玩家接口:Player 彼得兔 更新时间: 2024-07-28 17:49:05 继承自 Actor 具体函数名及描述如下: 序号 函数名 函数描述 1 getAttr(...) 玩家属性获取 2 setAttr(...) 玩家属性设置 3 getHostUin(...) 获取房主uin 4 isMainPlayer(...) …...
探秘 C 语言:编程世界的基石与传奇
一、C 语言的前世今生 C 语言诞生于 20 世纪 70 年代,由贝尔实验室的丹尼斯・里奇(Dennis Ritchie)开发。它最初是为了配合 UNIX 操作系统的开发,旨在提供一种高效、灵活且可移植的编程语言。在那个硬件资源有限的年代࿰…...
docker:Dockerfile案例之自定义centos7镜像
1 案例需求 自定义centos7镜像。要求: 默认登录路径为 /usr可以使用vim 2 实施步骤 编写dockerfile脚本 vim centos_dockerfile 内容如下: #定义父镜像 FROM centos:7#定义作者信息 MAINTAINER handsome <handsomehandsome.com># 设置阿里云…...
1、语言的本质
语言的本质 1.1 语言的产生生物重演律 1.2 语言的本质1.3 语系1.4 文字的起源汉字的构成和使用 后记 语言是人类传递信息的工具,其本质是信息的载体。 语音和文字是构成语言的两个基本属性,语音是语言承载的物理信号,文字是记录语言的逻辑符…...
学习笔记:IC存储总结(ROM,RAM, EEPROM, Flash, SRAM, DRAM, DDL)
一,概述 半导体存储器是一种可以存储大量二值信息的半导体器件。在电子计算机及一些其他的数字系统的工作过程中,需要对大量的数据进行储存。由于数据处理的数据量和运算速度的要求,因此把存储量和存取速度作为衡量存储器的重要指标。 在电子…...
Scala:统计每个单词出现的个数并打印
目录 问题拆解: 解题步骤: 1. 拆分所有字符串为单词 2. 遍历所有单词并统计 3. 打印结果 基础版代码实现: 代码解释: 输出结果: 为什么这样设计? 继承的APP是个啥? 使用高阶函数式编…...
C++前缀和
个人主页:[PingdiGuo_guo] 收录专栏:[C干货专栏] 大家好,今天我们来了解一下C的一个重要概念:前缀和 目录 1.什么是前缀和 2.前缀和的用法 1.前缀和的定义 2.预处理前缀和数组 3.查询区间和 4.数组中某个区间的和是否为特定…...
图解MOE大模型的7个核心问题并探讨DeepSeekMoE的专家机制创新
原文地址:https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-mixture-of-experts #mermaid-svg-FU7YUSIfuXO6EVHa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-FU7YUSIfuXO6EVHa .error-icon{fill…...
SpringBoot项目集成ElasticSearch
1. 项目背景 处于失业找工作的阶段,随便写写吧~ 没啥背景,没啥意义,Java后端越来越卷了。第一学历不是本科,感觉真的是没有一点路可走。 如果有路过的小伙伴,如果身边还有坑位,不限第一学历的话࿰…...
DeepSeek大模型深度解析:架构、技术与应用全景
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。https://www.captainbed.cn/north 文章目录 一、大模型时代与DeepSeek的定位1.1 大模型发展历程回顾大模型发展历程时间轴(20…...
SQL AND OR 操作符详解
SQL AND & OR 操作符详解 在SQL(结构化查询语言)中,AND 和 OR 是两种非常重要的逻辑操作符,它们用于在查询条件中组合多个条件。理解并正确使用这些操作符对于编写有效的SQL查询至关重要。 引言 在处理数据库查询时,我们常常需要根据多个条件来筛选数据。AND 和 OR…...
Dubbo+Zookeeper
Apache ZooKeeper 通过当前页面下载Zookeeper 在这里启动zookeeper 可以根据这个页面简单学习一下,但是没有集成mysql,也会出现一些报错,且在这之后我们要使用的管理页面是vue的dubbo-admin dubbo学习三:springboot整合dubbozo…...
从源到目标:深度学习中的迁移学习与领域自适应实践
引言:数据驱动的智能时代与迁移挑战 在深度学习快速发展的今天,模型训练对数据量和质量的依赖成为核心瓶颈。面对新场景时,标注数据不足、数据分布差异等问题常导致模型性能骤降。迁移学习(Transfer Learning)与领域自…...
从厨电模范到数字先锋,看永洪科技如何助力方太集团开启数字新征程
在数字化洪流席卷全球的宏大背景下,企业转型升级的紧迫性与重要性日益凸显,成为驱动行业进步的关键引擎。在这一波澜壮阔的转型浪潮中,方太集团——厨电领域的璀璨明珠,以其前瞻性的战略视野和不懈的创新精神,携手数据…...
Redis大key
Redis大key基本概念,影响 Redis 大 key 指在 Redis 中存储了大量数据的键,它会对 Redis 的性能和内存管理产生影响。 大key的定义与value的大小和元素数量有关,但这个定义并不是绝对的,而是相对的,具体取决于系统的使用…...
在 Apache Tomcat 中,部署和删除项目
在 Apache Tomcat 中,部署和删除 WAR 文件是常见的操作。以下是详细步骤: 1. 删除 WAR 文件 (1) 停止应用 进入 Tomcat 的管理界面(默认地址:http://localhost:8080/manager/html)。 找到需要删除的应用,…...
前端基础之组件自定义事件
我们可以通过使用给组件绑定事件,当组件触发该事件时,就能进行值得返回 我们可以使用v-on属性来给子组件绑定自定义事件,此时该事件就会存在vc中,然后通过this.$emit来触发绑定的事件, 这样就能实现不需要app.vue来给子…...
在 Docker 中,无法直接将外部多个端口映射到容器内部的同一个端口
Docker 的端口映射是一对一的,即一个外部端口只能映射到容器内部的一个端口。 1. 为什么不能多对一映射? 端口冲突: 如果外部多个端口映射到容器内部的同一个端口,Docker 无法区分外部请求应该转发到哪个内部端口,会…...
基于DeepSeek(本地部署)和RAGFlow构建个人知识库
总结自视频(很强的小姐姐视频,讲解清晰明了):【知识科普】【纯本地化搭建】【不本地也行】DeepSeek RAGFlow 构建个人知识库_哔哩哔哩_bilibili 1. 背景 deepseek官方网页版也虽然很强,能够满足绝大部分需求…...
学习工具的一天之(burp)
第一呢一定是先下载 【Java环境】:Java Downloads | Oracle 下来是burp的下载 Download Burp Suite Community Edition - PortSwigger 【下载方法二】关注的一个博主 【BurpSuite 安装激活使用详细上手教程 web安全测试工具】https://www.bilibili.com/video/BV…...
2025-03-05 学习记录--C/C++-PTA 习题5-8 空心的数字金字塔
合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻 一、题目描述 ⭐️ 二、解题步骤 ⭐️ 下面以n5举例:🦋 第1步 🎀、外层循环(从1到…...
C++课程设计【宿舍管理查询软件】
宿舍管理查询软件 一、题目描述二、源码以及说明宿舍管理查询软件设计与实现1. 系统设计思路1.1 功能需求1.2 数据结构2. 系统实现3. 代码说明3.1 数据结构3.2 功能实现3.3 文件存储4. 示例运行输入输出5. 总结其他QT文章推荐一、题目描述 (一)问题描述 为宿舍管理人员编写一…...
Stable Diffusion模型采样方法与参数配置详解(含步数及画风适配表)
Stable Diffusion模型采样方法与参数配置详解(含步数及画风适配表) 以下为当前主流采样方法的性能对比及参数配置建议,结合显存占用、生成速度、适用场景等维度分类总结: 一、采样方法对比表 采样方法推荐步数显存占用生成速度…...
极狐GitLab 17.9 正式发布,40+ DevSecOps 重点功能解读【三】
GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料: 极狐GitLab 官网极狐…...
