上一篇文章采用langchain_community包协助LangChain实现了对话记忆功能,但langchain_community属于早期链式架构的临时补丁,仅适配简单线性对话。
LangChain官方推荐使用LangGraph实现复杂的会话记忆功能,LangGraph是从底层统一管理全流程状态、支持长短双记忆、原生持久化、适配复杂Agent的标准化记忆架构,常作为生产环境的首选方案。接下来介绍LangGraph在会话记忆方面的简单用法。
一、使用LangGraph的环境准备
在命令行窗口执行下面命令,即可安装LangChain及其用到的Ollama插件,以及记忆功能需要的LangGraph:
pip install langchain langchain-core langchain-ollama langgraph
确保本地已经通过Ollama下载了离线大模型,比如在命令行窗口执行下面命令,即可下载大模型qwen2:1.5b:
ollama pull qwen2:1.5b
等待大模型下载完毕,在命令行窗口执行下面命令,即可启动Ollama并加载大模型:
ollama serve
二、使用LangGraph记住历史会话
在Python代码开头添加下面的导包语句,表示引入LangChain的智能体组件create_agent、LangChain的大模型工具OllamaLLM,以及LangGraph的内存保存器InMemorySaver:
from langchain.agents import create_agent
from langchain_ollama import ChatOllama
from langgraph.checkpoint.memory import InMemorySaver # 内存存储
在OllamaLLM的构造方法中填写model参数,指定当前引用的离线大模型名称,如下:
llm = ChatOllama(model="qwen2:1.5b") # 改成你本地的模型
然后编写下面的LangChain调用代码,先调用create_agent创建启用短期记忆的智能体实例,再通过智能体实例的invoke方法调用离线大模型,示例代码如下:
agent = create_agent(
model=llm,
checkpointer=InMemorySaver(), # 启用短期记忆
)
# 测试对话
print("=== 内存中的临时记忆 ===")
while True:
user_input = input("用户:")
if user_input in ["退出", "exit", "quit"]:
print("对话结束")
break
# 调用离线大模型
result = agent.invoke(
{"messages": [{"role": "user", "content": user_input}]},
{"configurable": {"thread_id": "session_001"}}
)
print(f"AI:{result['messages'][-1].content}\n")
运行上面的Python代码,根据提示先后输入问题内容"我叫张三"、"我叫什么?",输出日志结果如下:
=== 内存中的临时记忆 ===
你:我叫张三
AI:你好,张三。有什么问题或需要帮助的吗?
你:我叫什么?
AI:你的名字是"张三"。
由日志信息发现,AI应用在第一个问答中得知用户叫做张三,在第二个问答中仍然记得用户叫做张三。可见通过LangGraph的内存保存器InMemorySaver,初步实现了简单的AI对话记忆功能。
三、使用SummarizationMiddleware压缩历史记忆
前面虽然实现了初步的记忆功能,但随着问答的交互次数增长,要记忆的历史会话也越来越多。为了节省大模型的Token消耗,势必精简历史记忆,以便保留最新的会话记录。
LangGraph提供了摘要中间件SummarizationMiddleware,支持在历史会话超出限制时自动压缩会话记录。引入SummarizationMiddleware之后,增加的代码部分说明如下:
在Python代码开头添加下面的导包语句,表示引入LangChain的摘要中间件SummarizationMiddleware:
from langchain.agents.middleware import SummarizationMiddleware
另外声明新的大模型实例,用于压缩历史会话记录,如下:
llm_summary = ChatOllama(model="qwen2:0.5b") # 改成你本地的模型
调用create_agent创建智能体实例时,增加输入middleware参数,并设定摘要中间件用到的摘要大模型、Token个数限制、保留消息数等配置,示例代码如下:
agent = create_agent(
model=llm,
checkpointer=InMemorySaver(), # 启用短期记忆
# 压缩历史记忆并移除早期记忆
middleware=[
SummarizationMiddleware(
model=llm_summary,
trigger=("tokens", 100), # 超过 100 token 触发
keep=("messages", 3), # 保留最近 3 条消息
)
]
)
重新运行修改后的Python代码,根据提示先后输入问题内容"我叫张三"、"我叫什么?"、"长江有多长?"、"黄河有多长?"、"珠江有多长?"、"黑龙江有多长?"、"我叫什么?",输出日志结果如下:
=== 内存中的临时记忆 ===
你:我叫张三
AI:你好,张先生。有什么我可以帮助你的吗?
你:我叫什么?
AI:你好,张先生。你叫张三。
你:长江有多长?
AI:长江是中国最长的河流,全长约6300公里。
你:黄河有多长?
AI:黄河是中国第二长的河流,全长约5464公里。
你:珠江有多长?
AI:珠江是长江流域的一条重要河流,全长约2794公里。
你:黑龙江有多长?
AI:黑龙江是亚洲最长的河流之一,全长约1800公里。
你:我叫什么?
AI:根据您的描述,您似乎没有提供自己的名字。如果您有其他姓名,请告知我以便我能为您提供更准确的回答。
由日志信息发现,在第一次询问"我叫什么?"时,AI应用能够正确回答用户叫做张三;但多轮对话后再次询问"我叫什么?",AI应用已经忘记了用户叫什么。可见通过SummarizationMiddleware初步实现了压缩历史记忆,在会话记录超出限制后将只保留最新的问答信息。
本系列的AI应用开发文章目录为《15天学会AI应用开发全目录(零基础小白,零Token消耗)》。