langchain 尚硅谷day4-5 记忆缓存部分!

我们现在对大模型的调用没法实现对记忆的缓存,要是想实现记忆的缓存的话,我们需要去实现问答的存储以及重新调用。记忆是真正实现对话交互的一个非常重要的模块。

当我们直接去连续调用大模型的时候并没有记忆的存储:如下图所示:

在我们传本地的参数前,把历史对话传入提示词中,并会记录更新历史对话。实现这种操作的模块就叫做记忆模块。

python 复制代码
chain = RunnableWithMessageHistory(
    prompt | llm,
    get_session_history,
    input_messages_key="question",
    history_messages_key="history"
)

用于保存聊天记录的抽象基类的名字叫做BaseChatMessageHistory。这个抽象基类有以下一个重要的属性跟三个重要方法需要因类而异的方法:

基于这个抽象基类会有很多的不同的存储的方式的扩展,最重要的就是下面框下的几个内容,

下面我们需要去展示一下如何存在内存里。存在内存里有两种方法。

首先,在修改前我们需要对提示词的生成进行更改!我们需要引用core.prompts中的对话模板与占位MessagePlaceholder类。并且去设置占位变量名字为history(或者是我喜欢的不同内容)。

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages([
    # 用于插入历史消息
    MessagesPlaceholder(variable_name="history"),
    ("human", "{input}")
])

第二步去设置初始化大模型:

python 复制代码
from langchain.chat_models import init_chat_model

llm = init_chat_model(
    model="qwen-plus",
    model_provider="openai",
    api_key=,
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

第三步是设置解析器跟设置整个链路:

python 复制代码
parser = StrOutputParser()
# 构建处理链:将提示词模板、语言模型和输出解析器组合
chain = prompt | llm | parser

第四步,我们需要创建一个要传入提示词中的参数history。这个参数是类InMemoryChatMessageHistory的实例化对象。

python 复制代码
# 创建内存聊天历史记录实例,用于存储对话历史
history = InMemoryChatMessageHistory()

第五步,创建带历史消息的可运行对象:

python 复制代码
from langchain_core.runnables import RunnableWithMessageHistory, RunnableConfig

runnable = RunnableWithMessageHistory(
    chain,
    get_session_history=lambda session_id: history,
    input_messages_key="input",  # 指定输入键
    history_messages_key="history"  # 指定历史消息键
)

第六步,及时清除历史消息,并且为每轮完整对话设置一个编号。RunnableConfig(),传入编号然后

python 复制代码
# 清空历史记录
history.clear()
# 配置运行时参数,设置会话ID
config = RunnableConfig(configurable={"session_id": "user-001"})

logger.info(runnable.invoke({"input": "我叫张三,我爱好学习。"}, config))
logger.info(runnable.invoke({"input": "我叫什么?我的爱好是什么?"}, config))

然后上面这一大段的内容就是如何从内存中实现记忆功能的方法。

下面的这段代码其实比上面的会更适合全面一点,这个代码设置了记忆分对话存储的功能,他为每个不同的用户初始化了一个不同的实例。

python 复制代码
"""
可持续记忆(RunnableWithMessageHistory)
"""

from langchain.chat_models import init_chat_model
from langchain_core.chat_history import InMemoryChatMessageHistory  # 内存型消息记录
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
import os

# 设置本地模型
llm = init_chat_model(
    model="qwen-plus",
    model_provider="openai",
    api_key=,
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)


# 定义全局的"会话存储",用来保存每个 session 的聊天历史
#    (真实项目中可改为 Redis、SQLite 等)
store = {}

def get_session_history(session_id: str):
    """
    根据 session_id 获取对应的历史消息对象。
    如果不存在则创建一个新的 InMemoryChatMessageHistory。
    """
    if session_id not in store:
        store[session_id] = InMemoryChatMessageHistory()
    return store[session_id]


# 定义 Prompt 模板
#     - system: 给模型设定角色
#     - MessagesPlaceholder: 历史消息将注入这里
#     - human: 当前用户输入
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个友好的中文助理,会根据上下文回答问题。"),
    MessagesPlaceholder("history"),
    ("human", "{question}")
])


#构建基本链:Prompt → LLM → 输出解析
memory_chain = prompt | llm | StrOutputParser()

# -----------------------------------------------------
# 将链包装为支持记忆的版本
with_history = RunnableWithMessageHistory(
    memory_chain,              # 原始链
    get_session_history=get_session_history,       # 获取历史函数
    input_messages_key="question",  # 对应 prompt 输入的 key
    history_messages_key="history", # 对应 MessagesPlaceholder 的变量名
)

# -----------------------------------------------------
# 模拟一个会话,用 session_id 区分不同用户
cfg = {"configurable": {"session_id": "user-001"}}

'''# 第一次提问:告诉模型"我叫张三"
print("用户:我叫张三。")
print("AI:", with_history.invoke({"question": "我叫张三。"}, cfg))
'''
# 第二次提问:让模型回忆前面的对话
print("\n 用户:我叫什么?")
print("AI:", with_history.invoke({"question": "我叫什么?"}, cfg))

但我们在内存里面没有办法去实现持久化的操作。所以我们需要去看看怎么连一些数据库之类的。

然后现在我们需要去实现的就是redis stack的存储方式,因为redis stack其实是满血redis,所以它支持了很多redis以前不支持的功能。

然后下载redis的方法:在命令行中执行就行。

docker run -d --name redis-stack-server -p 26379:6379 redis/redis-stack-server

下面是我们如何将内容存在redis里的python代码。

python 复制代码
from langchain_community.chat_message_histories import RedisChatMessageHistory
import redis 

首先我们需要去导入这两个与redis有关的库。

然后跟上面一样。初始化提示词。当然此处用了MessagesPlaceholder去装历史信息,变量question用来装载输入

python 复制代码
# 创建提示模板
prompt = ChatPromptTemplate.from_messages([
    MessagesPlaceholder("history"),
    ("human", "{question}")
])

然后就是我们需要初始化大模型

python 复制代码
# 设置本地模型
llm = init_chat_model(
    model="qwen-plus",
    model_provider="openai",
    api_key=,
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

第三步:我们需要去返回一个RedisChatMessage的会话历史对象。创还能这个对象需要去输入session_id跟url。

python 复制代码
def get_session_history(session_id: str) -> RedisChatMessageHistory:
    """获取或创建会话历史(使用 Redis)"""
    # 创建 Redis 历史对象
    history = RedisChatMessageHistory(
        session_id=session_id,
        url=REDIS_URL,
        #ttl=3600  # 注释:关闭自动过期,避免重启后数据被清理
    )

    return history

然后第四步,我们需要去用RunnableWithMessageHistory去创建一个有历史信息的chain。

python 复制代码
chain = RunnableWithMessageHistory(
    prompt | llm,
    get_session_history,
    input_messages_key="question",
    history_messages_key="history"
)

然后当我们想看目前redis里面到底有什么东西的时候,我们可以去执行下面的代码:

python 复制代码
docker exec -it redis-stack-server redis-cli

然后去执行Keys *就可以看到有啥在redis里了。

关于redis其实我不太熟悉。后面找个时间需要抽空补充一下redis的一些基本知识。

然后以上就是我们如何实现记忆功能的办法了。其中最关键的其实就是1.RedisChatMessageHistory()/InMemoryChatMessageHistory()/其他的持久化工具ChatMessageHistory 2.RunnableWithMessageHistory(),这两个函数的调用。其中RedisChatMessageHistory()构建History需要去传递一些参数,下面是具体的参数的展示。

相关推荐
Irissgwe3 小时前
LangChain之聊天模型核心能力(二)
人工智能·langchain·llm·langgraph
墨染天姬3 小时前
[AI]ai应用框架LangChain
人工智能·langchain
FrontAI3 小时前
深入浅出 LangGraph —— 第8章:人机交互:中断与审批流程
人工智能·langchain·人机交互·ai agent·langgraph
深海鱼在掘金12 小时前
深入浅出 LangChain — 第一章:AI Agent 开发导论
typescript·langchain·agent
深海鱼在掘金12 小时前
深入浅出 LangChain — 导读
typescript·langchain·agent
dinl_vin18 小时前
LangChain 系列·(四):RAG 基础——给大模型装上“外脑“
人工智能·算法·langchain
何雷 — 智能网联汽车19 小时前
Harness Engineering学习一 —— 基本概念
langchain·openai·harness·智能体编程·ai驱动编程
果汁华20 小时前
LangChain:构建 AI 应用的革命性框架
人工智能·langchain
tangweiguo0305198721 小时前
RAG 从零到一:让大模型读懂你的文档
python·langchain