数据截至 (上游 commit ac9c2a586ba7)
OpenMemory — 架构与原理
30 秒导读: OpenMemory 是一个自托管的"给 AI 装长期记忆"的引擎。你
add("用户喜欢暗色模式"),它search("偏好")能把这条捞回来——但它不只是把文本塞进向量库,而是把每条记忆归到五个认知"脑区"(情景/语义/程序/情绪/反思),用相似度 + 新近度 + 联想链路 + 标签的复合分来召回,并让记忆随时间衰减、被用到就增强。Python 与 Node 两套等价实现。
1. 这是什么(零基础也能懂)
-
一句话定义: OpenMemory 是一个"认知记忆引擎"——把 LLM/agent 需要长期记住的东西存进本地数据库(SQLite/Postgres),并在需要时按"人类记忆"的方式召回。
-
解决什么问题 / 给谁用: LLM 天生健忘,一轮对话结束就忘光。给它接一个记忆系统的人通常做成 RAG:切块 → 嵌入 → 按余弦相似度检索。OpenMemory 的立场是:那只是"带 marketing 的向量库",它不知道一条记忆是事实还是情绪、有多新、有多重要、跟别的记忆怎么关联。做 agent、copilot、日记系统、编码助手的人,想让"记忆"更像大脑而不是查询缓存,就是它的目标用户。
-
它能做什么(功能):
- 多脑区记忆:episodic(事件)/ semantic(事实)/ procedural(技能步骤)/ emotional(情绪)/ reflective(洞察)。
- 复合打分召回:不只看向量相似度,还叠加 token 重叠、waypoint(联想边)权重、新近度、标签匹配。
- 衰减 + 强化:老记忆逐渐淡出;被召回的记忆重要度回升,还会顺着联想边"带动"邻居。
- 时间知识图谱:facts 带
valid_from/valid_to,新事实自动关闭旧事实,支持"某时刻真值"查询。 - 自托管、本地优先:默认落地一个 SQLite 文件,数据在你自己手里。
- 接口齐全:Python SDK、Node SDK、HTTP 服务、MCP server(给 Claude/Cursor/Windsurf 当工具)、VS Code 扩展。
-
用起来什么样: 三行,本地文件,零云配置。
from openmemory.client import Memorymem = Memory()await mem.add("user allergic to peanuts", user_id="user123") # 存一条results = await mem.search("allergies", user_id="user123") # 语义召回真源码里
add/search是 async 的:packages/openmemory-py/src/openmemory/main.py:20(Memory.add)、:27(Memory.search)。 -
一句话直觉/类比: 把它当成 agent 的海马体:不是硬盘(什么都原样存、按 key 取),而是会"分门别类、按重要度和联想遗忘/回忆"的大脑记忆区。RAG 是"全文搜索引擎",OpenMemory 想做的是"记忆器官"。
2. 顶层全景(它大概怎么转)
这一节给你"大盘":一条记忆写进去经过哪些部件,一次查询又怎么把它捞回来。
2.1 两条主线
整个系统就两条端到端路径,吃透它们等于吃透 80%:
写入(add / ingest)
文本 ──▶ 抽取(estimate tokens)──▶ 太大?拆 root+child
│
└─小▶ add_hsg_memory:
simhash 去重 ─┬─命中▶ 复用旧记忆、加分,返回
└─未命中▶ 分区(classify)→ 多脑区嵌入
→ 存 memories/vectors → 建 waypoint 边
查询(search / hsg_query)
query ──▶ 分区 ──▶ 逐脑区向量检索(取 k*3)
│
├─置信度低?──▶ 沿 waypoint 边扩散,拉进联想到的记忆
│
└─▶ 对候选逐条算复合分(相似×跨区共振×惩罚 + 重叠 + 边权 + 新近 + 标签)
→ 排序取 top-k → 命中的记忆当场强化(salience 回升、联想扩散)
2.2 部件一句话职责
| 部件 | 干什么 | 在哪个文件(Python) |
|---|---|---|
Memory 门面 | 对外 add/search/get/delete/history/source | main.py(Memory) |
| ingest | 抽取文本、判断大小、root-child 拆分 | ops/ingest.py(ingest_document) |
| extract | PDF/DOCX/HTML/音视频 → 纯文本 | ops/extract.py(extract_text) |
| HSG 核心 | 去重、分区、嵌入、建链、复合打分召回 | memory/hsg.py(add_hsg_memory、hsg_query) |
| sector 分类 | 正则打分把内容归到 5 个脑区 | memory/hsg.py(classify_content)+ core/constants.py(SECTOR_CONFIGS) |
| embed | 多脑区嵌入,默认 synthetic(无 API) | memory/embed.py、ai/synthetic.py |
| vector store | 向量落库 + 暴力余弦检索 | core/vector_store.py(SQLiteVectorStore) |
| waypoint | 联想边的建立/扩散/强化/剪枝 | memory/hsg.py(create_single_waypoint、expand_via_waypoints) |
| decay | 后台批量衰减 + 命中强化 | memory/decay.py(apply_decay、on_query_hit) |
| dynamics | 跨区共振、trace 强化、联想扩散公式 | ops/dynamics.py |
| reflect | 聚类相似记忆、生成"反思"摘要 | memory/reflect.py(run_reflection) |
| temporal graph | 带时间窗的事实图谱 | temporal_graph/store.py、query.py、timeline.py |
| MCP server | 把 query/store/get/list/delete 暴露成工具 | ai/mcp.py(run_mcp_server) |
注意 Python 与 Node 双实现。
packages/openmemory-py(Python)与packages/openmemory-js(Node/TS)是同一套认知模型的两份等价实现,文件名几乎一一对应(hsg.py↔memory/hsg.ts,decay.py↔memory/decay.ts)。本文以 Python 版为主线讲解,差异处会点名 JS 侧。
2.3 主线走一遍(高层)
- 写:
Memory.add→ingest_document抽取并估 token → 短文本走add_hsg_memory:先 simhash 去重,再classify_content分区,embed_multi_sector对每个脑区各嵌一个向量,存进memories/vectors,最后create_single_waypoint给它连一条到最相似记忆的边。 - 读:
Memory.search→hsg_query:对 query 分区、逐脑区检索、必要时沿 waypoint 扩散、对候选算compute_hybrid_score、排序取 top-k,并对命中记忆做on_query_hit(强化)。
3. 怎么读这套文档(阅读地图)
由浅入深,建议顺序:
01-hsg-ingest-recall.md— 先看这个。 核心中的核心:分区、simhash 去重、多脑区嵌入、waypoint 建链,以及hsg_query那套复合打分。看完你就懂"一条记忆怎么进、怎么出"。02-decay-reinforce.md— 记忆的"生命":为什么老记忆会淡、被用到为什么会变重要、联想扩散怎么让相关记忆一起回暖。这是它区别于 RAG 的灵魂。03-temporal-graph.md— 另一条独立子系统:时间知识图谱。"CompanyX 的 CEO 2021 是 Alice、2024 变 Bob"这类会随时间变化的事实怎么建模。04-deep-and-map.md— 存储与向量结构、值得借鉴的巧思、边界与坑、横向对比、以及给 agent 的代码地图跳转表。
每章开头都有 frontmatter 和"这章讲什么",agent 可先读 index 与各章 essence 决定下钻哪一章,不必打开全部文件。