比較的前提是同一個座標系,因此以下所有欄位都用 分類學 的詞彙,而不是各家自己的命名。這些表格描述的是 2026 年 9 月的狀態,而這個領域的 API 與預設值變動很快——結構性的差異(時間模型、真源位置、寫入決策的歸屬)比具體功能穩定得多,選型時應該以前者為準。
主表:六條路線的核心差異
| Letta (MemGPT) | Mem0 | Zep / Graphiti | Cognee | LangMem / LangGraph | 檔案原生(OpenClaw / Hermes / Claude memory tool) | |
|---|---|---|---|---|---|---|
| 定位 | agent runtime | 記憶服務 / SDK | 時序記憶引擎 + 託管服務 | 記憶控制平面 / ETL 管線 | 框架內建機制 + SDK | agent runtime 的內建能力 |
| 真源 | 資料庫中的 block + archival | 向量庫條目 | 圖(episode 不可變) | 圖 + 向量 | Store(namespace/key) | Markdown 檔案 |
| 主要儲存 | DB + 向量 | 向量(可選圖) | 圖(Neo4j 等)+ 向量 | 圖 + 向量 + 關聯式 | KV / Postgres(可接向量) | 檔案 + SQLite(FTS5 + embedding) |
| 寫入決策歸屬 | agent 自己(工具呼叫) | LLM 管線(抽取+判斷) | LLM 抽取+消解(每 episode) | ECL 管線(批次) | 開發者(自己實作邏輯) | agent 自己(週期性自我審視) |
| 寫入時機 | 迴圈內 + sleep-time | 呼叫方決定(同步或背景) | 攝取時同步 | 批次 / 非同步 | hot path 或 background(顯式選擇) | 週期性 nudge / 工具呼叫 |
| 召回方式 | block 常駐 + 工具搜尋 recall/archival | 向量 top-k + scope 過濾 | 語意+關鍵字+圖遍歷 + 時間過濾 | 向量 + 圖遍歷 + ontology 過濾 | namespace/key 精確定址 + 語意搜尋 | 常駐載入 + memory_search(語意+FTS) |
| 時間模型 | 無 | 弱(靠 UPDATE/DELETE) | 雙時間軸(四時間戳) | 弱(有時間脈絡欄位) | 無 | 無(只能寫在文字裡) |
| 遺忘 / 壓縮 | context 分頁 + block 容量上限 | UPDATE / DELETE,無容量控制 | 標記失效不刪除(會單向成長) | 管線重跑 / 資料集管理 | 開發者自理 | 寫入門檻把關(預設不寫) |
| 多跳推理 | 弱 | 弱(圖變體中等) | 強 | 強 | 弱 | 弱 |
| 可觀測性 | API + ADE 可檢視狀態 | API 可列舉條目 | 圖可視化 + episode provenance | 圖可視化 | Store 可列舉 | cat 就看得到、可 diff、可 Git |
| 綁定程度 | 高(換 runtime) | 低(非侵入) | 中(需營運圖庫) | 中高(管線與後端) | 高(綁 LangGraph) | 高(綁該 agent runtime) |
成本結構:最常被忽略的一欄
幾乎所有框架都在寫入路徑上呼叫 LLM,這使記憶成本與對話量成正比,而不是與召回量成正比。這個性質在低流量的原型階段完全看不出來,在生產流量下會變成主要成本項。
| 框架 | 每次寫入的 LLM 呼叫 | 每次召回的 LLM 呼叫 | 常駐 token 稅 |
|---|---|---|---|
| Letta | 1 次以上(agent 推理內;sleep-time 另計) | 0(工具搜尋不需額外 LLM) | 高——block 每輪都在 context |
| Mem0 | 至少 2 次(抽取 + 判斷操作) | 0 | 低——只注入 top-k 精煉事實 |
| Zep / Graphiti | 多次(實體抽取、消解、衝突比對、時間抽取) | 0 | 低—中 |
| Cognee | 多次(分類、抽取、摘要) | 0 | 低—中 |
| LangMem | 取決於自己的實作(hot path 或 background) | 0 | 取決於召回策略 |
| 檔案原生 | 週期性 1 次(nudge / 自我審視) | 0 | 高——長期記憶檔案每 session 全量載入 |
兩個結論值得直接拿來用:
寫入成本高的框架(Zep、Cognee、Mem0)應該把寫入搬離 hot path。 它們的每次寫入涉及多次 LLM 呼叫,放在使用者等待路徑上既慢又貴。
常駐 token 稅高的路線(Letta 的 block、檔案原生的全量載入)必須有嚴格的容量紀律。 這個成本是每一輪都要付的,因此一個多寫了 2000 token 的記憶檔案,在十萬輪對話上的成本遠超過任何寫入成本的差異。Hermes 的 periodic nudge 之所以預設不寫入,直接源於這個算術。
能回答哪些問題:功能對照
選型最實際的判準不是分數,而是「我的產品需要回答什麼問題,這個框架答不答得出來」。
| 問題 | Letta | Mem0 | Zep | Cognee | LangMem | 檔案原生 |
|---|---|---|---|---|---|---|
| 「使用者的名字是什麼」(精確取回) | ✅ block | ⚠️ 靠相似度 | ✅ | ✅ | ✅ key | ✅ 常駐 |
| 「使用者喜歡什麼」(語意召回) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 「三個月前他的偏好是什麼」(時序) | ❌ | ❌ | ✅ | ⚠️ | ❌ | ❌ |
| 「系統為什麼相信這件事」(溯源) | ⚠️ | ⚠️ | ✅ episode provenance | ✅ | ❌ | ✅ Git 歷史 |
| 「A 的同事的專案用什麼技術」(多跳) | ❌ | ⚠️ 圖變體 | ✅ | ✅ | ❌ | ❌ |
| 「刪除這個使用者的所有資料」 | ✅ | ✅ scope | ⚠️ 圖上級聯較難 | ⚠️ | ✅ namespace | ⚠️ 需掃檔案 |
| 「這條規則一定要被遵守」(不可漏召回) | ✅ 唯讀 block | ❌ | ❌ | ❌ | ✅ 精確 key | ✅ 常駐 |
| 「兩個 agent 共用同一份知識」 | ✅ block 共享 | ⚠️ scope 共用 | ✅ 同一圖 | ✅ | ⚠️ 自理 | ❌ |
| 「抽取邏輯改進後重跑歷史」 | ❌ | ❌ | ✅ episode 不可變 | ✅ 管線可重跑 | ❌ | ✅ 檔案是真源 |
這張表比任何 benchmark 都更接近選型的實際需要。 做法是把左欄換成你的產品真正需要回答的十個問題,然後看哪一欄的 ✅ 覆蓋得最完整——通常結論會是「沒有一欄全中」,而那正是 自己組一套 的理由。
其中「這條規則一定要被遵守」那一列值得特別注意:只有常駐或精確定址的機制能保證不漏召回,任何經過相似度篩選的路徑都不能。 把專案規則放進向量庫是一個很常見、後果很糟的設計錯誤。
三個結構性分歧
拋開功能清單,六條路線的差異可以收斂成三個彼此獨立的設計決策。新專案要做的其實就是這三個決定。
一、寫入決策交給誰? agent 自己(Letta、檔案原生)/一條專門的 LLM 管線(Mem0、Zep、Cognee)/開發者的規則(LangMem)。交給 agent 的判斷有脈絡但不可稽核;交給管線的可稽核但沒脈絡;交給規則的最可控但覆蓋率最差。 沒有一個是全面較優的,混用是常態。
二、真源在哪裡? 資料庫/圖/檔案。這個決定最不可逆,因為它決定了可觀測性的上限、可攜性的上限,以及「抽取邏輯改進後能不能重跑」。
三、時間怎麼處理? 忽略(多數)/覆寫(Mem0)/雙時間軸(Zep)。如果你的領域裡事實會改變而歷史有價值,這一題只有一個答案;如果不會,雙時間軸是不必要的複雜度。