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

大模型记忆实战

Day07|大模型记忆实战——给你的 AI 装上"三层记忆"

前言:世界上最聪明的失忆症患者

大模型就像一个智商 180 但只有 5 秒记忆的人。

你跟他聊了一下午,讲了你的项目叫"星火计划"、你团队有 8 个人、你的技术栈是 Python + FastAPI。他听得很认真,回答得很专业。你心想:这个 AI 真懂我。

然后你关掉窗口,第二天重新打开。

"你好,我叫什么?""我的项目是什么?"

它一脸无辜:"抱歉,我不知道你在说什么。"

这不是段子。这是 2026 年大模型的现状——GPT-4o 能写代码、能做数学证明,但它记不住你昨天说过的一句话。

上一篇 Day06 讲了 RAG,解决了"模型不知道你的私有数据"。但 RAG 管的是外部知识——公司文档、产品手册。有一个问题它管不了:模型记不住你说过什么。

没有记忆的 AI 助手,永远是个聪明的陌生人——每次对话都要从头自我介绍,用户没有归属感,产品没有粘性。

这篇文章干四件事:

  1. 讲透三层记忆架构——短期、中期、长期各管什么
  2. 讲 FIFO 机制怎么保证记忆实时性,不被过时信息干扰
  3. 给你一个可运行的三层记忆系统 demo(Python,直接跑)
  4. 工程落地的实战经验——踩过什么坑,怎么避

读完你会发现,给大模型装记忆,不是"把所有对话存下来"那么简单——它需要像人脑一样,知道什么该记、什么该忘、什么该更新。


PART 01:三层记忆架构——短期、中期、长期

先想一个问题:人是怎么记忆的?

你跟同事聊了 30 分钟项目方案。聊完你记住了什么?

  • 刚刚说的几句话——精确到原文("他说 API 限流改成 200 次/分钟")
  • 今天讨论的几个要点——大意记得,原文忘了("他提了个缓存方案,大致是 Redis + TTL")
  • 这个同事是谁——结构化事实("他叫老王,负责后端,偏好 Go")

这三种记忆,对应大模型记忆系统的三层:

短期记忆:最近 N 轮对话,原样保留

定义:当前会话中,最近 K 轮对话的原始内容。

这就是模型的"工作台"——正在聊什么,一目了然。实现最简单,就是把最近的消息原封不动塞进 prompt。

容量:由上下文窗口决定。GPT-4o 是 128K tokens,大约能装 128~256 轮对话。但实际项目中你不会用满——token 越多,API 成本越高,响应也越慢。

实际设定:一般保留最近 5~10 轮(10~20 条消息),大约 2K~5K tokens。够模型理解"当前在聊什么"就行。

核心价值:精确。原文一字不差,不存在信息损失。

中期记忆:对话摘要,压缩存储

定义:超出短期窗口的历史对话,被 LLM 压缩为摘要后存储。

当对话越来越长,早期的消息被"挤出"短期窗口。直接丢掉太可惜——里面可能有重要信息。所以用一个折中方案:让 LLM 把旧对话总结成一段摘要,存起来。

触发时机:短期记忆满 K 轮时自动触发。把被挤出的对话交给 LLM 做摘要,摘要结果存入中期记忆。

核心价值:省 token。一段 10 轮对话可能 5K tokens,压缩成摘要只要 200~500 tokens。信息密度提升 10 倍以上。

代价:有细节损失。摘要保留了"主旨",但可能丢掉具体数字、精确措辞。这是可接受的折中——大多数场景下,知道"他提了个缓存方案"就够了,不需要记住原文。

长期记忆:用户画像,持久存储

定义:从对话中提取的结构化事实——用户是谁、做什么、偏好什么。

这是最"高级"的记忆。它不是存对话原文,也不是存摘要,而是提取出关于用户的关键信息,像"用户画像"一样存着。

提取方式:每次对话结束后,用 LLM 从对话中抽取关键事实:

  • 姓名、职业、公司
  • 项目名、技术栈
  • 偏好、习惯("喜欢用 Python"、"不喜欢 Java")
  • 重要决策("决定用 Redis 做缓存")

核心价值:跨会话、不衰减。关掉窗口再打开,模型依然"认识你"。这是让 AI 从"工具"变成"伙伴"的关键。

三层对比总结

维度短期记忆中期记忆长期记忆
存什么最近 N 轮原文对话摘要用户特征/偏好
容量5~10 轮数十条摘要数十条事实
精确度100%(原文)80%(主旨)95%(结构化)
生命周期会话内跨会话,可更新跨会话,持久
token 消耗高(原文)中(摘要)低(JSON)

PART 02:FIFO 机制——保证记忆的实时性

三层记忆搭好了,但有个问题:记忆不是越多越好。

想象一下:用户三个月前说"我在做电商项目",今天说"我转做短视频了"。如果你的长期记忆里还存着"做电商",模型会给出电商相关的建议——完全过时了。

过时的记忆不是资产,是噪音。

这就是 FIFO(First In, First Out)的价值——让记忆系统保持"新鲜",及时淘汰过时信息。

短期记忆:严格 FIFO,满了就丢

短期记忆最简单——滑动窗口,新消息进来,旧消息挤出。

消息流:[msg1, msg2, msg3, ..., msg10, msg11, msg12] 窗口 K=5(保留最近 5 轮 = 10 条消息): → [msg3, msg4, ..., msg12] # msg1, msg2 被挤出

被挤出的消息不是直接丢掉——它们会被送入中期记忆做摘要压缩。这样既控制了短期窗口的大小,又不丢失历史信息。

中期记忆:合并 + LRU,旧摘要被新摘要替代

中期记忆不是简单堆叠。同一个话题的多次摘要,应该合并而不是追加。

举个例子:

  • 第 1 次摘要:"讨论了 API 限流方案,决定用令牌桶算法"
  • 第 2 次摘要(同一个话题):"讨论了 API 限流方案的具体实现,确定限流阈值 200 次/分钟"

这两条应该合并为:"API 限流方案:令牌桶算法,阈值 200 次/分钟。"

淘汰策略:LRU(Least Recently Used)。如果一条摘要长期没被引用(用户再也没提过相关话题),它的优先级降低。当摘要数量超过上限时,低优先级的先被清理。

长期记忆:Update,不是 Append

这是最容易踩坑的地方。长期记忆不是堆积信息,而是更新画像。

用户说"我在做电商"→ 长期记忆存{"project": "电商"}。三个月后用户说"我转做短视频了"→ 长期记忆应该更新{"project": "短视频"},而不是追加成{"project": "电商, 短视频"}

关键区别:

  • Append(追加):所有历史事实堆在一起 → 过时信息干扰判断
  • Update(更新):同一实体的最新状态覆盖旧状态 → 永远是最新画像
# 错误做法:追加 long_term_memory.append({"key": "project", "value": "短视频"}) # 结果:[{"key": "project", "value": "电商"}, {"key": "project", "value": "短视频"}] # 正确做法:更新 long_term_memory.update("project", "短视频") # 结果:[{"key": "project", "value": "短视频"}]

三层淘汰策略对比

策略触发条件处理方式
短期严格 FIFO超出 K 轮挤出 → 送入中期做摘要
中期LRU + 合并同话题重复 / 超上限合并同类摘要,清理低频
长期Update 覆盖新事实与旧事实冲突用新值覆盖旧值

PART 03:一个可运行的三层记忆系统 demo

理论讲完了,下面给一个完整的、可以直接跑的三层记忆系统。

""" Day07 三层记忆系统完整 demo 短期记忆(FIFO滑动窗口)+ 中期记忆(对话摘要)+ 长期记忆(用户画像) 依赖:pip install openai 环境变量:OPENAI_API_KEY """ import os import json import time from openai import OpenAI client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) # ========== 短期记忆:FIFO 滑动窗口 ========== class ShortTermMemory: """短期记忆:保留最近 K 轮对话原文""" def __init__(self, max_rounds: int = 5): self.messages: list[dict] = [] self.max_messages = max_rounds * 2 def add(self, role: str, content: str) -> list[dict]: """添加消息,返回被挤出的消息""" self.messages.append({"role": role, "content": content}) evicted = [] while len(self.messages) > self.max_messages: evicted.append(self.messages.pop(0)) return evicted def get_context(self) -> str: if not self.messages: return "" return "\n".join(f"{m['role']}: {m['content']}" for m in self.messages) # ========== 中期记忆:对话摘要存储 ========== class MidTermMemory: """中期记忆:将被挤出的对话压缩为摘要""" def __init__(self, max_summaries: int = 20): self.summaries: list[dict] = [] self.max_summaries = max_summaries self.buffer: list[dict] = [] def add_evicted(self, messages: list[dict]): self.buffer.extend(messages) if len(self.buffer) >= 4: self._summarize() def _summarize(self): if not self.buffer: return conversation = "\n".join(f"{m['role']}: {m['content']}" for m in self.buffer) prompt = f"请将以下对话总结为简洁摘要(200字以内),保留主题、关键结论、具体数字和名称:\n{conversation}\n请输出摘要:" resp = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}], temperature=0.3, ) self.summaries.append({ "content": resp.choices[0].message.content.strip(), "created_at": time.time(), "access_count": 0, }) self.buffer = [] if len(self.summaries) > self.max_summaries: self.summaries.sort(key=lambda s: s["access_count"]) self.summaries = self.summaries[-self.max_summaries:] def get_context(self) -> str: if not self.summaries: return "" lines = [] for s in self.summaries: s["access_count"] += 1 lines.append(f"- {s['content']}") return "[对话历史摘要]\n" + "\n".join(lines) # ========== 长期记忆:用户画像 ========== class LongTermMemory: """长期记忆:提取并维护用户画像""" def __init__(self): self.facts: dict[str, str] = {} def extract_and_update(self, user_message: str): current_profile = json.dumps(self.facts, ensure_ascii=False) if self.facts else "(空)" prompt = f"""从以下用户消息中提取需要长期记住的关键事实。 如果新事实与已有画像冲突,输出 update 操作。如果没有新事实,输出空 JSON。 当前画像:{current_profile} 用户消息:"{user_message}" 输出 JSON:{{"facts": {{"key": "value"}}, "updates": {{"key": "new_value"}}, "deletes": ["key"]}} 只输出 JSON:""" resp = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}], temperature=0, ) try: result = json.loads(resp.choices[0].message.content.strip()) for k, v in result.get("facts", {}).items(): self.facts[k] = v for k, v in result.get("updates", {}).items(): self.facts[k] = v for k in result.get("deletes", []): self.facts.pop(k, None) except (json.JSONDecodeError, KeyError): pass def get_context(self) -> str: if not self.facts: return "" return f"[用户画像]\n{json.dumps(self.facts, ensure_ascii=False, indent=2)}" # ========== 记忆管理器 ========== class MemoryManager: def __init__(self, short_rounds: int = 5): self.short_term = ShortTermMemory(max_rounds=short_rounds) self.mid_term = MidTermMemory() self.long_term = LongTermMemory() def process(self, role: str, content: str): if role == "user": self.long_term.extract_and_update(content) evicted = self.short_term.add(role, content) if evicted: self.mid_term.add_evicted(evicted) def build_prompt(self, new_message: str) -> str: parts = [] long_ctx = self.long_term.get_context() if long_ctx: parts.append(long_ctx) mid_ctx = self.mid_term.get_context() if mid_ctx: parts.append(mid_ctx) short_ctx = self.short_term.get_context() if short_ctx: parts.append(f"[最近对话]\n{short_ctx}") parts.append(f"user: {new_message}") return "\n\n".join(parts)

跑完你会看到这样的流转过程:

阶段短期记忆中期记忆长期记忆
第 1 轮后1 轮原文{"name": "张明", "project": "星火计划"}
填充 10 轮后最近 3 轮2~3 条摘要不变
第 12 轮(回忆)命中 ✅摘要可参考name=张明, project=星火计划
第 13 轮(更新)最新新增摘要project 更新为 短视频

核心要点:三层记忆各司其职——短期保证"正在聊什么"、中期保证"之前聊过什么"、长期保证"用户是谁"。FIFO 贯穿三层,保证信息不过时。


PART 04:工程落地——记忆系统的实战经验

demo 能跑通,但真正上线会遇到很多坑。分享几个我在实战中踩过的。

坑一:事实提取不准确——把闲聊也存进了长期记忆

最常见的问题。用户开玩笑说"我是个外星人",提取器就存了{"identity": "外星人"}

解法:在提取 prompt 中明确约束:

EXTRACT_PROMPT = """从用户消息中提取需要长期记住的事实。 规则: 1. 只提取明确的、严肃的个人信息(姓名、职业、项目、技术偏好) 2. 忽略:闲聊、玩笑、一次性问题、测试内容 3. 如果不确定是否值得记住,不提取(宁可漏掉,不可错记) 4. 如果新事实与旧事实冲突,标记为 update"""

关键是第三条——宁可漏掉,不可错记。记忆污染比记忆缺失更影响体验。

坑二:摘要丢细节——关键数字被省略

LLM 做摘要时经常省略具体数字。比如原文"API 限流改成 200 次/分钟",摘要变成"讨论了 API 限流调整"——关键数字丢了。

解法:在摘要 prompt 中强制要求保留实体——必须保留具体数字、人名、项目名、技术名称。

坑三:长期记忆更新冲突

用户说"我不喜欢 Python 了,转 Go 了"。你希望长期记忆从{"language": "Python"}变成{"language": "Go"}

解法:在提取 prompt 中明确区分update(覆盖旧值)和append(新增属性),以及delete + append(否定旧信息时)。

与 RAG 整合:统一检索架构

Day06 讲的 RAG 是检索外部文档。长期记忆本质上也可以存入向量库——检索"用户是谁"和检索"公司退货政策"用的是同一套技术。RAG 和 Memory 共用一套向量基础设施,运维成本更低。

性能考量:控制额外 LLM 调用

三层记忆系统每条消息可能触发:事实提取(1 次 gpt-4o-mini)+ 摘要压缩(溢出时触发)+ 回答生成(主模型)。额外成本大约主调用的 20%~30%

  • 事实提取和摘要都用gpt-4o-mini(便宜、快)
  • 摘要不要每轮都触发,积累到阈值再压缩
  • 长期记忆提取可以异步执行——不阻塞用户响应

结尾:记忆是 AI 从"工具"变"伙伴"的分水岭

回头看这篇文章的核心:

  • 三层记忆:短期(最近 N 轮原文)→ 中期(对话摘要)→ 长期(用户画像)
  • FIFO 流转:短期满了挤出去做摘要,摘要中提取事实更新画像——信息逐层沉淀,不是堆积
  • 淘汰策略:短期严格 FIFO、中期合并 + LRU、长期 Update 覆盖——保持记忆"新鲜"

为什么这套架构重要?因为记忆是 AI 从"工具"变成"伙伴"的分水岭

一个没有记忆的 AI,每次对话都像跟失忆的天才聊天——它很聪明,但它不认识你。

一个有三层记忆的 AI,它知道你是谁、之前聊过什么、现在在讨论什么——这种感觉,才叫"我的 AI 助手"。

大模型最缺的不是算力,是记忆——一个没有记忆的 AI,永远是个聪明的陌生人。

互动时间:你的 AI 应用里,记忆系统是怎么搭的?三层都上了,还是只用了短期?踩过什么坑?欢迎评论区聊聊。


下一篇 Day08 预告:大模型 MCP 实战——让大模型不只生成文本,还能调用你的工具和服务。关注小刘檀木,不错过每一篇。
我是小刘檀木,一个从二本摸爬滚打到上市公司 AI 负责人的普通人。关注我,把 AI 学进简历

— END —

小刘檀木 · 帮普通人把 AI 学进简历

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

相关文章:

  • 月结流程概述
  • 2026 薪酬数字化调研:AI 薪资系统将核算工时压缩 80%,大幅降低合规稽查风险
  • 2026年裸眼3D制作行业观察
  • 简历看起来都差不多?怎么挑出真正“对的人”
  • Linux安全防护全解析
  • Gemini for Slides深度调优指南:从提示工程到幻灯片结构语义解析,让AI真正听懂你的“商业逻辑”
  • 用ChatGPT驯服Midjourney:从模糊需求到可商用图像的完整闭环(含23个行业专属Prompt模板+效果对比数据)
  • 苏州市市级企业技术中心和江苏省企业技术中心认定对比
  • Linux用户管理与文件权限实操学习总结
  • SSH爆破应急响应
  • PDS2000E系列 实测|大功率宽范围直流电源,国产高性价比测试电源推荐
  • PHP 8.1.0-dev 后门利用与PHPJM混淆审计:2种PHP代码审计实战解析
  • 老电脑C盘飘红卡顿 清理流程
  • GitHub Copilot for PR审查:2024最新版API行为日志分析与安全合规审查清单
  • 开放式耳机什么品牌好?2026年性价比高的开放式耳机推荐
  • 科大讯飞六麦阵列 ROS 功能包深度解析:5 步实现机器人语音交互与 360° 声源定位
  • [数电] 第1章:数制与编码
  • TensorFlow 2.x 自定义Transformer层实战:从零构建IMDB情感分析模型,准确率87%
  • JD-GUI:Java字节码逆向工程的架构演进与技术哲学
  • 增加接口配置MES地址
  • 【DALL-E 3 vs Midjourney终极对决】:20年AI图像生成实战者亲测的5大关键差异与选型决策指南
  • 一线团队已全面启用:Cursor inline chat企业级落地手册(含安全沙箱配置、私有模型接入、审计日志埋点)
  • 校招中刷不出存在感?让岗位站在C位试试!
  • AI时代企业核心竞争力:从基础模型到学习回路的构建策略
  • 学了Python却做不出软件?你的痛,我们懂
  • 智慧水务平台硬件配套选型指南 —— 智能远程调压阀核心适配优势
  • 互联网医院|互联网医院成品搭建快速上线
  • 【2024最全Gemini Slides操作图谱】:覆盖97%高频场景的32个隐藏快捷指令与权限配置陷阱预警
  • 从ChatGPT小白到提示词工程师:Prompt Engineering入门必经的9个认知跃迁(含企业级评估量表V2.1)
  • 公考机构哪家强?从零基础到上岸,这份备考攻略帮你少走弯路