同一個程式庫,昨天才請 Coding Agent 加過鍵盤快捷鍵,今天又要它改一個類似功能,它卻可能重新搜尋檔案、閱讀測試、再踩一次相同的坑。第一次探索當然要花成本;問題是,第二次為什麼還得付同樣的學費?

最近在 Show HN 原始討論 看到一個名為 Singularity 的開源專案。它想把已完成的程式修改整理成可重複使用的工作流程,記住該到哪些位置、如何驗證、先前有哪些陷阱。當新的任務出現,就先比對可能用得上的步驟,再交給 Agent。

這個方向很吸引人。但我更在意的是:記憶被找出來之後,我們憑什麼確定它仍適用於眼前的任務?

我把研究固定在 Singularity 的 commit 9d241f2,讀了原始碼,也做了一組不使用模型的輕量合成測試。先說明範圍:這不是安裝 Singularity 後的端對端實測,更不是 Claude Code 或 Codex 的 Token 成本對照。它檢驗的是根據原始碼獨立改寫的比對規則,以及這些規則可能誤判的地方。

記住的不是聊天紀錄,而是做事的路徑

依照固定版本的 README,Singularity 會在成功完成程式修改後累積經驗,再由模型將多次經驗歸納成工作流程。工作流程可能告訴 Agent:某種功能通常要改哪些檔案、應該執行哪些測試、之前在哪裡失敗過。

這與把完整對話存進長期記憶不同。原始聊天內容很長,其中不少嘗試只有在當下有用;工作流程則試著留下值得重複的操作順序。這篇文章討論的是工作流程步驟與線索的重用,並不是對這個專案是否採用其他快取機制的全面稽核。即使記憶曾指出精確的檔案位置,程式庫結構變了之後,還是得重新確認。

費用也有兩筆。學習工作流程可能需要呼叫模型;使用已產生的工作流程線索挑選步驟,則未必需要模型。專案中的 workflows-cues 路徑就是後者。

但這不表示 Singularity 所有路徑都沒有模型成本。固定版本的評估程式 StepSelector.ts 會呼叫模型判斷哪些步驟適用;而 Memory.ts 則將 workflows-cues 描述成不需模型的線索選取。兩條路徑的成本結構不同,但我沒有針對真實任務測量延遲或 Token 差異,因此不能推論哪一條整體更划算。

不呼叫模型的比對,到底做了什麼

接著看 apps/cli/src/workflows/Cues.ts。

核心邏輯相當直接:先將任務文字轉成一致的大小寫,嘗試移除含有 not、never、without 等字詞的否定子句,再檢查剩下的文字是否包含工作流程預先產生的線索短語。命中允許線索、又沒有命中排除線索,才選取這個工作流程;個別步驟還可以依自己的線索再次篩選。

這個模組沒有請模型判斷「兩個任務在語意上是否相似」。它比較像整理過的字串規則表。優點是便宜、快速、容易重現;缺點是,文字重複不代表意圖相同。

假設觸發詞是 keyboard shortcut。「Add a keyboard shortcut」理應命中;「Review keyboard shortcuts in documentation only」雖然含有同一個詞,卻不代表使用者想修改功能。

原始碼確實處理了一部分明確否定,但不能因此認為它理解所有複雜否定、暗示條件或跨句意圖。比對器負責找出候選記憶,無法光靠這個步驟證明操作正確。

五組人工輸入,測試這條界線

我參考固定提交的 Cues.ts,將文字正規化、否定子句過濾,以及允許與排除線索的核心判斷,手動獨立改寫成只使用 Node.js 標準函式庫的測試。這不是官方測試套件,也不保證涵蓋上游所有邊界情況。測試沒有安裝 Singularity、連接模型或操作真實程式庫。

測試腳本與結果清單保留在私人研究紀錄,沒有提供公開下載副本。以下列出全部五組觀察值。這是根據原始碼規則做的合成重現,不是上游 CLI 的端對端行為報告。

人工任務輸入比對結果觀察重點
新增鍵盤快捷鍵命中正常召回
修復資料庫連線不命中排除無關任務
明確要求不要新增快捷鍵不命中簡單否定有效
只檢查文件中的快捷鍵敘述命中字面相似造成誤召回
要新增快捷鍵,但記憶指向的舊檔已刪除命中比對不會檢查檔案是否還存在

這些預期結果是在執行前依據簡化規則設定的:相關任務應命中,無關任務與明確否定應落空;只討論文件卻含有觸發詞的任務仍可能命中,而宣告舊路徑失效的文字,也不會讓比對器檢查檔案系統。

五個斷言都符合事先預期。但最後兩項是刻意設計的不理想結果。所以「5/5 通過」不是準確率,更不是五個真實任務都被正確處理的證據;它只證明這組獨立合成規則的預測與觀察一致。

最後一個案例尤其重要。只看文字線索,cueChoice 無法得知檔案是否已被搬移、刪除或重構。後續 Agent 或許會重新確認檔案,但過時路徑仍可能先被召回。記憶命中是一項提示,不是當前程式庫狀態的證明。

README 的 Token 節省數字該怎麼看

作者公開了一組 Excalidraw 任務對照。在某個與記憶高度相關的長任務中,報告中的 Token 數由約 190 萬降至 42.3 萬,成本由約 0.81 美元降至 0.30 美元,回合數中位數由 28.5 降至 9.5。每組只有大約 3–4 次執行,實驗主要集中在少數程式庫。

數字值得追查,但它們仍是作者報告的特定任務結果。碰到沒學過的新型修改,或很小的一次性修補,收益可能趨近於零;學習工作流程本身也會產生成本。

減少讀取檔案的 Token,未必等於降低整體工程成本。如果召回錯誤步驟,Agent 可能花更多時間修正;如果程式經過大幅重構,舊記憶反而可能增加排查負擔。

我沒有重跑作者的模型對照,也沒有測量真實 Token 或美元成本,因此不提供獨立節省百分比。要估出有意義的數字,至少要讓同一批任務在有記憶與無記憶的條件下對照,並計入學習呼叫、錯誤召回修復及任務完成的總成本。這次測試沒有那些資料。

我會怎麼使用這類記憶

對於重複任務多、目錄結構相對穩定、測試流程明確的程式庫,工作流程記憶值得嘗試。但我會把它視為待確認的索引,不會讓 Agent 盲目照著執行。

比較實際的作法是替每條記憶附上來源提交、涉及路徑、最近驗證日期與適用條件。使用前確認檔案仍存在、測試命令仍有效;如果連續幾次召回都需要人工糾錯,就重新學習或停用該記憶。這是我的建議,不是宣稱 Singularity 已完整實作這套失效偵測。

是否安裝記憶系統,也不應只看宣傳的 Token 節省幅度。如果每次都在不同程式庫、語言與問題間切換,維護記憶的成本未必划算。

我更期待下一輪公開對照:固定同一批真實任務,同時記錄有效召回率、誤召回次數、過時記憶、學習費用與最終總成本。只有這樣,才能分辨記憶是真正省下重複探索,還是只把探索成本轉成維護成本。

參考資料:Singularity 專案 · 固定版本的線索比對原始碼 · 作者的實驗與限制