知識圖譜也會記錯: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。這樣即使後來發現對錯,也能改映射,不必重寫原始來源。
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_entity、predicate、target_entity 與 evidence_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_version或content_hash:當時實際讀到的版本。quote:支持該關係的原文片段。offset:片段在保存內容中的位置,方便重新定位。run_id:哪一次抽取或人工修正建立這條關係。model、prompt_version、schema_version:日後重跑與比較的依據。
一條 relation 也可能有多份 evidence。三篇獨立來源都支持同一關係,和三篇文章都轉述同一篇新聞,可信度並不相同。若要做來源品質評分,應另外保存 publisher、publication time 與引用鏈,而不是讓模型憑語氣猜 confidence。
Provenance 的目的不是讓資料表更漂亮,而是支持三個動作:回答時引用、錯誤時定位、更新時判斷哪些結果受影響。缺少任何一個,圖譜就很難成為可維護的長期記憶。
Temporal Truth:不要用 UPDATE 抹掉歷史
「某人任職於某公司」通常不是永遠成立的真相。若 2025 年的來源說 A 在 X 公司,2026 年的新來源說 A 已加入 Y 公司,直接把 works_at 從 X 改成 Y,會失去回答歷史問題的能力;同時保留兩條沒有時間的邊,又會讓系統以為 A 同時任職兩處。
關係至少應區分:來源發布時間、系統觀察時間、事實有效時間。簡化實作可在 relation 保存 valid_from、valid_to、observed_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、圖資料庫或搜尋引擎,上述語意問題都不會自動消失。
用錯誤預算設計評估,而不是只算節點數
節點和邊增加不代表記憶變好。評估至少要涵蓋以下資料集:
- 同名不同人,用來測 over-merge。
- 縮寫、改名、跨語言 alias,用來測 under-merge。
- 主詞受詞容易顛倒的句子,用來測 relation direction。
- 否定、傳聞與條件句,用來測 assertion handling。
- 同一事實不同時期,用來測 temporal validity。
- 沒有足夠證據的問題,用來測系統是否回傳
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,而不是模型用了幾句推理。
安全的寫入閘門
一條候選關係從模型輸出到共享記憶,中間可以有五個閘門:
- Zod/JSON Schema 驗證結構。
- mention、quote 與 offset 對照原文。
- entity type、predicate allowlist 與方向驗證。
- resolution validation 與低信心隔離。
- 寫入 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 建立可追溯的多代理共享記憶。
來源與延伸閱讀
- Anthropic Knowledge Graph Cookbook
- Anthropic Structured Outputs
- Anthropic:Demystifying evals for AI agents
- Supabase:Row Level Security
常見問題
Structured Output 能避免知識圖譜寫入錯誤嗎?
它能保證輸出符合指定的 JSON schema,不能保證抽取內容符合來源。系統仍須驗證實體、關係方向、證據片段與時間,並處理 refusal 或輸出截斷。
Entity Resolution 做錯後可以修復嗎?
可以,但前提是保留 mention、source、run 與版本。合併應建立可逆映射而不是破壞性刪除,修正後再重算受影響的關係、查詢結果與快取。
知識圖譜需要多久重新建立一次?
沒有固定週期。應依來源更新、schema 或 prompt 版本、人工修正與品質警報做增量重建;只有重大 schema 變更才考慮全量重算,平常不需要為了形式定期全部重做。
利益揭露:本文含聯盟連結,透過連結購買我可能取得少量分潤,不影響你的價格與本文內容。