大家好,我是锋哥。最近连载更新《基于LangChain的RAG与Agent智能体》技术专题。
本课程主要介绍和讲解RAG,LangChain简介,接入通义千万大模型,Ollama简介以及安装和使用,OpenAI库介绍和使用,以及最重要的基于LangChain实现RAG与Agent智能体开发技术。同时也配套视频教程 《2027版 基于LangChain的RAG与Agent智能体开发视频教程》
前面我们写过一个聊天会话示例:
这里的历史会话记录我们是写死的,不符合实际的业务。我们经常用一些AI大模型产品,比如deepseek,我们新建一个会话,和AI聊天,AI每次的回复的内容都是基于你之前的提问再回答的,这里就有一个会话记忆功能。我们今天来讲下内存级临时会话记忆,就是把会话历史记录存内存里,是一种简单会话记忆功能能实现,当然后面还有持久化的长期记忆实现。
我们使用RunnableWithMessageHistory+InMemoryChatMessageHistory来实现临时会话记忆功能。
RunnableWithMessageHistory 是 LangChain 框架中一个非常实用的类,它的主要作用是为你的链(Chain)或可运行程序(Runnable)自动管理和注入聊天消息历史。
简单来说,它能让你的应用程序拥有“记忆”,像人一样在对话中记得之前聊过什么。
🧠 核心功能:为链添加记忆
在构建聊天机器人等应用时,模型本身是无状态的,不会记住之前的对话。RunnableWithMessageHistory 就是为了解决这个问题而设计的。它像一个包装器,包裹着你的核心链,并自动处理以下工作:
- 读取历史:在每次调用你的链之前,它会根据提供的
session_id(会话ID)从历史存储中加载之前的消息。 - 注入上下文:它会将加载到的历史消息和当前用户输入合并,一起传给语言模型,让模型知道对话的来龙去脉。
- 更新历史:在模型生成回复后,它会自动将这次的对话(用户问题 + 模型回答)追加到对应的历史记录中。
🛠️ 如何工作:核心要素
要使用 RunnableWithMessageHistory,你需要提供三个核心部分:
-
要包装的 Runnable (runnable) :这是你希望赋予记忆功能的核心链。它可以是任何符合特定输入/输出格式的 LCEL 链。
-
会话历史获取函数 (get_session_history) :这是一个关键的可调用函数。它的职责是根据你提供的标识符(如
session_id)来返回一个对应的BaseChatMessageHistory实例。LangChain 提供了多种历史存储实现:- 内存存储:
InMemoryChatMessageHistory,适合测试和开发,数据存储在内存中,程序重启后丢失。 - 持久化存储:如
FileChatMessageHistory、RedisChatMessageHistory、PostgresChatMessageHistory等,用于生产环境,确保数据不丢失。
- 内存存储:
-
消息键名配置 (input_messages_key 等) :当你的链接收的是一个字典(dict)作为输入时,你需要告诉这个包装器,字典里的哪个键对应的是用户输入,哪个键是用来放置历史消息的。
我们来看一个具体示例:
from langchain_community.llms.tongyi import Tongyi
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableWithMessageHistory
# 1. 定义聊天提示模板(和图片结构一致)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个友好的AI助手,会结合对话历史回答用户问题。"), # 系统消息:设定AI基础角色
MessagesPlaceholder("history"), # 对话历史占位符:后续会被真实历史数据替换
("human", "请回答如下问题:{question}") # 当前用户的提问(带变量占位)
])
model = Tongyi(model="qwen-plus") # 创建模型
chain = prompt | model
# 创建会话历史数据存储对象
store = {} # key是session_id,value是InMemoryChatMessageHistory类对象
# 实现根据session_id获取InMemoryChatMessageHistory类对象
def get_session_history(session_id):
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
# 创建带有会话历史数据的链
message_history_chain = RunnableWithMessageHistory(
chain, # 被增强的原有链
get_session_history, # 根据会话id获取InMemoryChatMessageHistory类对象
input_messages_key="question", # 输入消息的键名
history_messages_key="history" # 历史消息的键名
)
if __name__ == '__main__':
session_config = {
"configurable": {
"session_id": "user01"
}
}
result = message_history_chain.invoke({"question": "IT行业里哪个细分领域职位最有前途,直接告诉我职位名称即可"},
session_config)
print("第一次AI大模型回答:", result)
result = message_history_chain.invoke({"question": "这个职位需要多少技术积累?简单回答即可"}, session_config)
print("第二次AI大模型回答:", result)
result = message_history_chain.invoke({"question": "这个职位在北京5年经验年薪平均多少万?简单回答即可"},
session_config)
print("第三次AI大模型回答:", result)
运行结果: