Essential GraphRAGを読んだ

· takatori
GraphRAGRAGNeo4j知識グラフLLM

Essential GraphRAG

Essential GraphRAGという本を実装しながら読んだので、学んだ内容をまとめた。 実装したコードは以下においてある。本ではOpenAIのAPIを使用していたが、コストをかけたくなかったのでOllamaで実装してみた。

https://github.com/takatori/essential-graph-rag

章ごとの紹介

ここからは章ごとに本から学んだことをまとめている。

1章

1章は導入的な内容で、知識カットオフ問題やハルシネーション等のLLMの限界について。それらを克服するための、従来のRAGについての紹介。従来のベクトル検索を用いたRAGは主に非構造化データを対象としており、知識グラフを使うことで、構造化データと非構造化データを統合し、RAGの性能を向上させることができる。

2章

2章は、通常のベクトルRAGを実装していくパート ベクトルインデックスと全文検索のハイブリット検索をNeo4jで実装していく。 Neo4jのデータベース上にベクトルインデックスと全文検索用のインデックスを構築し、それぞれで検索。 高い方のスコアを返すシンプルな実装する。

Neo4jだけでハイブリッド検索を実現できるのは、簡単に使えて便利そう。

3章

3章はベクトルRAGの検索精度を上げる手法の紹介。

ユーザのクエリから直接生成される埋め込みは、用語や文脈の違いにより文書の埋め込みと必ずとも一致しない可能性がある。クエリの書き換えドキュメントの埋め込み戦略の変更によってユーザのクエリとドキュメントの間のギャップを埋め、検索精度を向上させることができる。

クエリの書き換えとして、以下ような手法がある。

また、ドキュメントの埋め込み戦略として、例えば、以下のような手法がある。

この章の内容はGraphDBを使わなくても実現できるが、親文書とチャンクをグラフに保存しておけば、チャンク同士の類似度などから関連ドキュメントの取得などもできそうだなと思った。

4章

4章は自然言語の質問からCypherクエリを生成する手法の紹介。

クエリの言語生成は、ベクトル検索だけでは回答できない、何らかの集計が必要な場合やグラフから特定のデータを取得したい場合などに有効。

自然言語による質問からCypherクエリを生成するワークフローは以下のようになっている。

  1. ユーザからの質問を取得する
  2. 知識グラフのスキーマを取得する
  3. 用語のマッピング、フォーマットの指示、few-shot exampleなど、そのほかの有用な情報を定義する
  4. LLMのプロンプトを生成する
  5. プロンプトをLLMに私、Cypherクエリを生成する

また、適切なCpyherクエリを生成するために有用なプラクティスが紹介されていた。

CypherではなくSQLなどを生成する場合にも同じワークフローやテクニックが有効だと思われる。

5章

5章ではエージェント型のRAGを構築する。

エージェントRAGは、ユーザーの質問に答えるため、さまざまな検索ツール(エージェント)を使い分けることができるシステム。

エージェントRAGが必要なのは、さまざまなデータソースがあり、最適なデータソースを業務に使用したい場合や、データソースが非常に広範であったり複雑で必要なデータを取得するために専門的な検索が必要な場合。

エージェントRAGには以下のコンポーネントが必要になる。

6章

6章では知識グラフの構築方法を学ぶ。

知識グラフの構築フローは以下。

  1. LLMでデータから構造化情報を抽出
  2. 抽出した情報をグラフにインポート
  3. エンティティの解決

LLMでデータから構造化情報を抽出

LLM以前にもデータから情報抽出は行われていたが、高いコストと技術的な障壁により簡単ではなかった。 LLMは非構造化テキストから構造化されたデータを抽出し、使用可能な形式に変換するのに効果的であり、簡単にデータ抽出できるようになった。 OpenAIのAPIで提供されているStructred Outputs機能を使うことで、Pydanticのようなライブラリで定義したデータスキーマに従ってモデルの応答を出力させることができる。

抽出した情報をグラフにインポート

抽出したデータをグラフにインポートする際、クエリの完全性の保証およびパフォーマンス向上のために、可能な限りの制約とインデックスを定義しておく。

エンティティの解決

インポート後にエンティティの解決し、データ一貫性と精度を向上させる必要がある。 エンティティ解決とは、同じ実世界のエンティティの異なる表現を特定し、統語するプロセス。大規模なデータセットの場合、スペルのバリエーション、異なる命名規則、データ形式のわずかな不一致のような矛盾のために、同じエンティティが複数の形で現れることが一般的。 エンティティ解決のための技術としては、文字列マッチング、クラスタリングアルゴリズム、機械学習による手法などがあるが、ユースケースやドメインに大きく依存する。

7章

7章ではMircosoftのGraphRAG(Edge et al., 2024) を実装する。

この論文では従来のベクトルRAGの問題点を克服するためにGraphRAGを提案している。 従来のベクトルRAGでは「過去10年間で、科学的発見は学際的研究からどのような影響を受けてきたか、その主要な傾向は何か?」といった、データセット全体の包括的な理解を必要とするクエリには対応できない。

GraphRAGでは、知識グラフを使ってこの問題に対処する。具体的には、まず、元のドキュメントからエンティティとリレーションシップを抽出し知識グラフを構築する。次に、知識グラフからコミュニティを検出し、コミュニティの要約を生成する。検索時には、各コミュニティの要約を使って中間の回答を生成し、最終的にそれらをまとめてグローバルな回答をユーザに返す。

Graph RAGの詳細なステップは以下になる。

インデックス時

インデックス構築は大きく分けて2段階で行われる。 第一段階では知識グラフを構築する。第二段階では構築した知識グラフ上でコミュニティを検出し、各コミュニティの要約を生成する。

第一段階
第二段階

検索時

グローバルな検索とローカルな検索の両方に対応できる。

グローバルな検索は、関連性の高い情報を検索するためにグラフ全体を考慮する。 具体的には、中間応答としてコミュニティの要約を使用する。 グローバルな検索では以下の2つのステップを踏む。

ローカル検索は、特定のエンティティに焦点を当てたクエリに有効。 ローカル検索では、ユーザがクエリを入力すると、まず、ベクトル検索で最も意味的に関連するエンティティを特定する。 つぎに、特定されたエンティティに関連する情報を知識グラフから取得する。 これには、テキストチャンク、リレーションシップ、接続されているエンティティ、関連するコミュニティの要約を含む。 これらの情報を関連度の高い順にランキングし、コンテキストウィンドウに収まるようにフィルタリングする。 最後に、LLMが最終的な応答を生成する。

8章

8章はRAGアプリケーションの評価について。 この章では5章で実装した、エージェント型RAGを評価していく。

RAGパイプラインでの各ステップで評価するポイント

ベンチマークデータセットの設計

以下のようなさまざまな側面をテストする入力クエリを設計する必要がある。

評価指標

ここでは、RAGASを使って評価する方法を紹介している。 RAGASを含めたLLMの評価指標については、LLMの精度ってどう測るの?評価指標を調べてみたの方が参考になる。

合わせて読んだ本

まとめ

Essential GraphRAGを読んで学んだことをまとめた。実際に手を動かすことでかなり理解が進んだ。 ベクトル検索だけでは対応できないクエリでは、グラフを活用することで対処できることを学んだ。 さらなる発展はナレッジグラフを活用するGraphRAGを俯瞰するに詳しくまとまっていそうなので、参考にしたい。 また、Graph Neural Networkも学ぶ必要がありそうなので、Graph Neural Networks in Actionも気になっている。