CCCMKホールディングス TECH LABの Tech Blog

TECH LABのエンジニアが技術情報を発信しています

ブログタイトル

Microsoft GraphRAGの仕組みとPrompt Tuning, Knowledge Graphの可視化までの手順をまとめてみました。

こんにちは、CCCMKホールディングスAIエンジニアの三浦です。

最近AIに参照させるデータの持ち方としてKnowledge Graphについて調べていました。AIに参照させるデータの持たせ方ではVector DBがよく使われていると思うのですが、ドキュメントをDBに取り込む際に分割(Chunking)をするとデータの持つつながりが失われてしまいます。これによってよく問題になるのが物事の前後関係がうまく説明できなくなる、ということです。

たとえば「私は今日スーパーに行って、ドラッグストアに立ち寄って、駅に向かいました。」という文章があったとして、「私は今日スーパーに行って」、「ドラッグストアに立ち寄って」、「駅に向かいました」といった感じにChunkを生成したとします(こんなに短いChunkは実際には作らないと思いますが)。こうなってしまうとそれぞれのChunkの前後関係が分からなくなってしまうので、たとえば「今日私のしたことは?」といった質問に「駅に行って、スーパーに行って、ドラッグストアに行きました。」といったような回答をAIがしてしまう可能性が出てしまうのです。

これを解決するには「スーパー」から「ドラッグストア」に向かい、「ドラッグストア」から「駅」に向かったといったような文章の中の登場人物(Entity/Node)とその関係性(Relationship/Edge)を保持する必要があります。これを解決するのに役立ちそうなのが知識のグラフ表現"Knowledge Graph"です。

文章からKnowledge Graphを構築する方法は色々あります。経験に基づくものや機械学習を活用するものなどがありますが、文章の中にどんなEntityがあって、それらの間にどのようなRelationshipがあるのかをLLMを使って自動的に抽出するアプローチもあります。

LLMを使ってKnowledge Graphを自動的に構築し、さらにLLMを利用してKnowledge Graphから情報を検索するアプローチがMicrosoftのGraphRAGです。

github.com

GraphRAGでどのようにKnowledge Graphを構築し、情報を検索しているのかは以下の論文で説明されています。

Title: From Local to Global: A Graph RAG Approach to Query-Focused Summarization
Authors: Darren Edge, Ha Trinh, Newman Cheng, Joshua Bradley, Alex Chao, Apurva Mody, Steven Truitt, Dasha Metropolitansky, Robert Osazuwa Ness, Jonathan Larson
Submitted: 24 Apr 2024 (v1), last revised 19 Feb 2025
arXiv: https://arxiv.org/abs/2404.16130

今回の記事では、この論文の内容からGraphRAGでどのようにKnowledge Graphを構築し、情報検索を実現しているのかを振り返り、GraphRAGの基本的な使い方から内部で実行されるPromptのチューニング方法についてまとめます。さらに構築したKnowledge Graphを描画する方法まで触れていこうと思います。

GraphRAGの動作の仕組み

GraphRAGでKnowledge Graphの構築(Indexing)から情報検索(Query)までの一連の流れ(Pipeline)について、先述したGraphRAGの論文の中では以下の図で表現されています。

【引用元】From Local to Global: A Graph RAG Approach to Query-Focused Summarization, Figure 1

それぞれどのような処理が行われるのか、以下簡単にまとめていきます。

Entity/Relationshipの抽出

GraphRAGでは与えられたテキストデータを事前に設定されたサイズのChunkに分割します。その後、それぞれのChunkごとに含まれるEntityとRelationship、各Entityを説明するClaimをLLMを使って抽出します。

Knowledge Graphの構築

Chunkごとに抽出されたEntity, Relationshipはその後Entityの名前を元に集約されます。その際にRelationshipやEntityに与えられたClaimもLLMによって要約されます。複数回発生したRelationshipはGraph構築時のEntity間のつながりの強さを示す重み(Weight)として扱われます。

Communityの生成とReportの生成

Graphの中で特につながりが強いNodeの集まりをCommunity(集団)として抽出します。Communityの生成は階層的に実行され、大きいCommunityをさらに細かいCommunityに分割していきます。

Community生成後、各Communityに所属するNode(Entity), Edge(Relationship), Claimの情報を元にLLMに各Communityの要約Reportを生成させます。

このReportはKnowledge Graphから情報を検索するQuery Timeで使用されます。

ここまでがKnowledge Graph構築時に実行される処理の流れです。

Community Reportを使った情報の検索

ここからは情報を検索する際に実行される処理です。あらかじめ設定された階層のCommunity Reportを用いて情報の検索が行われます。

最初にCommunity ReportのChunkingが行われ、情報が偏ることを防ぐためシャッフルを行います。その後設定されたToken Sizeに収まるように塊(Batch)にまとめられ、Batchごとに入力Queryに対する回答が生成されます。

次に各Batchごとに生成された回答をLLMに評価させ、評価スコアが低い回答は除外します。最後に評価を通過した回答を集約してQueryに対する最終的な回答を生成します。

・・・というような流れでGraphRAGでは情報の検索が実行されます。

GraphRAGでKnowledge Graphを生成してみる

ここからはGraphRAGを使って実際にKnowledge Graphを生成する手順をまとめていきます。

まずはGraphRAGのインストールです。

pip install graphrag

GraphRAGは専用のWorkspaceを用意し、その中に必要なファイルを格納したり結果を出力したりします。最初にこのWorkspaceを以下のように用意します。

import os
os.system(f'mkdir {ws_dir}')
os.system(f"graphrag init --root {ws_dir}")

するとWorkspace用のディレクトリ配下に以下のようなディレクトリやファイルが生成されます。

ws_dir/
├── cache/
├── input/
├── logs/
├── output/
├── prompts/
├── .env
└── settings.yaml

"input"ディレクトリの中に取り込むドキュメントファイルを格納します。対応している形式は"txt", "csv", "json"です。

microsoft.github.io

私は今回Azure OpenAIのモデルを使用しました。そのために、まず".env"ファイルを開き、Azure OpenAIのAPIキーを記入します。

GRAPHRAG_API_KEY={API key}

"settings.yaml"には様々な設定値がありますが、"models"の項目を正しい値に設定すれば動作させることは可能です。Azure OpenAIを使う場合は以下のように使用するChat ModelとEmbedding Modelを設定します。

models:
  default_chat_model:
    type: azure_openai_chat
    model_provider: openai
    api_base: {API Endpoint}  # Azure OpenAIのAPIエンドポイント
    api_version: 2025-01-01-preview # API version
    deployment_name: gpt-4.1-mini # 使用するModel
    model: gpt-4.1-mini # 使用するModel
    ...
  default_embedding_model:
    type: azure_openai_embedding
    model_provider: openai
    api_base: {API Endpoint}  # Azure OpenAIのAPIエンドポイント
    api_version: 2025-01-01-preview # API version
    deployment_name: text-embedding-3-small # 使用するModel
    model: text-embedding-3-small # 使用するModel
    auth_type: api_key
    api_key: ${GRAPHRAG_API_KEY}
    ...

以上で準備は完了です。次のようにKnowledge Graphの構築を開始します。

os.system(f"graphrag index --root {ws_dir}")

正常に実行が完了すると、"output"ディレクトリの中に複数のparquet形式のファイルが生成されます。

Knowledge Graphから情報を検索するにはPythonのクライアントを使用することが出来ます。ここでは以前私が書いたこちらの記事を使って構築したKnowledge Graphを参照させています。

techblog.cccmkhd.co.jp

import graphrag.api as api
from graphrag.config.load_config import load_config
import pandas as pd

graphrag_config = load_config(Path(pj_dir))

entities = pd.read_parquet(f"{ws_dir}/output/entities.parquet")
communities = pd.read_parquet(f"{ws_dir}/output/communities.parquet")
community_reports = pd.read_parquet(
    f"{ws_dir}/output/community_reports.parquet"
)

response, context = await api.global_search(
    config=graphrag_config,
    entities=entities,
    communities=communities,
    community_reports=community_reports,
    community_level=2,
    dynamic_community_selection=False,
    response_type="single paragraph", # 出力する形式を指定可能
    query="今年のDATA AI Summitのスケジュールはどんな感じでしたか?",
)

print(response)

結果です。

'今年のData + AI Summit 2025は、Databricksが主催する年次イベントで、データ、AI、機械学習をテーマに多様なセッションや新機能発表が行われる重要な技術情報の発信源として機能しています。キーノートセッションや新機能発表がスケジュールの中心となっており、これらが参加者の知識獲得やネットワーキングに直結しています。イベントはアメリカ・サンフランシスコのMoscone Centerで開催され、開催地の街中や最寄りのPowell St.駅ではDatabricksの広告が展開され、参加者の動線や関心を高める工夫がなされています。こうした物理的な開催場所の選定は、イベントの規模や参加者数、展示内容の充実度に影響を与え、現地でのネットワーキングやリアルイベントの開催がオンラインコミュニティの活性化にも寄与していると考えられます。なお、具体的な日程や時間割の詳細は提供されていませんが、データ、AI、機械学習に関する多様なセッションがクラスター化され、参加者の専門性や興味に基づく交流が促進されていることが示唆されています。今後は参加者の交流パターンや情報拡散経路の詳細分析が推奨されており、イベントは技術トレンドや製品アップデートの主要なハブとしてコミュニティ内での知識共有や技術交流の核となっています[Data: Reports (5, 9, 34, 46, 64, +more)]。'

Knowledge Graphを生成時に使用するPromptのTuning

何回かデフォルトの設定でGraphを生成していると、時々日本語の文章にも関わらず抽出されるEntityが英語表記になってしまうことがありました。GraphRAGでKnowledge Graphを生成する際にはLLMを利用しているのですが、そこで使用されるPrompt Templateが英語の一般的な文章を想定した内容になっていることが要因として考えられます。

GraphRAGには内部で使用するPrompt Templateを自動Tuningする機能が備わっています。これを利用すると、例えば言語やドキュメントが属するドメインなどを考慮したPrompt Templateを生成することが出来ます。

自動Tuningについての情報はこちらのドキュメントに掲載されています。

microsoft.github.io

たとえば言語が日本語でドキュメントがブログであれば、以下のように指定することが出来ます。この中で--selection-method auto --k 3のオプションは、ドキュメントのサイズが比較的小さい時を想定したものです。Prompt Tuningをする際にChunkからサンプリングする処理があるようなのですが、その際デフォルトで15個のサンプルを取得する動きになっているようです。そしてChunk数の総数が15個以上ないとサンプリング時にエラーが発生してしまいます。それを防ぐためサンプルの取得数を手動で設定しています。

import os
os.system(f'python -m graphrag prompt-tune --root {pj_dir} --config {pj_dir}/settings.yaml --language Japanese --selection-method auto --k 3 --domain "tech blog of japanese company"')

コマンドを実行したディレクトリ内に"prompts"というディレクトリが生成され、その中に"community_report_graph.txt", "extract_graph.txt", "summarize_descriptions.txt"の3つのPrompt Templateが生成されます。

このPrompt Templateを使用するにはWorkspace内の"prompts"ディレクトリに最初から含まれている同名ファイルを上書きするか、"settings.yaml"の以下の項目で使用するTemplateを指定します。

extract_graph:
  model_id: default_chat_model
  prompt: "../prompts/extract_graph.txt"
  entity_types: [organization,person,geo,event]
  max_gleanings: 1
...
summarize_descriptions:
  model_id: default_chat_model
  prompt: "../prompts/summarize_descriptions.txt"
  max_length: 500
...
community_reports:
  model_id: default_chat_model
  graph_prompt: "../prompts/community_report_graph.txt"
  text_prompt: "prompts/community_report_text.txt"
  max_length: 2000
  max_input_length: 8000
...

Knowledge Graphの可視化

生成したKnowledge Graphを可視化する方法をご紹介します。"Pyvis"というNetwork Graphを表示するライブラリを使った方法です。

pyvis.readthedocs.io

ライブラリのインストールをします。

pip install pyvis

"output"ディレクトリの中に出力された"relationships.parquet"というファイルにKnowledge Graphに含まれるEntity, Relationship, weightといったGraph表示に必要な情報が格納されています。最初にこのファイルを読み込みます。

import pandas as pd

node_edge = pd.read_parquet(f"{ws_dir}/output/relationships.parquet")
node_edge = node_edge[["source","target","description","weight"]]

これをGraphとして取り込みます。ドキュメントによってはEntityの数が膨大になり、Graph描画が重たくなってしまうので、"weight"が小さいEntityとRelationshipは表示しないようにします。

import networkx as nx
from pyvis.network import Network

G = nx.DiGraph()

for i, row in node_edge_spark_ja_df.iterrows():
  if row['weight'] <= 1:
    # weightが小さいものは表示しない
    continue
  G.add_edge(
    row['source'], 
    row['target'], 
    label=row['description_ja'],
  )

net_g = Network(
    height="750px", 
    width="100%", 
    directed=True
)
net_g.from_nx(G)

Graphのデザインを変更します。

for node in net_g.nodes:
    node['title'] = node['id'] # マウスホバーで表示されるテキストを設定
    node['size'] = 15

GraphをHTMLファイルに出力します。表示を調整できるコントロール機能を.show_buttons(filter_=['physics'])を呼び出して追加することが出来ます。

net_g.show_buttons(filter_=['physics'])
net_g.save_graph("graphrag_knowledge_graph.html")

生成されたHTMLファイルをブラウザで開くとGraphを見ることが出来ます。たとえばこちらの記事の内容を可視化すると以下のようになります。

Knowledge Graphの描画

まとめ

ということで今回はMicrosoftのGraphRAGについて、動作の仕組みと使い方、生成されたGraphの表示方法まで一通りまとめてみました。自分が書いたブログをKnowledge Graphにしてみたりしたのですが、自分の知識の整理にとても役立ちそうだな、と感じました。今回まとめた手順で様々なドキュメントがKnowledge Graphで表現できると思います。ぜひ試してみてください。