Ian Chou's Blog

Skill Graph 進階:YAML Schema 只是骨架,Entity Similarity 從哪來?

Skill Graph 進階:YAML Schema 只是骨架,Entity Similarity 從哪來?

在上一篇介紹 Skill Chunk MD 格式指南 中,我們談到了如何透過 YAML 嚴謹定義文件中的 Entity 與 Chunk:

但如果你夠敏銳,可能會發現一個問題:「在這些 YAML Schema 裡,完全沒有一個欄位是用來存 entity_similarity(相似度)的?」

沒錯,這其實是故意的,而且這樣才更適合做真正的 Entity Embedding Graph。


核心觀念:Schema 是骨架,Similarity 是後處理的「邊權重」

一句話來總結這個概念:

CtxFST 的 Entities Schema 本身不能、也不會直接產生相似度。它的真實價值是把骯髒的文字變成「乾淨、可計算的節點」。

真正的相似度,是你後續把這些標準化的節點抽出來,拿去做 Embedding (向量化處理)或 Graph Algorithms (圖演算法)時才計算出來的。

所以:

  1. Schema: 是圖的骨架(定義了 Nodes 與基礎 Edges)。
  2. Similarity: 是後續動態算出來的邊權重(用來畫出「相似邊」)。

這種設計確保了你的資料源頭(Markdown 文件)永遠保持乾淨,而相似度的認定標準(例如用 OpenAI 的模型算、還是用本地的小模型算)則可以隨著你的問答系統靈活抽換。


既然不在 Schema 裡,相似度從哪裡來?

要讓 Entity 之間產生關聯(例如讓 entity:fastapi 自動靠近 entity:python),目前實務上最常見有三種做法:

1. 用 Entity 自身的文字做 Embedding

這是最基礎也最直接的方法:把每個 Entity 的定義轉成一段文字,餵給 Embedding Model。
例如針對 entity:fastapi,你可以組合出這樣的字串:

FastAPI
type: framework
aliases: []

或是稍微豐富一點:

FastAPI
type: framework
used in: Python backend APIs, async services, REST API development

接著把每一份實體的這段文字都變成向量(Vector),並計算兩兩之間的餘弦相似度(Cosine Similarity):

這些算出來的分數,就是 Entity Graph 裡「相似邊(Related Edges)」的來源。

2. 用 Chunk「反推」Entity 的動態語意(最強做法)

這通常比單純只 Embed Entity Name 要強大非常多。
因為在你的 Skill Chunk 中,你已經擁有了豐富的關聯結構:Chunks 裡面有 Context(上下文描述)、Content(具體內文)、以及包含這個 Entity 的其他共同 Entity。

你可以把所有連到 entity:fastapi 的 Chunk 收集起來,為它撰寫出一段「動態生成的語意描述」:

name: FastAPI
type: framework
mentioned in chunks:

當我們把這一段濃縮過的文字丟去算 Embedding 時,FastAPI 就會因為這些大量的共同特徵,自然而在向量空間中向 PythonREST API 靠攏。這讓模型的判斷不再只依靠名詞本身,而是你在筆記裡累積的真實使用情境

3. 用圖結構本身的拓樸特徵(Graph Embedding)

既然我們手頭上已經有:

  1. Chunk -> Entity 的基礎連線
  2. Chunk -> Chunk 的 Dependencies
  3. 甚至可能有人工追加的 Entity -> Entity 上下位關係

你已經可以利用如 node2vec 這類的圖神經網路演算法(Graph Neural Networks)去跑純粹的「結構化 Embedding」。
也就是說:

在進階的體系裡,這兩者甚至能混合使用,給出最精確的推薦路徑。


為什麼這套 Schema 對 Entity Graph 如此關鍵?

你可能會問:「如果相似度都是後來算的,為何我們一開始還要搞這麼複雜的 YAML Schema?」

原因很簡單:它解決了以前做知識分類時最難的「實體身分(Entity Identity)不穩定」問題。

在以前只有 Tags(標籤)的年代,你很難讓機器知道:

  1. K8sKubernetes 到底是不是同一個東西?
  2. Python 究竟是一個標籤、一項技能、還是一個工具分類?
  3. Backend 這種泛用的關鍵字,到底該不該在圖譜中佔據一個具體的節點?

現在有了 CtxFST 的 Entity Layer,你已經提前幫 AI 梳理好一切:

entities:
  - id: entity:kubernetes
    name: Kubernetes
    type: platform
    aliases: [K8s]

這代表未來不論你用哪種模型計算 Embedding,它在算相似度的時候,面對的都是一個穩定、標準化、不可動搖的 Canonical Node(權威節點),而不是你在散落文章中隨手寫下的一堆「又髒又臭的字串」。


實戰工作流:如何從 Schema 走到 Similarity 線條?

綜合以上,一個能成功落地的 Skill Entity Graph 實作流程通常如下:

  1. 打樁建骨:在 Markdown 檔案內定義 entities
  2. 綁定血肉:把內文的 chunks 連至實體(建構 Chunk ↔ Entity 邊)。
  3. 彙整語意:透過腳本為每個 Entity 收集關聯的 Chunk 資訊,組合成一段豐富的 Representation Text(代表文本)。
  4. 計算向量:對每一段代表文本呼叫 Embedding API 產生座標。
  5. 矩陣測距:計算所有 Entity 兩兩之間的 Cosine Similarity。
  6. 建立鄰居關係:設定閾值(Threshold)自動建邊。例如:
    • 計算相似度 > 0.82 ➡️ 建立 [related_to] 關聯邊。
    • 計算相似度 > 0.90 ➡️ 建立 [very_close_to] 關聯邊。

至此,你的實體知識庫就不再是一座座孤島,而是一張四通八達、由語意相似度牽橋搭線的巨大航空圖。

結論

以前只有 Chunk (段落) 時,所有的 RAG 和相似度系統都在算「段落和段落像不像」。
這很容易導致文不對題、或找到一堆包含相同廢話的無關筆記。

現在有了 Entity Layer,你可以真正開始算「概念和概念像不像」。
這就是為什麼 CtxFST 將 Entity 單獨抽出來做成 Schema 是如此關鍵的原因,它不在 Frontmatter 裡把關係寫死,卻精準地為你的 Skill Graph 提供了最強大的起飛跑道。