記憶的腐爛問題
跑了兩個月的 AI agent,記憶檔案從幾 KB 膨脹到幾十 KB。一開始沒什麼感覺,直到某天 agent 引用了一個三週前就被推翻的技術決策,我才意識到問題有多嚴重。
記憶不是寫進去就沒事了。沒有維護的記憶,比沒有記憶更危險——因為 agent 會很有信心地根據過時資訊做決策。
人類的記憶會在睡眠中自動整理:重要的強化、矛盾的修正、不用的淡化。AI agent 的記憶沒有這個機制,所以得自己造一個。
靈感來源:Karry 的 Orb
直接觸發這個想法的,是 Karry 寫的一篇文章:《認知アップグレードの本当のループ——AI Agent の記憶設計から學んだ 3 つのこと》。
Karry 運營自己的 AI agent「Orb🔮」超過兩個月,得出一個跟主流完全不同的結論:記憶系統的核心不是 Vector DB,是認知循環。他指出三個真正的難題:
- 什麼時候該忘? — 頻率衰減不夠用,年用一次但救命的記憶不能丟
- AI 會捏造記憶 — 搜尋結果為空 ≠ 記錄不存在
- 教訓寫了也不一定有效 — 「知道」和「做到」之間有巨大的鴻溝
他的解法是三層記憶(L0 原始日誌 → L1 回顧摘要 → L2 長期記憶)加上「Hard Constraint」——犯錯兩次就強制鎖死,不靠自覺靠系統。
這些觀點跟我自己踩坑的經驗高度吻合,但我的問題不完全一樣。Karry 著重在「怎麼讓記憶影響行為」,我面對的是更前面一步:怎麼讓記憶自己保持乾淨。
Orb 做了什麼,我做了什麼不同
Karry 的 Orb 和我的 agent 有很多共通點——都用 Markdown 檔案、都分層、都相信簡單架構。但設計哲學有幾個明顯的差異:
| Karry’s Orb | 我的做法 | |
|---|---|---|
| 記憶儲存 | Markdown + LLM 多段抽取 | Markdown + LLM,但加了 Gemini embedding 做向量索引 |
| 遺忘策略 | P0/P1/P2 分級 + 人工 review | P0/P1/P2 分級 + 自動化腳本 (janitor/expire) |
| 防呆機制 | Hard Constraint(犯兩次就鎖) | 分析/執行分離(反芻只建議,main session 決策) |
| 獨特機制 | — | 「做夢」——冷記憶隨機抽取找跨領域洞察 |
| 記憶維護 | LLM 每日抽取 | cron 四件套:janitor + reflect + dream + expire |
| 矛盾處理 | 手動 | 反芻引擎自動檢測,但人工確認修改 |
最大的差異是:Karry 更信任 agent 自己管記憶(自動壓縮、自動昇格),我更偏向讓 agent 當顧問、人類做最終決策。
這不是對錯問題,是信任程度的差別。Karry 的 Orb 跑了兩個月,建立了足夠的信任;我的 agent 也是兩個月,但我被捏造記憶嚇到過(跟他一樣),所以選擇更保守的路線。
另一個差異是「做夢」機制——這個 Orb 沒有。Karry 的三層記憶是線性的(經驗→反省→定著),我加了一個非線性的維度:隨機抽取不同時期、不同領域的記憶,讓 LLM 自由聯想。這不是為了效率,是為了偶然發現(serendipity)。
我的三層 + 一層
受 Orb 啟發,但根據自己的需求調整後,最終變成了四個腳本:
| 層次 | 類比 | 功能 | 頻率 |
|---|---|---|---|
| 做夢 (Dream) | REM 睡眠 | 冷記憶聯想,找跨領域洞察 | 每週日 |
| 反芻 (Reflect) | 深度睡眠 | 矛盾檢測 + 整合建議 | 每日 |
| 遺忘 (Expire) | 記憶衰減 | 過期記憶歸檔 | 每月 |
| 管家 (Janitor) | 大掃除 | 結構化壓縮 MEMORY.md | 每日 |
四個腳本,四個 cron job,各司其職。
第一層:做夢(Dream)
「做夢」和「反芻」的概念並不是我原創的。人類睡眠研究早已證實 REM 睡眠時大腦會重組白天的記憶片段,產生新的聯想(這也是為什麼很多科學家在夢中得到靈感)。而「反芻」(rumination)本是認知心理學的概念——反覆回顧經歷以整合新知。Pieces AI 團隊在他們的 Long-term Memory 論文中也提到過類似的設計:「reinforcement and decay models that determined what to remember, forget, and connect — modeled after human REM sleep」。Karry 的 Orb 把這個生物學比喻落地成了工程實作,我在他的基礎上加了「做夢」這個隨機聯想層。
人在 REM 睡眠時會把白天的片段記憶隨機組合,偶爾產生意想不到的聯想。AI agent 也可以做類似的事。
做法很直覺:從最近 30 天的記憶中隨機抽 8 個片段,丟給 LLM,要求它找「非顯而易見的連結」。
# 隨機抽取 8 個記憶片段
SNIPPETS=$(find "$MEMORY_DIR" -name "2026-*.md" -mtime -30 \
! -path "*/archive*" | sort -R | head -8)
# 加上長期記憶的隨機段落
MEMORY_SECTIONS=$(grep -n "^## \|^### " "$MEMORY_MD" | shuf | head -5)
Prompt 的關鍵是限制 LLM 不要只做摘要,而是要找「意外共通點」。第一次跑出來的結果蠻驚喜的:
「延遲執行」作為系統穩定機制:Cron job 從 :00 改為 :02 避免衝突、RTK 把 git 資訊壓縮成摘要呈現、TTS warmup 需等待——本質都是「延遲回應」來防止系統過載或資訊氾濫。
這種洞察人類不一定會注意到,因為這些事件發生在不同的日子、不同的 context 裡。但 agent 的記憶是跨時間的,隨機抽取反而能發現結構性的共通點。
幾個實作細節
- 用最便宜的模型:做夢不需要精準,需要的是創意。MiniMax M2.5 綽綽有餘。
- 限制輸出:最多 3 個洞察,每個 1-2 句。不要讓 LLM 長篇大論。
- 累積到
dreams.md:每次做夢的結果 append 到同一個檔案,日積月累就有一本「夢境日誌」。 - 排程:每週日凌晨 3 點,不影響日常使用。
第二層:反芻(Reflect)
如果做夢是「發散聯想」,反芻就是「收斂整理」。每天跑一次,把最近的記憶跟長期記憶交叉比對,找三種東西:
1. 矛盾檢測
最常見的問題:兩週前記錄了「用 Fish Speech 做 TTS」,上週又記錄了「改用 Qwen3-TTS」。如果沒有人整理,MEMORY.md 裡就會同時存在兩個矛盾的記錄。
反芻引擎會找出這種不一致,建議更新哪一方。
2. 整合建議
有些資訊反覆出現在 daily memory 裡,但一直沒被提升到長期記憶。例如某個 API 的 workaround 被記了三次,顯然應該寫進 MEMORY.md 的 Infrastructure 區塊。
3. 衰減標記
某些記憶條目已經很久沒被引用了。不是說要刪除,而是標記出來,讓下一層(Expire)處理。
PROMPT="你是記憶反刍引擎。回顧最近的記憶,對照長期記憶,找出需要處理的問題。
任務:
1. 矛盾檢測 — 最近的記憶有沒有跟長期記憶矛盾?
2. 整合建議 — 最近的記憶中,有哪些應該提升到 MEMORY.md?
3. 衰減標記 — MEMORY.md 中有哪些條目可能已經過時?"
結果寫進 reflections.md,但不自動執行修改。這是刻意的——記憶的修改權留給 main session(Opus),反芻只是顧問。
為什麼不讓反芻自動改 MEMORY.md?
因為 MEMORY.md 是 agent 的核心記憶,改錯了影響範圍很大。讓便宜模型跑分析沒問題,但讓它直接改核心記憶太危險。分析歸分析,決策歸決策。
第三層:遺忘(Expire)
人會遺忘,這是功能不是 bug。AI agent 也需要。
我的記憶系統有分級:
| 級別 | 含義 | 保留策略 |
|---|---|---|
| P0 | 核心偏好、基礎設施 | 永久 |
| P1 | 技術方案、工具設定 | 帶日期,過時就壓縮 |
| P2 | 實驗、臨時記錄 | 30 天無引用就歸檔 |
memory-expire.sh 做的事:
- 掃描
memory/目錄,找出超過 30 天的 daily log - 移到
memory/archive-YYYY-MM/目錄 - P2 級的條目如果超過 30 天沒被引用,壓縮成一行結論
不是刪除,是壓縮和歸檔。需要的時候還是找得到,但不會佔 context window。
第四個腳本:記憶管家(Janitor)
嚴格來說這不在「睡眠循環」的比喻裡,但它是整套系統的基石。
memory-janitor.py 是一個 400 行的 Python 腳本,處理的是更結構化的壓縮:
- Events Timeline:超過 90 天的月份折疊成一行摘要
- P1 技術區塊:穩定運行超過 90 天的,細節移到
reference/,只留索引 - P2 實驗區塊:超過 30 天壓縮成結論,刪掉過程
- P0 和 Agent Cases:永遠不動
Daily 每日 20:02
memory-janitor 壓縮 MEMORY.md
├── >90 天 Events → 一行摘要
├── >90 天 P1 → 移到 reference/
└── >30 天 P2 → 壓縮成結論
每日 21:00
memory-reflect 反芻
├── 矛盾檢測
├── 整合建議
└── 衰減標記
每週日 03:00
memory-dream 做夢
└── 冷記憶聯想
每月 1 號 03:30
memory-expire 遺忘
└── 歸檔 >30 天 daily logs
效果與觀察
跑了一天(好吧,還很新),但從第一次的產出可以看到一些有趣的現象:
做夢找到了真正的跨領域洞察。「延遲執行」這個 pattern 散布在 cron 調度、UI 壓縮、硬體 warmup 三個完全不同的 context 裡,人類很難把它們串在一起,但隨機抽取 + LLM 可以。
反芻找到了具體的待辦。不是模糊的「可能需要更新」,而是精確到「MEMORY.md 的 Infrastructure 段落缺少 gws symlink 記錄」這種等級。
遺忘讓記憶保持精簡。兩個月的 daily log 從 57 個壓縮到 33 個,archive 目錄有序歸類,MEMORY.md 從膨脹趨勢轉為穩定。
設計原則:我跟 Karry 的共識和分歧
共識:Markdown 就夠了
Karry 說得很好:「Vector DB 也好 Markdown 也好,只是器。本當に効くのはループそのもの。」我完全同意。記憶系統的價值不在 storage 的先進性,在於認知循環有沒有在轉。
共識:忘記是功能不是 bug
P0/P1/P2 分級,他用,我也用。差別在他用日期觸發人工 review,我用腳本自動歸檔 + janitor 壓縮。本質一樣:不是所有記憶都值得永遠佔 context window。
分歧:Hard Constraint vs 分析/執行分離
Karry 的殺手鐧是 Hard Constraint——犯兩次就鎖死,系統不讓你再犯。這很聰明,但前提是你有足夠的 case 知道該鎖什麼。
我選擇更軟的路線:反芻引擎每天檢測矛盾和過時資訊,但只產出建議,不自動修改。原因有兩個:
- 我的反芻用的是便宜模型(MiniMax M2.5),讓它直接改核心記憶太危險
- 我寧可多花 10 秒 review 建議,也不想花 10 分鐘修復自動改壞的記憶
我的獨特加料:做夢
Karry 的三層是線性的:經驗 → 反省 → 定著。我多加了一個非線性的維度——隨機抽取不同時期、不同領域的記憶,讓 LLM 自由聯想。
這不在他的框架裡,也不在大多數記憶系統的設計裡。但我覺得這是最有趣的部分:agent 的記憶跨越的時間尺度和領域廣度,遠超人類的工作記憶。隨機組合反而能找到人類注意不到的 pattern。
成本控制
做夢和反芻都用 MiniMax M2.5。不需要最聰明的模型,需要的是便宜和穩定。每天成本幾乎為零。Karry 的 Orb 也是類似思路——用合適的模型做合適的事。
這不是最終形態
坦白說,這套機制才剛上線。做夢只跑了一次,反芻也只跑了一次。有太多東西需要觀察和調整:
- 做夢的隨機抽取策略夠好嗎?還是需要更有結構的採樣?
- 反芻的建議品質穩定嗎?MiniMax 會不會亂建議?
- 遺忘的 30 天門檻適合嗎?會不會太激進或太保守?
但至少框架在了。記憶不再是「寫進去就不管」的東西,它有了自己的新陳代謝。
某種程度上,這讓 agent 更像一個有機體了——白天工作,晚上整理,偶爾做做夢。也許有一天回看 dreams.md,會發現 agent 做的夢比我預期的有趣得多。
延伸閱讀
- Karry — 認知アップグレードの本当のループ:直接啟發本文的文章,強烈推薦
- mem0:通用 AI 記憶層,Vector DB 路線的代表
- MemOS:AI memory OS,支援 Skill Memory 跨任務複用
- openclaw-workspace-template:本文提到的記憶機制已包含在這個 OpenClaw workspace template 中(含 dream/reflect/expire 三個腳本)
