LangChain 实战:RunnableWithMessageHistory 深度详解
在构建聊天机器人Chatbot时**“记忆”Memory**是核心能力之一。早期的 LangChain 使用ConversationChainMemory对象来管理历史但在 LCELLangChain Expression Language时代官方推荐使用更灵活、更解耦的RunnableWithMessageHistory。本文将以一个完整的 Python 示例为基础深入剖析RunnableWithMessageHistory的工作原理、核心参数及最佳实践。1. 为什么需要它在没有RunnableWithMessageHistory之前手动管理对话历史通常需要以下繁琐步骤查询根据 User ID 从数据库查出历史记录。拼接手动把历史记录塞进 Prompt 中。调用执行 LLM。保存手动把 User Input 和 AI Output 追加保存回数据库。RunnableWithMessageHistory就像一个自动化的切面Aspect它包装了你的 Chain自动在后台完成了上述“查询-注入-保存”的所有工作让你只需要关注当前轮次的交互。2. 实战代码演示以下是一个可运行的完整示例 (src/examples/memory/demo_runnable_with_history.py)。2.1 准备工作首先我们需要定义基础组件LLM、Prompt 以及历史记录的存储位置。fromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholderfromlangchain_core.runnables.historyimportRunnableWithMessageHistoryfromlangchain_community.chat_message_historiesimportChatMessageHistoryfromsrc.llm.gemini_chat_modelimportget_gemini_llm# 1. 定义存储这里使用内存字典模拟数据库store{}# 2. 定义工厂函数告诉系统如何根据 session_id 获取历史对象defget_session_history(session_id:str):ifsession_idnotinstore:store[session_id]ChatMessageHistory()returnstore[session_id]# 3. 初始化 LLMllmget_gemini_llm()# 4. 定义 Prompt必须包含历史记录的占位符promptChatPromptTemplate.from_messages([(system,You are a helpful assistant.),MessagesPlaceholder(variable_namehistory),# --- 关键点预留位置(human,{input}),])# 5. 创建基础 Chainchainprompt|llm2.2 核心包装这是最关键的一步。我们将无状态的chain包装成有状态的with_message_history。with_message_historyRunnableWithMessageHistory(chain,get_session_history,input_messages_keyinput,history_messages_keyhistory,)2.3 调用执行调用时我们需要通过config传递session_id。# 第一轮告诉我是 Bobresponse1with_message_history.invoke({input:Hi! My name is Bob.},config{configurable:{session_id:session_1}})print(fAI:{response1.content})# 第二轮问我的名字response2with_message_history.invoke({input:What is my name?},config{configurable:{session_id:session_1}})print(fAI:{response2.content})# 输出: AI: Your name is Bob. (成功记住了)3. 参数深度剖析 (非常重要)RunnableWithMessageHistory的构造函数接收 4 个核心参数理解它们是掌握 LCEL Memory 的关键。1.runnable(位置参数 1)含义被包装的基础对象通常是Prompt | LLM组成的 Chain。要求这个 Chain 本身必须是无状态的。它不知道“历史”的存在它只知道接收一个包含消息列表的 Prompt 并输出结果。历史的注入是在它运行之前由包装器完成的。2.get_session_history(位置参数 2)含义一个工厂函数Factory Function。签名(session_id: str) - BaseChatMessageHistory。作用这是 LangChain 与外部存储Redis, Postgres, Memory交互的接口。当invoke开始时系统调用此函数加载旧记录。当invoke结束时系统调用此函数保存新记录。实战生产环境中这里通常返回RedisChatMessageHistory或PostgresChatMessageHistory的实例。3.input_messages_key(关键字参数)含义“哪个 Key 代表用户的新消息”背景Chain 的输入通常是一个字典例如{input: 你好, style: 幽默}。系统需要知道要把哪一个值作为HumanMessage保存到历史记录中。设定在上面的例子中我们调用 invoke 时用了{input: ...}所以这里填input。4.history_messages_key(关键字参数)含义“历史记录应该填到 Prompt 的哪个坑里”背景在 Prompt 中我们预留了一个占位符MessagesPlaceholder(variable_namehistory)。设定系统加载出历史记录List[Message]后会自动将其注入到这个 key 中。所以这里必须填history以匹配 Prompt 中的变量名。4. 运行流程图解当你执行with_message_history.invoke({...}, config{...})时内部发生了什么提取 ID从config中读取session_id。加载历史调用get_session_history(session_id)获取当前的历史消息列表。注入 Prompt创建一个新的输入字典。将用户输入 (input) 放入。将历史列表 (history) 放入。执行 Chain运行基础 Chain (prompt | llm)。保存历史将用户的输入 (HumanMessage) 追加到历史对象。将 AI 的输出 (AIMessage) 追加到历史对象。返回结果将 AI 的输出返回给用户。5. 总结RunnableWithMessageHistory是 LangChain 中优雅管理状态的瑞士军刀。它通过配置化的方式将繁琐的历史记录读写逻辑从业务逻辑中剥离出来极大地简化了代码结构。记忆口诀Config定身份 (session_id)。Factory找仓库 (get_session_history)。Keys做映射 (input/history keys)。6. 架构关系图 (Mermaid)下图直观地展示了RunnableWithMessageHistory、get_session_history、MessagesPlaceholder和ChatPromptTemplate之间的协作关系。LLMMessagesPlaceholderChatPromptTemplateChatMessageHistory (Storage)get_session_historyRunnableWithMessageHistoryUserLLMMessagesPlaceholderChatPromptTemplateChatMessageHistory (Storage)get_session_historyRunnableWithMessageHistoryUser1. 用户发起调用2. 加载历史记录3. 准备 Prompt 输入4. 渲染 Prompt5. 执行推理6. 保存新对话7. 返回结果invoke(inputHi, config{session_id: 1})1调用工厂函数(session_id1)2获取/创建历史对象3返回 List[BaseMessage] (旧历史)4传入 {input: Hi, history: [旧历史]}5遇到 variable_namehistory6展开 [旧历史] 列表7填充 {input} 到 HumanMessage8生成最终完整消息列表9发送完整消息列表10返回 AI 回复 (Hello!)11add_user_message(Hi)12add_ai_message(Hello!)13返回 Hello!14图解说明RunnableWithMessageHistory是总指挥负责协调所有组件。get_session_history是仓库管理员负责根据 ID 找到对应的历史记录本。MessagesPlaceholder是 Prompt 里的“占位符”负责把从仓库拿出来的历史记录“平铺”到对话中。ChatPromptTemplate是最终的拼装车间输出给 LLM 的是包含历史和新输入的完整列表。

相关新闻

社会网络仿真软件:Pajek_(1).Pajek入门与基础操作

社会网络仿真软件:Pajek_(1).Pajek入门与基础操作

Pajek入门与基础操作 1. Pajek简介 Pajek 是一个用于大型网络分析和可视化的软件工具,广泛应用于社会网络分析、生物网络分析、信息网络分析等领域。Pajek 支持多种网络数据格式,提供了丰富的网络分析功能和可视化选项,使用户能够高效地处理…

2026/5/17 1:31:24 阅读更多 →
基于微信小程序的驾校预约管理系统的小程序_u6pho7j3

基于微信小程序的驾校预约管理系统的小程序_u6pho7j3

一、项目技术介绍 开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:eclipse/myeclipse/…

2026/5/17 1:31:21 阅读更多 →
基于微信小程序的健康管理系统的设计与实现_387dlt2q

基于微信小程序的健康管理系统的设计与实现_387dlt2q

一、项目技术介绍 开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:eclipse/myeclipse/…

2026/5/17 1:31:21 阅读更多 →

最新新闻

GPTs商业化落地首周数据报告:TOP10盈利模型曝光,其中2个已获OpenAI官方推荐(附转化漏斗SOP)

GPTs商业化落地首周数据报告:TOP10盈利模型曝光,其中2个已获OpenAI官方推荐(附转化漏斗SOP)

更多请点击: https://kaifayun.com 第一章:GPTs商业化落地的底层逻辑与趋势洞察 GPTs(Generative Pre-trained Transformers)的商业化并非简单地将大模型API接入业务系统,而是围绕“场景闭环—数据飞轮—价值可度量”…

2026/7/3 0:38:06 阅读更多 →
AI绘画赋能软件测试:基于Stable Diffusion的UI用例视觉化实践

AI绘画赋能软件测试:基于Stable Diffusion的UI用例视觉化实践

1. 项目概述:当AI绘画遇上软件测试最近在搞一个挺有意思的尝试,把“云容笔谈东方红颜影像生成系统”这套专门画古风美人的AI,用到了软件测试的自动化流程里,核心目标是让它自动生成UI测试用例图。乍一听可能觉得有点跨界&#xff…

2026/7/3 0:38:06 阅读更多 →
8个Illustrator自动化脚本终极指南:彻底告别重复性设计工作

8个Illustrator自动化脚本终极指南:彻底告别重复性设计工作

8个Illustrator自动化脚本终极指南:彻底告别重复性设计工作 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts Adobe Illustrator是设计师日常工作的核心工具,但…

2026/7/3 0:30:04 阅读更多 →
清单来了:2026年最值得信赖的专业AI论文工具

清单来了:2026年最值得信赖的专业AI论文工具

2026年AI论文写作工具已从“基础生成”升级为具备全流程支持与学术合规能力的专业平台,核心评价维度包括文献真实性、格式合规性、长文本逻辑、查重降重、AIGC合规等。本次测评覆盖6款主流工具,涵盖中英文、全流程与专项功能、免费与付费场景&#xff0c…

2026/7/3 0:28:04 阅读更多 →
PIC18F67K40与IS31FL3731驱动LED矩阵开发指南

PIC18F67K40与IS31FL3731驱动LED矩阵开发指南

1. IS31FL3731与PIC18F67K40的硬件协同架构IS31FL3731是一款专为LED矩阵设计的驱动芯片,采用I2C接口控制,内置144个恒流驱动通道。其核心特性包括:支持169(144像素)单色LED矩阵8位PWM调光(256级亮度&#x…

2026/7/3 0:28:04 阅读更多 →
ONNX 推理优化:导出成功只是部署的第一步

ONNX 推理优化:导出成功只是部署的第一步

ONNX 推理优化:导出成功只是部署的第一步 一、模型能导出,不代表线上能稳定推理 PyTorch 模型导出 ONNX 后,通常可以接入 ONNX Runtime、TensorRT 或其他推理引擎。但导出成功并不等于部署完成。算子兼容性、动态 shape、数值误差、batch 策略…

2026/7/3 0:26:04 阅读更多 →

日新闻

Nginx防御TLS重协商攻击实战:从原理到配置与监控

Nginx防御TLS重协商攻击实战:从原理到配置与监控

1. 项目概述:为什么TLS重协商攻击至今仍需警惕十多年前的CVE-2011-1473,一个关于TLS/SSL协议重协商机制的漏洞,现在提起来还有必要吗?很多运维和开发朋友可能会觉得,这都老掉牙了,现代服务器和客户端不都默…

2026/7/3 0:03:59 阅读更多 →
华为防火墙双通道远程管理实战:Web与SSH配置详解

华为防火墙双通道远程管理实战:Web与SSH配置详解

1. 项目概述:为什么需要双通道远程管理防火墙?在任何一个稍具规模的企业网络里,防火墙都是那个默默守护在边界的关键角色。作为网络工程师,我们不可能每次都跑到机房,插上console线去配置它。远程管理能力,…

2026/7/3 0:03:59 阅读更多 →
AD74413R与PIC18F65K40的高精度工业数据采集方案

AD74413R与PIC18F65K40的高精度工业数据采集方案

1. 项目概述:AD74413R与PIC18F65K40的协同工作在工业自动化和精密测量领域,同时实现高精度模数转换(ADC)和数模转换(DAC)功能是许多复杂系统的核心需求。AD74413R作为一款四通道可配置模拟输入/输出器件,与PIC18F65K40微控制器的组合&#xf…

2026/7/3 0:05:59 阅读更多 →

周新闻

月新闻