SimpleMem:长期记忆不是存得更多,而是让每个 token 更有信息密度
SimpleMem长期记忆不是存得更多而是让每个 token 更有信息密度一句话定位SimpleMem 是一个面向 LLM Agent 的长期记忆框架用结构化语义压缩、在线合并和意图感知检索降低长期交互里的冗余和 token 成本。论文 / 页面arXiv / 项目主页GitHubaiming-lab/SimpleMemStar 数约 3K 到 3.2K公开页面显示区间会议状态ICLR 2026 Workshop Oral / Spotlight不是 ICLR 主会论文适合读者正在做长期对话记忆、个人 AI 助手、Agent Memory、MCP 记忆服务、长期用户画像系统的人。1. 为什么长期记忆会变成 token 黑洞Agent 只做一次任务时记忆问题并不明显。用户给一段上下文模型完成一次回答历史可以直接丢掉。但一旦 Agent 要长期服务同一个用户问题就变了。用户今天说过的偏好三周后可能还要用上次纠正过的项目约定下次改代码时还要记得过去一次失败的操作路径下次遇到类似任务最好不要重来。于是系统需要长期记忆。最直接的做法是保存完整历史。这样看起来最安全因为信息都在。但真实系统很快会遇到三个问题。第一是冗余。长期对话里大量内容只是寒暄、重复确认、临时推理、失败尝试和中间状态。它们不是完全没用但大多数时候不值得再次进入上下文。第二是成本。历史越长检索、重排、摘要和最终 prompt 都会变贵。即使有超长上下文也不代表应该把所有内容都塞进去。第三是噪声。记得太多不一定更聪明。过期偏好、旧计划、错误假设和被用户否定过的信息如果没有被整理和合并反而会干扰后续推理。另一类做法是每次查询时再让 LLM 迭代筛选历史先找候选再反思再压缩再回答。这样能提高质量但代价是每次请求都引入额外模型调用和 token 消耗。SimpleMem 试图解决的就是这个两难完整保留会冗余爆炸临时过滤又会 token 暴涨。它的核心思路是把成本前移在写入记忆时就把历史变成高密度、结构化、可合并的 memory unit。2. SimpleMem 的核心直觉SimpleMem 的核心直觉很简单长期记忆不应该主要保存“原始历史”而应该保存“未来可直接使用的信息单位”。普通 RAG 保存的是 chunk。chunk 的优点是简单、保真、容易实现缺点是信息密度不稳定。一个 chunk 里可能只有一句真正有用的话其余都是上下文噪声。SimpleMem 想保存的是更原子化的记忆。例如用户偏好用户更喜欢中文技术解释。项目事实当前项目的文章目录位于articles/agent-memory-papers。时间计划用户计划在某个日期完成某项任务。决策记录某次讨论中用户明确否定了某个方案。这些记忆有两个特点。第一它们是自包含的。也就是说后续检索出来后不需要再读原始对话才能明白“他”“那个项目”“下周”指的是什么。第二它们是可索引的。系统可以围绕语义、关键词、实体、时间、事件类型等多个角度组织它们而不是只靠 embedding 相似度。这就是 SimpleMem 所说的 semantic structured compression不是把对话摘要成一段短文本而是把历史改写成更适合长期存储和检索的结构化语义单元。3. 第一层机制语义结构化压缩SimpleMem 的第一步是把原始交互压成 memory unit。这一步看起来像摘要但它和普通摘要不同。普通摘要通常追求“短一点讲完这段话”而长期记忆更关心“未来可能用到什么”。例如一段对话可能是用户说“以后给我写这类文章别太学术开头要直接说结论。”如果直接保存原文后续检索时还要重新判断这句话的作用。SimpleMem 更希望把它转成类似这样的记忆用户偏好写论文介绍类文章时用户偏好非学术化表达。用户偏好文章开头应先给结论再展开解释。适用场景博客文章、论文解读、技术介绍。这样做的意义是记忆不再是一段过去说过的话而变成了未来写作时可以直接调用的约束。论文里强调的几个操作包括过滤低信息密度内容减少寒暄、重复和无关推理。补全指代让“他”“那个”“下周”变成明确对象。做时间锚定把相对时间转成更稳定的时间信息。生成多视角索引让同一条记忆可以从不同问题入口被找到。这一步决定了 SimpleMem 的上限。如果压缩质量好后面的检索会很省如果压缩时抽错事实错误也会被长期保存。4. 第二层机制在线语义合并长期记忆系统最怕的一件事是“同一件事被记很多遍”。例如用户多次表达类似偏好“文章别写得太像论文。”“我想要适合公众号的表达。”“少一点术语多一点人话。”如果系统每次都新增一条孤立记忆库会越来越大检索时也会召回一堆相似内容。SimpleMem 的做法是在线合并相关记忆把它们整合成更抽象、更稳定的表示。这可以理解为一种轻量级 memory consolidation。新记忆进入后系统会判断它和已有记忆是否语义相关。如果相关就不是简单追加而是更新或生成一个更高层次的合并记忆。这样记忆库的增长速度会慢下来重复内容也会减少。从产品角度看这一点很关键。长期 Agent 不是跑一次 benchmark而是要面对几个月甚至几年的历史。如果没有合并机制任何“保存记忆”的系统最后都会变成历史垃圾堆。5. 第三层机制意图感知检索压缩和合并解决的是“记什么”和“怎么存”。查询时还要解决“取多少”和“取什么”。SimpleMem 的检索不是固定 top-k。它会先判断当前问题的意图和复杂度再决定检索范围。简单问题只需要很少记忆。例如用户问“我之前说文章风格要怎样”系统可能只需要取写作偏好相关的几条。复杂问题需要更多上下文。例如用户让 Agent 继续一个跨多次会话的项目计划系统可能要取项目目标、已完成步骤、用户偏好、关键决策和未解决问题。这种 adaptive retrieval 的意义是控制上下文预算。长期记忆系统真正要优化的不是“召回越多越好”而是“用尽量少的 token 给模型足够信息”。这也是 SimpleMem 和普通向量检索的差别。普通向量检索常常把问题和历史片段做相似度匹配再取 top-k。SimpleMem 更强调先理解任务需要哪类记忆再调整搜索深度和范围。6. 实现架构总览如果只看论文摘要SimpleMem 很容易被理解成“一个更聪明的摘要器”。但从官方 README、包使用文档和代码结构看它更像一套完整的 memory service。它的核心运行链路大概是入口层接收 dialogue、fact 或 session event。MemoryBuilder / LLM 负责把原始输入压缩成原子记忆。MemoryEntry 作为标准数据模型保存自包含事实、关键词、时间、实体和主题。VectorStore 负责把 MemoryEntry 写入 LanceDB。写入时同时建立 semantic、lexical、symbolic 三类索引。后台 consolidation 逻辑合并相似记忆减少重复。查询时先做 planning判断问题复杂度和检索范围。HybridRetriever 并行执行向量检索、关键词检索和结构化过滤。多路结果按 entry_id 去重必要时做 reflection 检查信息是否足够。context builder 在 token budget 内拼出最终上下文再交给 LLM 回答。这个架构里SimpleMem 不是只做“存”和“搜”而是在写入、组织、检索、上下文注入四个阶段都做了 token 效率优化。7. MemoryEntrySimpleMem 到底保存什么SimpleMem 保存的基本单位叫MemoryEntry。它不是普通 RAG 里的文本 chunk而是一个 Pydantic 风格的数据模型。公开代码里的字段大致是classMemoryEntry(BaseModel):entry_id:strlossless_restatement:strkeywords:list[str]timestamp:str|Nonelocation:str|Nonepersons:list[str]entities:list[str]topic:str|None这里最重要的字段是lossless_restatement。它是被 LLM 改写后的自包含事实目标是离开原始对话也能理解。比如原始对话里用户说“以后这种文章别太学术开头先讲结论”保存时不会只存原句而会转成类似“用户在论文介绍类文章中偏好博客化表达并希望文章开头先给结论”的记忆。keywords服务于关键词检索适合专有名词、产品名、变量名、工具名这类向量检索容易漏掉的信息。timestamp、location、persons、entities、topic属于 symbolic metadata用于结构化过滤。entry_id用于全局唯一标识后面多路检索结果合并时也靠它去重。写成 JSON大概是这种形态{entry_id:550e8400-e29b-41d4-a716-446655440000,lossless_restatement:用户偏好论文介绍类文章采用博客化表达开头先给结论减少学术腔。,keywords:[论文介绍,博客化表达,先给结论,写作偏好],timestamp:2026-06-05T21:40:00,location:null,persons:[用户],entities:[SimpleMem],topic:写作风格偏好}这就是 SimpleMem 和普通 chunk-based RAG 的第一处差别它尽量把“原始历史”变成“未来可直接用的结构化记忆”。8. 写入阶段从 dialogue 到 MemoryEntry写入阶段可以拆成四步。第一步是分窗处理。论文实现细节里提到 semantic structured compression 使用滑动窗口窗口大小W10。也就是说系统不会把无限历史一次性交给模型而是按局部交互窗口提取信息。第二步是语义密度判断。论文里描述为 entropy-aware filtering 或 semantic density gating实验配置里阈值tau0.35。直观理解就是只有当一段内容相对已有历史有足够信息增益才值得进入长期记忆。寒暄、重复确认、低价值中间推理会被过滤掉。第三步是 lossless restatement。保留下来的内容会被 LLM 改写成自包含事实补全代词补全主体锚定时间把“他”“这个项目”“下周”这类依赖上下文的表达变成明确表述。第四步是抽取索引字段。系统会为每条记忆生成关键词、人物、实体、主题、时间、地点等字段并为lossless_restatement生成 dense embedding。这样一条记忆在写入时就具备三种检索入口语义、关键词、元数据。这一步的伪代码可以这样理解defadd_dialogue(dialogue):windowssliding_window(dialogue,size10)entries[]forwindowinwindows:ifsemantic_density(window)0.35:continueentryllm_extract_memory_entry(window)entry.vectorembedding_model.encode(entry.lossless_restatement)entries.append(entry)vector_store.add_entries(entries)consolidation.maybe_merge(entries)真实代码会比这个复杂但主逻辑就是先判断是否值得记再把值得记的内容变成结构化条目最后写入索引。9. 存储层为什么是 LanceDBSimpleMem 的主要存储引擎是 LanceDB。官方文档里SimpleMemConfig有lancedb_path配置默认类似./lancedb_dataSimpleMemSystem也允许通过db_path指定数据库目录。LanceDB 的优势是同时适合列式存储和向量检索。SimpleMem 的 MemoryEntry 既有文本字段又有 metadata 字段还有 vector 字段用传统纯向量库会不够灵活用普通关系数据库又不方便做 dense vector search。LanceDB 正好可以把这些字段放在同一个表里。VectorStore初始化时会连接 LanceDB并创建或打开 memory table。表结构大致包含entry_id:string lossless_restatement:string keywords:list[string]timestamp:string location:string persons:list[string]entities:list[string]topic:string vector:list[float32]官方 README 还提到跨会话 / MCP 相关模块里有两类存储cross/storage_sqlite.py更偏 session、event、observation 这类后台记录。cross/storage_lancedb.py更偏带 provenance 的长期记忆向量存储。这说明 SimpleMem 在工程实现上不是只用一个向量库装所有东西。短期事件、会话状态和长期记忆条目是分层处理的SQLite 适合结构化事件账本LanceDB 适合长期 memory entry 的向量与混合检索。10. 多视图索引一条记忆建三套入口SimpleMem 的VectorStore实现了 three-layer indexing也就是每个MemoryEntry同时进入三套检索视图。第一套是 semantic layer。它使用 dense vector similarity负责概念相似度。查询时系统会调用 embedding model 把 query 编码成向量再在 LanceDB 中检索相似的vector。第二套是 lexical layer。它使用 FTS / BM25-style keyword matching。公开代码里提到本地可用 Tantivy FTS云端可用 LanceDB native FTS。它主要解决专有名词和精确词匹配问题。例如用户问某个 API 名、变量名、论文名向量语义可能觉得相近但不精确关键词索引更可靠。第三套是 symbolic layer。它使用 SQL-like metadata filtering按timestamp、persons、entities、topic、location过滤。比如“上周和 Bob 讨论产品 XYZ 的记录”就可以同时使用时间、人物和实体约束。对应到 API就是semantic_resultsvector_store.semantic_search(query)keyword_resultsvector_store.keyword_search(query)structured_resultsvector_store.structured_search(filters)多视图索引的意义是避免单一 embedding 检索的盲区。长期记忆里有很多信息既需要语义泛化也需要精确命中还需要结构化过滤。SimpleMem 把三种能力放在同一个记忆单元上而不是为三套系统各存一份历史。11. 在线语义合并怎么避免越记越乱只做结构化写入还不够。长期记忆系统如果一直追加 MemoryEntry很快会出现重复记忆。SimpleMem 的第二层机制是 Online Semantic Synthesis也可以理解成 recursive memory consolidation。它的目标是在写入阶段或后台维护阶段把相关记忆合并成更高层次的抽象表示。论文实现细节里提到当一个 memory cluster 内部的平均 pairwise semantic similarity 超过tau_cluster0.85时会触发 recursive consolidation。直观理解就是如果一组记忆彼此太像说明它们可能在描述同一个偏好、同一个事实或同一类事件系统应该把它们合并而不是继续让它们分散存在。比如已有三条记忆用户希望技术文章不要太学术。 用户希望博客文章开头先给结论。 用户希望论文介绍写得更像公众号而不是论文摘要。合并后可以形成用户偏好技术论文介绍采用博客化表达开头先给结论减少学术腔适合公众号或博客读者。这个合并过程有三个效果。第一减少冗余。检索时不用召回很多表达相近的碎片。第二提高抽象层次。系统从多次局部表达中归纳出更稳定的长期偏好。第三降低上下文成本。最终注入给 LLM 的是合并后的高密度记忆而不是一串重复历史。工程上这类 consolidation 通常会由后台 worker 执行。官方 README 里也能看到cross/consolidation.py这类 memory maintenance worker 模块说明它不是只在查询时临时合并而是把记忆维护作为长期服务的一部分。12. 检索阶段planning、hybrid retrieval、reflectionSimpleMem 的检索不是固定 top-k。它会先做 query-aware / intent-aware retrieval planning。论文里把查询复杂度记为Cq。低复杂度查询更像直接事实查找高复杂度查询可能需要多条记忆、多跳组合或更细粒度证据。实现细节里提到检索深度会从k_min3到k_max20动态变化。例如“我喜欢什么写作风格”属于低复杂度查询取少量高层偏好记忆即可。“根据我过去几次对 agent memory 文章的要求帮我设计下一篇博客结构”属于高复杂度查询需要召回写作偏好、历史文章主题、最近修改意见、项目目录等多类记忆。planning 之后系统进入 hybrid retrieval。三类检索可以并行执行semantic_resultssemantic_search(query)keyword_resultskeyword_search(query)structured_resultsstructured_search(filters)mergeddeduplicate_by_entry_id(semantic_resultskeyword_resultsstructured_results)结果合并时不做简单拼接而是按entry_id去重。因为同一条 MemoryEntry 可能同时被向量检索和关键词检索命中重复塞进上下文只会浪费 token。官方包配置里还有enable_planning、enable_reflection、max_reflection_rounds、enable_parallel_retrieval、max_retrieval_workers等参数。planning 负责把复杂问题拆成更合适的查询或检索计划reflection 负责检查召回内容是否足够必要时补检索parallel retrieval 负责减少多路检索的延迟。所以 SimpleMem 的检索更接近一个小型 retrieval workflow而不是一句vector_db.similarity_search(query, k5)。13. 包使用和服务形态官方文档里 SimpleMem 可以作为 Python 包使用也可以作为 MCP memory service 接入 Cursor、Claude Desktop、LM Studio 等工具。Python 使用方式大致是fromsimplememimportSimpleMemSystem systemSimpleMemSystem(db_path./memory_db)system.add_dialogue(speakerUser,content以后写论文介绍时开头先给结论少一点学术腔。)answersystem.ask(我之前说过文章风格要怎样)更完整的配置会显式指定模型、embedding、LanceDB 路径和并行参数configSimpleMemConfig(llm_modelgpt-4.1-mini,embedding_modelQwen/Qwen3-Embedding-0.6B,lancedb_path./my_memory_db,enable_parallel_processingTrue,max_parallel_workers8,enable_parallel_retrievalTrue,max_retrieval_workers8,enable_planningTrue,enable_reflectionTrue,max_reflection_rounds2,)需要注意的是论文实验配置和开源包默认配置不完全一致。论文实现细节里提到 dense embedding 使用text-embedding-3-small1536 维仓库 README / package usage 里默认 embedding model 显示为Qwen/Qwen3-Embedding-0.6BREADME 还提到 1024 维向量。写文章或复现时最好区分“论文实验设置”和“当前工程默认设置”。MCP 形态下它更像一个外部长期记忆服务Agent 或客户端通过工具调用写入 memory、查询 memory、查看 stats 或清空 memory。README 里提到 MCP / FastAPI 相关模块例如cross/api_mcp.py、cross/api_http.py、cross/context_injector.py。这意味着 SimpleMem 不只是论文 pipeline也在尝试变成可接入实际 AI 工具链的记忆服务。14. 实验结果怎么看SimpleMem 在公开材料里强调两个结果效果提升和 token 成本下降。在 LoCoMo 等长期对话记忆 benchmark 上它报告了相比 Mem0、A-Mem、LightMem 等 baseline 更高的 F1并且显著降低推理时 token 消耗。项目页里给出的核心叙事是SimpleMem 可以在更少 token 下获得更好的长期记忆问答效果。这个结果符合它的方法直觉。因为它不是到回答时再把大段历史塞进去而是在写入阶段就把信息压成更短的结构化记忆。检索阶段拿到的上下文天然更短。不过看这类结果时要注意两点。第一长期记忆 benchmark 和真实产品仍有差距。真实产品里有权限、隐私、用户纠错、过期记忆、冲突记忆、多设备同步等问题这些通常不是论文主线。第二压缩型记忆的风险很隐蔽。原始历史保存得少意味着一旦抽取错了后续系统可能很难发现。所谓“语义无损压缩”更像目标而不是可以无条件相信的性质。15. 和 Mem0、GraphRAG、普通摘要的区别和 Mem0 这类通用 memory API 相比SimpleMem 更强调压缩质量和检索成本之间的平衡。它不是只提供 add/search/update 接口而是把写入、合并、检索都围绕“信息密度”设计。和 GraphRAG 相比SimpleMem 不一定把世界建成实体关系图。它更关心长期交互中的语义事实如何被压缩、索引和召回。GraphRAG 更适合知识库组织SimpleMem 更贴近对话与 Agent 历史。和普通摘要相比SimpleMem 的记忆更细粒度。摘要通常是一段文本适合人读SimpleMem 的 memory unit 更像机器可检索、可合并、可更新的事实单元。一句话说普通摘要是把历史写短SimpleMem 是把历史改写成更适合未来使用的记忆结构。16. 对工程实践的启发如果你在做 Agent MemorySimpleMem 至少有三个值得借鉴的点。第一写入时就做信息密度控制。不要等到上下文爆了再总结也不要把所有历史都丢进向量库。越早清理冗余后续成本越低。第二记忆单元要自包含。真实系统里最常见的问题之一是检索出来的片段离开原始上下文就读不懂。长期记忆应该尽量补全主体、时间、适用场景和来源。第三检索范围要和任务复杂度绑定。简单偏好查询不需要召回十几条历史复杂多跳任务也不能只取一个 top-1 片段。检索策略应该理解当前任务需要什么类型的记忆。如果放到产品里可以把 SimpleMem 拆成四层写入层抽取事实、偏好、计划、约束和决策。合并层处理重复、冲突、过期和层级抽象。索引层按语义、实体、时间、项目、任务类型组织记忆。检索层根据当前请求选择检索深度和输出格式。17. 局限与风险SimpleMem 最大的风险是压缩错误。长期记忆不像一次性回答错了会持续影响后续行为。只要系统把“用户临时说过的话”误当成长期偏好或者把一次失败经历总结成错误规则后续 Agent 就可能反复犯错。第二个风险是冲突处理。用户偏好会变化项目事实会过期计划会取消。SimpleMem 的压缩和合并能减少冗余但真实系统还需要明确的版本、时间衰减、来源追踪和人工纠错机制。第三个风险是评估不足。长期记忆的好坏不只看 QA F1还要看错误记忆率、遗忘率、冲突解决、隐私删除、跨任务迁移和用户可控性。所以 SimpleMem 更适合作为 memory architecture 的参考而不是直接等同于完整产品级记忆系统。18. 适合怎么借鉴如果你要做个人 AI 助手可以借鉴它的“高密度用户记忆”把长期偏好、固定事实、项目约定、持续目标压成结构化条目而不是保存聊天全文。如果你要做编码 Agent可以把项目约定、调试经验、用户偏好的代码风格、常用验证命令做成自包含 memory unit并在每次任务前按意图召回。如果你要做企业知识 Agent可以借鉴它的检索范围规划但还需要额外补上权限、引用、审计和删除机制。19. 一句话判断SimpleMem 的价值不是“发明长期记忆”而是把长期记忆里最现实的成本问题讲清楚了Agent 不应该记得越来越多而应该把历史压成更少、更准、更能直接服务未来任务的信息单位。