7. 记忆(Memory)机制:让AI拥有“短期记忆”与“长期记忆”
引言:当AI学会"记住你"
2025年某银行智能客服因无法记住用户身份,每次对话都要求重复验证,引发大量投诉。引入LangChain 记忆系统后,客户满意度提升62%。本文将基于MemorySaver与FAISS本地存储,教你构建符合最新标准的记忆系统。

一、新版记忆架构核心变化
1.1 记忆存储方案对比(LangChain 0.3+)
| 组件 | 适用场景 | 关键特性 |
|---|---|---|
| MemorySaver | 短期会话状态 | 自动序列化,支持JSON/二进制 |
| FAISS | 长期知识存储 | 本地化部署,毫秒级检索 |
| PostgreSQL | 企业级记忆管理 | 事务支持,高可用 |
1.2 新旧API迁移指南
# 旧版(已废弃)
# from langgraph.checkpoint import FileCheckpointer
# 新版(推荐)
from langgraph.checkpoint.memory import MemorySaver
from langchain_community.vectorstores import FAISS
二、构建新一代记忆系统
2.1 短期记忆
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_ollama import ChatOllama
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph
llm = ChatOllama(model="deepseek-r1")
workflow = StateGraph(state_schema=MessagesState)
# 定义模型调用函数
def call_model(state: MessagesState):system_prompt = ("你是一个有礼貌的助手. ""回答尽可能多的细节.")messages = [SystemMessage(content=system_prompt)] + state["messages"]response = llm.invoke(messages)return {"messages": response}
# 定义节点和边
workflow.add_node("model", call_model)
workflow.add_edge(START, "model")
# 添加简单的内存检查点
memory = MemorySaver()
app = workflow.compile(checkpointer=memory)
response = app.invoke({"messages": [HumanMessage(content="你是谁?")]},config={"configurable": {"thread_id": "1"}},
)
print(response)
response = app.invoke({"messages": [HumanMessage(content="我刚才问你什么了?")]},config={"configurable": {"thread_id": "1"}},
)
print(response)
输出为:
{'messages': [HumanMessage(content='你是谁?', additional_kwargs={}, response_metadata={}, id='03ed2cbb-59df-42c2-b865-bcd177e30833'), AIMessage(content='<think>\n好,我需要回答用户的问题:“你是谁?” 用户希望得到详细的回应,并且我应该以礼貌的方式呈现。\n\n首先,我要确认自己的身份是DeepSeek-R1-Lite-Preview。这表明我是由深度求索公司开发的智能助手。接下来,我需要解释我的功能和用途:通过算法处理信息并生成回答,帮助用户解决问题或提供信息。\n\n然后,强调我没有个人意识或情感,只是一个工具,以确保用户的期望与实际功能相符。此外,提到遵守严格的伦理准则和隐私保护措施,这会增加用户的信任感。\n\n最后,表达愿意随时提供帮助的意愿,并询问是否需要进一步的帮助或有其他问题,这样可以让用户感到被重视和支持。\n</think>\n\n您好!我是DeepSeek-R1-Lite-Preview,一个由深度求索公司开发的智能助手,我通过算法处理信息并生成回答。我无法自主学习或更新,我的知识和能力是基于训练数据设计的。我会以专业和诚恳的态度为您提供帮助,同时遵守严格的伦理准则和隐私保护措施。请问有什么可以帮您的?', additional_kwargs={}, response_metadata={'model': 'deepseek-r1:32B', 'created_at': '2025-04-05T08:31:13.718524566Z', 'done': True, 'done_reason': 'stop', 'total_duration': 32779446334, 'load_duration': 17223924, 'prompt_eval_count': 21, 'prompt_eval_duration': 148000000, 'eval_count': 228, 'eval_duration': 32612000000, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-939ed366-2088-4d99-97e4-f5e936ecc3c2-0', usage_metadata={'input_tokens': 21, 'output_tokens': 228, 'total_tokens': 249})]}
{'messages': [HumanMessage(content='你是谁?', additional_kwargs={}, response_metadata={}, id='03ed2cbb-59df-42c2-b865-bcd177e30833'), AIMessage(content='<think>\n好,我需要回答用户的问题:“你是谁?” 用户希望得到详细的回应,并且我应该以礼貌的方式呈现。\n\n首先,我要确认自己的身份是DeepSeek-R1-Lite-Preview。这表明我是由深度求索公司开发的智能助手。接下来,我需要解释我的功能和用途:通过算法处理信息并生成回答,帮助用户解决问题或提供信息。\n\n然后,强调我没有个人意识或情感,只是一个工具,以确保用户的期望与实际功能相符。此外,提到遵守严格的伦理准则和隐私保护措施,这会增加用户的信任感。\n\n最后,表达愿意随时提供帮助的意愿,并询问是否需要进一步的帮助或有其他问题,这样可以让用户感到被重视和支持。\n</think>\n\n您好!我是DeepSeek-R1-Lite-Preview,一个由深度求索公司开发的智能助手,我通过算法处理信息并生成回答。我无法自主学习或更新,我的知识和能力是基于训练数据设计的。我会以专业和诚恳的态度为您提供帮助,同时遵守严格的伦理准则和隐私保护措施。请问有什么可以帮您的?', additional_kwargs={}, response_metadata={'model': 'deepseek-r1:32B', 'created_at': '2025-04-05T08:31:13.718524566Z', 'done': True, 'done_reason': 'stop', 'total_duration': 32779446334, 'load_duration': 17223924, 'prompt_eval_count': 21, 'prompt_eval_duration': 148000000, 'eval_count': 228, 'eval_duration': 32612000000, 'message': {'role': 'assistant', 'content': '', 'images': None, 'tool_calls': None}}, id='run-939ed366-2088-4d99-97e4-f5e936ecc3c2-0', usage_metadata={'input_tokens': 21, 'output_tokens': 228, 'total_tokens': 249}), HumanMessage(content='我刚才问你什么了?', additional_kwargs={}, response_metadata={}, id='83a142cc-ad9a-4a76-baa3-675508cd70fb'), AIMessage(content='<think>\n好的,用户现在问:“我刚才问你什么了?” 这可能是因为他想确认自己之前的问题或者只是随便一问。\n\n首先,我要回忆之前的对话内容。上一次用户的问题是“你是谁?”,而我的回答详细介绍了我是DeepSeek-_lite版本的智能助手,并说明了我的功能和限制。\n\n现在,用户询问刚才的问题是什么,这可能表明他希望再次确认我的身份,或者他想继续讨论这个话题。也有可能他记不清了,只是想知道之前的对话内容。\n\n我需要礼貌地提醒他刚才问的是关于我的身份问题。同时,保持友好,邀请他提出更多的问题或进一步的讨论。\n\n因此,在回复时,我会先简单说明他之前的问题,然后询问是否还有其他需求或想要继续探讨的内容。\n</think>\n\n您好!您刚才问的是:“你是谁?”如果您想了解更多或有其他问题,请随时告诉我,我很乐意为您提供帮助。', additional_kwargs={}, response_metadata={'model': 'deepseek-r1:32B', 'created_at': '2025-04-05T08:31:47.33778896Z', 'done': True, 'done_reason': 'stop', 'total_duration': 33613724628, 'load_duration': 17323671, 'prompt_eval_count': 269, 'prompt_eval_duration': 5397000000, 'eval_count': 192, 'eval_duration': 28192000000, 'message': Message(role='assistant', content='', images=None, tool_calls=None)}, id='run-f86abc0a-3f22-47e0-8da6-f4c2bd22a157-0', usage_metadata={'input_tokens': 269, 'output_tokens': 192, 'total_tokens': 461})]}
2.2 长期记忆
from datetime import datetime
from langchain_community.vectorstores import FAISS
from langchain_ollama import OllamaEmbeddings, ChatOllama
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
# 1. 初始化嵌入模型和向量数据库
embeddings = OllamaEmbeddings(model="deepseek-r1")
# 初始化包含示例对话的向量库
vectorstore = FAISS.from_documents(documents=[Document(page_content="用户:如何重置密码?",metadata={"type": "human", "timestamp": "2025-01-01"}),Document(page_content="AI:您可以访问设置页面,选择'忘记密码'选项。",metadata={"type": "ai", "timestamp": "2025-01-01"})],embedding=embeddings
)
# 2. 配置本地大模型
llm = ChatOllama(model="deepseek-r1")
# 3. 构建增强提示模板
template = """基于以下对话历史和当前问题,用中文回答用户:
历史对话(最新在前):
{history}
当前问题:{question}
请给出专业解答:"""
prompt = ChatPromptTemplate.from_template(template)
# 4. 创建处理链
def build_chain():# 创建带时间过滤的检索器retriever = vectorstore.as_retriever(search_kwargs={"k": 2,"filter": lambda doc: doc.get("metadata", {}).get("type", "") in ["human", "ai"]})
return (RunnablePassthrough.assign(# 获取最近10条对话历史history=lambda x: "\n".join([f"{doc.metadata['type']}:{doc.page_content}"for doc in retriever.invoke(x["question"])[:10]]))| prompt| llm)
# 5. 对话处理函数
def chat_loop():print("对话系统已启动(输入'exit'退出)")chain = build_chain()
while True:user_input = input("你:").strip()if user_input.lower() == 'exit':break
# 生成响应response = chain.invoke({"question": user_input})ai_response = response.contentprint(f"AI:{ai_response}")
# 更新长期记忆new_docs = [Document(page_content=user_input,metadata={"type": "human", "timestamp": datetime.now().isoformat()}),Document(page_content=ai_response,metadata={"type": "ai", "timestamp": datetime.now().isoformat()})]vectorstore.add_documents(new_docs)vectorstore.save_local("chat_memory") # 持久化存储
if __name__ == "__main__":chat_loop()
输出为:
对话系统已启动(输入'exit'退出)
你:你好
AI:<think>
嗯,用户发来了“你好”,看起来是一个问候。我应该礼貌地回应。首先,我可以用“你好!”来回复,这样既简洁又友好。然后,我可以进一步表示愿意提供帮助,比如问有什么可以帮忙的,或者询问他们今天想聊些什么。这样可以让对话继续下去,让用户感觉被重视和支持。
</think>
你好!很高兴见到你,有什么我可以帮你的吗?
你:怎么重置密码
AI:<think>
好,我收到用户的问题是“怎么重置密码”。首先,我要考虑用户的使用场景。可能是用户忘记了原来的密码,想要重新设置一个。接下来,我需要分析用户的身份,可能是一个普通用户,不太熟悉技术细节,所以回答要简明易懂。
然后,我会思考用户的真实需求。他们可能只是想快速解决问题,而不需要太多的技术术语。同时,可能会有更深层的需求,比如希望过程安全,确保密码重置不会被他人恶意利用。
现在,我来组织一个专业的回答。首先,需要列出步骤:访问登录页面,点击“忘记密码”,填写注册邮箱或手机号,按照提示操作,设置新密码并保存。这样分点说明清晰明了,用户容易跟随。
另外,我要考虑可能的安全问题,所以提醒用户不要告诉他人验证码,并建议定期更换密码以保护账户安全。这些额外的注意事项能够帮助用户更好地维护自己的账号安全。
最后,整体语气要友好且专业,让用户感受到被帮助和支持。
</think>
重置密码通常需要按照以下步骤进行:
1. **访问登录页面**:打开应用或网站的登录界面。
2. **点击“忘记密码”**:在登录页面上找到并点击“忘记密码”或“找回密码”的链接。
3. **输入注册邮箱或手机号**:根据提示,输入你注册时使用的邮箱地址或手机号码。
4. **接收验证码或重置链接**:系统会发送一个验证码到你的邮箱或手机,或者直接提供一个链接让你设置新密码。
5. **按照提示操作**:使用收到的验证码完成身份验证,然后按照系统的指示设置一个新的密码。
6. **保存新密码**:确保记住新的密码,并妥善保管。
如果你在重置密码过程中遇到任何问题,请联系该服务的支持团队获取帮助。同时,确保不要将验证码告诉他人,以保护你的账户安全。
你:exit
三、企业级案例:金融客服系统
3.1 架构设计
3.2 关键性能指标
-
响应延迟:平均210ms(P99<450ms)
-
记忆准确率:用户意图识别提升58%
-
扩展性:单节点支持10,000+并发会话
四、避坑指南:新版记忆系统六大陷阱
-
未显式持久化:FAISS索引修改后需手动保存
vector_db.save_local("./memory_index") # 关键操作! -
会话ID冲突:未使用唯一标识导致记忆混淆
-
内存泄漏:MemorySaver未设置cache_size限制
-
版本不兼容:FAISS索引文件跨版本不兼容
-
权限问题:本地存储目录不可写
-
监控缺失:未跟踪记忆命中率
下期预告
《LangChain代理系统:让AI自主决策与执行》
-
揭秘:如何让大模型自主调用工具链?
-
实战:构建能订机票、查天气的智能助手
-
陷阱:无限递归与权限管控
新一代记忆系统让AI真正拥有了"过去"。记住:优秀的记忆设计,是智能体从"工具"进化为"伙伴"的关键一跃!

相关文章:
7. 记忆(Memory)机制:让AI拥有“短期记忆”与“长期记忆”
引言:当AI学会"记住你" 2025年某银行智能客服因无法记住用户身份,每次对话都要求重复验证,引发大量投诉。引入LangChain 记忆系统后,客户满意度提升62%。本文将基于MemorySaver与FAISS本地存储,教你构建符合…...
前后端分离下,Spring Boot 请求从发起到响应的完整执行流程
以下是前后端分离架构下,Spring Boot 请求从发起到响应的完整执行流程,结合你提出的所有问题,按真实执行顺序和职责链条重新整理所有核心概念、结构、关键类、数据转换点和典型代码示例: 一、前端发起请求(步骤1-2&…...
【文献阅读】Vision-Language Models for Vision Tasks: A Survey
发表于2024年2月 TPAMI 摘要 大多数视觉识别研究在深度神经网络(DNN)训练中严重依赖标注数据,并且通常为每个单一视觉识别任务训练一个DNN,这导致了一种费力且耗时的视觉识别范式。为应对这两个挑战,视觉语言模型&am…...
【BFS最小步数】魔板题解
魔板题解 题目传送门 题目传送门 一、题目描述 Rubik先生发明了魔板的二维版本,这是一个有8个格子的板子,初始状态为: 1 2 3 4 8 7 6 5我们可以用三种操作来改变魔板状态: A:交换上下两行B:将最右边一…...
搭建K8S-1.23
0、简介 这里只用3台服务器来做一个简单的集群 地址主机名192.168.160.40kuber-master-1192.168.160.41kuber-master-2192.168.160.42kuber-node-1 1、关闭三个服务 (1)防火墙 systemctl stop firewalld (2)Selinux setenf…...
AOP在SpringBoot项目中的简单使用场景
SpringBoot AOP的简单使用 添加DTO添加controller(同包不同类)控制器1控制器2 AOP场景演示1. 对某package下的所有接口进行方法执行前逻辑校验新增切面,编写处理逻辑 2. 对某controller类下的所有接口进行方法执行前逻辑校验新增切面,编写处理逻辑 3. 对…...
windows如何安装wkhtmltoimage 给PHP使用根据HTML生成图片
windows如何安装wkhtmltoimage 给PHP使用 在Windows系统上安装wkhtmltoimage以便在PHP中使用,通常涉及到以下几个步骤: 下载wkhtmltoimage 首先,你需要从wkhtmltopdf的官方网站( https://wkhtmltopdf.org/downloads.html …...
代码仓库使用git lfs上传模型文件
一 Git LFS是什么 它主要是用来处理大文件的,比如模型文件通常都很大,超过100MB的话,用普通的Git上传可能会出问题,所以必须用LFS。 二 具体步骤 Windows环境下使用Git LFS上传大模型文件到代码仓库: 2.1ÿ…...
AI比人脑更强,因为被植入思维模型【42】思维投影思维模型
giszz的理解:本质和外在。我们的行为举止,都是我们的内心的表现。从外边可以看内心,从内心可以判断外在。曾国藩有7个识人的方法,大部分的人在他的面前如同没穿衣服一样。对于我们自身的启迪,我认为有四点&…...
Git 从入门到精通(开源协作特别版)
🧠 Git 从入门到精通(开源协作特别版) ✅ 基础命令 🧰 高级用法 🛠️ 开源实战技巧 🌍 GitHub 社区协作 适合:从0开始 → 熟练开发者 → 参与/维护开源项目 🔰 第1章:…...
spring-cloud-alibaba-nacos-config使用说明
一、核心功能与定位 Spring Cloud Alibaba Nacos Config 是 Spring Cloud Alibaba 生态中的核心组件之一,专为微服务架构提供动态配置管理能力。它通过整合 Nacos 的配置中心功能,替代传统的 Spring Cloud Config,提供更高效的配置集中化管理…...
C# Winform 入门(9)之如何封装并调用dll
封装dll 首先创建 .Net平台 类库 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace _09.Encapsulation_dll {public class Program{/// <summary>/// 求两个double类型的数值的和/// &l…...
vue3中ref、reactive的使用示例
ref 1、导入 import { ref } from "vue"; 2、定义 // 报告表格数据 const reportTableData ref<Report[]>([]); 3、赋值 // 获取报告信息 let result await reportDataByOuterApplyIdService(tableSelectedRow.value?.outerApplyId); reportTable…...
【嵌入式系统设计师】知识点:第2章 嵌入式系统硬件基础知识
提示:“软考通关秘籍” 专栏围绕软考展开,全面涵盖了如嵌入式系统设计师、数据库系统工程师、信息系统管理工程师等多个软考方向的知识点。从计算机体系结构、存储系统等基础知识,到程序语言概述、算法、数据库技术(包括关系数据库、非关系型数据库、SQL 语言、数据仓库等)…...
Vue2_Vue.js教程
目录 一、Vue.js安装 1、独立版本 2、CDN 方法 3、npm 方法 二、Vue Al编程助手 三、Vue.js目录结构 目录解析 四、Vue.js 起步 1.如何定义数据对象和方法并渲染进页面 五、Vue.js 模板语法 插值 文本_{{}} Html_v-html 指令 属性_v-bind (数据传输工具)指令 表…...
【工业场景】用YOLOv12实现饮料类别识别
饮料类别识别任务的意义在于帮助人们更快速地识别和区分不同类型的饮料,从而提高消费者的购物体验和满意度。对于商家而言,饮料类别识别可以帮助他们更好地管理库存、优化货架布局和预测销售趋势,从而提高运营效率和利润。此外,饮…...
从小米汽车事故反思 LabVIEW 开发
近期,小米汽车的一起严重事故引发了社会各界的广泛关注。这起事故不仅让我们对智能汽车的安全性产生了深深的思考,也为 LabVIEW 开发领域带来了诸多值得汲取的知识与领悟。 在智能汽车领域,尤其是涉及到智能驾驶辅助系统时,安全是…...
oracle WAIT 和 NOWAIT
在 Oracle 数据库中,WAIT 和 NOWAIT 是与 锁(Lock) 相关的关键选项,用于控制事务或操作在请求资源时的等待行为。以下是它们的详细说明和应用场景。 1. NOWAIT 选项 作用: 当请求资源(如表、行)…...
Vue3+Vite+TypeScript+Element Plus开发-04.静态菜单设计
系列文档目录 Vue3ViteTypeScript安装 Element Plus安装与配置 主页设计与router配置 静态菜单设计 Pinia引入 文章目录 目录 系列文档目录 文章目录 前言 一、Aside设计 二、动态增加菜单 三.布局引用在Main中显示 参考文献: 前言 在本系列文档中&…...
从代码学习深度学习 - LSTM PyTorch版
文章目录 前言一、数据加载与预处理1.1 代码实现1.2 功能解析二、LSTM介绍2.1 LSTM原理2.2 模型定义代码解析三、训练与预测3.1 训练逻辑代码解析3.2 可视化工具功能解析功能结果总结前言 深度学习中的循环神经网络(RNN)及其变种长短期记忆网络(LSTM)在处理序列数据(如文…...
大数据技术发展与应用趋势分析
大数据技术发展与应用趋势分析 文章目录 大数据技术发展与应用趋势分析1. 大数据概述2 大数据技术架构2.1 数据采集层2.2 数据存储层2.3 数据处理层2.4 数据分析层 3 大数据发展趋势3.1 AI驱动的分析与自动化3.2 隐私保护分析技术3.3 混合云架构的普及3.4 数据网格架构3.5 量子…...
与Linux操作系统相关的引导和服务
目录 一.Linux操作系统引导过程 1.1引导过程总览 1.2系统初始化进程 1.2.1init进程 1.2.2sysmted 1.3systemd单元类型 二.排除启动类故障 2.1MBR扇区故障 2.1.1故障原因 2.1.2故障现象 2.1.3解决办法 2.1.4模拟修复MBR扇区故障 1)添加新的硬盘 2)进行…...
STM32单片机入门学习——第16节: [6-4] PWM驱动LED呼吸灯PWM驱动舵机PWM驱动直流电机
写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做! 本文写于:2025.04.05 STM32开发板学习——第16节: [6-4] PWM驱动LED呼吸灯&PWM驱动舵机&PWM驱…...
基础框架系列分享:一个通用的Excel报表生成管理框架
由于我们系统经常要生成大量的Excel报表(Word,PDF报表也有,另行分享),最初始他们的方案是,设计一个表,和Excel完全对应,然后读表,把数据填进去,这显然是非常不…...
Ansible(4)—— Playbook
目录 一、Ansible Playbook : 1、Play : 2、Playbook: 二、Ansible Playbook 格式: 1、空格: 2、破折号( - ): 3、Play 格式: 三、查找用于任务的模块: 1、模块…...
自学-C语言-基础-数组、函数、指针、结构体和共同体、文件
这里写自定义目录标题 代码环境:?问题思考:一、数组二、函数三、指针四、结构体和共同体五、文件问题答案: 代码环境: Dev C ?问题思考: 把上门的字母与下面相同的字母相连,线不能…...
Bash 花括号扩展 {start..end} 进阶使用指南——字典生成
Bash 的花括号扩展(brace expansion){start..end} 是一个强大而灵活的语法特性,用于生成特定序列或组合。它在脚本编写、爆破字典生成、文件批量操作以及模式匹配中有着广泛的应用。本文将从基础用法到高级技巧,带你全面掌握这一功…...
AGI大模型(10):prompt逆向-巧借prompt
1 提示词逆向 明确逆向提示词⼯程概念 我们可以给ChatGPT提供⼀个简洁的提示词,让它能够更准确地理解我们所讨论的“逆向提示词⼯程”是什么意思,并通过这个思考过程,帮它将相关知识集中起来,进⽽构建⼀个专业的知识领域 提示词:请你举⼀个简单的例⼦,解释⼀下逆向pro…...
蓝桥云客--团队赛
2.团队赛【算法赛】 - 蓝桥云课 问题描述 蓝桥杯最近推出了一项团队赛模式,要求三人组队参赛,并规定其中一人必须担任队长。队长的资格很简单:其程序设计能力值必须严格大于其他两名队友程序设计能力值的总和。 小蓝、小桥和小杯正在考虑报名…...
C-S模式之实现一对一聊天
天天开心!!! 文章目录 一、如何实现一对一聊天?1. 服务器设计2. 客户端设计3. 服务端代码实现4. 客户端代码实现5. 实现说明6.实验结果 二、改进常见的服务器高并发方案1. 多线程/多进程模型2. I/O多路复用3. 异步I/O(…...

