Ian Chou's Blog

GraphRAG + 證據選擇,為什麼很像自然語言的 AST?

GraphRAG + 證據選擇,為什麼很像自然語言的 AST?

我很喜歡用一句話描述 GraphRAG:

GraphRAG 是把「可被走訪、可被組合、可被稽核」的知識結構顯式化。

如果你有編譯器 / 靜態分析背景,這會讓你立刻想到 AST(Abstract Syntax Tree)。

這個類比在「只有 GraphRAG」時已經像;但當你把 證據選擇(evidence selection) 加進來,就會更像,因為整條管線開始呈現一種熟悉的形狀:

建結構 → 走訪/擴張 → 找出最小充分子結構 → 下游推理 / 生成

本文把這個類比拆解到工程層級,並補上你可以拿來做系統設計討論的細節:什麼地方像、什麼地方不像、哪裡最容易踩坑。


先對齊名詞:GraphRAG 與 Evidence Selection 在做什麼?

GraphRAG(圖式檢索)

GraphRAG 通常會把資料切成「節點」並建立「關係」:

查詢時不只做相似度檢索,還會沿著關係擴散或做子圖擷取,把跨文件、跨實體、多跳的上下文找齊。

證據選擇(Evidence Selection)

證據選擇的目標不是「把資訊變短」,而是:

你可以把它看成把上下文從「材料堆」升級成「可稽核證據包」。


核心類比:GraphRAG + Evidence Selection ≈ AST + Program Slicing

一張對照表(工程語言版)

編譯/分析系統 自然語言/知識系統
Parse source code 從文件抽實體、抽關係、建圖
AST(中介表示 IR) Knowledge Graph / Document Graph(中介表示 IR)
Traversal / dataflow 圖擴散、路徑搜尋、多跳檢索
Program slicing Evidence subgraph / evidence spans selection
Pretty-print / lowering Context assembly(把證據包轉成 LLM 可吃的格式)
Typecheck / lint Verifier / self-check(答案是否被證據支持)

類比成立的關鍵,不是「都有圖」,而是 都有 IR + selection + verification 這種「把推理變成可控流程」的結構。


為什麼「加上證據選擇」之後更像?

如果你只做 GraphRAG 而不做 evidence selection,你常會停在:

這比較像把整棵 AST 直接丟給後端,期望後端自己找到正確的 expression;可行但不優雅,且容易被雜訊拖垮。

而 evidence selection 會強迫系統回答一個很編譯器的問題:

為了支持這個結論,最少需要哪幾個節點/片段?

一旦你開始做「最小充分」:

這就是 slicing 的精神:只保留會影響結論的那部分 IR。


更精準一點:GraphRAG 更像哪一種 AST?

如果你說的 AST 是「語法樹」,GraphRAG 並不完全像,原因是:

所以更準確的說法是:

GraphRAG 更像「自然語言的 IR(資訊檢索的中介表示)」
而不是「100% 可證明正確的語法樹」

也因此,GraphRAG 系統要更重視:


一個可落地的設計:Evidence Subgraph as the Contract

要把「像 AST」的好處吃到,你需要把輸出契約(contract)從「chunks」提升為「evidence object」。

一個實用的 evidence 物件至少包含:

{
  "claim": "答案中的一個可驗證敘述",
  "evidence": [
    {
      "source_id": "doc:policy-2025-11",
      "locator": { "page": 12, "section": "3.2", "span": "L45-L62" },
      "quote": "原文片段…",
      "edge_path": ["term:GDPR", "refers_to", "clause:3.2"]
    }
  ]
}

重點在於:

這就像 AST node 帶著 source location,讓你可以把 warning/error 精確貼回原始程式碼。


實務流程:從 query 到 evidence subgraph

下面是一個簡化但足夠工程化的流程:

flowchart TD
  Q[Query] --> P[Parse intent / entities]
  P --> S[Seed retrieval]
  S --> X[Graph expansion]
  X --> C[Candidate subgraph]
  C --> R[Rerank nodes/paths]
  R --> E[Evidence selection: minimal supporting set]
  E --> A[Context assembly]
  A --> G[Generate claims + citations]
  G --> V[Verify each claim]
  V -->|retry| X
  V -->|ok| O[Answer]

這裡的關鍵不是「有圖」,而是中間那個 E


一個小小的 pseudo-code(把 slicing 味道做出來)

def answer(query):
    seeds = seed_retrieve(query)              # dense/keyword/metadata
    subgraph = expand_graph(seeds, hops=2)    # graph traversal

    ranked = rank_nodes_and_paths(query, subgraph)
    evidence = select_minimal_support(query, ranked)  # slicing

    claims = generate_claims(query, evidence, citations=True)
    verdict = verify(claims, evidence)

    if verdict.need_more_evidence:
        query = rewrite_query(query, verdict.missing_aspects)
        return answer(query)

    return claims

select_minimal_support 的概念就是:不要讓「更多」假裝成「更準」。


什麼時候這個類比會失效?

  1. 你的關係邊不穩定

    • 抽取的關係錯、版本沒更新、同義詞沒規範化,整張圖會像壞掉的 AST:走訪得到錯誤依賴。
  2. 你把摘要當證據

    • AST slicing 的輸出仍然是原始 IR 的子集;如果你用摘要替代原文片段,就像 slicing 後又把 node 改寫成另一份不可追溯的碼。
  3. 你沒有 verifier

    • 沒有 verifier 的 GraphRAG 更像「把 IR 丟給生成器」而不是「可驗證的推理系統」。

結語:把 GraphRAG 當成 AST,最大的收益是“工程可控性”

把 GraphRAG 類比成 AST 不是為了炫技,而是為了讓系統討論更精準:

而 evidence selection 是讓 GraphRAG 真正像 AST 的那個關鍵齒輪:它把上下文從「一堆材料」變成「最小充分證據包」,讓準確率、成本、可稽核性都能進入可工程化迭代的範圍。