跳到主要內容
Lab Grimoire
TW EN
請喝咖啡
Agent 架構

AI 記得住,卻想不起來:我們的 AI 記憶系統一年心得

我們讓多個 AI CLI 在同一個工作區共用一套自己設計的記憶系統一年,累積約一千筆情節記憶與五百多篇知識筆記。真正造成損失的不是 AI 忘記,而是它相信了沒驗證過的東西。本文整理 Ghost In Shell 5.2 的三項修正,以及六個親身踩過的坑與對應的檢查動作。

作者
CY
發表
更新
AI 記得住,卻想不起來:我們的 AI 記憶系統一年心得

導讀:你的 AI 助理是不是明明記得上週的教訓,這週卻照樣重犯?記憶系統的價值不在記得多,而在該停下來的時候讓 AI 停下來;好的記憶就像在對的路口亮起的一盞燈。


記錄存在,只是沒有在需要的那一刻出現

真正造成損失的,幾乎都不是 AI 忘了,而是它相信了沒驗證過的東西。

我們讓多個 AI CLI 在同一個工作區共用一套記憶,一年下來累積了約 1,000 筆情節記憶和 570 多篇知識筆記。回頭整理,真正造成損失的幾乎都不是「AI 忘了」,而是「AI 相信了一個看起來可靠、其實沒驗證過的東西」。

每一個 AI CLI 的 session 都從零開始。今年初,我們開源了 Ghost In Shell,替 Claude Code、Gemini CLI、Codex CLI 這類工具加上一層本地記憶:結構化的事實檔、按時間記錄的情節記憶,以及會隨時間衰減、隨回想增強的強度公式。

每天實際使用之後,我們發現這套系統記得住,卻不一定想得起來。情節記憶裡清楚寫著「上週部署回報成功,但線上其實還是舊版」,AI 隔週照樣只看部署工具的回報就宣告完成。

先說明一點:這是我們依自己的需求設計的系統,不一定與主流方案相同。常見的 AI 記憶方案多半把對話轉成向量做語意檢索,或使用 AI 工具內建的記憶功能;我們用的是純文字檔、關鍵字比對,加上一份人工維護的觸發詞索引,不使用向量資料庫。我們沒有和其他方案做過對照測試,本文的心得都來自我們自己的工作區,適用範圍有這個限制。

這篇文章分兩部分。第一部分是我們對系統做的修正,已經寫進 Ghost In Shell 5.2;第二部分是這一年踩過的六個坑,每個坑都附上我們現在用的檢查動作。


第一部分:這一年我們改了什麼

5.2 的三項修正,分別補在索引、本體、夜間整理這三種角色上。

先看全貌:索引、本體、夜間整理

這套記憶系統裡有三種角色。

  • **索引負責指路。**每個 session 開工時只載入一份短索引,每行只有一個觸發詞和一個連結。索引就像圖書館的門牌,本身不放內容。
  • **本體負責記內容。**結構化的事實、按時間記錄的情節、一則一檔的知識筆記,命中索引才去讀。
  • **夜間整理負責維護。**每晚依序回放、重組、評分、修剪、自檢。重要度低又久未使用的情節會先淡出,再歸檔,不會直接刪除。

上層只放指向下層的連結,不重複內容,所以同一件事只需要改一個地方。5.2 的三項更新,分別補在這三個角色上。

一、觸發詞要寫成你當下會有的症狀

啟動索引的每一行只有兩樣東西:一個觸發詞,加上一個連到知識筆記的連結。

關鍵在觸發詞怎麼寫。早期我們寫成因:「工具回報不可靠」。為什麼這一行幾乎從來沒被觸發過?因為 AI 真的需要它的時候,腦中想的是「工具說成功了,應該好了吧」。如果它已經懷疑工具回報,就不需要這則提醒。

所以規則改成:**觸發詞寫症狀,不寫成因。**觸發詞要寫成 AI 犯錯當下腦中的那句話。

另一條規則是雙向都要掛。很多失效有兩個方向:閘門可能漏擋,也可能誤擋。我們曾經只替一則筆記掛了「閘門沒在擋」這個方向。某天 AI 被閘門擋了三次,它想的是「它擋了我,但我沒下那個旗標」,這句話對不上任何一行索引,答案明明早就寫在筆記裡。一則記憶失效,不一定是內容錯,可能只是門牌掛在 AI 不會走的那條路上。

二、索引有預算,而且超過時不會報錯

每加一行索引,就會用掉每個 session 的一點載入預算。筆記越堆積越多,索引跟著變長;我們用的 CLI 在啟動記憶檔超過一定大小後,會直接把尾段吃掉,沒有任何警告。被丟掉的偏偏是最新加上的幾行,也就是剛學到的教訓。

5.2 加入 gish index budget,以字元量測索引。中文一個字和英文一個字母的位元組數差很多,用位元組會量錯。量測結果用結束碼表示:0 正常;1 超過上限,要先壓縮再加;2 已越過截斷點,尾段正在被丟掉;3 找不到索引檔,要先執行 gish init。以我們的工作區為例,目前索引約 16,000 字元,上限設在 20,000,實測約 24,400 字元之後的內容會被截掉。

我們也把索引分成兩層,判準是**「AI 會不會主動去查」**,不是「重不重要」。

  • 啟動索引只放「你不知道自己做錯了」、而且每個任務都可能碰到的鐵律,例如驗收、派工、刪除資料前的提醒。這一層每個 session 都要付載入成本。
  • 書架索引放「你知道自己在查」的內容,例如工具用法,或只在寫某類程式時才會踩的坑。需要時才讀。

拿不定的時候放書架索引。之後再升到啟動索引很容易;但啟動索引撞到上限時,被截掉的尾段不會有任何警告。

三、寫入紀律:不讓記憶被自己寫壞

讀錯記憶只影響一次回答;寫錯記憶,會影響之後每一個相信它的 session。5.2 把三條寫入規則寫進程式:

  • **只有一台主機寫入。**多台機器共用工作區時,其他機器只能讀。機器角色存在本機設定,不放進會同步的資料夾。
  • **整合要先提案、再審查、才套用。**合併舊記憶的那一步不能自己替自己打分數。審查評為 A 到 C 才套用,套用前再核對一次來源;評為 D 或 F 時,原始資料一行都不動。
  • **不刪除,只歸檔。**被合併的原始記憶搬進歸檔檔,新條目記下它從哪幾筆合併而來。

做這三條規則時還有一個安全上的發現:原本工作區設定可以指定外部審查指令。如果工作區是同步資料夾或別人 clone 來的,等於任何能改工作區的人,都能在每台打開它的機器上執行程式。5.2 改成只讀裝置本地設定;工作區設定若出現這個欄位,直接拒絕,不執行。


第二部分:一年下來,AI 的記憶是怎麼壞掉的?

六個坑都出在同一處:AI 相信了一個看起來已經驗證過的東西。

以下六個坑,每一個都已經寫成知識筆記,也收進 Ghost In Shell 的第 21 章。小標題是 AI 犯錯當下腦中的那句話,也就是我們寫進索引的觸發詞。

坑一:「工具說成功了,應該好了吧」

部署工具回報成功,使用者打開網頁卻還是舊版,因為中間有一層快取。編輯器回報存檔成功,格式化工具卻在下一秒刪掉剛加的那一行。

**教訓:**工具回報只是宣稱,不是證據。

**檢查動作:**在使用者會看到的地方,親自讀一次最終狀態。驗證網頁時加上避開快取的參數,否則驗到的是快取,不是線上版本。

坑二:「錯誤數是 0,所以沒問題」

我們曾把驗收條件寫成「載入失敗的次數等於 0」。實際執行,結果確實是 0,看起來全部通過。但服務早在載入那一步之前就已經異常結束,根本沒機會失敗。

**教訓:**0 也可能代表「根本沒跑到那一步」。

檢查動作:「錯誤數為 0」一定要搭配一個「確實跑完」的訊號,例如出現完成訊息,或處理筆數等於預期。

坑三:「那道檢查我們早就寫好了」

一支檢查函式有自己的單元測試,全部通過,記憶裡也有一則筆記提到它。但扣掉定義和測試之後,程式裡沒有任何地方呼叫它。它從來沒在正式流程中跑過。

**教訓:**零個呼叫點就是死碼,測試再綠也一樣。

**檢查動作:**數呼叫點,扣掉定義行與測試檔之後還剩幾個。第一次接上線時,先拿真實資料跑一輪,不要直接設成會擋人的閘門。

坑四:「記憶裡寫著這個工具不支援」

一則筆記寫著某工具不支援某功能,但工具早在幾個月前就加上了。反方向也會發生:記憶說某筆資料存在,搜尋一次沒找到,AI 就判定不存在。

**教訓:**記憶裡的否定句是有日期的快照。

**檢查動作:**我們現在替這類筆記加上 expires 到期日,gish knowledge lint 會提醒過期的筆記。搜尋查無結果時,回報要附上試過的關鍵字與查詢方式。

坑五:「來壓縮記憶索引吧,裡面一定很多過時條目」

這個提議在不同 session 裡反覆出現,甚至被重複開成好幾筆待辦,卻從來沒有人量過。我們終於拿 301 個 session 的逐字稿,逐條比對索引指向的 59 篇筆記:沒有任何一篇是零命中,其中 39 篇被 10 個以上的 session 用到。要清理的目標其實是空集合。

每篇索引筆記被多少個 session 用到:0 個 session 的有 0 篇,1–2 個 4 篇,3–9 個 16 篇,10 個以上 39 篇

圖 1. 每篇索引筆記被多少個 session 用到(逐字稿中出現該筆記的檔名)。2026-08-21 量測,301 個 session 逐字稿;整份讀過索引的 1 個 session 已扣除。

更重要的發現是:最關鍵的鐵律,本來就很少被查。它之所以是鐵律,正是因為 AI 不知道自己正在犯錯。量測當天就有一個例子:一則只被 5 個 session 用到的筆記,阻止了一次「把某段規則當成多餘內容刪掉」的錯誤。用使用頻率來砍鐵律,就像拆掉自己的煞車。

**教訓:**動工前先量分母。

**檢查動作:**先問這筆成本多久付一次、付幾次;看到「0 次使用」時,要有兩種獨立的計量方式都同意,才算真的是 0。

坑六:「另一個 agent 交回來的結論,跟我想的一模一樣」

我們曾在派給研究 agent 的工單裡,憑印象把一家公司寫成某集團旗下,請它「確認與該集團的關係」。幸好這句是問句:研究結果回報查無佐證,真正的淵源是另一個集團。

如果當初寫成陳述句,報告裡就會出現一段附上看似合理來源的錯誤敘述,之後每份引用它的文件都會繼承這個錯誤。

**教訓:**交接時,還沒驗證的想法要寫成問句,不要寫成陳述句。

**檢查動作:**驗收時拿原始資料比對,而不是拿自己的預期比對。交回來的結論跟你想的一模一樣時,更要回頭查一次來源。


結語:好的記憶系統,會在該停下來的時候讓 AI 停下來

記得多不是目標,在犯錯的那一刻想起來才是。

年初,我們以為記憶系統的目標是「記得越多越好」。一年後回頭看,六個坑有一個共同點:AI 手上都有一個「看起來已經驗證過」的東西,可能是工具回報、一個 0、一支有測試的函式、一句記憶裡的否定句、一個直覺,或一份跟預期相符的報告。

觸發詞寫成症狀、索引守住預算、寫入有紀律,都是為了讓對的那一則記憶,在 AI 準備相信這些東西的那一刻出現。


想自己試試看

Ghost In Shell 以 MIT 授權開源。把 repo clone 下來之後,三行指令就能建立工作區並檢查知識筆記:

git clone https://github.com/cyhsieh817/Ghost_In_Shell
cd Ghost_In_Shell
pip install -e .
gish init ./my-workspace
gish knowledge lint --workspace ./my-workspace

如果想先看圖再讀文字,我們另外整理了一篇圖解版:《我們自己設計的 AI 記憶系統:Ghost In Shell 5.2 圖解》。

參考文獻

  1. Ghost In Shell 5.2.0 (GitHub repository)

常見問題

AI 明明把教訓寫進記憶了,為什麼下週還是重犯?

每一個 AI CLI 的 session 都從零開始。我們讓多個 AI CLI 在同一個工作區共用一套記憶,一年下來累積約 1,000 筆情節記憶和 570 多篇知識筆記。情節記憶裡清楚寫著「上週部署回報成功,但線上其實還是舊版」,AI 隔週照樣只看部署工具的回報就宣告完成。 記錄存在,只是沒有在需要的那一刻出現。這套系統記得住,卻不一定想得起來。記得多不是目標,在犯錯的那一刻想起來才是。

索引的 16,000、20,000、24,400 代表什麼?

以我們的工作區為例,目前索引約 16,000 字元,上限設在 20,000,實測約 24,400 字元之後的內容會被截掉。我們用的 CLI 在啟動記憶檔超過一定大小後,會直接把尾段吃掉,沒有任何警告。被丟掉的偏偏是最新加上的幾行,也就是剛學到的教訓。 5.2 加入 `gish index budget`,以字元量測索引。中文一個字和英文一個字母的位元組數差很多,用位元組會量錯。結束碼 0 表示正常;1 表示超過上限,要先壓縮再加;2 表示已越過截斷點,尾段正在被丟掉;3 表示找不到索引檔,要先執行 `gish init`。 索引分成兩層,判準是 AI 會不會主動去查,不是重不重要。啟動索引只放「你不知道自己做錯了」、而且每個任務都可能碰到的鐵律,例如驗收、派工、刪除資料前的提醒。書架索引放「你知道自己在查」的內容,例如工具用法。拿不定的時候放書架索引。之後再升到啟動索引很容易;啟動索引撞到上限時,被截掉的尾段不會有任何警告。

觸發詞為什麼要寫成症狀,不寫成因?

啟動索引的每一行只有兩樣東西:一個觸發詞,加上一個連到知識筆記的連結。早期我們寫成因「工具回報不可靠」。AI 真的需要它的時候,腦中想的是「工具說成功了,應該好了吧」。如果它已經懷疑工具回報,就不需要這則提醒。所以觸發詞要寫成 AI 犯錯當下腦中的那句話。 另一條規則是雙向都要掛。很多失效有兩個方向:閘門可能漏擋,也可能誤擋。我們曾經只替一則筆記掛了「閘門沒在擋」。某天 AI 被閘門擋了三次,它想的是「它擋了我,但我沒下那個旗標」,這句話對不上任何一行索引,答案明明早就寫在筆記裡。一則記憶失效,不一定是內容錯,可能只是門牌掛在 AI 不會走的那條路上。

這套做法比向量檢索好嗎?

不能這樣說。我們沒有和其他方案做過對照測試。本文的心得都來自我們自己的工作區,適用範圍有這個限制。 常見的 AI 記憶方案多半把對話轉成向量做語意檢索,或使用 AI 工具內建的記憶功能。我們用的是純文字檔、關鍵字比對,加上一份人工維護的觸發詞索引,不使用向量資料庫。這是我們依自己的需求設計的系統,不一定與主流方案相同。

常見誤解是「來壓縮記憶索引吧,裡面一定很多過時條目」。可以依使用頻率刪掉鐵律嗎?

不要依使用頻率刪。這個提議在不同 session 裡反覆出現,甚至被重複開成好幾筆待辦,卻從來沒有人量過。我們拿 301 個 session 的逐字稿,逐條比對索引指向的 59 篇筆記:沒有任何一篇是零命中,其中 39 篇被 10 個以上的 session 用到。分布是 0 個 session 的有 0 篇,1–2 個 4 篇,3–9 個 16 篇,10 個以上 39 篇。要清理的目標其實是空集合。整份讀過索引的 1 個 session 已扣除。 最關鍵的鐵律本來就很少被查。它之所以是鐵律,正是因為 AI 不知道自己正在犯錯。量測當天,一則只被 5 個 session 用到的筆記,阻止了一次把某段規則當成多餘內容刪掉的錯誤。用使用頻率來砍鐵律,就像拆掉自己的煞車。看到「0 次使用」時,要有兩種獨立的計量方式都同意,才算真的是 0。 <!-- origin: themis-worker/writer; device: primary; date: 2026-10-07 -->

覺得這篇有幫助?

追蹤以收到新的 AI × 生醫研究筆記:

或請我喝杯咖啡,讓新內容持續產出。

☕ 請我喝杯咖啡