ABEJA Tech Blog

中の人の興味のある情報を発信していきます

MicrosoftのGraphRAGを使ってみた

初めに

こんにちは、ABEJAでデータサイエンティストを務めている嘉藤です。今回はMicrosoftが発表した、GraphRAGを試してみました。GraphRAGは、テキストデータからLLMを用いてグラフ構造を生成し、生成されたグラフ構造を用いて質問応答を行うためのツールです。今回は、簡単にインデックスの作成から質問応答までを試してみました。

データ準備

対象のデータは今回使用するLLMであるGPT4o-miniが2023年10月までのデータで学習されたものであるため、それ以降に発売されたDLC藍の円盤に登場したポケモンの情報をwikipediaからスクレイプして使用しました。

環境準備

まずは公式のドキュメントに従って、GraphRAGをインストールし、./ragtest/inputにデータを配置します。

次にpython -m graphrag.index --init --root ./ragtestで環境の初期化を行い、.envファイルにOpenAIのAPIキーを記述します。Azure OpenAIを使用する際にはsetting.ymlファイルでapi_versionやdeployment_nameを追加で設定する必要があります。

GRAPHRAG_API_KEY="YOUR_KEY"

インデックスの作成

インデックスはpython -m graphrag.index --root ./ragtestのコマンドでinputに配置されているtxt形式またはcsv形式のファイルを元に作成されます。

通常のRAGではtxtファイルをsplitterで分割し、embeddingでベクトル化することでインデックスを作成しますが、前述の通り、GraphRAGではLLMを用いてグラフ構造を生成し、そのグラフ構造を用いて質問応答を行います。

大まかには以下のような流れでインデックスが作成されます。

  1. Compose Text Unit テキストデータを入力として受け取り、テキストデータを分割、合成し、それぞれのテキストデータを処理するための単位を生成する。
  2. Graph Extraction テキストデータからエンティティを抽出し、抽出されたエンティティ間の関係を抽出する。
  3. Graph Augmentation Leiden 階層クラスタリングとNode2vecを用いてグラフの特徴を抽出する。(デフォルトだとNode2vecは使用されないみたいです。)
  4. Community Summarization 前段で抽出されたコミュニティについて階層のレベルごとに要約を生成し、次にその要約を生成することでコミュニティレポート(コミュニティの内容を説明する文章)を作成する。
  5. Document Processing ドキュメントとText Unitの間の関係を抽出する。 詳細な説明はこちらにあります。

色々と書いてありますが、従来のRAGと比較して特に異なる点としては以下の二点が挙げらると思います。 - グラフ構造を利用することでエンティティ間の関係までモデル化されており、クエリにない情報でも関係性を頼りにコンテキストを探してくることができる。 - コミュニテレポートのような全体を俯瞰する文章が用意されていることで従来のRAGで苦手とされていたデータセット全体を参照するような質問にも回答ができる。

回答の生成方法

GraphRAGではLocal searchとGlobal searchの2つの検索方法があります。

Local searchはクエリに対して近いエンティティを検索し、そのエンティティに関連するText Unit、コミュニティレポート、他エンティティとの関係などから回答を生成します。Global searchはクエリに対して全体的な検索を行い、その結果からをコンテキストとして回答を生成します。

Global searchは通常のRAGが苦手としているデータセット全体を参照しなければ回答が難しい質問にも答えられるような検索方法で、クエリから近い任意のレベルのコミュニティレポートをコンテキストとして参照することで回答を生成します。

グラフの可視化

GraphRAGではsetting.ymlに以下のように設定することでoutput/timestamp/artifacts/以下に中間生成のグラフも含めて、graphml形式で生成したグラフを出力することができます。

snapshots:
  graphml: True
  raw_entities: false
  top_level_nodes: True

最終的に出力されたグラフが以下のようになります。

生成されたグラフ

サトシのエンティティ

グラフの一例としてサトシのエンティティを見てみると、typeがPERSONであることと、サトシの説明がdescriptionにあることがわかります。

サトシの詳細

Satoshi is a prominent character in the Pokémon anime series, known for his journey to become a Pokémon Master.
He is a skilled Pokémon trainer who captures and battles with various Pokémon throughout his adventures. 

リザードンのエンティティ

次にリザードンのエンティティを見てみると、typeがPOKEMONであって欲しいところ、PERSONになってしまっています。これはsetting.ymlでentity_typeとしてデフォルトで設定されているtypeが[organization,person,geo,event]の4つしかないことに起因します。entity_typeを追加する、もしくはプロンプトを直接編集することでentity_typeを追加することができます。(自動プロンプトチューニングという機能もあるみたいです)

リザードンの詳細

The entity "リザードン" is a powerful Pokémon that evolves from "リザード" and is known for its formidable capabilities. It is characterized by its ability to utilize various types of powerful attacks, including those associated with fire and flying. In its advanced form, "リザードン" can be seen as a strong contender in battles, often employing a range of techniques that showcase its versatility and strength. "リザードン" is depicted as a dragon-like creature that can take on different forms, including its Mega Evolutions, which enhance its abilities further. It is known to engage in battles using its fire-based attacks, and it has been involved in various competitive scenarios, demonstrating its prowess against other Pokémon. The creature is also recognized for its strategic use of moves, such as "かえんほうしゃ" (Flamethrower) and "いわなだれ" (Rock Slide), which allow it to adapt to different battle situations effectively. In summary, "リザードン" is a highly regarded Pokémon that embodies strength and adaptability, making it a popular choice among trainers and a formidable opponent in battles. Its evolution from "リザード" signifies its growth into a powerful entity capable of utilizing a diverse array of techniques to dominate in combat.
entity_extraction:
  ## llm: override the global llm settings for this task
  ## parallelization: override the global parallelization settings for this task
  ## async_mode: override the global async_mode settings for this task
  prompt: "prompts/entity_extraction.txt"
  entity_types: [organization,person,geo,event]
  max_gleanings: 1

回答してみる

2023年10月以降に発売された追加DLCにて新しく進化することができるようになったポケモンであるジュラルドンについて質問してみます。

GrapgRAGなし

比較のためにまずはGPT-4o-miniで「ジュラルドンの進化は?」というプロンプトを入れて出力を見てみます。

ジュラルドンは進化しないポケモンです。ジュラルドンは、ポケットモンスター ソード・シールドで登場した鋼・ドラゴンタイプのポケモンで、進化系や進化前の形態は存在しません。

GPT-4o-miniはジュラルドンの知識を持っていないことが確認できました!

Global search

Global searchはpython -m graphrag.query --root ./ragtest --method global "ジュラルドンの進化は?" のようなコマンドで質問を行うことができます。 回答は以下のようになりました。

SUCCESS: Global Search Response: 
## ジュラルドンの進化について

ジュラルドンは、ポケモンの中でも特異な存在であり、進化しないポケモンです。具体的には、ジュラルドンは他のポケモンから進化することもなく、また他のポケモンに進化することもありません。この特性により、ジュラルドンはポケモンの世界において独自の地位を持つことが強調されています [Data: Reports (4, 5, 6, 7, 8)]。

### 進化の関係

ジュラルドンは、進化しないポケモンである一方で、他のポケモンとの進化的な関係が存在します。例えば、ジュラルドンはダンゴロから進化することが知られており、この進化はジュラルドンの能力を向上させる重要な要素となっています [Data: Reports (0)]。ダンゴロからジュラルドンへの進化は、ポケモンの成長と戦略において重要な役割を果たします。

### 戦略的な意義

ジュラルドンの進化しない特性は、プレイヤーにとって戦略的な選択肢を提供します。進化しないことで、ジュラルドンはそのままの形で特定の能力を持ち続け、特にジムバトルなどの競技において有利に働くことができます。ジュラルドンの軽量な構造や特定の能力は、戦闘において重要な要素となります [Data: Reports (36)]。

### 結論

ジュラルドンは進化しないポケモンであり、その特性はポケモンの戦略や役割において重要な意味を持ちます。進化の過程を経ないことで、ジュラルドンは独自のアイデンティティを確立し、プレイヤーにとっての戦略的な選択肢を提供します。このように、ジュラルドンはポケモンの世界において特異な存在であり、その特性はゲームプレイにおいて重要な影響を与えます [Data: Reports (1, 2, 3, 4, 5)]。

Global searchでは全体的な検索を行うため、ジュラルドンという個別のポケモンについての正しいコンテキストを取得することができず、正しい回答を得ることができませんでした。

Local search

Local searchはpython -m graphrag.query --root ./ragtest --method global "ジュラルドンの進化は?" のようなコマンドで質問を行うことができます。 回答は以下のようになりました。

## ジュラルドンの進化について

ジュラルドンは、ドラゴン/はがねタイプのポケモンであり、進化することでブリジュラスになります。この進化は、特定のアイテム「ふくろうきん」を使用することによって実現します。ジュラルドンからブリジュラスへの進化は、ポケモンの育成や戦略において重要な要素となります。進化の過程では、プレイヤーはアイテムの管理や進化条件を考慮する必要があります [Data: Entities (258, 259); Relationships (803, 810)]。

## ジュラルドンの特徴

ジュラルドンは、体重が40.0 kgで高さが1.8 mのポケモンで、軽量な体型を持っています。この特性により、バトルにおいて機敏な動きをすることが可能です。また、ジュラルドンは「ジムリーダー」能力を持ち、特にジムバトルにおいてその性能を発揮します。さらに、ジュラルドンは「キョダイマックス」する能力も持っており、これにより強力な技を使用することができます [Data: Sources (29); Relationships (809)]。

## ブリジュラスの特徴

ブリジュラスは、ジュラルドンの進化形であり、体重は60.0 kgで高さは2.0 mです。ブリジュラスは、進化後に「エレクトロビーム」という専用技を使用することができ、特攻を上げた後に強力なビームを放つことが可能です。この技は、特にバトルにおいて大きな影響を与えることができます [Data: Entities (259); Relationships (812)]。

ジュラルドンからブリジュラスへの進化は、ポケモンの戦略や育成において重要な要素であり、プレイヤーはその特性を活かしてバトルを有利に進めることが求められます。

しっかりとジュラルドンの進化について回答が返ってきました!

少し難しい質問をしてみる

次に「ジュラルドンの進化後のポケモンの特徴」についてというプロンプトで質問してみます。 このプロンプトだと、通常のRAGで用いられるような単純なベクトル検索では「ジュラルドンの進化後の特徴」というプロンプトとベクトル的に近いインデックスを参照するため、ジュラルドンに関する情報を取得することはできるものの、その進化後のポケモンであるブリジュラスに関する情報まで得ることは難しいと考えられます。

ブリジュラスは、以下の特性を持っています:

- **ライトメタル**: ポケモンの重さを半分にする効果があります。
- **ヘヴィメタル**: ポケモンの重さを倍にする効果があります。
- **かくれ特性**: すじがねいりという特性を持ち、相手の技や特性の影響を無視することができます。

### 戦闘能力

ブリジュラスは、非常に頑丈な体を持ち、攻撃を受けても簡単には倒れません。特に、キョダイマックス形態に変化することができ、これによりさらに強力な技を使用することが可能です。キョダイマックス技「キョダイゲンスイ」は、相手の技のPPを減少させる効果があります。

### 生息地と行動

ブリジュラスは、山奥に生息し、両手の爪で山を削り取って食べる習性があります。また、同じ生息地に住むバンギラスとは縄張り争いをすることが多いです。

このように、ジュラルドンの進化後のブリジュラスは、特性や戦闘能力において非常にユニークなポケモンであり、プレイヤーにとって魅力的な選択肢となっています [Data: Sources (15), Relationships (565)].

うまくブリジュラスの特徴の情報まで取得することができました。

参照した情報は以下の通りになっています。 relationshipsからはジュラルドンが進化後にブリジュラスになること、relationshipsに紐づけられたentities、text_unitsからブリジュラスの詳しい特徴が取得できていることがわかります。

[{'id': '68762e6f0d1c41cd857c6b964a8e76c3',
  'name': 'ジュラルドン',
  'type': 'キャラクター',
  'description': 'ジュラルドンは、ポケモンNo. 0884であり、ごうきんポケモンに分類される。はがねとドラゴンのタイプを持ち、高さ1.8m、重さ40.0kgである。',
  'human_readable_id': 178,
  'graph_embedding': None,
  'text_unit_ids': array(['608d253970bf6a3e3ef3a7419f1c4755'], dtype=object),
  'description_embedding': array([0.02497506, 0.01680369, 0.02093128, ..., 0.01885701, 0.03737877,
         0.01585036])},
 {'id': '70634e10a5e845aa8c6a32fe7e8eb2b2',
  'name': 'ブリジュラス',
  'type': 'キャラクター',
  'description': 'ブリジュラスはジュラルドンの進化後の形態であり、次回作の追加コンテンツで進化できるようになった。',
  'human_readable_id': 179,
  'graph_embedding': None,
  'text_unit_ids': array(['608d253970bf6a3e3ef3a7419f1c4755'], dtype=object),
  'description_embedding': array([ 0.03532511,  0.03118643,  0.03287952, ...,  0.01355523,
          0.02874084, -0.00295508])}]
{'source': 'ジュラルドン',
 'target': 'ブリジュラス',
 'weight': 1.0,
 'description': 'ジュラルドンは進化後にブリジュラスになる。',
 'text_unit_ids': array(['608d253970bf6a3e3ef3a7419f1c4755'], dtype=object),
 'id': 'a6b9881f3fa04c87b336dec3f310a499',
 'human_readable_id': '565',
 'source_degree': 12,
 'target_degree': 1,
 'rank': 13}
[{'id': '608d253970bf6a3e3ef3a7419f1c4755',
  'text': '\nジュラルドン No. 0884\n\n\n分類: ごうきんポケモン\n\nタイプ: はがね/ ドラゴン\n\n高さ: 1.8m\n\n重さ: 40.0kg\n\n\n特性: ライトメタル/ ヘヴィメタル\n\nかくれ特性: すじがねいり\n\n進化前: なし\n\n進化後: ブリジュラス\nジュラルミンの体を持つ恐竜のようなポケモン。重そうな見た目でありながら体重は意外と軽く、そのため見た目に反して機敏な動きをする。鏡面加工のように滑らかでちょっとの攻撃では傷つかない頑丈さを持つが、一方で錆びやすい弱点があり、故に雨が苦手。また、熱がこもりやすいため尻尾のスリットから放熱する。山奥に住んでおり、両手の爪で山を削り取って食べる。同じ生息地に住むバンギラスとはよく縄張り争いをしており、しばしば争っている[27]。\nかくれ特性の「すじがねいり」は「スクリューおびれ」と同じく相手の技を引き受ける技(「このゆびとまれ」や「いかりのこな」など)や特性(「ひらいしん」や「よびみず」など)の影響を無視する。\nゲーム本編では「ソード・シールド」でジムリーダーのキバナがエースポケモンとして使用し、キョダイマックスさせてくる。「スカーレット・バイオレット」ではアカデミー教師で四天王のハッサクが使用する。\n次回作である『スカーレット・バイオレット』の追加コンテンツ「ゼロの秘宝 後編・藍の円盤」ではブリジュラスに進化できるようになった。\nテレビアニメ第7シリーズ(『新無印編』)ではゲームと同様にジムリーダーのキバナのポケモンとして第27話から登場し、キョダイマックスも披露している。声優はサクラギ博士役の中村悠一が担当。\nキョダイマックスのすがた\n高さ43.0m以上。重さ不明。胴体に窓ガラスのような模様がつき、ビルのようになっている。摩天楼の如く巨大化した姿で、溢れるエネルギーで体の一部が航空障害灯のように赤く発光している。細胞の硬度ははがねタイプの中でもトップクラスで、地震にも強い。(ただし地面技の「じしん」は弱点攻撃である)ドラゴンタイプの技が専用キョダイマックス技「キョダイゲンスイ」になり、攻撃後に相手が直前に出した技のPPを1減らす。\nまた、ブリジュラスの登場によりピカチュウ・ニャース・イーブイを除く、唯一のキョダイマックスが可能な進化前ポケモンとなった。\nテレビアニメ第7シリーズ(『新無印編』)ではゲームと同様にジムリーダーのキバナのポケモンとして第27話から登場。他にも第71話から第135話までのエンディング映像のラストのみで登場。',
  'n_tokens': 1122.0,
  'document_ids': array(['12f3ad0b8e67bad041dd0df2652ea0b7'], dtype=object),
  'entity_ids': array(['e69dc259edb944ea9ea41264b9fcfe59',
         '68762e6f0d1c41cd857c6b964a8e76c3',
         '70634e10a5e845aa8c6a32fe7e8eb2b2',
         '04085f7cf46544b79597fc49286ff84d',
         'd203efdbfb2f4b2a899abfb31cf72e82',
         '6731a665561840c2898ce8c9788e4c88',
         '4026806fa92f4e849a59a7f5c9a45c79',
         '68e0c60d2e8845d89d9d0ad397833648',
         '101572f552b54e529fe7765c05168981',
         '60c58026b2764b40adffca6eaa31d6d9',
         'ad1595a78935472999444c9330e7730e',
         '735d19aea0744b2295556841c5c4c3fd',
         'c725babdb14a485582f8fbdf95429030'], dtype=object),
  'relationship_ids': array(['9397185bb4d7492b88eaa20fa10c0ae5',
         'a6b9881f3fa04c87b336dec3f310a499',
         '93a8d868d1144b78ba3ff6afef7bb0b0',
         '4e0732ec06084e24be340438b0ccac57',
         '22e88c70f00646c0af4d146f3744597d',
         'b9f05ce67dbb422999aa6ae12441b698',
         '595c1aba61704a64a4eb34edf81faab4',
         '1fc84b6246c8424696b9ee118323066e',
         '8a7ad98304a747f4b32748ea76fbc85c',
         '6df8d88308214890b6a6dd5c3bdfdf8a',
         'd63c24dc1cc44520aa78b3e91c04343c',
         'eee1e9b4ebb44e41b30068039c5cd32b'], dtype=object)}]

まとめ

RAGシステムは今や様々な場面で利用されるようになってきている一方で、ただ導入すればうまくいくようなものではなく、データセットに合わせた設定やプロンプトの調整が必要になります。 GraphRAGは従来のRAGと比較してグラフ構造を利用することでエンティティ間の関係までモデル化されており、クエリにない情報でも関係性を頼りにコンテキストを探してくることができるという特徴がありますが、今回の結果からGraphRAGにおいても従来のRAGと同様に、データセットに合わせた設定やプロンプトの調整が必要になることがわかりました。今後はGraphRAGを用いて、より複雑な質問にも回答できるようにプロンプトチューニングやよりカスタムした設定についても調べてみる予定です。