Nat 鍾承恩

觀點 2026 / 06 約 4 分鐘

代碼圖刻意不用 embedding——因為你的料早就有邊了

代碼圖工具(像 codegraph、Graphify 這類)有個容易被誤讀的設計決定:它們不用 embedding。在一個什麼都要丟進向量庫的年代,這看起來像偷懶,或像還沒跟上。其實剛好相反——這是一個算過帳的賭注。我想把這個賭注拆開講,因為它背後的判準,適用的遠不只代碼。

先問:你的料有沒有客觀結構

embedding 解決的是一個很特定的問題:一堆非結構化、散落的文字,你要在其中找語意相近的段落。幾萬份 PDF 政策文件問「X 條款怎麼說」,答案可能藏在任何一份彼此不相連的文件裡——這時候你沒有別的辦法,只能把語意壓成向量、靠相似度去撈。embedding 在這裡是賺的。

但程式碼不是這種料。A 呼叫 B、這個檔 import 那個模組、這個 class extends 那個——這些邊不是猜出來的,是程式語言寫死在語法裡的既成事實。tree-sitter 解析一遍就能精確抽出來,零猜測、零幻覺。你手上的料早就帶著一張確定的圖,卻還要把它打散成向量、再用近似相似度重新猜回那些連線——這不只是多花錢,是把一份確定的答案降級成一份機率性的答案。

所以判準很簡單:料有客觀結構,就別付 embedding 的稅;沒結構,才需要。 別因為兩種工具的輸出都長得像圖(節點加邊),就以為它們可以互換。

確定性先打到底,LLM 只推最後一小段

把這個判準展開,建圖其實該分層,按確定性程度排:能用確定性工具抽的,先抽到極限。code 那層用 tree-sitter,免費、本地、不會錯;只有真正非結構化的料——散文、文件、圖片——才輪到 LLM 上場做語意分析,而那一段近似 RAG,卻往往連真正的 embedding 都不必要。

這條脊椎我在很多地方都看到:把貴而不可靠的那層,壓到最小、最後。多數連結是免費且不幻覺的;你只在「沒有客觀結構、只能靠語意」的那一小塊,才掏錢給模型。先用確定性,模型收尾。

省下的不只是錢

這個切法的紅利會連帶冒出來,而且都不是硬湊的。

隱私是順手劃好的。 因為 code 那層在本地解析,整個流程只把語意內容送上游,原始碼從不離開機器。純 code 的專案因此根本不需要 API key,可以全離線跑。對受規範產業或要保密的場景,raw source 不上線等於少一條外洩面——這不是額外加的功能,是「先在本地抽結構」這個決定自帶的。

地圖不會腐。 預建圖的死穴是新鮮度:repo 一直變,圖會過期。但既然 AST 那層是確定性又便宜的,就掛一個 post-commit hook,每次提交後只重算改動部分——看什麼變了、現在連到誰、重建那一小棵子樹。純確定性、零 API 成本。結果是一張持續更新又便宜的活地圖,而不是建一次就開始 drift 的快照。衍生物不存死,讓真相源(git 的實際變更)去驅動它增量更新。

它真的會被用到。 建好圖不代表模型會查它——模型仍可能偷懶直接 grep。所以靠的不是拜託它記得,而是一個 PreToolUse hook:在每次檔案搜尋之前強制先查圖。希望模型自律是不可靠的;把這件事做成 hook、在它出手前由外圍結構確定性地插進去,才可靠。

回到那個判準

這些好處——免幻覺、省成本、顧隱私、不腐、強制被用——沒有一個是 embedding 路線能順手給的。它們全都長在同一個根上:這份料有客觀結構,所以我不必付那筆稅。

下次評估一個「圖譜」或「智能檢索」工具,別停在它輸出長得像不像圖。先問一句:我的料,有沒有天生的邊?有,就別讓任何工具說服你把它打散成向量再猜回來。