【LangChain】存储与管理对话历史

news2025/3/6 18:06:34

0. 代码演示

from langchain_community.chat_message_histories import SQLChatMessageHistory

def 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 StrOutputParser

model = ChatOpenAI(model="gpt-4o-mini", temperature=0)

runnable = model | StrOutputParser()

runnable_with_history = RunnableWithMessageHistory(
    runnable, # 指定 runnable
    get_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 SQLChatMessageHistory

def 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 等字段
  • 扩展性:可替换为其他存储后端(如PostgreSQL、Redis)

2. 对话链构建模块

from langchain_core.runnables.history import RunnableWithMessageHistory

model = 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"}} # 指定会话
)
  • 执行流程:
    1. 根据 session_id="wzr" 从数据库加载历史消息
    2. 将当前消息 "你好,我叫麦酷" 添加到历史记录
    3. 组合历史消息 + 当前输入 → 发送给 GPT-4
    4. 解析模型输出 → 返回最终响应
    5. 将新消息对(用户输入 + 模型回复)保存到数据库

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. 典型应用场景

  1. 客服系统

    # 根据用户手机号保持对话连续性
    session_id = user.phone_number
    
  2. 教育机器人

    # 为每个学生保存学习进度
    session_id = f"{student_id}-{course_id}"
    
  3. 多设备同步

    # 通过用户账户实现跨设备同步
    session_id = user.account_id
    

该代码展示了如何快速构建具备长期记忆能力的对话系统,通过简洁的接口实现复杂的状态管理,是开发智能对话应用的基石。

通过 LCEL,还可以实现

  1. 配置运行时变量:https://python.langchain.com/v0.2/docs/how_to/configure/
  2. 故障回退:https://python.langchain.com/v0.2/docs/how_to/fallbacks
  3. 并行调用:https://python.langchain.com/v0.2/docs/how_to/parallel/
  4. 逻辑分支:https://python.langchain.com/v0.2/docs/how_to/routing/
  5. 动态创建 Chain: https://python.langchain.com/v0.2/docs/how_to/dynamic_chain/

更多例子:https://python.langchain.com/v0.2/docs/how_to/lcel_cheatsheet/

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

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

相关文章

docker:Dockerfile案例之自定义centos7镜像

1 案例需求 自定义centos7镜像。要求&#xff1a; 默认登录路径为 /usr可以使用vim 2 实施步骤 编写dockerfile脚本 vim centos_dockerfile 内容如下&#xff1a; #定义父镜像 FROM centos:7#定义作者信息 MAINTAINER handsome <handsomehandsome.com># 设置阿里云…

学习笔记:IC存储总结(ROM,RAM, EEPROM, Flash, SRAM, DRAM, DDL)

一&#xff0c;概述 半导体存储器是一种可以存储大量二值信息的半导体器件。在电子计算机及一些其他的数字系统的工作过程中&#xff0c;需要对大量的数据进行储存。由于数据处理的数据量和运算速度的要求&#xff0c;因此把存储量和存取速度作为衡量存储器的重要指标。 在电子…

Scala:统计每个单词出现的个数并打印

目录 问题拆解&#xff1a; 解题步骤&#xff1a; 1. 拆分所有字符串为单词 2. 遍历所有单词并统计 3. 打印结果 基础版代码实现&#xff1a; 代码解释&#xff1a; 输出结果&#xff1a; 为什么这样设计&#xff1f; 继承的APP是个啥&#xff1f; 使用高阶函数式编…

C++前缀和

个人主页&#xff1a;[PingdiGuo_guo] 收录专栏&#xff1a;[C干货专栏] 大家好&#xff0c;今天我们来了解一下C的一个重要概念&#xff1a;前缀和 目录 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. 项目背景 处于失业找工作的阶段&#xff0c;随便写写吧~ 没啥背景&#xff0c;没啥意义&#xff0c;Java后端越来越卷了。第一学历不是本科&#xff0c;感觉真的是没有一点路可走。 如果有路过的小伙伴&#xff0c;如果身边还有坑位&#xff0c;不限第一学历的话&#xff0…

DeepSeek大模型深度解析:架构、技术与应用全景

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。https://www.captainbed.cn/north 文章目录 一、大模型时代与DeepSeek的定位1.1 大模型发展历程回顾大模型发展历程时间轴&#xff08;20…

Dubbo+Zookeeper

Apache ZooKeeper 通过当前页面下载Zookeeper 在这里启动zookeeper 可以根据这个页面简单学习一下&#xff0c;但是没有集成mysql&#xff0c;也会出现一些报错&#xff0c;且在这之后我们要使用的管理页面是vue的dubbo-admin dubbo学习三&#xff1a;springboot整合dubbozo…

从厨电模范到数字先锋,看永洪科技如何助力方太集团开启数字新征程

在数字化洪流席卷全球的宏大背景下&#xff0c;企业转型升级的紧迫性与重要性日益凸显&#xff0c;成为驱动行业进步的关键引擎。在这一波澜壮阔的转型浪潮中&#xff0c;方太集团——厨电领域的璀璨明珠&#xff0c;以其前瞻性的战略视野和不懈的创新精神&#xff0c;携手数据…

前端基础之组件自定义事件

我们可以通过使用给组件绑定事件&#xff0c;当组件触发该事件时&#xff0c;就能进行值得返回 我们可以使用v-on属性来给子组件绑定自定义事件&#xff0c;此时该事件就会存在vc中&#xff0c;然后通过this.$emit来触发绑定的事件&#xff0c; 这样就能实现不需要app.vue来给子…

基于DeepSeek(本地部署)和RAGFlow构建个人知识库

总结自视频&#xff08;很强的小姐姐视频&#xff0c;讲解清晰明了&#xff09;&#xff1a;【知识科普】【纯本地化搭建】【不本地也行】DeepSeek RAGFlow 构建个人知识库_哔哩哔哩_bilibili 1. 背景 deepseek官方网页版也虽然很强&#xff0c;能够满足绝大部分需求&#xf…

学习工具的一天之(burp)

第一呢一定是先下载 【Java环境】&#xff1a;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 空心的数字金字塔

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 二、解题步骤 ⭐️ 下面以n5举例&#xff1a;&#x1f98b; 第1步 &#x1f380;、外层循环&#xff08;从1到…

vue+neo4j 四大名著知识图谱问答系统

编号: D039 视频 vueneo4j四大名著知识图谱问答系统 技术架构 vuedjangoneo4jmysql技术实现 功能模块图 问答&#xff1a;基于知识图谱检索、支持图多跳、显示推理路径 姜维的师傅的主公的臣是谁&#xff1a; 马谡 知识图谱&#xff1a;四大名著总共4个图谱 红楼梦图谱 …

【智能体架构:Agent】LangChain智能体类型ReAct、Self-ASK的区别

1. 什么是智能体 将大语言模型作为一个推理引擎。给定一个任务&#xff0c; 智能体自动生成完成任务所需步骤&#xff0c; 执行相应动作&#xff08;例如选择并调用工具&#xff09;&#xff0c; 直到任务完成。 2. 先定义工具&#xff1a;Tools 可以是一个函数或三方 API也…

基于eRDMA实测DeepSeek开源的3FS

DeepSeek昨天开源了3FS分布式文件系统, 通过180个存储节点提供了 6.6TiB/s的存储性能, 全面支持大模型的训练和推理的KVCache转存以及向量数据库等能力, 每个客户端节点支持40GB/s峰值吞吐用于KVCache查找. 发布后, 我们在阿里云ECS上进行了快速的复现, 并进行了性能测试, ECS…

Vue的简单入门 三

目录 侦听器 watch 注意 表单输入绑定 v-model v-model修饰符​编辑 lazy number Trim 模板引用 组件组成 组件引用三步走 组件的嵌套关系 header Main Aside Aritice Item App.vue组件引入三个子组件 组件的注册方式 全局注册组件的方法 (1) Vue 2 语…

指纹细节提取(Matlab实现)

指纹细节提取概述指纹作为人体生物特征识别领域中应用最为广泛的特征之一&#xff0c;具有独特性、稳定性和便利性。指纹细节特征对于指纹识别的准确性和可靠性起着关键作用。指纹细节提取&#xff0c;即从指纹图像中精确地提取出能够表征指纹唯一性的关键特征点&#xff0c;是…

STM32——串口通信 UART

一、基础配置 Universal Asynchronous Receiver Transmitter 异步&#xff0c;串行&#xff0c;全双工 TTL电平 &#xff1a;高电平1 低电平0 帧格式&#xff1a; 起始位1bit 数据位8bit 校验位1bit 终止位1bit NVIC Settings一栏使能接受中断。 之前有设置LCD&#xff0c;…

PHP fastadmin 学习

安装php环境安装mysql插件 修改 php.ini下载 phpstudy、fastadmin 错误 安装FastAdmin could not find driver 参考链接 安装插件 创建1.php <? phpinfo(); ?>运行 http://127.0.0.1/1.php 查看 POD 页面访问404 伪静态 Apache <IfModule mod_rewrite.c> O…