定義:RAG(檢索增強生成)。在提問時,檢索器會從文件儲存庫中找到最相關的片段(通常透過嵌入相似度,有時透過關鍵字搜尋),並將它們貼到提示詞中。模型會根據這些片段回答問題。儲存庫是原始資料的副本,被分割成多個部分。沒有任何內容會被寫回;下一個問題會從相同的儲存庫開始。
代理式檢索:這是目前大多數程式碼代理實際採用的變體,沒有嵌入索引。代理會執行 grep 指令,開啟檔案並循環讀取,直到能夠回答問題。這與 RAG 的概念相同,只是檢索器本身就是模型,並配備了 shell 工具。Claude Code 在裸儲存庫上就是這樣運作的,這也是以下測量中「無維基」這一側的設定。我沒有運行向量資料庫 RAG;在需要說明的地方我會特別指出。
LLM 維基:一個由代理撰寫和維護的 Markdown 頁面資料夾。每個概念、決策或模組都有一頁,每個主張都引用來源(檔案:行號、變更日誌版本或註明日期的對話),並透過 [[wikilinks]] 連結,代理會先讀取索引。當問題無法從頁面中回答時,代理會讀取原始資料並將學到的內容寫回,這樣下一個問題就不需要再讀取原始資料。
Andrej Karpathy 在一個 gist 中勾勒了這個模式;我使用的工具包是其針對 Claude Code 的實作。
記憶檔案(CLAUDE.md、.cursorrules、memory/ 目錄):代理每次會話都會載入的事實和偏好列表。它們很有用、很小且非結構化。當記憶檔案超出單一檔案的限制,並需要引用和索引時,就會演變成維基。
一句話的對比:RAG 檢索已寫下的內容。維基則會記錄已決定的內容。所有其他差異都是由此而來。
測量目標:pallets/itsdangerous,這是 Flask session 下的簽章函式庫。它包含 8 個模組,共 1,176 行 Python 程式碼,一個 292 行的 CHANGES.rst 檔案,以及 7 個文件頁面。淺層複製版本為 672971d。
測試使用 Claude Code 2.1.286,預設模型,每次執行皆為無頭模式(headless),以 claude -p 在全新會話中執行,並使用 --output-format json。成本取自 CLI 的 total_cost_usd,執行時間則測量每次呼叫的實際耗時。
四個問題:這些問題是一位整合該函式庫的開發人員可能會實際提出的:如果我輪換 SECRET_KEY,舊金鑰簽署的 token 是否仍然有效,這樣做的成本是多少?salt 參數實際作用是什麼,它是一個加密鹽嗎?為什麼移除了 JWS 支援,我應該改用什麼?TimestampSigner token 中的時間戳是如何編碼的,以及傳輸格式何時改變?
A 方案:無維基,代理直接讀取原始碼。提示詞是:「請根據此程式碼庫的原始碼(src/、CHANGES.rst、docs/)回答以下問題。每個主張都必須引用檔案:行號或 CHANGES.rst 版本。請勿建立或修改任何檔案。」
問題 | 執行時間 | 輪次 | 成本 | 正確性
1 密鑰輪換 | 33 秒 | 6 | $0.62 | 是,引用 signer.py:247-253 說明從最新到最舊的循環
2 鹽 | 28 秒 | 3 | $0.45 | 是,引用 docs/concepts.rst:59-62(「不一定是隨機的」)
3 JWS 移除 | 28 秒 | 4 | $0.38 | 是,0.18 版新增 / 2.0.0 版棄用 / 2.1.0 版移除,建議使用 Authlib
4 時間戳格式 | 35 秒 | 5 | $0.47 | 是,找到 1.0.0 版從 2011 年紀元切換到完整 Unix 時間
總計 | 2 分 4 秒 | 18 | $1.93 | 4 / 4
我將每個答案與其引用的檔案進行了核對。所有四個答案都正確,並且都引用了存在的行號。
建立維基:與我的程式碼庫維基指南中使用的兩個提示詞相同:先執行 /llm-wiki:init,然後執行一個建構提示詞,要求每個模組建立一個架構頁面,每個有來源的設計決策建立一個決策頁面。
步驟 | 執行時間 | 成本 | 輸出
init | 60 秒 | $0.65 | 骨架,自己的提交
build | 6 分 51 秒 | $3.58 | 17 頁,6,331 字,86 個 [[連結]](0 個損壞,0 個孤立),110 個檔案:行號引用(0 個指向不存在的行)
總計 | 7 分 51 秒 | $4.23
值得注意的是:兩天前在相同的提交版本上執行相同的提示詞,產生了 21 頁、8,441 字,花費 $4.08。建構過程並非確定性的。如果您將頁面數量視為品質指標,請運行檢查器,而不是依賴您對上次運行的記憶。
B 方案:透過維基回答相同的四個問題。使用指令 /llm-wiki:query <問題>。該指令會先讀取 wiki/index.md,然後讀取相關頁面,並附帶頁面引用來回答問題。只有當頁面內容不足時,才會回溯到原始碼,並將學到的內容寫回。
問題 | 執行時間 | 輪次 | 成本 | 執行動作
1 密鑰輪換 | 57 秒 | 6 | $0.82 | 維基頁面缺少每個密鑰的驗證成本 → 讀取 signer.py 和 docs/concepts.rst,將成本寫回兩個頁面
2 鹽 | 66 秒 | 6 | $0.64 | 從維基回答,與 docs 和原始碼確認,在一個頁面中新增術語說明
3 JWS 移除 | 25 秒 | 5 | $0.50 | 從 decisions/api-scope 回答,與 CHANGES.rst 驗證,頁面無變更
4 時間戳格式 | 43 秒 | 6 | $0.63 | 從 decisions/timestamps 回答,與原始碼驗證,頁面無變更
總計 | 3 分 11 秒 | 23 | $2.59 | 4 / 4 正確
再次回答問題 1,在寫回後 | 28 秒 | 5 | $0.59 | 「從維基回答,頁面無變更」
所有四個答案都正確,每個答案都引用了維基頁面和底層的檔案:行號。
數據說明:
| | 無維基 | 維基(首次嘗試) | 維基(寫回後) |
|---|---|---|---|
| 每個問題 | 31 秒, $0.48 | 48 秒, $0.65 | 28 秒, $0.59 |
| 前期成本 | $0 | $4.23 和 8 分鐘 | |
| 正確性 | 4 / 4 | 4 / 4 | 1 / 1 |
對於一個 1,200 行的程式碼庫,維基作為 RAG 的表現甚至不如沒有 RAG。首次嘗試時,每個問題的速度慢了 55%,成本高了 34%。即使在寫回之後,重複問題的成本與直接讀取原始碼的成本也大致相同(28 秒 vs 33 秒,$0.59 vs $0.62),因為查詢指令在回答之前會驗證其頁面引用與原始碼的一致性。
檢索節省的成本永遠無法彌補 $4.23 的建構成本。對於這種規模的程式庫,沒有損益平衡點。
有兩個反向的注意事項,我沒有測量,因此不會提供具體數字:對於 1,200 行的程式庫,整個程式庫都可以放入上下文視窗中。如果是一個「讀取原始碼」意味著讀取 200k 行的 50 個檔案的儲存庫,那麼 A 方案每個問題的成本會增加,而維基的成本則不會。
我預計存在一個交叉點,但我不知道在哪裡。無頭模式運行時沒有人類等待。維基的答案讀起來更短,因為它們帶有決策頁面的框架(「拒絕的替代方案:…」),而不是從分散的行中重建。
第五個問題:維基是唯一選擇。現在來看看最重要的問題。在程式碼審查後,團隊對函式庫的使用方式做出了一個決定。這個決定不在 src/ 中,不在 CHANGES.rst 中,也不在任何人的文件中。我扮演了團隊的角色:我們剛剛在審查中決定:我們的應用程式在 secret_key 列表中最多保留三個金鑰,每 30 天淘汰最舊的一個,因為維基顯示一個被拒絕的 token 會導致每個金鑰產生一個 MAC 成本。我們拒絕了保留無限列表的方案,也拒絕了單一金鑰的硬性切換方案。
/llm-wiki:capture。然後我詢問了兩方:「我們的應用程式保留多少個密鑰用於輪換,多久淘汰最舊的一個,以及為什麼?」
方案 | 執行時間 | 成本 | 答案
無維基(與 A 方案相同的提示詞,在 capture 前的相同 checkout 中運行) | 53 秒 | $0.51 | 「原始碼無法回答這個問題的前兩個部分。」然後它正確解釋了函式庫將金鑰數量和頻率留給呼叫者決定,引用了 docs/concepts.rst:112-114,並說明文件中三個金鑰的範例僅為說明,而非建議。
capture | 34 秒 | $0.57 | decisions/key-derivation-and-rotation.md 上新增了頂部條目:策略、兩個被拒絕的替代方案、引用函式庫輪換條目和 signer.py:195-220 的成本推理,以及我沒有說出口的「任何 max_age 應保持在 60 天以下」的後果。作為其自己的維基提交。
維基(/llm-wiki:query) | 22 秒 | $0.47 | 三個金鑰,每 30 天淘汰最舊的一個,原因,兩個被拒絕的替代方案,以及 60 天的後果,所有內容都引用了註明日期的條目。
關於「無維基」這一行的誠實說明:在我運行它時,前一節的維基已經存在於 checkout 中。提示詞將代理限制在 src/、CHANGES.rst 和 docs/,而且該決策尚未被捕獲,因此結果與在裸複製上相同,但它不是裸複製。這不是性能差異。
這是一個系統能否回答問題的差異,因為 RAG 和代理式檢索只能檢索別人寫下的內容,而除非工具能讓它成為一個單行指令,否則沒有人會寫下審查決策。維基的 capture 就是那個指令。它花費了 34 秒和 $0.57 來記錄,現在這個決策位於 decisions/key-derivation-and-rotation.md 中,與函式庫自己的輪換歷史並列,引用了註明日期的對話,下一個查詢(或下一個工程師)可以在那裡找到它。
何時使用哪種方式:
在以下情況使用 RAG 或純代理式檢索:答案在原始碼中且原始碼穩定(API 文件、函式庫本身的程式碼、規範);語料庫龐大且主要用於讀取,因此索引比直接讀取更有效;不需要改變知識,只需要找到它。
在以下情況使用 LLM 維基:知識部分存在於原始碼中,部分存在於人們的腦海、審查、事件、聊天記錄中;那些沒有被寫下來的「為什麼」;您在多個會話中詢問代理關於同一個專案,並希望第二個會話能從第一個會話停止的地方開始;您需要審計追蹤:每個主張都有引用,每個變更都在 log.md 中,所有內容都在 Git 中。
當語料庫很大時,兩者並用:維基用於決策和綜合,檢索用於原始資料。維基的 raw/ 目錄正是 RAG 會索引的文件儲存庫,因此兩者在原始資料方面並不競爭。不要將維基用作檢索的快取。上述測量結果就是原因。如果您唯一想要的是從現有語料庫中獲得更快的答案,維基會增加建構成本和驗證成本,卻沒有給您任何您原本沒有的東西。
我沒想到的:查詢指令的驗證步驟是維基耗時的原因。四個維基答案中有三個說「已針對 CHANGES.rst 驗證」或「已針對 signer.py 確認」,即使頁面中已經有答案。對於一個以引用為賣點的工具來說,這是正確的行為,這也是為什麼維基在這麼小的儲存庫上從未比直接讀取原始碼更便宜的原因。如果您想要速度,您需要一個信任頁面內容的不同指令,並且您需要知道您要求了它。
capture 選擇了「揮發性」而非「固定」。該工具包允許代理決定是將對話中決定性的行複製到 raw/conversations/ 中,還是僅作摘要。兩天前,對於相同的決策,它選擇了固定;這次它選擇了摘要並引用「來自對話,已摘要(無謄本)」。
當時的模式允許兩種方式。我第二天將其設為規則(免費範本 1.0.4,2026-10-02):任何命名被拒絕替代方案、記錄反轉或被告知「固定此項」的 capture 都會固定。這個決策命名了兩個被拒絕的替代方案,因此在目前的規則下它會固定。自從更改後我還沒有重新運行過。在舊版本的範本上,請告知它固定。
相同的提示詞,相同的提交,一天產生 17 頁,隔天產生 21 頁。已經說過,值得重複:建構是一個樣本,而不是一個固定值。
重現實驗:整個循環,除了外掛程式安裝,就是三個指令和一個循環。成本由 CLI 報告;執行時間則圍繞呼叫時間測量。
git clone --depth 1 https://github.com/pallets/itsdangerous.git app && cd app
Q = "If I rotate my