← 返回研究
AI 系統 2026-05-04

我們把向量搜尋加進記憶 plugin。結果退步了 13 個百分點。

純 FTS5 在 LongMemEval-S 達到 95.40% R@5。加上 384 維 ONNX 向量管線做加權融合之後,掉到 82.40%。原因是什麼,以及這對你建 AI 記憶的架構決策意味著什麼。

所有在 AI 裡做記憶的人都預設需要 embeddings。我們也是。然後我們跑了 benchmark。

FTS5 —— SQLite 內建的全文搜尋 —— 在 LongMemEval-S 上達到 95.40% R@5。 加上 384 維 ONNX 向量管線做加權融合之後,掉到 82.40%。這是用公開 ICLR 2025 dataset 的 500 道題跑出來的,任何人都可以獨立驗證。

還有一個更出乎意料的發現:改用 max-fusion(兩個訊號取最大值而非加權平均)之後,成績維持在 95.40%。逐題比對命中集合:Mode A 與 Mode B 命中的 477 個 question ID 完全相同。向量搜尋在 top-5 沒有帶來任何額外命中。

Mode說明R@5跑完 500 題耗時
A純 FTS595.40%10s
BFTS5 + ONNX MiniLM-L6(max fusion)95.40%~25 分鐘
CFTS5 + ONNX(60/40 加權)82.40%~13 分鐘

memesh 以 300 KB 的 npm package 出貨,完全跑在使用者自己的機器上 —— 沒有雲端 round-trip、不需要 API key、沒有向量索引。Mode A 距離 MemPalace 廠商自報的上限 96.6%(向量 + reranker stack)只差 1.2 個百分點。


我們怎麼測的

LongMemEval 模擬的是真實情境:你跟 AI 對話了好幾週,現在問一個答案藏在很久之前對話裡的問題。500 道題,每題都有一個 haystack,包含約 50 個歷史對話 session —— 有些是使用者自己的,有些是泛用公開 Q&A 的干擾項(ultrachat_*sharegpt_*)。

指標是 R@5:正確答案 session 出現在 top-5 retrieval 結果裡的題目比例。Dataset SHA256:08d8dad4be43ee2049a22ff5674eb86725d0ce5ff434cde2627e5e8e7e117894

這是 retrieval test,不是 end-to-end LLM 測試。我們量的是 memory layer 能不能浮出對的 session。LLM 拿到之後怎麼用,不在範圍內。

Mode A pipeline —— 全部就這些:

  1. 把 haystack 每個 session 灌進全新 SQLite 資料庫。每個 session 存成一個 entity,完整文字截斷在 8,000 字元。FTS5 用 unicode61 remove_diacritics tokenization 建索引。
  2. 斷詞 query。去掉非英數字字元,丟掉長度 ≤ 2 的 token,最多取 20 個,OR 串接成引號 quoted terms。
  3. FTS5 MATCH 配 default BM25 ranker,取前 20 名。
  4. 依排名位置打分:score = 1 − (rank / n_results)
  5. 回傳排序清單,計算 R@5。

沒有 embedding。沒有 API call。沒有向量倉。


純 FTS5 為什麼能到 95%

大家的直覺是「語意搜尋一定要用向量」—— 對跨詞彙 retrieval 是對的,對個人記憶不是(或者沒那麼對)。

在公開語料庫裡,問「我的焦慮要怎麼處理」可能要 match 到「應對恐慌症」—— 詞彙不同,意圖相同。Vector embeddings 跨越這個落差。

在個人記憶裡,haystack 是使用者自己過去寫的東西。他們現在問問題用的詞彙,和當時記下記憶用的詞彙,統計上很接近。BM25 加關鍵字,意外地常常就是對的工具。

從 dataset 實際打開 session 內容驗證過的案例:

  • Questione47becba,類型 single-session-user):“What degree did I graduate with?”
  • Haystack:54 個 sessions,涵蓋生產力 app、健行、約會、副業,加上 26 個泛用公開 Q&A 干擾項。
  • Answer sessionanswer_280352e9,haystack 索引 52):一段 8 輪、關於任務管理 app 的對話。學位是使用者在第三輪裡若無其事提到的:“I graduated with a degree in Business Administration, which has definitely helped me in my new role.” 整段對話主要聊 Todoist、Trello、meal-prep。學位只出現一句。
  • Mode A 結果:答案 session 排名第 2。Top-5 回傳:02bd2b90_3, answer_280352e9, sharegpt_Cr2tc1f_0, ultrachat_214101, f6859b48_2

FTS5 把一個冗長且離題的 session 裡唯一一次出現的關鍵字「graduated」,排在另外 53 個 session 之上 —— 包括泛論教育但缺乏使用者詞彙指紋的干擾項。這就是詞彙指紋的優勢:使用者自己的特定用詞是比語意相似度更強的訊號。

Mode A 仍然失敗的 23 道題(4.6%)集中在:

  • 時間推理(8 題)“What’s the order of the three trips I took in the past three months?” FTS5 沒有時間戳概念,排名只看詞彙相關度。
  • 跨 session 聚合(7 題)“How many different doctors did I visit?” 需要合併多個 session 的證據,而不是取出單一答案 session。
  • 單一 session 偏好(5 題):相關過去 session 用了領域詞彙,而現在的問題沒有直接呼應。
  • 其他(3 題):兩題 abstention、一題 knowledge-update。

三分之二的失敗(15/23)在時間推理與跨 session 聚合。正解不是換更好的 embedder,而是不同的 retrieval 模式:時間戳感知排名,或在原始 retrieval 之上加 graph/aggregation 層。


為什麼加向量讓結果更差

Mode C 是更有意思的發現。直覺:「FTS5 給你 95.40%,向量再給一個獨立訊號,60/40 混合應該 ≥ 95.40%,甚至更高。」實測:82.40%,退步 13 個百分點。

根本原因:LongMemEval 的 haystack 裡有 ultrachat_*sharegpt_* 這類泛用公開 Q&A session,對幾乎任何 query 都有高 cosine 相似度。它們是廣義 chatbot 訓練對話,語意上和所有東西都有重疊。它們不是使用者的個人記憶。

Mode A 正確地把它們排在後面:它們沒和 query 共享使用者特定的關鍵字。

Mode B(max-fusion)保留了 FTS5 主導性:FTS5 把對的答案排在前面,向量訊號擠不掉它。命中集和 Mode A 完全相同。

Mode C(加權平均)用弱的向量訊號稀釋了強的 FTS5 訊號。泛用 Q&A 干擾項在排名上被推上來,把真正屬於使用者個人記憶的 session 擠下去。

教訓:融合機制比是否加入特徵更重要。 弱訊號用 max-fusion 加進來無傷大雅;同一個訊號用加權平均加進來,在 haystack 有對抗性 distractor 時會主動造成傷害。

這不是 memesh 特有的發現,而是任何在個人資料之上做 retrieval 的系統都適用的架構教訓。Mode C 的退步結果是與其他 mode 一起發表、沒有省略,因為這個退步就是這篇文章要說的事。


對你的架構決策意味著什麼

對個人記憶 retrieval(單一使用者、自己的對話歷史、幾千條 entity 以內):

從 FTS5 開始。 它已經在你的 SQLite 裡。不需要 embedding pipeline、向量倉,寫入時也不需要付 API 成本。大概可以直接到 90%+ R@5。

把向量當 tie-breaker,不要當主訊號。 Max-fusion 配 FTS5 主導是安全的。加權混合不是 —— 只要你的 haystack 裡有任何不屬於特定使用者的內容就不行。

用公開 methodology 驗證廠商數字。 MemPalace 的 96.6% 是廠商自報,可能用了 cleaned 版 dataset。Mem0 和 Zep 是 LongMemEval 原論文在同一個 dataset 變體上公佈的數字,可以直接比。Supermemory 是廠商估計。把這幾種不同來源的數字放在同一張表,每行都要標清楚。

系統R@5來源
MemPalace96.6%廠商自報;用了 reranker;可能是 longmemeval-cleaned 變體
memesh(Mode A)95.40%本 benchmark,跑在 longmemeval_s
Supermemory~82%廠商估計
Zep63.8%LongMemEval 論文 arXiv:2410.10813,跑在 longmemeval_s
Mem049.0%LongMemEval 論文 arXiv:2410.10813,跑在 longmemeval_s

對全語料規模 retrieval(數百萬筆、多使用者、跨語言),trade-off 反過來,向量搜尋就是必要的。memesh 不是要取代 pgvector 或 Pinecone,而是另一種押注:對個人記憶,簡單架構是更好的架構。


95.40% 沒有包含的東西

這個 benchmark 只跑 retrieval pipeline。生產版 plugin 還包含以下功能,在 benchmark 裡關掉以保持比較公平:

  • 多因子評分 —— recency、frequency、confidence、impact 一起加權,不只是 retrieval 相關度。
  • LLM query expansion(「Smart Mode」)—— FTS5 之前先用 LLM 把問題擴展同義詞。
  • 跨 entity 圖譜遍歷 —— 支援需要追隨 entity 關係的問題。
  • 自動衰減 —— 過久沒用的記憶在排名上淡出但不刪除。

生產版 R@5 很可能高於 95.40%。我們還沒把這些功能單獨切出一個發佈數字,這裡也不宣稱。


8 步重現

npm install 大約需要 30–60 秒(視網速而定)。整個流程包含下載 dataset,全部跑完預計 10–15 分鐘。

git clone https://github.com/PCIRCLE-AI/memesh-llm-memory.git
cd memesh-llm-memory
git checkout bench/longmemeval-public-r1
npm install
curl -L "https://huggingface.co/datasets/xiaowu0162/longmemeval/resolve/main/longmemeval_s" \
  -o /tmp/longmemeval_s.json
shasum -a 256 /tmp/longmemeval_s.json   # 預期 08d8dad4be43ee2049a22ff5674eb86725d0ce5ff434cde2627e5e8e7e117894
node benchmarks/longmemeval/run.mjs --mode A --dataset /tmp/longmemeval_s.json
node -e "const d=require('./benchmarks/longmemeval/results/mode-A-2026-05-03T12-31-26.json'); console.log('R@5:', (d.overall_metrics.r_at_5 * 100).toFixed(2) + '%')"

預期輸出:R@5: 95.40%。Mode B 和 Mode C 因為要下載並執行 ONNX MiniLM-L6 模型,分別需要約 25 分鐘和 13 分鐘。

Repository:github.com/PCIRCLE-AI/memesh-llm-memory Benchmark 分支:bench/longmemeval-public-r1 License:MIT

延伸問題

  • FTS5-only 配置從每題約 50 個 sessions 擴展到單一使用者 5,000+ entities 時還能維持嗎?
  • 更小、更貼合領域的 embedder(而非 384 維 MiniLM-L6)是否真的能帶來新增的 top-5 命中?還是 FTS5 上限對個人記憶任務來說是結構性的?