☰
Deepseek新论文Engram:大模型记忆痕迹的技术推演与工程实践
2026/10/20 16:09:30 网站建设 项目流程

Deepseek的新论文取名叫“Engram”,单是这个词就值得单独写一篇。Engram是神经科学里的术语,中文通常译作“记忆痕迹”,指的是某一记忆在神经系统中留下的物理或生化变化。一家做大模型的团队,放着“Long Context”“Agent Memory”这种一看就懂的名字不用,偏偏选了一个学术味极重的词,这说明他们要讲的不是把上下文窗口加长一点,也不是给Agent挂个临时缓存,而是想从底层重新思考:模型到底该怎样“记住”东西。

这篇内容不是论文的逐字翻译,我也拿不到比大家更多的内部细节。我基于标题命名、Deepseek模型一贯的技术风格、以及大模型记忆方向这几年来公认的难点,做一次有根据的推演,并给出工程上可以落地的实验方案。适合这几类读者:被长对话漂移问题折磨过的应用开发者,在做Agent记忆模块的算法工程师,还有单纯想理解“大模型记忆”这个方向为什么突然变热的人。

1. 为什么“Engram”这个词本身,比论文摘要信息量更大

1.1 从神经科学借用过来的核心含义

Engram这个概念最早来自一百多年前的生物学研究,当时的学者发现,生物体经历过某个事件后,大脑里会留下一个可供后续唤醒的痕迹。它不是一个单独存放记忆的抽屉,而是一组神经元被激活后形成的连接模式。你回忆一件事,不是从数据库里“查”出来,而是把过去激活过的那组神经回路重新点亮一次。这个说法放到大模型身上非常贴切:如果上下文是模型正在处理的“工作台”,KV Cache是工作台上的草稿纸,那Engram想做的,就是把这些东西沉淀成可以长期保存、随时再激活的“神经回路”。

Deepseek给论文起这个名字,等于在一开始就划清了边界。它要做的不是更长的上下文窗口,而是另一种形态的存储。上下文窗口无论多长,本质上都是对话开始后临时搭建的空间,一轮会话结束就清空。KV Cache虽然能复用,但它保存的是注意力计算过程中的中间产物,不是语义层面的记忆,而且占用显存的成本非常高。Engram指向的是“经历过后留下的痕迹”,这个痕迹必须能跨会话生存,必须能在下次相关场景出现时被重新触发。这个定位一出来,后续技术路线的选择空间反而变得清晰了。

1.2 Deepseek做记忆这件事,为什么不是“锦上添花”

Deepseek的开源模型在推理能力和性价比上已经积累了不少口碑,开源社区里有很多基于它的应用,比如本地知识库助手、自动化Agent、个人日记分析工具。这类应用的共同痛点恰恰是记忆:每次对话开始时模型是“全新的”,它不认识你,不记得上次聊到哪,不知道你反复强调过的偏好。如果推理模型只会“每问必答”,却无法把历史经验累积下来,那它就永远只是一个更聪明的问答机,而不是一个能长期协作的伙伴。

所以Engram这篇论文放在这个时间点出现,本质上是把大模型的竞争从“单次对话的智力”拉到了“跨时间的一致性”上。这和我平时做AI应用开发时的体感完全一致:跑通一个单轮推理demo只需要几天,但让同一个模型在几十轮交互后不跑偏、不遗忘、不把旧信息和当前事实搞混,难度会指数级上升。Deepseek如果能在Engram里给出一条工程上可复制的路线,那它比单纯刷榜带来的实际价值要大得多。

1.3 读者最应该先建立的认知框架

在往下拆之前,先建立一个统一的框架:记忆系统一定包含三个阶段。先是编码,也就是决定“这段信息值不值得记、该记成什么样子”;然后是存储,决定“记在哪里、用什么结构、保存多久”;最后是提取,决定“在什么时机、用什么线索、把哪些记忆重新拿回工作上下文里”。现在市面上绝大多数所谓的“记忆方案”,其实只做了存储阶段最粗糙的一部分,比如把历史对话塞进向量数据库。Engram如果要做的是真记忆,就必须把另外两个阶段也补上,而且三个阶段要能联合优化。

这篇文章后续的推演和实验方案,也都按照“编码—存储—提取”这条主线展开。无论Engram论文最终的具体实现是什么,只要它还在“记忆痕迹”这个概念框架内,那核心要处理的必然是这三件事。

2. 先说清楚大模型现有的“失忆症”到底严重到什么程度

2.1 长上下文并没有真正解决记忆问题

很多人的第一反应是:记忆问题不是已经被128K、1M上下文解决了吗?其实完全不是一回事。长上下文的本质是“允许你在一次对话中带进来更多材料”,但它不做任何区分,所有内容都摊在工作台上。你问一个几百轮之前的细节,模型要在海量的历史文本里自己翻找;翻找失败时,它不会诚实地说“我找不到了”,而是会用当前上下文里最后出现的信息进行补全,产生看起来很合理但实际错误的内容。这就是所谓的长对话漂移,越聊到后面,模型对早期信息的失真越严重。

我在实际项目中观察到另一个更加隐蔽的现象:上下文越长,模型的注意力越容易被末尾内容主导。前面第二轮说过“我不吃辣”,到第四十七轮点菜推荐时,模型大概率会忘记这个约束,因为那层信息早就被几十轮对话冲淡了。长上下文能容纳信息,但容纳不等于理解,更不等于随时可用。这类似于把一万本书堆在桌面上,你说“桌面容量很大”,但你要找特定的一句话时,效率反而比只放几本关键笔记还要低。

2.2 现有兜底方案各自的短板

目前应对记忆问题,主流做法有三类,但每一类都有明显缺口。

第一类是RAG(检索增强生成),把外部文档切片后做成向量索引,回答问题时先检索再生成。RAG擅长处理“静态知识”,比如产品文档、规章制度,因为这些内容不会频繁变动,检索到了照着念就行。但真实记忆里大量是“动态经历”,比如用户的偏好变化、任务的完成状态、对话中产生的中间结论,这些内容几乎不会沉淀成文档,也没有被切片索引的机会。

第二类是总结压缩,每一轮对话后让模型生成一段摘要,下一轮把摘要塞进上下文。压缩的问题在于丢掉细节,尤其是那些当时觉得没用、后面突然变得关键的信息。比如用户两小时前提过一个备选方案,你可能觉得不重要没有写进摘要,结果后来他说“就按之前提过的备选来”,系统彻底懵了。

第三类是KV Cache复用,保存Attention中间状态来加速多轮推理。这个方案距离语义层太远,开发者几乎无法控制模型记住了什么、忘记了什么。它解决的是计算效率问题,不是记忆问题。

2.3 记忆的三个环节,目前大多数系统只做了半个

结合编码、存储、提取三阶段框架来看,现有方案的问题会非常明确。RAG做的是“外部存储”加“按相似度提取”,但它的编码完全交给Embedding模型,模型可不管什么该记什么不该记;总结压缩做的是“编码”,但没有独立的提取机制,所有东西都堆在一起重新过一遍;KV Cache则是彻底绕开了记忆语义,只停留在计算状态层。

一个完整的Engram式系统,应该是先通过一个“记忆编码器”判断这段经历是否有保存价值,然后把它改写成一个紧凑且保留细节的记忆痕迹,存进一个支持增删改查的记忆库;等到新问题出现时,再通过一个“记忆触发器”判断当前场景是否需要唤醒旧记忆,如果需要,就把相关痕迹放回主提示词里。整个过程必须由大模型参与决策,而不是靠简单的相似度检索走天下。想清楚这一点,再看任何一篇记忆方向的论文,都能很快定位它到底改进了哪个环节。

3. 从标题反推Engram的技术路线:记忆痕迹,而不是记忆文本

3.1 写入端:把经历改写成痕迹,而不是原文存档

如果只是把对话原文存进数据库,那Engram这个名字就没意义了,那叫日志系统。既然叫记忆痕迹,写入端就必须发生一次“形态变换”。我推测Engram会把一段经历压缩成带有结构化属性的痕迹对象,比如时间、参与者、事件类型、影响强度、关键内容摘要,以及一个可检索的语义向量。在这个流程里,模型要做的不是摘要,而是“痕迹提取”——只保留对后续决策可能有影响的部分,丢弃纯寒暄和过程噪音。

这一点其实非常反常规。普通摘要追求完整概括,而痕迹提取更像做减法:这一轮对话里,哪些事实是需要长期记住的?哪些是用户表达的偏好?哪些任务是“待办状态”?把这些抽出来,每个都变成一个独立的小记忆单元。这样存储的就不是“聊天记录”,而是“发生过的事情”。以后召回时,模型不是在看历史文本,而是在“重放经历”,这更接近Engram一词的本意。

3.2 存储端:记忆之间的冲突与遗忘机制

有记忆就必然有遗忘。如果每条记忆痕迹都永远保留,系统很快会被低价值信息淹没,召回的准确率也会整体下降。Engram大概率会给每条痕迹设置一个“可访问度”,初始权重高,随时间和未被访问次数逐渐衰减。当某条记忆与更新的记忆发生事实冲突时,系统需要有能力做版本淘汰或标记。这就像人脑的遗忘曲线:不常用的记忆逐渐变淡,但在特定线索触发下还能重新激活。

存储端另一个绕不开的问题是格式化。个人级的记忆可以松散,但Agent级的记忆必须能看到完整的任务状态迁移:计划是什么、已执行到哪步、剩余依赖是什么。所以我更倾向于Engram的存储不是单一向量库,而是“向量索引加结构字段”的混合形态。向量负责柔性召回,结构化字段负责精确过滤,比如“只找昨天之前、状态为未完成的任务”。这种设计在工程上完全可行,也符合Deepseek一贯偏向实用主义的技术风格。

3.3 提取端:被动检索与主动触发并存

提取端是最容易做出差异化、也最能看出论文功底的部分。RAG时代的提取是被动的:用户提问,系统拿问题去向量库里搜,搜到什么就给什么。Engram必须往前走一步:不仅用户提问时召回,还要在模型推理过程中自发地判断“现在该用哪段记忆了”。这有点类似人类聊天时会突然想起一件旧事,因为它和当下的话题存在隐含关联。

实现上可以有两种路径。第一种是工具式触发,在Agent的执行流程里增加一个“记忆检索”步骤,由模型自己决定当前是否调用、用什么关键词调用。第二种是隐式注入,把候选记忆作为少量额外上下文直接拼到新一轮对话里,让模型自己去用。第一种更干净,可控性强;第二种响应更快,实现简单。Engram的论文大概率会讨论这两者的融合方式,因为只有主动触发,才能解决“用户没有直接提及,但旧记忆其实很重要”的那类场景。

3.4 与现有技术的关系:不是替代,而是补位

用一张表把Engram式记忆和现有方案放在一起对照,差异会更清楚。

维度RAG上下文压缩KV Cache复用Engram式记忆痕迹
记忆对象静态文档会话摘要注意力状态结构化经历
写入方式离线切片模型总结自动缓存痕迹提取
提取方式向量相似度全量注入计算复用主动触发+相似度
跨会话能力强弱弱强
动态偏好记忆差一般无强
冲突处理无无无可编辑可遗忘

表格里的“Engram式”并不代表论文的最终实现,但我判断它至少要达到右侧这行能力才算配得上这个标题。如果只是做一个升级版RAG,叫“DeepRAG”就够了,不必动用Engram这么重的概念。换句话说,这篇论文真正值得期待的地方,是大模型能不能第一次拥有“自省式记忆”——自己决定记什么、自己决定怎么忘、自己决定何时想。

4. 在项目里快速复现Engram思路的最小记忆模块

4.1 先划定边界:这个复现方案验证的是什么

论文的完整训练流程我们暂时无法复刻,但在应用层完全可以先做一个“Engram风格”的记忆模块,用来验证思路本身是否成立。我给自己的要求是:不依赖任何重型框架,用普通Python代码加一个Embedding接口就能跑起来。验证目标有三个:用户偏好能不能跨会话保留、任务状态能不能被准确召回、旧记忆和当前事实冲突时能不能纠正。

这套验证跑通之后,你会清楚地看到“记忆痕迹”和“历史文本存档”在实际体验上的差别。前者让模型越用越懂你,后者只是让模型能翻旧账。我这里给出一版高度简化的参考实现,核心逻辑保留,方便你拆开改造成自己的版本。

4.2 记忆写入:用启发式信号判断“值不值得记”

最朴素的问题就是:不可能每句话都存,那应该存什么。我用了两组信号:一组是显式的关键信息信号,比如用户提到时间、地点、决定、偏好、任务状态;另一组是模型自评信号,让模型自己回答“这条对话有没有值得跨会话保留的实体信息”。判断为需要保留的内容,才进入痕迹提取环节。

import time from dataclasses import dataclass, field from typing import List, Optional @dataclass class MemoryTrace: text: str trace_type: str # preference / task / fact / plan created_at: float access_count: int = 0 active: bool = True class TraceMemory: def __init__(self, llm_encoder, llm_extractor): self.encoder = llm_encoder # 返回文本向量的函数 self.extractor = llm_extractor # 返回结构化痕迹的模型调用 self.traces: List[MemoryTrace] = [] self.index: List[str] = [] # 保存向量对应的trace id def add(self, conversation_turn: str, user_meta: Optional[dict] = None): # 第一道闸门:是否值得记录 important_markers = ["我喜欢", "我决定", "目标是", "已完成", "地址是", "密码是", "下次记得"] if not any(m in conversation_turn for m in important_markers): judged = self._ask_model_should_keep(conversation_turn) if not judged: return # 第二道闸门:提取痕迹 trace_payload = self.extractor(conversation_turn, user_meta) trace = MemoryTrace( text=trace_payload["text"], trace_type=trace_payload["trace_type"], created_at=time.time(), ) vec = self.encoder(trace.text) self.traces.append(trace) self.index.append(vec)

这段代码里最关键的其实是trace_payload的输出格式,我会让模型返回{"text": "……", "trace_type": "preference"}这样的JSON。text字段不是原句,而是“痕迹化”后的句子,比如用户说“今天开始我吃素了,别给我推荐牛排”,痕迹化后存的是“用户饮食偏好:素食,自某日起生效”。这样以后召回时,模型拿到的是干净的事实,而不是一段带着情绪和废话的原话。

4.3 记忆提取:相似度初筛加模型重排

提取端我不能只依赖向量相似度,因为相似度检索会漏掉那些“词面不相关但语义相关”的旧记忆。我在初筛后加了一个模型重排步骤:先取出Top 20候选痕迹,再让模型判断其中哪些与当前问题真正相关,最终只保留Top 3到5条进入上下文。

def recall(self, question: str, top_k: int = 20, final_k: int = 3) -> List[str]: if not self.traces: return [] qvec = self.encoder(question) scored = [ (cosine_similarity(qvec, tr_vec), idx) for idx, tr_vec in enumerate(self.index) if self.traces[idx].active ] scored.sort(key=lambda x: x[0], reverse=True) candidates = [self.traces[idx] for _, idx in scored[:top_k]] # 模型重排:在候选里只挑真正相关的 selected_texts = [] for tr in candidates: relevance = self._ask_model_relevance(tr.text, question) if relevance: selected_texts.append(tr.text) if len(selected_texts) >= final_k: break return selected_texts

这个结构其实学的是搜索引擎常用的“粗排加精排”架构。粗排用向量保证效率,精排用模型保证准度。实际跑下来最大的体感是:召回的内容质量明显高于纯向量检索,因为模型重排能识别出很多“用词完全不同但实际指同一件事”的痕迹。

4.4 接入大模型主流程的参数建议

接入主流程时,我建议把召回结果放在用户问题之前,并用明确的标识符分隔。

[记忆痕迹] 1. 用户饮食偏好:素食(自2025年3月生效) 2. 当前任务:本周五前完成季度汇报PPT,依赖销售数据 3. 计划备注:汇报后与A同事确认下周评审时间 [结束] [当前问题] 帮我准备一下汇报的提纲

三个参数值得细调。一是top_k,候选量太少会漏,候选量太大会让重排模型变慢,我常用20到30;二是final_k,也就是最终注入条数,普通问答建议3条以内,长任务规划可以放到5条;三是记忆的“新鲜度加权”,在计算相似度时给近期痕迹乘一个大于1的系数,比如1.15,这样既能保留长期偏好,又能让近几轮的临时状态更容易被召回。

4.5 这一版方案的局限在哪里

必须坦白地说,上述代码只是验证“记忆痕迹”这个思路的最小骨架,距离Engram论文可能描述的完整机制还有很大距离。算子级的端到端优化、记忆间冲突消解、自动遗忘策略、以及记忆结构如何参与模型训练,这些在这版里都没有碰。但它有一个好处:能让团队在几天之内就获得对记忆系统的直观手感。先体会到“痕迹化比存档原文好用”,再看论文里更复杂的机制,就不会一头雾水。

我在自己项目里用这套结构做了一个个人助理类的Agent,跑了一个月后最明显的改变是:用户不用反复强调自己的偏好,系统在第三天开始能主动说出“按你之前的习惯,我把汇报时间安排在下午”。这种体验上的跃迁,是任何单轮评测指标都体现不出来的。

5. 落地Engram式记忆时,最容易翻车的三个地方

5.1 把流水账当记忆,导致提取结果一路跑偏

第一个坑是我在所有项目里都见过的:团队觉得记忆很重要,于是把每一轮对话全部存下来,结果没过多久,系统召回的内容越来越杂乱,模型开始在回答里引用毫不相关的历史碎片。原因很简单,流水账不等于记忆。真正值得形成痕迹的,是能够影响后续决策的信息,比如长期偏好、进行中任务、明确约定、用户主动提供的个人事实。而“今天天气不错”“嗯嗯好的”这类内容,存进去只会稀释检索质量。

解决办法是要在写入端设置足够强的过滤闸门。宁可漏掉一些潜在有用信息,也不要把无关内容放进来。漏掉的信息还可以通过未来重读历史补回来,但一旦垃圾痕迹混入且被模型当作依据引用,纠正成本极高。如果拿不准某个信息要不要存,可以退一步问自己:三个月后,这条信息还会对对话决策产生影响吗?如果大概率不会,就不该写进去。

5.2 召回到错误记忆,比没有记忆更糟糕

没有记忆的模型犯错,错在“不知道”;召回错误记忆的模型犯错,错在“自信地错”。两类错误里,后者对用户体验的伤害更大。我遇到过非常典型的案例:用户之前说“暂时不考虑上云方案”,结果系统把这条记成了“用户偏好本地部署”,后续所有跟部署相关的推荐都被带偏,而且每次都能在记忆片段里找到自信的依据。

应对这个问题,需要在提取端加一道“相关性确认”步骤,而不是让召回的痕迹直接拼进提示词。可以让模型在引用记忆前先输出一个简短判断:“这条记忆是否适用于当前问题,有没有更新的信息覆盖它”。现场跑的时候可以给大模型一次人工纠正的机会,用户说“不对”之后,系统要能当场标记这条记忆为失效或降权。没有纠正和更新机制的所谓记忆系统,最终都会变成一种慢性误导源。

5.3 记忆系统评测:不要拿单轮问答的指标来自欺欺人

落地记忆系统最容易被忽视的,是评测方式和传统模型评测完全不同。传统问答可以看准确率、看RAG的命中率,但记忆系统真正要测的是“跨时间的保持能力”。我建议至少设计三类测试场景。一类是偏好保持,第一轮让用户明确告知一个偏好,隔二十轮后再次询问,看模型是否还能遵从;第二类是状态追踪,在长达几十轮的任务中随机插入“当前任务进展到哪一步”的问题,看模型是否还能准确回答;第三类是记忆更新,在第一轮给出一个旧事实,中间轮次给出新事实,最后询问模型用的是哪个版本。

我给一个我自己常用的量化口径:记忆保持率,定义为“测试模型在需要旧记忆才能正确回答的问题上,给出正确回答的比例”。基线是完全不加载记忆的原始模型,对照组是加载原文日志的RAG式方案,实验组是Engram式痕迹记忆。跑完对比,你会非常直观地看到痕迹化处理带来的提升。尤其是在跨会话、长距离、干扰信息多的场景里,“原文存档”和“痕迹记忆”的正确率差距会非常稳定地拉开。

6. 关于Engram这个方向,我能给出的最实际判断

Engram这篇论文最终披露的技术细节,我还没有看到,但这不妨碍我们对方向做出判断。大模型的能力分两头,一头是“即时的智能”,也就是单轮推理、代码生成、逻辑分析,这个方向已经被卷得很厉害;另一头是“持续的智能”,也就是跨时间保持一致性、积累经验、越用越懂你,这一头目前还处在非常早期。Deepseek选择在这个时间点打出Engram这张牌,至少说明头部团队已经把记忆问题当作下一代模型的胜负手,而不是某个应用层可以自行修补的小问题。

从工程实践者的角度看,我现在不会等论文开源才开始动工。上面的最小实现、参数调法、三类测试场景,任何团队都可以在本周内搭起来跑一轮真实数据。先在自己的业务里积累对编码、存储、提取三环节的体感,等Engram的正式方案出来时,你能够一眼看出它站在这个框架里的哪个位置,哪些环节做了更强的优化,哪些设计比你现在用的方案更优雅。用我自己的话说:读一篇热门论文的最好方式,是带着你自己动手跑过的经验去读,而不是空着手去看热闹。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询