Ian Chou's Blog

Schema 穩定後的自然產物:實作能自動生長邊界的 Entity Graph Builder

Schema 穩定後的自然產物:實作能自動生長邊界的 Entity Graph Builder

在上一篇文章 《做 GraphRAG 之前,為什麼要先「穩定 Schema」?》 裡,我們建立了 CtxFST 的 v1.1 核心規格,同時嚴格遵守著一個信念:Schema 本身只是固定的節點與區塊(Edges 與相似度不屬於此層)。

有了這堅實的基礎,我們終於能來到最令人興奮的一步:打造一張由 Embedding 構成的 Entity Graph!

而最好的是,在實作這張圖譜時,我們完全不需要再去修改現有的 CtxFST Spec 規格書。因為這支生長 Graph 的程式,只是一個單純的「下游轉換器(Downstream Builder)」。

這篇文章,讓我帶你看看這套設計帶來的威力,以及剛出爐的 build_entity_graph.py 實作成果。


為什麼說這「不需要改 Schema」?

只要你有了前置作業:

  1. Markdown 文件 (定義了 entities 節點清單,以及各 chunks 所掛載的實體)
  2. export_to_lancedb.py 腳本,負責產出乾淨、具備 JSON Schema 驗證的 chunks.json

那麼,你要做 Similarity Graph 的原材料已經 100% 備齊了。

我加入了一支新的下游腳本——skill-chunk-md/scripts/build_entity_graph.py
它的運作邏輯完美體現了什麼叫作 關注點分離 (Separation of Concerns)

這不是作者在 YAML Frontmatter 用人工填寫的固定欄位,這是計算出來的動態關聯結果!


build_entity_graph.py 腳本的運作解密

這支剛加入的腳本提供了「最小可用版但極具體」的展示,完全不需要安裝複雜的 PyTorch 或去叩 OpenAI 的昂貴 API,它讓想嘗試架構的人立刻就能看見 GraphRAG 最初心的樣貌。

支援的三大實用參數

實際輸出的 JSON 結構搶先看

{
  "nodes": ["entity:fastapi", "entity:python", "entity:pandas", "entity:go"],
  "edges": [
    {
      "source": "entity:fastapi",
      "target": "entity:python",
      "relation": "SIMILAR",
      "score": 0.63
    },
    {
      "source": "entity:fastapi",
      "target": "entity:pandas",
      "relation": "SIMILAR",
      "score": 0.97
    }
  ]
}

從範例解析「血緣關係 (Bloodline Relatives)」的威力

我們拿實際案例來跑測試,對比了 --mode metadata--mode contextual 兩種運算模式。這份測試完美地展現出為什麼「把 Chunk Context 加進 Embedding 裡」能讓圖譜變得更有人味:

實體對照 (Entity Pair) Metadata 模式分數 Contextual 模式分數 導致差異的真實原因
FastAPIPandas 0.21 💥 0.97 在範例文件中,它們都頻繁共存於同一個 Chunk (skill:python) 裡面,而且 Context 描述高度重疊,它們是強烈關聯的技術棧工具!
FastAPIPython 0.23 0.63 FastAPI 只有出現在 1 個區塊,但 Python 出現在 3 個,有交集但權重被稀釋。
GoPython 0.54 (最高) 0.53 Metadata 模式給的分數最高,因為兩者都是 type: skill(屬性相同被誤認親密);Contextual 將其校正為普通同袍關係(各自負責一個 API 區塊)。
GoFastAPI 0.23 0.16 因為在內文的 Chunk 中,這兩個技術從未並肩作戰過,它們本來在業務面就是兩條平行線。

看到這裡就會發現:在 metadata 模式下,機器覺得 Go 與 Python 最像(它們都叫程式語言);但在 contextual 的真實圖譜裡,系統知道 FastAPI 與 Pandas 才是最強的連結,因為你的文章中告訴系統「這兩個傢伙總是一起出現在資料處理與後端建置中」。

這,就是方式 B:「血緣親屬」的極致展現。


為什麼只提供輕量的「Reference Builder」?

眼尖的讀者可能會問:「為什麼這支腳本只使用 TF-IDF + Cosine Similarity,而不直接整合強大的 sentence-transformers、OpenAI、Gemini 或 LanceDB Vector Ops?」

答案是:為了維持 CtxFST 作為「規格與教學」專案的純粹性,也是一個最安全的選擇。

build_entity_graph.py 的定位是一個 Lightweight Reference Builder(輕量參考建置器),它具有幾個重要特質:

  1. 零外部依賴:任何人 clone 專案下來,不需要註冊 API Key,也不用安裝肥大的 PyTorch 機器學習框架,就能一條龍跑完「撰寫 CtxFST ➡️ export JSON ➡️ build entity graph」的流程。
  2. 高可讀性:它是最佳的教材,用純 Python 展演了圖譜建構的最核心邏輯。
  3. 安全且解耦:完全不跟特定雲廠商或單一神經網路框架綁在一起。

對於一個「規格 + Skill」型的 Repository 來說,這種零依賴的小實作是最好的示範。它讓任何人都能馬上跑出成果,同時,只要你理解了概念,這支 Scripts 的邏輯隨時可以被你抽換。

生產環境升級指南:Production-grade embedding pipeline (out of scope for this repo)

當你要將這套架構推向正式的 Production(商業生產環境)時,我們強烈建議將這層基礎的 TF-IDF 邏輯抽換成重型的 Embedding Backend。這些進階的實作方向適合獨立拆解成專屬的 Repo 或 Microservice,而不是與標準規格混作一團。

以下是常見的進階實作升級策略:

總結來說:CtxFST Repo 負責定義穩定的標準與參考實作;而真正強大的 Embedding 基礎設施,則交給你的正式產品線來發揮!


Separation of Concerns 驗證:一條完整的 Pipeline 閉環

我們回頭來看這次架構升級有沒有違反我們立下的任何紀律?

  1. ctxfst-spec.md (Formal Spec):維持 Frozen v1.1 —— 沒動!
  2. schema.json (Validation):維持 Freeze Draft-07 —— 沒動!
  3. export_to_lancedb.py (上游匯出):依舊照著標準產出 JSON —— 沒動!
  4. build_entity_graph.py (新增角色下游 Builder):純粹去「消費」上游的 JSON。

腳本只讀 Schema 產出的通用資料,然後算出來的 SIMILAR Edges 完全沒有逆向塞回 CtxFST 的 Markdown 或 Metadata 裡,這證明了我們這條流水線在職責劃分上的正確性!

有了這支腳本,我們正式完成了從文本到 Graph DB 匯入規格的黃金四部曲打通:

Markdown 撰寫 ➡️ export_to_lancedb.py (提取) ➡️ build_entity_graph.py (關聯) ➡️ 匯入 Lance Graph / HelixDB / Neo4j

準備好把這些生成的 .json 拋進圖資料庫了嗎?我們的 Entity Embedding Pipeline 這下真正成型了!