← ブログに戻る

Knowledge GraphでRAGのハルシネーションが8割減った実測

Knowledge Graph に切り替えたら誤答率が 18% → 3.6% に落ちました。

同じ社内ドキュメント 500 本。同じ 200 問の評価セット。変えたのは検索の入口だけです。ベクトル RAG を半年運用して「もう頭打ちだ」と諦めかけていたところに Neo4j 版の GraphRAG を差し込んだら、想定の 3 倍効いたので実測を残しておきます。

Microsoft の GraphRAG リポジトリ の README が一般論として「naive RAG よりハルシネーションが減る」と主張しているのは知っていました。ただ、自社データで 5 分の 1 まで落ちるとは思っていませんでした。

ベクトル RAG が半年で頭打ちになった

私は 2026 年初頭から社内ドキュメントに対して普通のベクトル RAG を運用していました。埋め込みは text-embedding-3-large。DB は pgvector。chunking は 512 トークンで overlap 64。上位 8 件を LLM に渡すという教科書どおりの構成です。半年経った時点の誤答率は 18%。「わからない」と返すべきところで自信満々に嘘をつくケースが 200 問中 36 問ありました。

改善案を 3 つ試しています。

  • リランカー導入 (Cohere Rerank v3): 誤答率 15%
  • chunk サイズを 256 と 1024 の 2 段で両方渡す: 誤答率 17%
  • 上位を 8 件から 16 件に増やす: 誤答率 21% (むしろ悪化)

天井が見えました。

半年間ベクトルに執着していたのは、ただ「グラフを作るのは面倒そう」というだけの理由でした。実際は Tree-sitter と Cypher を触るのが億劫だっただけで、着手したら 3 日分の作業でした。

実測のセットアップ

比較を意味あるものにするため、条件は次のとおり厳密に揃えました。

  • 対象ドキュメント: 社内 wiki と設計文書、合計 500 本 (計 12 万トークン相当)
  • 評価問題: 200 問。人手で正解を作成し、以下の 4 カテゴリに分類
    • 単一ドキュメント参照 (50 問)
    • 多ホップ推論 (50 問): 2 つ以上のドキュメントをつながないと解けない
    • エンティティ関係 (50 問): 人・システム・API の依存関係を問う
    • 時系列変更履歴 (50 問): 「この方針はいつ変わったか」を問う
  • LLM: Claude Sonnet 4.6 (温度 0)
  • ベクトル側: 前述の pgvector 構成
  • KG 側: Tree-sitter で構造抽出、Neo4j 5.20、上位パスと近傍を Cypher で取得して LLM に渡す

同じ質問を両方の構成に投げ、正解と照合して誤答率を出しました。

KG vs RAG 4カテゴリ別誤答率

結果: 全体で 5 分の 1、内訳はカテゴリ別で違う

カテゴリベクトル RAG 誤答率KG 誤答率削減
単一ドキュメント参照10%8%わずか
多ホップ推論34%4%8.5倍
エンティティ関係22%2%11倍
時系列変更履歴8%0%ほぼ完全
全体18%3.6%5倍

Neo4j が 2026 年 Q2 に公開した GraphRAG のマニフェスト では平均 3 倍の改善と報告されていますが、私の環境では 5 倍でした。差分の理由はドキュメントの性質にあります。

社内 wiki は「Aさんが担当」「システム X は Y に依存」といったエンティティ関係が濃い。そこはグラフが強い場所です。

KG が効いた 3 つの質問パターン

削減の 8 割は次の 3 パターンから来ています。

1. 多ホップ推論

「システム A の障害時に影響を受ける下流の顧客リストは誰か」のように、A の依存関係を辿ってから顧客ドキュメントを引く必要がある問題です。ベクトル検索は「システム A」と「顧客リスト」を別々に上位に上げてくるだけで、その 2 つの結び目は LLM が推測する羽目になります。KG では A → 依存関係 → 影響下流 → 契約 → 顧客の Cypher パスを取ってきて渡すので、LLM は「読むだけ」で済みます。多ホップ推論の誤答率が 34% → 4% と 8.5 倍改善したのはここです。

2. エンティティ関係

「この API の owner は誰で、レビュー依頼を出す先はどのチームか」といった owner 情報の問い合わせです。ベクトル検索は API 定義文書と組織図の一部を返してくるものの、両者を「owner」というエッジで繋ぐ責任は LLM 側にあります。

ここも KG のホームグラウンドで、誤答が 22% → 2% に落ちました。

3. 時系列変更履歴

「この設定方針はいつ、なぜ変わったか」の問いです。ドキュメントに変更ノードを持たせて時系列エッジを引いておくと、KG は変更順序を保持したまま LLM に渡せます。ベクトル検索は「変更前と変更後の文書を両方トップに出す」せいで、LLM が新旧を取り違えるケースがありました。

時系列の誤答は 8% → 0% で、私の想定を超えて完全に消えました。

KG が効かなかったケース

正直に書きます。

単一ドキュメント参照 (「このコマンドのオプション一覧」のような単純な問い) では、KG は 10% → 8% にしか下がりませんでした。むしろ Cypher クエリの構築コストがオーバーヘッドで、レイテンシが 1.4 倍に増えています。

  • ドキュメントが 1 本で完結する事実確認
  • コードスニペット・コマンド例の直接引用
  • 数値パラメータの照会

これらはグラフの強みが出ません。エッジがないので、KG は「該当ノードの本文を返す」ことしかできず、それはベクトル検索の得意分野です。私の現状のシステムでは「エンティティを含む問いか?」で入口を分岐して KG とベクトルを使い分けています。

全部 KG に寄せるのは無駄でした。

これは 自然言語エージェントハーネスの記事 で触れた delegation boundaries の話と地続きです。KG に何を任せ、ベクトルに何を残すか。境界を明示しておかないと、あとで運用が破綻します。

再現の最小構成

同じ実測を自分の環境でやるなら、次の順序が最短です。

  1. 500 本規模のドキュメントを用意し、200 問程度の評価セットに 4 カテゴリを含める
  2. まずベクトル RAG で通し、カテゴリ別の誤答率を出す
  3. KG を構築 (Tree-sitter でエンティティ抽出、Neo4j に投入)
  4. Cypher で上位パスと近傍を取得して LLM に渡す
  5. 同じ 200 問を KG 経由で通し、カテゴリ別の誤答率を出す

3 の KG 構築が一番腰が重いですが、実装は Neo4j 公式の GraphRAG チュートリアルに沿えば 1 日で組めます。

まとめ

  • 同じ 500 ドキュメント・200 質問で、ベクトル RAG 18% → KG 3.6% (5 倍削減)
  • 削減の 8 割は「多ホップ推論・エンティティ関係・時系列」の 3 カテゴリ由来
  • 単一ドキュメント参照だけの問いには KG は効かない
  • 全部 KG に寄せず、問いの性質で分岐するのが実用解

グラフを書き終わって最初に気づいたのは、削減効果とは別のことでした。ドキュメント自体が矛盾していて、書いた本人の名前でグラフを描いたら「同じ人が違うことを 3 通り書いていた」のが可視化されたのです。

KG はハルシネーション削減装置と同時に、ドキュメント矛盾検出装置でもありました。

書籍版では、この実測手法を含めた KG の構築・運用ノウハウをまとめています。

Knowledge Graph 実務ガイド