【技术专题】基于LangChain的RAG与Agent智能体 - 临时会话记忆功能实现

0 阅读4分钟

大家好,我是锋哥。最近连载更新《基于LangChain的RAG与Agent智能体》技术专题。

QQ截图20260324143646.jpg 本课程主要介绍和讲解RAG,LangChain简介,接入通义千万大模型,Ollama简介以及安装和使用,OpenAI库介绍和使用,以及最重要的基于LangChain实现RAG与Agent智能体开发技术。同时也配套视频教程 《2027版 基于LangChain的RAG与Agent智能体开发视频教程》

前面我们写过一个聊天会话示例:

image.png

这里的历史会话记录我们是写死的,不符合实际的业务。我们经常用一些AI大模型产品,比如deepseek,我们新建一个会话,和AI聊天,AI每次的回复的内容都是基于你之前的提问再回答的,这里就有一个会话记忆功能。我们今天来讲下内存级临时会话记忆,就是把会话历史记录存内存里,是一种简单会话记忆功能能实现,当然后面还有持久化的长期记忆实现。

我们使用RunnableWithMessageHistory+InMemoryChatMessageHistory来实现临时会话记忆功能。

RunnableWithMessageHistory 是 LangChain 框架中一个非常实用的类,它的主要作用是为你的链(Chain)或可运行程序(Runnable)自动管理和注入聊天消息历史

简单来说,它能让你的应用程序拥有“记忆”,像人一样在对话中记得之前聊过什么。

🧠 核心功能:为链添加记忆

在构建聊天机器人等应用时,模型本身是无状态的,不会记住之前的对话。RunnableWithMessageHistory 就是为了解决这个问题而设计的。它像一个包装器,包裹着你的核心链,并自动处理以下工作:

  • 读取历史:在每次调用你的链之前,它会根据提供的 session_id(会话ID)从历史存储中加载之前的消息。
  • 注入上下文:它会将加载到的历史消息和当前用户输入合并,一起传给语言模型,让模型知道对话的来龙去脉。
  • 更新历史:在模型生成回复后,它会自动将这次的对话(用户问题 + 模型回答)追加到对应的历史记录中。

🛠️ 如何工作:核心要素

要使用 RunnableWithMessageHistory,你需要提供三个核心部分:

  1. 要包装的 Runnable (runnable) :这是你希望赋予记忆功能的核心链。它可以是任何符合特定输入/输出格式的 LCEL 链。

  2. 会话历史获取函数 (get_session_history) :这是一个关键的可调用函数。它的职责是根据你提供的标识符(如 session_id)来返回一个对应的 BaseChatMessageHistory 实例。LangChain 提供了多种历史存储实现:

    • 内存存储InMemoryChatMessageHistory,适合测试和开发,数据存储在内存中,程序重启后丢失。
    • 持久化存储:如 FileChatMessageHistoryRedisChatMessageHistoryPostgresChatMessageHistory 等,用于生产环境,确保数据不丢失。
  3. 消息键名配置 (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)

运行结果:

image.png