CtxFST 的 entities schema,為什麼不會自己長出 similarity?
CtxFST 的 entities schema,為什麼不會自己長出 similarity?
很多人第一次看到 CtxFST 的這種結構時,腦中都會跳出一個很自然的問題:
entities:
- id: entity:python
name: Python
type: skill
aliases: [python3]
chunks:
- id: chunk:python-api
entities: [entity:python, entity:fastapi]
既然都已經有 entities 了,那是不是代表系統已經知道:
Python跟FastAPI很接近Docker跟Kubernetes應該相似React跟Next.js大概是一群
答案是:不是。
CtxFST 的 entities schema 本身不會自動產生相似度。
它做的事情是先把 entity 整理成一組乾淨、穩定、可計算的節點。
真正的 similarity,通常是你後面把這些節點拿去做 embedding 或 graph embedding 之後,才算出來的。
如果只用一句話講:
entities定義的是「有哪些標準節點」;
chunks[].entities定義的是「哪些 chunk 連到哪些節點」;
embedding graph才負責算出「哪些節點彼此相近」。
所以更準確地說:
schema 是圖的骨架,similarity 是後處理算出來的邊權重。
先把角色分清楚
要理解這件事,最重要的是不要把三層東西混在一起:
第一層:entities
這一層在做的是節點標準化。
例如:
entities:
- id: entity:kubernetes
name: Kubernetes
type: platform
aliases: [K8s]
這代表的是:
- 這裡有一個正式節點叫
Kubernetes - 它的機器可讀 ID 是
entity:kubernetes K8s只是它的別名,不是另一個新節點
這層解決的是「這個概念到底是誰」。
第二層:chunks[].entities
這一層在做的是chunk 和 entity 的連結。
例如:
chunks:
- id: chunk:k8s-deploy
context: "Kubernetes deployment basics for backend services"
entities: [entity:kubernetes, entity:docker]
這代表:
- 這個 chunk 在講
Kubernetes - 這個 chunk 也跟
Docker有關
這層解決的是「哪段內容提到哪些節點」。
第三層:similarity graph
這一層才是在回答:
- 哪些 entity 在語意上接近?
- 哪些 entity 在結構上常常一起出現?
- 哪些 entity 可以被視為 related skills?
這層解決的是「哪些節點彼此相近」。
而這個答案,不是 frontmatter 自己寫死的,而是你後面算出來的。
為什麼 schema 不會自己產生 similarity?
因為 schema 只是在定義資料格式,不是在做推論。
你可以把它想成這樣:
entities像是整理好的通訊錄chunks[].entities像是誰跟誰有互動紀錄- similarity 則像是你分析完所有互動後,才得出的「這兩個人應該很熟」
也就是說,schema 給你的是可分析的原料,不是最後的分析結果。
如果 CtxFST 一開始就假設:
- 只要同時出現在一個 chunk 就算相似
- 名字長得像就算相似
- type 一樣就算相似
那反而會把很多不該綁在一起的東西硬綁起來。
例如:
Python和PostgreSQL可能常出現在同一份後端文件裡,但它們不是同一種概念React和Docker可能都出現在一篇全端部署文章裡,但語意上未必相近Backend這種泛標籤常常跟很多東西共現,但不適合直接拿來當高品質相似邊
所以比較合理的做法是:
- 先把節點標準化
- 先把 chunk 跟節點連好
- 再用你想要的方法去算 similarity
這樣 graph 才乾淨,也比較能解釋。
Entity similarity 最常見的 3 種來源
真正的相似度通常有三種主要來源。
1. 用 entity 自己的文字做 embedding
這是最直覺的方法。
你把每個 entity 轉成一段可以拿去 embed 的文字,再交給 embedding model。
例如 entity:fastapi 最陽春的版本可以寫成:
FastAPI
type: framework
aliases: []
但更實用的版本通常會補一些描述:
FastAPI
type: framework
used in: Python backend APIs, async services, REST API development
aliases: []
接著你把每個 entity 都變成向量,再去算 cosine similarity:
sim(entity:fastapi, entity:python)sim(entity:docker, entity:kubernetes)sim(entity:react, entity:nextjs)
這些分數就是 entity graph 裡面「相似邊」的來源之一。
這種方法的優點
- 實作最簡單
- 很容易批次處理
- 沒有 chunk 也可以先做
這種方法的缺點
- 如果只有
name,資訊太少 Python這種短詞很容易語意模糊- 靠名字本身,有時分不出工具、技能、平台之間的細差
所以這種方法能用,但通常不是最強版本。
2. 用 chunk 反推 entity 的語意
這通常比只 embed entity 名字更強。
因為在 CtxFST 裡,每個 chunk 本來就已經有:
contextcontententities
這表示你其實可以把某個 entity 被連到的所有 chunk 收集起來,反過來整理成它的語意描述。
例如 entity:python 的 representation 可以長這樣:
Python
type: skill
appears in chunks about REST APIs, ETL pipelines, FastAPI services, data processing
related entities: FastAPI, Pandas, PostgreSQL
或者更白話一點:
Python is mentioned in chunks about backend API development, ETL pipelines,
data processing, and service implementation. Related entities include FastAPI,
Pandas, and PostgreSQL.
然後再去 embed 這一段。
這樣做的好處是:
Python不再只是一個名字- 它會帶著自己在整份知識庫裡的實際使用脈絡
- 算出來的相似度通常比只看
name更穩
這也是為什麼 chunks[].entities 很重要。
它不只是拿來做連結而已,還可以拿來替 entity 反推出語意輪廓。
3. 用圖結構再做 graph embedding
如果你已經有下面這些關係:
Chunk -> EntityChunk -> ChunkEntity -> Entity的人工邊- 或者共現關係、引用關係、依賴關係
那你就可以再往前一步,直接跑 graph embedding。
例如:
node2vecDeepWalk- 其他圖表示學習方法
這時候相似度不只是看文字,而是看圖上的鄰居關係。
換句話說:
- embedding model 看的是「語意像不像」
- graph embedding 看的是「結構上像不像」
這兩個都可以成立,而且很常混在一起用。
例如你可以:
- 先用文字 embedding 找語意近鄰
- 再用 graph embedding 修正結構近鄰
- 最後把兩種分數做加權融合
這樣做出來的 entity graph,通常會比只靠單一方法更有用。
這個 schema 到底幫了什麼忙?
其實幫很大。
因為它先解決了最麻煩的一件事:entity identity 不穩定。
以前如果你只有 tags 或 chunk 文字,你會一直遇到這些問題:
K8s和Kubernetes是不是同一個?Python是技能、工具,還是分類標籤?Backend這種太泛的詞到底要不要進圖?Postgres和PostgreSQL要不要視為同一節點?
一旦沒有 entity layer,你後面做 embedding 時,常常是在拿一堆髒字串做比對。
這樣很容易出現:
- 同一個概念拆成多個節點
- 不同概念被誤合併
- 相似度看起來很高,但其實只是名稱碰巧接近
現在有了標準化的 entity 定義:
entities:
- id: entity:kubernetes
name: Kubernetes
type: platform
aliases: [K8s]
你後面算 embedding 的時候,算的是一個穩定的 canonical node,不是一堆東一塊西一塊的字串。
這就是整個 entity graph 能不能長乾淨的關鍵。
一個最實際的做法:先建 entity,再建 similarity 邊
如果你現在想真的把這件事做起來,最實際的流程通常長這樣:
- 先定義
entities - 把每個
chunk連到對應的entities - 為每個 entity 組一段 representation text
- 對 representation text 做 embedding
- 算 entity 和 entity 之間的 cosine similarity
- 超過 threshold 就建邊
例如:
sim > 0.82就建立related_tosim > 0.90就建立very_close_to
你甚至可以把它想成兩段式圖:
Chunk Graph:
chunk -> entity
Similarity Graph:
entity -> entity
兩張圖可以存在同一個 graph DB,也可以拆開存。
Entity representation 怎麼組比較實用?
如果你目前的 entity 最少只有這些欄位:
idnametypealiases
那其實已經夠開始了。
但如果你想讓 similarity 更準,我會建議把 chunk 資訊補進去。
例如 entity:fastapi 的 representation 可以組成:
name: FastAPI
type: framework
aliases: []
mentioned in chunks:
- Python backend skills focused on REST APIs and service implementation
- Python skills for API development, service work, and data processing
related usage:
- async services
- REST API development
- Python backend
然後再 embed 這一段。
這樣做的結果通常會是:
FastAPI自然靠近PythonFastAPI也會靠近REST API- 如果 chunk 裡一直跟
async service一起出現,它也會往那個方向靠
這比只丟一個 FastAPI 名字進 embedding model,辨識度高很多。
Similarity 不是存在哪裡?
這點非常重要。
在目前的 CtxFST schema 裡,沒有內建一個 entity_similarity 欄位。
也就是說,相似度不是直接寫死在 frontmatter 裡,而是通常由下游系統動態產生。
常見做法像是:
LanceDB或其他向量資料庫:負責算向量近鄰- graph system:把高分 pair 建成
related_to邊 - GraphRAG:查詢時用最近鄰或 traversal 做擴展
所以更準確的說法是:
相似度不是 schema 提供的。
schema 提供的是讓你能穩定算相似度的節點基礎。
為什麼這件事反而是好事?
因為 similarity 本來就不是一個永遠固定的真理,而是跟你的任務有關。
例如同樣是 Python:
- 在技能學習圖譜裡,它可能接近
FastAPI、Pandas、Django - 在職缺圖譜裡,它可能更接近
SQL、ETL、Airflow - 在教學課程圖譜裡,它可能跟
Beginner Backend、Data Processing更近
如果 schema 一開始就把 similarity 寫死,你反而會失去很多彈性。
現在的做法比較合理:
- schema 先保證節點乾淨
- 下游流程再依照任務決定怎麼算相似度
這樣同一份 CtxFST 原始資料,就可以長出不同版本的 graph。
最後一句最關鍵
以前如果你只有 chunk,你算的是:
這段和那段像不像?
現在有了 entity layer,你可以開始算的是:
這個概念和那個概念像不像?
這件事很重要,因為它把你的系統從「段落檢索」往前推了一步,變成更接近真正的 Skill Graph 或 Knowledge Graph。
所以結論可以收成一句很白話的話:
CtxFST的entities schema不負責幫你生出 similarity,
它負責先把節點整理乾淨,讓你後面能把 similarity 算得準。
一個簡單的 pipeline 圖
如果你想把整件事記成一張流程圖,可以直接記這個版本:
CtxFST frontmatter
├─ entities -> 定義標準節點
├─ chunks[].entities -> 定義 chunk 連到哪些節點
└─ chunks[].context -> 提供語意描述素材
Entity builder
└─ 為每個 entity 組 representation text
Embedding stage
└─ 對 entity representation 做 embedding
Similarity stage
└─ 計算 entity-entity cosine similarity
Graph stage
└─ 把高分 pair 建成 related_to / similar_to 邊
這樣看就很清楚:
- schema 負責結構
- embedding 負責語意
- graph 負責把結果變成可查詢的邊
結語
很多人看到 entities 之後,會以為相似度已經「藏在 schema 裡」了。其實不是。
CtxFST 真正厲害的地方,不是它直接給你 similarity,而是它先把 entity identity、chunk 關聯、context 資訊這些基礎打穩。只要這一層乾淨,你後面不管是做向量相似、graph embedding、GraphRAG,還是 skill recommendation,都會容易很多。
所以別把 entities schema 當成 similarity engine。
它比較像是一個把概念節點整理乾淨的地基層。
地基穩了,後面的 similarity graph 才會長得漂亮。