跳到主要內容
知識圖譜也會記錯:Entity Resolution、Provenance 與時間真相
/閱讀約 14 分鐘/

知識圖譜也會記錯:Entity Resolution、Provenance 與時間真相

知識圖譜不會自動成為真相層。本文拆解同名誤合併、關係方向、證據失聯與時間覆寫,並提出可以修復、完整追溯、持續評估的 Agent Memory 安全寫入流程。

目錄+

把 Agent 的輸出存進資料庫很容易,把它變成「可以長期相信的記憶」很難。知識圖譜看起來比聊天紀錄更結構化:人物是節點、任職是邊、每個查詢都有方向;但只要最初的實體或關係寫錯,結構反而會讓錯誤更容易被重用。

想像兩份文件都出現「Alex Chen」。第一份談一家新創的工程師,第二份談大學教授。Resolver 把兩人合併後,圖譜可能推導出「該教授任職於新創公司」。後續 Agent 不只會看到錯誤,還可能沿著錯誤節點連到更多公司、論文與投資人。這就是 graph memory 特有的風險:錯誤不是停在一段文字,而是沿關係傳播。

前兩篇先釐清了 工作流程圖與知識圖譜的責任邊界,以及 Context、Checkpoint、RAG、Knowledge Graph 的選型。這一篇進入最常被 demo 略過的三件事:Entity Resolution、Provenance、Temporal Truth。

第一種錯誤:Over-merge,把不同實體合成一個

Over-merge 常發生在同名人物、同縮寫公司或跨領域名詞。例如「Apple」可能是公司,也可能是水果;「Mercury」可能是產品、公司、行星或化學元素。只用 embedding 相似度或小寫後字串相等,會把語境完全不同的 mention 接到同一節點。

錯誤合併的代價很高。兩個實體原本各有五條正確關係,合併後十條關係都集中到同一節點;任一 multi-hop query 都可能把兩個世界混在一起。若系統再把查詢答案摘要成新關係寫回圖譜,錯誤會形成回授。

降低 over-merge 的第一個原則,是不同 entity type 永不自動合併。第二個原則,是名字相同只能成為 candidate,不能直接成為 canonical identity。還要比較描述、別名、時間、來源與鄰接關係。證據不足時,預設保持分離並標記待審,比積極合併安全。

第二種錯誤:Under-merge,同一實體被拆成很多個

Under-merge 則是「Anthropic」「Anthropic PBC」「該公司」被建立成三個節點。它不一定立即產生錯誤答案,卻會讓查詢漏掉關係:使用者從「Anthropic」出發,可能看不到寫在「Anthropic PBC」節點上的產品或人物。

這種錯誤常見於縮寫、公司更名、跨語言名稱、拼字差異與代名詞。解法不是單純放寬相似度門檻,而是保留 mention 層:原文出現的字串先成為 alias 或 mention,再由 resolution process 映射到 canonical entity。這樣即使後來發現對錯,也能改映射,不必重寫原始來源。

Entity Resolution 過度合併與錯誤拆分比較
Over-merge 會混合不同世界,under-merge 會漏掉關係;保留 mention 與可逆映射,才能在事後修復。

Resolution 應該是一個可重跑的判斷流程

可靠的 Entity Resolution 可以拆成四段。

第一段是 normalization:Unicode NFKC、空白、大小寫與常見標點正規化,但不能把原始字串丟掉。第二段是 blocking:先依 entity type、名稱或已知 alias 建立小型候選集合,避免所有節點兩兩比較。

第三段才交給模型或規則判斷 cluster。輸入需要包含候選 mention、上下文、來源日期與已知鄰居;輸出則是候選 cluster 與理由,而不是直接修改資料庫。第四段是 deterministic validation:同一 mention 只能出現在一個 cluster,不允許跨 type 合併,低信心結果維持 singleton。

每次 resolution 都應有 run ID、model、prompt version、schema version 與結果。合併最好是新增 alias-to-canonical 映射,而不是刪除節點。若人工判斷兩個 entity 其實不同,可以撤銷映射並重算受影響的 relation。

Resolution 要能重跑才有意義,而重跑意味著整批實體重新推論一次。這類批次工作放本地比雲端划算,麗臺 RTX PRO 4000 Blackwell 這個級距可以整晚跑不心疼。

Structured Output 保證形狀,不保證真相

Claude Structured Outputs 能讓抽取結果符合 Zod 或 JSON Schema,例如每條關係都有 source_entitypredicatetarget_entityevidence_quote。這解決了 malformed JSON、缺欄位與型別不一致,對 production pipeline 非常重要。

但 schema compliance 與 factual correctness 是兩回事。模型可以輸出完全合法的 JSON,同時把關係方向寫反、把推論寫成事實,或引用一段沒有支持該關係的文字。系統也要處理 refusal、max_tokens 截斷,以及來源本身互相矛盾。

因此抽取後至少做三種檢查:entity mention 是否真的出現在來源或有可解釋的 coreference;evidence quote 是否能在原文定位;predicate 是否在 allowlist 且方向符合 schema。高風險關係還可以要求第二個 verifier 或人工審核。

Provenance 不是一個 URL 欄位

很多 graph demo 在 relation 上加一個 source_url 就宣稱可追溯。實際上,一個 URL 會更新、消失或同時包含支持與反對的敘述。可用的 provenance 至少需要以下層次:

  • source_id:來源的穩定識別。
  • source_versioncontent_hash:當時實際讀到的版本。
  • quote:支持該關係的原文片段。
  • offset:片段在保存內容中的位置,方便重新定位。
  • run_id:哪一次抽取或人工修正建立這條關係。
  • modelprompt_versionschema_version:日後重跑與比較的依據。

一條 relation 也可能有多份 evidence。三篇獨立來源都支持同一關係,和三篇文章都轉述同一篇新聞,可信度並不相同。若要做來源品質評分,應另外保存 publisher、publication time 與引用鏈,而不是讓模型憑語氣猜 confidence。

Provenance 的目的不是讓資料表更漂亮,而是支持三個動作:回答時引用、錯誤時定位、更新時判斷哪些結果受影響。缺少任何一個,圖譜就很難成為可維護的長期記憶。

Temporal Truth:不要用 UPDATE 抹掉歷史

「某人任職於某公司」通常不是永遠成立的真相。若 2025 年的來源說 A 在 X 公司,2026 年的新來源說 A 已加入 Y 公司,直接把 works_at 從 X 改成 Y,會失去回答歷史問題的能力;同時保留兩條沒有時間的邊,又會讓系統以為 A 同時任職兩處。

關係至少應區分:來源發布時間、系統觀察時間、事實有效時間。簡化實作可在 relation 保存 valid_fromvalid_toobserved_at,並允許未知值。新資訊不是覆寫,而是結束舊關係的有效區間並新增一條關係。

時間也可能只有部分精度。原文只說「2024 年加入」,就不要虛構成 1 月 1 日零時。可以保存 date precision 或原始時間字串;回答時以來源能支持的精度呈現。

關係方向與否定也會污染圖譜

acquired(A, B)acquired(B, A) 都符合相同欄位型別,意義卻相反。每一個 predicate 都應有定義、允許的 source/target type 與方向範例。可對稱的關係如 collaborates_with,也應明確標示,避免查詢層任意猜測反向邊。

否定與不確定性更麻煩。「公司否認將收購 B」不能抽成 acquired(company, B);「正在洽談」也不是完成事件。最安全的做法,是只寫入 schema 明確支持的 assertion state,或讓未完成事件留在 evidence/event layer,避免壓扁成肯定關係。

如果你正在研究混合式 Agent Database,LangGraph 與 Oracle 的 Agent Memory 案例可以補充不同持久化層的角色;但不論底層是 Postgres、圖資料庫或搜尋引擎,上述語意問題都不會自動消失。

用錯誤預算設計評估,而不是只算節點數

節點和邊增加不代表記憶變好。評估至少要涵蓋以下資料集:

  1. 同名不同人,用來測 over-merge。
  2. 縮寫、改名、跨語言 alias,用來測 under-merge。
  3. 主詞受詞容易顛倒的句子,用來測 relation direction。
  4. 否定、傳聞與條件句,用來測 assertion handling。
  5. 同一事實不同時期,用來測 temporal validity。
  6. 沒有足夠證據的問題,用來測系統是否回傳 insufficient_evidence

除了 entity precision/recall,也要測 relation accuracy、provenance completeness、multi-hop answer correctness 與 repairability。最後一項很重要:當 gold set 宣告某次合併錯誤,系統能否列出所有受影響的 alias、relation、evidence 與 cache,並完成可重現的修復?

Anthropic 對 agent eval 的經驗指出,多步系統不一定每次走相同路徑,因此只要求固定步驟並不可靠。對會修改持久狀態的 Agent,更應檢查離散 checkpoint 與最終 state。套用到 graph memory,就是驗證最後留下哪些 canonical entities、relations 和 evidence,而不是模型用了幾句推理。

安全的寫入閘門

一條候選關係從模型輸出到共享記憶,中間可以有五個閘門:

  1. Zod/JSON Schema 驗證結構。
  2. mention、quote 與 offset 對照原文。
  3. entity type、predicate allowlist 與方向驗證。
  4. resolution validation 與低信心隔離。
  5. 寫入 owner-scoped transaction,保留 run、版本與 evidence。

回答端也要有閘門:query 只展開有限 hops,只回傳目前有效且屬於該使用者的 relation;模型必須引用 relation/evidence ID;子圖為空時明確說證據不足。不要在圖譜查不到時默默改用模型的參數記憶,否則使用者無法分辨答案來自資料還是猜測。

Repeat 的正確意思是可控更新

Graph pipeline 的 Repeat 應由事件觸發:來源內容 hash 改變、新文件加入、人工修正、schema 或 prompt 版本更新、gold set 品質下降。每次更新先記錄 run,再寫入新版本,成功後才切換讀取狀態;失敗則保留上一個可用版本。

小型系統不需要每天全量重建。可以依 source 找出受影響的 evidence,再沿 relation 與 canonical entity 做局部重算。只有當 identity schema 或 predicate ontology 大幅變更,才安排全量 rebuild。這樣才能控制 API 成本,也能比較每次改動究竟修好了什麼。

完整的 TypeScript、Claude Structured Outputs、Supabase RLS 與 recursive RPC 範例,已整理在訂閱教學:用 Claude+Supabase 建立可追溯的多代理共享記憶

來源與延伸閱讀

常見問題

Structured Output 能避免知識圖譜寫入錯誤嗎?

它能保證輸出符合指定的 JSON schema,不能保證抽取內容符合來源。系統仍須驗證實體、關係方向、證據片段與時間,並處理 refusal 或輸出截斷。

Entity Resolution 做錯後可以修復嗎?

可以,但前提是保留 mention、source、run 與版本。合併應建立可逆映射而不是破壞性刪除,修正後再重算受影響的關係、查詢結果與快取。

知識圖譜需要多久重新建立一次?

沒有固定週期。應依來源更新、schema 或 prompt 版本、人工修正與品質警報做增量重建;只有重大 schema 變更才考慮全量重算,平常不需要為了形式定期全部重做。

利益揭露:本文含聯盟連結,透過連結購買我可能取得少量分潤,不影響你的價格與本文內容。