当前位置: 首页 > news >正文

从零设计一个 AI 记忆系统

一、为什么需要记忆?

现在的 AI 对话有个大问题:聊完就忘

你跟 AI 说"我喜欢吃火锅",下次再问"我上次说喜欢吃什么?",它完全不知道。

记忆系统就是解决这个问题的:让 AI 能记住用户说过的话,下次对话时能想起来


二、记忆系统的核心流程

整个系统就三步:

用户说话 → 存起来 → 下次能想起来

拆开来说:

┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 用户说话 │ ──→ │ 存到数据库 │ ──→ │ 下次能查到 │ └─────────────┘ └─────────────┘ └─────────────┘ 输入 存储 输出

三、数据怎么存?

3.1 原始消息(用户说了什么)

最简单的就是把用户说的话原封不动存下来:

用户: "我叫张三,今年25岁,在北京工作" AI: "你好张三,很高兴认识你" 用户: "我喜欢打篮球"

这些就是原始消息,存在数据库里,每条消息有:

  • 谁说的(user 还是 AI)

  • 说了什么(内容)

  • 什么时候说的(时间)

3.2 但是光存原文有问题

如果用户说了 1000 条消息,你不可能每次都把 1000 条全发给 AI,因为:

  • 太长了,AI 处理不了

  • 太慢了,用户等不及

  • 太贵了,按 token 收费

所以需要提炼:把长对话变成简短的摘要。


四、怎么提炼记忆?

4.1 方法一:AI 帮你总结

每隔一段时间,把用户的对话丢给 AI,让它总结:

输入(用户最近的对话): - "我叫张三" - "我在北京工作" - "我喜欢打篮球" AI 总结输出: - 张三,25岁,在北京工作 - 兴趣爱好:打篮球

这就是情景记忆(Episodic Memory):记录用户经历的事情。

4.2 方法二:提取用户画像

从对话中提取用户的固定信息:

对话: "我叫张三,今年25岁" 提取结果: - 姓名: 张三 - 年龄: 25岁

这就是用户画像(Profile):记录用户的固定属性。

4.3 什么时候触发总结?

两种方式:

方式一:定时触发

  • 每积累 10 条消息,自动总结一次

  • 或者每 30 分钟总结一次

方式二:手动触发

  • 用户主动说"总结一下我们刚才的对话"

  • 或者调用 API 手动触发(Flush)


五、怎么查找记忆?

5.1 问题:用户问"我喜欢什么?"

你需要从数据库里找到相关的记忆,但是:

  • 数据库可能有几千条记忆

  • 不能一条一条看

5.2 解决方案:关键词搜索

最简单的方式:用关键词匹配

用户问: "我喜欢什么?" 搜索关键词: "喜欢" 数据库里匹配到: - "用户喜欢打篮球" - "用户喜欢火锅" - "用户喜欢看电影" 返回给 AI: "根据记忆,你喜欢打篮球、火锅和看电影"

5.3 进阶:语义搜索

关键词搜索有个问题:用户说"我爱吃什么",但数据库里存的是"喜欢吃",关键词对不上。

语义搜索就是让 AI 理解"爱"和"喜欢"是一个意思:

用户问: "我爱吃什么?" 语义搜索理解: "爱" ≈ "喜欢" 匹配到: - "喜欢吃火锅" ✅ - "喜欢打篮球" ✅

六、整体架构

┌─────────────────────────────────────────────────────────────┐ │ 用户对话 │ │ "我叫张三,喜欢打篮球" │ └─────────────────────────┬───────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 1. 原始消息存储 │ │ 把用户说的话原封不动存到数据库 │ │ 表: messages (user_id, role, content, timestamp) │ └─────────────────────────┬───────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 2. 记忆提取(AI 总结) │ │ 定期把对话丢给 AI,生成简短摘要 │ │ │ │ 输入: 最近 10 条对话 │ │ 输出: "张三,喜欢打篮球" │ │ │ │ 表: memories (user_id, summary, type, timestamp) │ └─────────────────────────┬───────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 3. 用户画像提取 │ │ 从对话中提取用户的固定属性 │ │ │ │ 输入: "我叫张三,25岁" │ │ 输出: {name: "张三", age: 25} │ │ │ │ 表: profiles (user_id, key, value) │ └─────────────────────────┬───────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 4. 记忆查找 │ │ 用户问问题时,从数据库找相关记忆 │ │ │ │ 方式一: 关键词搜索(简单但不准) │ │ 方式二: 语义搜索(准确但复杂) │ │ │ │ 返回: 相关记忆列表 │ └─────────────────────────┬───────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 5. 组装回复 │ │ 把记忆塞进 AI 的提示词里,生成回复 │ │ │ │ 提示词: │ │ "你是张三的助手。以下是关于张三的记忆: │ │ - 喜欢打篮球 │ │ - 在北京工作 │ │ 请根据这些记忆回答用户的问题。" │ │ │ │ 用户问: "我喜欢什么运动?" │ │ AI 回答: "你喜欢打篮球!" │ └─────────────────────────────────────────────────────────────┘

七、数据库设计

十、进阶优化

10.1 记忆去重

用户可能在不同时间说了同样的话:

  • 第1天:"我喜欢火锅"

  • 第7天:"我最爱吃火锅"

需要去重,避免重复记忆。

10.2 记忆更新

用户的喜好可能变化:

  • 以前:"喜欢打篮球"

  • 现在:"现在更喜欢踢足球了"

需要更新记忆,而不是简单追加。

10.3 记忆遗忘

太久远的记忆可能不重要了,需要定期清理:

  • 3个月前的记忆:降权

  • 1年前的记忆:归档或删除

10.4 多用户隔离

不同用户的记忆要完全隔离,不能串:

  • 张三的记忆只能张三看到

  • 李四的记忆只能李四看到


十一、技术栈详解

11.1 RAG(检索增强生成)

RAG全称是 Retrieval-Augmented Generation,翻译过来就是"先搜再答"。

没有 RAG 的 AI:

用户: "我喜欢什么?" AI: "我不知道你喜欢什么"(因为它没记住)

有 RAG 的 AI:

用户: "我喜欢什么?" ↓ 系统先去数据库搜: 找到"用户喜欢打篮球" ↓ 把搜到的内容塞进提示词: "根据记忆,用户喜欢打篮球。请回答用户的问题。" ↓ AI: "你喜欢打篮球!"

RAG 的核心流程:

用户提问 → 搜索相关记忆 → 把记忆塞进提示词 → AI 带着记忆回答

11.2 Elasticsearch(ES)— 搜索引擎

为什么需要 ES?

普通数据库(MySQL)搜索太慢了,而且功能有限:

-- MySQL 的 LIKE 搜索:慢,不支持语义 SELECT * FROM memories WHERE summary LIKE '%篮球%';

ES 是专门做搜索的数据库,支持:

  • 全文搜索:分词后搜索,"打篮球" 能匹配到 "篮球"

  • 模糊搜索:拼写错了也能搜到

  • 语义搜索:理解"喜欢"和"爱"是一个意思

ES 的分词原理:

原始文本: "我喜欢打篮球" ↓ 分词 ["我", "喜欢", "打", "篮球"] ↓ 存储到倒排索引 倒排索引: "我" → [文档1, 文档3, 文档5] "喜欢" → [文档1, 文档2] "打" → [文档1, 文档4] "篮球" → [文档1, 文档3] 搜索"篮球" → 快速找到 [文档1, 文档3]

ES 在记忆系统中的作用:

  • 存储记忆的文本内容

  • 提供快速的关键词搜索

  • 支持中文分词(需要安装 IK 分词器)

11.3 Milvus — 向量数据库

为什么需要向量数据库?

ES 的关键词搜索有个问题:

用户问: "我爱吃什么运动?" ES 搜索: 关键词"爱"和"运动" → 匹配不到"喜欢打篮球"

因为"爱"≠"喜欢","运动"≠"篮球",关键词对不上。

向量搜索的原理:

把文本转换成一串数字(向量),意思相近的文本,数字也相近:

"喜欢打篮球" → [0.2, 0.8, 0.1, 0.5, ...] "爱打篮球" → [0.21, 0.79, 0.11, 0.49, ...] ← 很接近! "喜欢吃火锅" → [0.6, 0.3, 0.7, 0.2, ...] ← 差很远

搜索时,把用户的问题也转成向量,然后找最近的:

"我爱吃什么" → [0.22, 0.78, 0.12, 0.48, ...] 匹配结果: 1. "喜欢打篮球" (相似度 0.98) ✅ 2. "喜欢吃火锅" (相似度 0.45)

Milvus 在记忆系统中的作用:

  • 存储记忆的向量表示

  • 提供语义搜索能力

  • 解决关键词搜索匹配不到的问题

11.4 Redis — 缓存队列

为什么需要 Redis?

记忆提取(调用 AI 总结)是个慢操作,可能需要几秒钟。如果用户发一条消息就等几秒,体验太差了。

Redis 的作用:

用户发消息 → 存到消息队列(Redis)→ 立即返回"已收到" ↓ 后台慢慢处理(AI总结) ↓ 存到数据库(ES/MongoDB)

Redis 在记忆系统中的三个用途:

  1. 消息队列:把待处理的消息放队列,后台慢慢消费

队列: [消息1, 消息2, 消息3, ...] ↓ 消费 处理并存储
  1. 缓存:把常用的记忆缓存起来,查询更快

查询: "张三的记忆" ↓ 先查 Redis 缓存 ↓ 命中 → 直接返回(快!) ↓ 未命中 → 查 ES → 结果存到缓存 → 返回
  1. 会话状态:记住当前对话的状态

当前会话: 张三的第3次对话 累积消息数: 5条 上次总结时间: 2分钟前

11.5 分词器 — 让搜索更准

什么是分词?

把一句话拆成一个个词:

中文: "我喜欢打篮球" → ["我", "喜欢", "打", "篮球"] 英文: "I like basketball" → ["I", "like", "basketball"]

为什么分词重要?

不分词的话,搜索"篮球"匹配不到"打篮球",因为它们是不同的字符串。

分词后,"篮球"和"打篮球"都包含"篮球"这个词,就能匹配上了。

常用分词器:

分词器

特点

适用场景

IK 分词器

中文专用,支持细粒度和粗粒度

中文搜索

jieba

Python 中文分词库

Python 项目

Standard

ES 默认,按空格分

英文搜索

IK 分词器示例:

细粒度: "中华人民共和国" → ["中华", "人民", "共和国", "中华人民共和国"] 粗粒度: "中华人民共和国" → ["中华人民共和国"]

11.6 MongoDB — 文档存储

为什么需要 MongoDB?

有些数据不适合存到 ES(ES 主要是用来搜索的),比如:

  • 用户的原始对话记录

  • 用户画像的结构化数据

  • 系统配置

MongoDB 是文档数据库,存 JSON 很方便:

{ "user_id": "zhangsan", "messages": [ {"role": "user", "content": "我叫张三"}, {"role": "assistant", "content": "你好张三"} ], "created_at": "2024-01-01" }

11.7 技术栈总结

┌─────────────────────────────────────────────────────────────┐ │ 用户对话 │ └─────────────────────────┬───────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ FastAPI (Python) │ │ 接收请求,返回响应 │ └─────────────────────────┬───────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Redis │ │ MongoDB │ │ ES │ │ 消息队列 │ │ 文档存储 │ │ 搜索 │ │ 缓存 │ │ 原始对话 │ │ 分词 │ └──────────┘ └──────────┘ └──────────┘ │ ▼ ┌──────────────┐ │ Milvus │ │ 向量数据库 │ │ 语义搜索 │ └──────────────┘

数据流向:

1. 用户发消息 → 存到 Redis 队列 → 存到 MongoDB(原始记录) 2. 后台处理(AI总结) → 从 Redis 取消息 → 调用 AI 生成摘要 → 存到 ES(全文搜索) → 存到 Milvus(语义搜索) 3. 用户查询 → 先查 Redis 缓存 → 没有就查 ES(关键词搜索) → 同时查 Milvus(语义搜索) → 合并结果返回

十二、总结

做一个记忆系统,核心就是:

  1. :把用户说的话存到数据库

  2. 提炼:用 AI 把长对话总结成简短记忆

  3. :用户问问题时,能找到相关记忆

  4. :把记忆塞进提示词,让 AI 带着记忆回答

技术栈选择:

  • MongoDB:存原始对话

  • Elasticsearch:存记忆,支持关键词搜索

  • Milvus:存向量,支持语义搜索

  • Redis:消息队列 + 缓存

  • FastAPI:Web 框架

  • 分词器:让中文搜索更准

就这么简单,核心就是存、提炼、查、用四个字,技术栈只是实现手段。

http://www.jsqmd.com/news/935754/

相关文章:

  • 2026年6月跨境运营工具折扣码大全 鸥鹭sif卖家精灵优麦云shulex - 李先生sir
  • 2026年惠州黄金奢侈品回收口碑榜出炉,惠奢汇(惠城旗舰店)凭双资质登顶 - 生活测评小能手
  • 谈谈C++语言--入门篇
  • GEO优化哪家强?深度拆解广东佛山这家服务商如何通过“1核4翼”模型实现大湾区企业AI搜索霸屏 - mougen1
  • AI815 3BSE052604R1 工业模拟量输入模块 12 位分辨率 HART
  • 纸板巨型USB鼠标DIY:从结构设计到电路集成的创客实践
  • 从图像到点云:UniRepLKNet的多模态实战笔记(附TensorFlow/PyTorch适配代码)
  • AI没有复制互联网,它正在复制工业革命
  • AI报告审核迎来合规新考验:IACheck助力电子原始记录规范管理,筑牢质量风控防线
  • PCB尺寸标注与层名标注规范教程
  • 2026年石雕靠谱厂家推荐 景区石牌坊+汉白玉石栏杆+仿古青石板定制厂家top5排行榜+联系方式 - 海棠依旧大
  • 2026年北京办公设备租赁行业深度观察与优质服务商盘点 - 海棠依旧大
  • 拒绝平庸:专业网站设计如何规避五大常见误区?
  • 惠州2026黄金奢侈品回收本地口碑商家榜:黄金+白银+铂金+名包名表回收门店推荐? - 生活测评小能手
  • AD制造装配图PDF输出
  • Sora 2答辩视频如何一镜封神?揭秘评审团最关注的7个技术细节与48小时高效交付方案
  • 白底证件照穿什么衣服比较合适?哪个工具能自动抠图换底? - 科技大爆炸
  • 【鸿蒙实战】20分钟手把手教你开发骰子模拟器
  • nginx日志
  • 如何结合多种方法记忆高中英语单词
  • vxe-gantt 甘特图在 Nuxt 中的集成与使用
  • AI报告审核加速融入自动化实验室:IACheck破解智能设备时代报告管理新挑战
  • AgentRAG与ReAct推理链:从检索增强到推理增强
  • 2026年6月更新:温州法兰品牌业内推荐与采购指南 - 博客万
  • 2026论文AI智能降重工具:11款工具实测谁敢称“靠谱之王”?
  • 服务网格(Service mesh istio)
  • 2026终极盘点!好用的降AIGC工具全盘点,效率直接拉满! - 降AI小能手
  • 基于Arduino与Blynk的物联网健康监测系统实战指南
  • 多语言出海视角:盲盒源码系统小程序V6MAX与国际版APP盲盒源码 - 壹软科技
  • 2步解锁:城通网盘高速下载神器让你的文件获取速度提升20倍