ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AI Agent记忆系统揭秘:双网络模型与工程落地全解析

2026/9/10 1:50:17 拓冰建站 浏览量
AI Agent记忆系统揭秘:双网络模型与工程落地全解析 “Agent 又忘了。”这是我在社区里被问到最多的一句话也是所有长期使用 AI Agent 的人最深的痛点。我前面两篇聊了 Agent 的规划能力和工具调用但很多人反馈真正拦住他们从“尝鲜”走向“依赖”的那道坎是 Agent 没有记忆。你上周告诉它你的代码风格偏好这周新开一个会话它全忘光你昨天让它整理了一份 Obsidian 知识库的阅读清单今天问它“上次我们说到哪了”它一脸茫然。这篇我打算把这层窗户纸捅破Agent 的记忆到底是怎么一回事短期记忆和长期记忆怎么分工双网络记忆模型怎么落地以及我在实际项目中踩过的迁移、压缩、召回那些坑。无论你是想自己搭一个 Agent还是仅仅想更深度地理解 Agent 运行逻辑这篇都值得你坐下来慢慢看。1. 为什么记忆是 Agent 从玩具走向工具的“分水岭”没有记忆的 Agent本质上是一个“每次都重新自我介绍”的陌生人。你可以让它完成一次漂亮的代码审查也能让它帮你生成一份结构完整的周报但下一次对话它又退回原点。这个体验很微妙单个任务层面它很强长期陪伴层面它几乎为零。我自己在早期用 Agent 辅助写代码时经常出现一种荒诞感——我不得不在每个新会话里重新粘贴一遍项目背景、技术栈、目录结构、命名约定然后祈祷这次它别再把异步写成同步。这种“罗里吧嗦地重复背景”的过程才是 Agent 效率的真正杀手。我后来给记忆下了一个更务实的定义记忆是智能体在决策时能够主动调用的、跨时间的状态信息而不是简单地把聊天记录存进数据库。区别在哪聊天记录是死的存储和召回是两条线。很多人的 Agent“看似有记忆”其实只是把几轮上下文拼在一起喂给模型一旦超出窗口就被截断真正的记忆应当是经过筛选、组织、索引之后在合适的时机以合适的方式重新进入模型的推理上下文里。这个定义直接决定了 Agent 的上限。记忆之所以成为“分水岭”是因为它牵扯到三个层面的能力记住你是谁用户画像与偏好、记住你做过什么行为历史与项目上下文以及记住你偏好怎么做决策风格与工作流。前面两点相对好实现存储和检索到位就行第三点才真正考验设计者的功力因为它不是简单回放而是要让 Agent 把历史经验“内化”成行为准则。举一个我自己的场景我长期给某几个开源项目做本地化维护每次修改代码前我要它先看一遍 CHANGELOG 和既有风格这个习惯如果每次都靠临时提醒它会做得磕磕绊绊一旦我把“修改前必须检索 CHANGELOG 和现存命名约定”写进长期记忆它连续几个星期都执行得极其稳定。所以这篇的核心其实就是两件事怎么设计一套可运行的记忆系统以及怎么让这套系统在真实项目中经得住考验。我会把短期记忆、长期记忆、用户画像、向量召回、记忆压缩和迁移这些概念一个个拆开全部用我实操过的项目场景来讲而不是堆工程术语。1.1 “记忆”的三个层次技巧层、事实层、习惯层如果继续细分我觉得 Agent 的记忆还能再划出三个层次。技巧层记忆是“怎么做”的方法论。比如“这个项目使用 pnpm 而不是 npm”、“错误日志优先查看 stderr”。这类记忆最容易被复用但也是最容易过时的。事实层记忆是“是什么”的知识点。比如“认证模块在auth/目录下核心逻辑在AuthService.java”。这类记忆高度依赖项目结构一旦重构就必须更新。习惯层记忆是“你偏好怎样”的画像。比如“代码提交信息要遵循 Conventional Commits”、“你习惯把外部 API 调用统一封装到clients/目录”。这类记忆最难获取往往需要多次交互才能提炼但一旦沉淀下来带来的体验提升最明显。在设计记忆系统时如果三个层次混在一起存、用同样的召回策略最后多半会互相干扰。下面讲的双网络模型其实就是给不同类型记忆提供两种差异化的通道让它们各归其位。2. 短期记忆、长期记忆先分清“缓存”和“硬盘”很多人一听到“Agent 记忆”就直接想到向量数据库这其实是把问题想窄了。在动手之前我们必须先分清短期记忆和长期记忆因为两者的存储介质、更新频率、召回方式、以及在意指标完全不同。用一个不太严谨但很好懂的类比短期记忆像电脑里的内存速度快、容量小、断电即失长期记忆像硬盘容量大、可持久化但访问时需要寻址和读取。短期记忆的核心是“上下文窗口管理”。大模型的输入长度有限不管窗口是 8K、128K 还是更大会话持续到一定程度一定会触顶。工程上常见的手段是滑动窗口只保留最近 N 轮对话或者用“摘要滚动”的方式把前面的对话总结成一段概述腾出空间给更近的内容。我在实际项目中通常会组合使用最近的对话完整保留再往前的按主题压缩成摘要。这样既照顾了即时上下文又保留了大局线索。长期记忆的核心是“可检索的结构化沉淀”。它要回答的是“这个用户上次说过什么偏好”“这个项目之前为什么选了这个方案”“类似问题过去是怎么解决的”。实现层通常是向量库、关系型数据库、知识图谱、或三者的组合。长期记忆的难点不在存而在取什么时候取哪部分注入提示词注入太少了没有效果注入太多了又挤占上下文窗口还把无关信息也带进来。短期记忆与长期记忆的差异我习惯用下面这张表来思考维度短期记忆长期记忆存储介质上下文窗口、会话缓存向量库、数据库、知识图谱容量受模型窗口限制理论上可无限扩展读取速度极快直接可见需要检索有延迟有效期单次会话或任务周期跨会话、跨天甚至跨年写入方式对话内容自动累积经过筛选、抽取、向量化后写入更新机制滚动淘汰旧内容按重要性/时效性定期更新典型故障窗口溢出早期内容被截断召回不相关、信息过时、重复冗余从这张表能看出短期记忆和长期记忆的“坑”完全不同。短期记忆最怕的是挤占和截断——记得太多反而把关键信息挤出去长期记忆最怕的是脏和偏——存进去的内容不准确、过时或者召回时检索到一堆噪音。任何一套靠谱的记忆系统都要为这两种故障分别设计对策。2.1 工作记忆容易被忽略的“第三态”除了短期和长期我不想让你忽略一个中间态工作记忆。这个概念借鉴自认知心理学指的是“当前任务执行过程中需要时刻持有的一组临时状态”。举个实际例子Agent 正在执行一个“重构登录模块”的任务它需要记住当前在改哪个文件、已经改了哪几处、下一步要动哪个函数。这些信息既不属于对话历史也不该永久写入长期记忆它就是任务进行中的一块暂存区。实现上可以用结构化 Task State 来承载比如一个 JSON 对象记录任务 ID、当前文件、已完成子目标和下一步计划任务结束后自动清空或归档。很多人做 Agent 时把工作记忆和短期记忆混为一谈结果任务一长上下文窗口被中间过程占满反而丢掉了最初的指令。把工作记忆单独拎出来管理是我见过性价比最高的优化之一。3. 双网络记忆模型语义网络与情景网络的协同提到 AI Agent 记忆绕不开一个概念双网络记忆模型。这个说法在李博杰等人的多份“深入理解 AI Agent”材料里被反复讲过它本质上是把记忆分成两个网络——语义网络和情景网络——两者协同工作模拟人脑记忆的分工机制。语义网络负责通用知识和结构性知识什么是 RAG、Python 的 GIL 是干什么的、常见的算法复杂度排序。这些知识不一定来自用户的具体交互更多来自模型的预训练权重或者是被整理好的外部知识库。它的特点是稳定、通用、不需要频繁更新。在工程上语义网络对标的是 RAG 里的文档库、知识图谱甚至模型自身的参数化知识。情景网络负责具体经历和个性化上下文这个用户上周三让我优化过哪个接口、他喜欢的代码风格是什么、之前那个需求最后为什么被驳回。这些记忆带有时空属性和个人色彩是真正的“与你相关”的信息。它的特点是高频变化、强主观、必须和具体实体绑定。工程实现上通常是带 metadata 的向量库或者 OneDrive/Obsidian 这类个人知识库再加上专门的召回流水线。双网络模型的价值在于它逼迫你在设计时区分“通用能力”和“个人上下文”不会一股脑把什么信息都塞进同一个库里。我在早期设计记忆模块时犯过一个典型错误——把用户偏好、项目结构、领域知识、临时结论全部放在同一个 collection 里用同一个 embedding 模型向量化。结果就是召回时经常“张冠李戴”问代码规范它把用户转发的一篇行业趋势文章召回出来了问上次改到哪它召回的是项目中某份技术文档。后来按双网络拆开后我把通用知识路由到知识库把个人上下文和项目经历留在情景记忆库问题立刻缓解了大半。3.1 语义网络的实现要点静态沉淀 周期更新语义网络的特点是“更新慢但要求准确”。如果你的 Agent 需要依赖一套专业文档或企业知识库这套网络通常的做法是对文档分段、清洗、向量化写入独立 collection。这里的几个细节直接影响召回质量。第一是分段策略不能无脑按固定字符切要尽量按照语义边界标题、章节、段落切分保证每段的主题完整。第二是Embedding 模型版本必须锁死我踩过这个坑后面会详说。第三是更新机制要克制不要每次对话都往里写新内容语义网络里的东西是被验证过的通识不是聊天时随口说的信息。一般可以设定每天或每周定期重建索引而不是实时写入。3.2 情景网络的实现要点实时沉淀 主动标注情景网络是“让 Agent 记住你”的关键通道。它的写入要有筛选规则不是所有对话都值得存。我在实践中用三条过滤规则一说出来的是偏好“我更喜欢用异步方式实现”纠正过的内容是错误校正“不是 A 模块是 B 模块”明确指定的是任务背景“这个项目要部署到内网不能走公网依赖”。符合这三类规则的对话片段才抽取成记忆条目写入情景库。写入时我会额外附上几个 metadata 字段时间戳、来源会话 ID、涉及的实体名比如项目名/文件名/用户名、和信任等级。这些字段在召回时会被当成过滤条件用处非常大。比如用户问“上次那个认证模块改得怎么样了”召回时直接加一个entityauth的过滤条件命中率能提升一大截而不是纯靠向量相似度碰运气。4. 让 Agent 真正“记住你”从用户画像到代码修改上下文的工程实现理论说完了下面进入实操。工程上实现“记得住”通常分三个阶段写入、召回、注入。每个阶段都有各自的细节我逐个展开。4.1 记忆写入什么该记、什么不该记记忆系统的地基是写入策略。写得太激进什么话都存后期召回会被大量无用信息淹没写得太保守长期只沉淀下寥寥几条摘要Agent 依然像失忆。我的经验是用两层过滤第一层是类型过滤判断当前轮对话里有没有值得记忆的目标。偏好声明、纠错反馈、决策记录、任务进展节点这四类优先写。日常寒暄、临时指令、中间过程的调试信息直接丢弃。第二层是内容去重与合并如果新记忆和旧记忆指向同一个实体且语义相似就不新增只更新原条目的相关字段。下面是一段简化的写入代码示例用 Python 配合 ChromaDB 做演示。真实项目里你可以替换成 Qdrant、Weaviate 或任何你熟悉的向量库。import chromadb from chromadb.utils import embedding_functions client chromadb.PersistentClient(path./agent_memory) col client.get_or_create_collection( nameepisodic_memory, embedding_functionembedding_functions.DefaultEmbeddingFunction(), ) def write_memory(text: str, entity: str, trust: float, session_id: str): # 去重先查是否已有相似度极高的记忆 existing col.query( query_texts[text], n_results1, where{entity: entity}, ) if existing[distances] and existing[distances][0][0] 0.1: # 距离极小说明语义几乎一致只更新时间戳即可 mem_id existing[ids][0][0] col.update(ids[mem_id], metadatas[{last_seen: now()}]) return mem_id uuid4().hex col.add( ids[mem_id], documents[text], metadatas[{ entity: entity, trust: trust, created_at: now(), session_id: session_id, }], )代码本身不复杂但里面有两个容易被忽视的细节。一是where{entity: entity}这个过滤条件它本质上把你的记忆库按实体分区避免项目 A 的记忆污染到项目 B 的召回。二是我特意在写入前做了一次相似度查询用距离阈值来决定是“新增”还是“更新”这个小动作能把记忆库的冗余度压到极低。4.2 记忆召回相似度检索只能算一半召回阶段是决定用户体验的直接环节。最常见的做法是把当前用户问题向量化去库里查 Top K 相似条目拼进上下文。但这个“朴素召回”在实际工程里通常不够用我在项目中会再加两道过滤第一道是时间衰减。同样是“用户偏好用 TypeScript”三周前记下的和三天前记下的置信度完全不同。召回时可以对分数做一个时间惩罚import time def recall(query_text: str, entity: str, top_k: int 5, half_life_days: int 7): results col.query(query_texts[query_text], n_resultstop_k * 3, where{entity: entity}) scored [] for doc, meta, dist in zip(results[documents][0], results[metadatas][0], results[distances][0]): age_days (time.time() - meta[created_at]) / 86400 decay 0.5 ** (age_days / half_life_days) score (1 - dist) * decay * meta.get(trust, 0.8) scored.append((score, doc, meta)) scored.sort(keylambda x: -x[0]) return scored[:top_k]这个函数里半衰期half_life_days7是个经验值表示记忆的权重每过 7 天衰减一半。你可以根据业务调整对于用户画像这种长期属性半衰期可以放宽到 30 天对于项目最近改动这种高频信息3 天可能更合适。第二道是重排Rerank。纯向量相似度召回出来的结果经常有“语义像但实际没用”的条目。条件允许的话接一个轻量的 Rerank 模型或者干脆用 LLM 自己对候选记忆做二元判断“这些历史记忆中哪些对解决当前问题有帮助” 这个方法开销略大但召回精度提升非常明显。我通常只会在用户问题涉及“上次/之前/之前你说过”这类跨会话指代时才启用 LLM 重排日常问题用向量召回基本就够。4.3 记忆注入让记忆出现在该出现的位置记忆召回出来之后不能简单塞进系统提示词里就完事。注入位置和注入格式直接影响 Agent 对记忆的使用效果。我的做法是把记忆分成两类分别放到不同位置。一类是稳定画像型记忆比如用户偏好、常用技术栈、沟通风格这类适合放系统提示词让 Agent 每轮都看见。另一类是任务上下文型记忆比如“上次改到哪”“当前项目有哪些待办”这类更适合跟随每次用户消息动态注入。把两类混在一起全塞进系统提示词不仅浪费 token还容易让模型把过时信息当成硬规则这就要靠记忆的更新机制来兜住了。4.4 记忆更新与冲突处理不能被旧信息带偏记忆最危险的并不是“没有”而是“有但过时了”。Agent 因为一段过时的项目结构记忆连续几轮都在错误目录里找文件这种体验比失忆更糟糕。所以记忆系统必须有清晰的更新链路。我倾向于给每条记忆加一个status字段取值是active、pending_review、archived。当新写入的记忆与旧记忆指向同一实体但语义冲突时不直接删除旧记忆而是把它标记为pending_review同时把新记忆置为active。下次召回时优先读取active的记忆并把冲突条目附带在上下文里提醒模型“这里有一条旧信息可能过时”。这个做法的好处是保留追溯能力万一新记忆是错的还能把旧记录捞回来。代码修改场景下特别能体现这个需求。你让代码型 Agent 记住“上一个阶段完成了哪些改动”如果 Agent 只记住了最新一次的日志而旧改动记录被直接覆盖一旦需要回滚版本或者复盘需求变更历史就找不回来了。所以我在记录代码修改历史时从来只追加不覆盖每条记录都带着提交时间、文件路径和改动摘要召回的优先级由时间和当前分支共同决定。5. 一个真实的记忆迁移踩坑历史对话记录如何变成可召回的记忆讲完设计框架我想分享一个实打实的项目经历。当时我想把一个叫 WorkBuddy 的本地助理工具从旧电脑迁到新电脑目标很朴素把过去几个月的聊天记录、用户偏好、项目备注完整搬过去让新环境里的 Agent 无缝延续旧“人设”。我原以为“记忆迁移”就是复制粘贴数据库文件。结果迁移之后新环境里的 Agent 表现得就像一个刚出厂的机器人不仅记不得我常去的几个项目路径甚至把我之前设定好的偏好回复得乱七八糟。排查了一整个下午我发现问题出在四个层面。第一是Embedding 版本不一致。旧电脑上向量化时用的 Embedding 模型是某个特定版本新环境里重新装了依赖版本升级了同一句话在旧表里的向量和新环境计算出的向量不在同一个向量空间里。新旧向量无法直接比较召回自然全乱。修复方式是必须锁死 Embedding 模型的版本哈希迁移时把模型版本号和向量库一起打包。第二是metadata 丢失。我当初导出数据时只导出了文本向量没有保留 metadata 字段。结果在新环境里所有记忆条目都失去了“来源会话”“实体标签”“创建时间”后加的按实体过滤和时间衰减策略全部失效。从那以后我导出任何记忆库都强制带上完整 metadata。第三是去重失效。旧环境里通过写入时查重保证了同一偏好只有一条记录但迁移到新环境时因为向量空间变了重算相似度时阈值不匹配原本去重过的数据在新库出现了大量重复项一个偏好可能有三四条近似记录。召回时 Top 5 里全是同一条记忆的变体。修复方法是在迁移后重新跑一遍全量去重再重建索引。第四是只迁移了“结果”没迁移“过程”。WorkBuddy 的历史对话记录本身是有时间线和因果的原版的记忆召回之所以准确是因为它能结合当时的对话背景理解“这个偏好是在什么场景下提出的”。迁移时我只导出了结构化的偏好条目丢了场景上下文导致 Agent 知道我的偏好但不知道偏好适用的边界。这直接印证了双网络模型里“情景网络”的价值——没有情景属性的记忆往往只是干巴巴的事实。这次迁移踩坑之后我对记忆系统的认知有了一个大的升级记忆迁移不是一个“拷贝文件”的动作而是一个“转换并重建索引”的过程。正确做法是把旧数据导出为中立格式比如 JSONL然后在目标环境里重新清洗、去重、向量化、建立索引而不是直接搬运数据库文件。5.1 代码场景中的“记忆召回”以 opencode 类工具为参照顺便聊聊代码型 Agent 的记忆召回。很多人问我 opencode 这类工具是怎么实现“召回上次代码修改情况”的虽然各家实现细节不同但思路高度一致把代码的变更历史做成可检索的记忆而不是把完整代码塞进上下文。我自己的项目是一个给代码仓库配的本地 Agent参考了这个思路。核心流程如下每次代码变更后对git diff --stat和关键 diff 内容做一次摘要提取“改了哪些文件”“核心改动是什么”“为什么改如果有 commit message”。把摘要连同文件路径、提交时间、当前分支名一起写入情景记忆库。下次 Agent 启动或用户询问“上次改到哪了”时用当前工作区的状态生成查询向量做一次针对性的召回。这个方案里的关键是第 2 步的“提取”不是把 diff 全文向量化而是先让 LLM 生成一段 200-300 字的自然语言摘要再对摘要向量化。这样做有两个好处一是压缩了存储二是提高了召回语义匹配度。用户问“上次重构了哪些文件”和摘要里“重构了 ConfigLoader 类拆分了配置解析逻辑”的语义距离比和原始 diff 的语义距离要近得多召回效果自然好。实际跑下来这个方案稳定运行了几个月每天大概写入几十条变更摘要召回准确率一直在可接受范围内。如果你也想给代码项目做一个类似的记忆召回机制可以直接复用第 4 节里的写入和召回代码把entity设为code_change把text设为 LLM 生成的变更摘要其余逻辑完全一致。6. 会记也要会忘记忆压缩、遗忘策略与防污染很多做 Agent 记忆的新手方向都放在“怎么记得更多更牢”忽略了“怎么忘得聪明”。事实上记忆系统的核心瓶颈往往不是容量而是信噪比。一个塞满陈旧信息、且每条信息权重都平等的记忆库在召回时只会制造噪音让 Agent 既记不准、又答不快。6.1 记忆压缩从“原始片段”到“递归摘要”记忆压缩的手段很多我用的策略是分级摘要。第一级单轮对话或小主题对话结束后如果这段对话有长期价值比如定义了一个新的项目规范就生成一条摘要写入。第二级当一个会话积累了大量一级摘要后定期把同一主题下的摘要合并成更高层的抽象。这个过程是递归的类似于人脑从具体经历中逐渐提炼出通用规则。举一个实际例子。你和 Agent 在几天内多次讨论“日志系统怎么改造”第一次讨论时它记住了“日志要按模块拆分”第二次时记住了“用 Level 字段标记上下文”第三次时记住了“线上环境日志要脱敏”。如果这三条分散存入每次召回的 Top 1 可能都不一样但如果你定期做一次二级摘要合成一条“日志改造规范按模块拆分、记录 Level、线上脱敏”召回时命中率和可用性都会大幅提升。6.2 遗忘策略重要性评分 时间衰减 主动淘汰遗忘不是 bug而是一种主动策略。我的设计同时考虑三个维度重要性评分写入时由规则或 LLM 打分比如“用户明确强调的偏好”作用为 0.9“随口一提的信息”为 0.5“调试过程中的临时结论”为 0.3。分数过低的条目初期就不建议写入。时间衰减第 4 节已经演示过按半衰期降低权重。不同记忆类型给不同半衰期。主动淘汰定期扫描记忆库把“评分低且长期未被召回”的条目归档或删除。我这里的阈值是连续 30 天未被召回、且信任分低于 0.6 的条目自动进入归档区。归档区不参与日常召回但保留人工恢复的可能性。这套策略的核心逻辑是让记忆库始终维持在一个“小而精”的状态。一个几千条高质量记忆的库远远好过一个几百万条但大部分是噪音的库。LLM 的上下文窗口是稀缺资源注入一条低价值记忆就等于挤掉一条高价值记忆的空间。6.3 防污染不要让每个词都变成记忆最后是防污染。记忆污染的来源主要有三种模型幻觉生成的“伪记忆”、用户随口说但并非真实偏好的信息、以及对话中误被当成结论的中间过程。我防污染的手段是从写入源头把关。只有满足至少一条以下条件的文本才允许进入长期记忆用户用了明确偏好词汇“我更喜欢”“务必”“不要”、内容是纠错“上次说错了应该是”、内容被用户显式要求记住“记住这点”、或者内容在后续对话中被反复提及并被确认。其他内容一律只保留在短期会话中会话结束即清空。这个过滤器会牺牲掉一些“擦边记忆”但换来的却是极高的记忆可信度我觉得非常划算。7. 面向 2026Agent 记忆的技术趋势与选型建议到了快收尾的地方我想聊一点对未来的判断。记忆一定是 Agent 走向真正“个人化”的必经之路也是 2026 年 Agent 量产落地的关键拼图。第一个趋势是记忆协议标准化。现在各家 Agent 的记忆接口五花八门有的存 SQLite有的用向量库有的直接塞 JSON 文件相互之间无法互通。未来会像 MCP模型上下文协议那样出现面向记忆的统一协议让 Agent 可以以标准方式读写不同来源的记忆。这意味着你现在为记忆做的数据结构设计未来能更容易地对接标准生态。第二个趋势是外部知识库与个人记忆打通。越来越多人在用 Obsidian、Notion 这类工具管理个人知识库Agent 如果能把这些知识库当成“第二大脑”接入记忆系统就不再需要手动把文档“喂”给模型而是按需检索。我目前已经在自己的 Agent 上把 Obsidian Vault 作为情景网络的一部分接入检索时优先命中个人笔记再补模型通用知识效果比纯用模型内置知识要准确得多。第三个趋势是本地优先 跨设备同步。记忆涉及大量个人隐私全部放云端并不合适。本地优先的记忆存储方案比如 SQLite 加向量索引会越来越受欢迎同时通过端到端加密在多设备之间同步。我自己的迁移案例也说明了把记忆做成标准格式、可导出可重建比绑死在某个工具里要安全得多。第四个趋势是记忆可解释、可编辑、可审计。未来的 Agent 应该允许用户查看自己记住了什么手动修改或删除某条记忆甚至回滚到过去某个记忆版本。这不仅是产品体验问题也是隐私合规的必然要求。在工具选型上我给一个简单直接的路线建议。如果你的场景刚起步、数据量不大几千条以内直接用 SQLite JSON 一个 Embedding 模型就够完全不需要上重型向量数据库。数据量涨到十万级以后再引入 ChromaDB 或 Qdrant。如果涉及复杂的实体关系和推荐逻辑比如“用户 A 与项目 B 的关系”那再加一个图数据库Neo4j 或轻量的 Kuzu做关系查询。不要一开始就把技术栈搞到最豪华记忆系统的演进通常是你对业务理解加深的过程过早引入重型基础设施只会拖慢迭代速度。最后补一句面试相关的观察。现在 AI Agent 岗位面试很喜欢问记忆相关的问题高频的包括RAG 和 Agent 记忆有什么区别怎么设计跨会话记忆如何避免记忆召回污染记忆过期和冲突怎么处理我写这篇博客里的不少思考其实就是从面试问题倒推出来的。如果你正在准备这类面试建议把第 3 节的双网络模型、第 4 节的写入召回流程、第 6 节的遗忘策略这三个部分用自己的话串起来讲一遍基本能应付大多数追问。这段内容能写出来的核心原因是我自己在真实项目里反复经历过“没记忆—乱记忆—会记忆”三个阶段。如果只能留一个建议给你那就是不要一开始就追求大而全先把“什么值得记、什么时候召回、怎么防止旧信息带偏”三件事想清楚哪怕用的是最朴素的 JSON 向量检索也能让 Agent 的体验上一个台阶。等基础链路跑通之后再回来折腾双网络、迁移和压缩你会发现一切都是水到渠成。