HN公開: FastGraphRAG – 従来のPageRankを活用した改良版RAG技術
(github.com/circlemind-ai)- Fast GraphRAGは、解釈可能で高精度なエージェントベース検索ワークフローのための簡素化されたGraphRAGフレームワークで、複雑なエージェントワークフローを直接構築せずに高度なRAGを検索パイプラインへ組み込むことに重点を置いている
- ナレッジグラフを人が探索可能な形にし、クエリ・可視化・更新を可能にするとともに、ドメインやオントロジー要件に合わせてグラフを自動生成・洗練する
- クエリ応答にはpersonalized PageRankベースのグラフ探索を使って関連情報を見つけ、READMEではこのアプローチの概要としてHippoRAG論文を案内している
- コスト例では The Wizard of Oz を基準に
fast-graphragは $0.08、graphragは $0.48 とされ、データサイズと挿入回数が増えるほど6倍のコスト削減はさらに改善するとしている - Python 3.10.1 以上で動作し、ソースからのインストールとPyPIインストールをサポートし、OpenAI APIキー設定後に文書の挿入とクエリを実行でき、同じ作業ディレクトリで知識を自動的に保持する
Fast GraphRAGが提供する検索フレームワーク
- Fast GraphRAGは、解釈可能でデバッグ可能な知識を目指すGraphRAGフレームワークである
- グラフは知識を人が探索できる形で提供し、次の作業をサポートする
- クエリ
- 可視化
- 更新
- 高度なRAG機能を提供しつつ、エージェントワークフローを直接構築・設計する負担を減らすことに重点を置いている
主な機能
- 高速かつ低コストで大規模実行が可能なよう設計されており、重いリソースやコスト要件を抑える方向性を持つ
- 動的データをサポートし、ドメインやオントロジー要件に合わせてグラフを自動生成・洗練する
- データが変化した際の増分更新をサポートし、リアルタイム更新を可能にする
- PageRankベースのグラフ探索を活用し、精度と信頼性を高めるインテリジェント探索を提供する
- 全体として非同期方式であり、完全な型サポートを通じて堅牢で予測可能なワークフローを志向している
コスト例
- The Wizard of Oz を使った例では、
fast-graphragのコストは $0.08、graphragのコストは $0.48 と示されている - READMEではこれを6倍のコスト削減と説明しており、データサイズと挿入回数が増えると削減効果はさらに改善するとしている
インストールと実行フロー
- 推奨インストール方式は、性能のためのソースインストールと安定性のためのPyPIインストールに分かれる
- ソースインストール: リポジトリをクローンした後
poetry install - PyPIインストール:
pip install fast-graphrag
- ソースインストール: リポジトリをクローンした後
- クイックスタート例では、まず
OPENAI_API_KEY環境変数を設定する - A Christmas Carol のテキストをダウンロードした後、Pythonコードで
GraphRAGを初期化する - 初期化例には次の値が含まれる
working_dir="./book_example"- 物語の登場人物、相互作用、場所、関係を分析する
domain - クエリ例の一覧
["Character", "Animal", "Place", "Object", "Activity", "Event"]エンティティタイプ
grag.insert(f.read())で文書を挿入し、grag.query("Who is Scrooge?").responseでクエリ結果を出力する- 同じ作業ディレクトリで再初期化すると、知識は自動的に保持される
- ローカルモデル利用時などにLLM同時処理タスク数を制御するには、
CONCURRENT_TASK_LIMIT=8のような環境変数を任意で設定できる
例と構成オプション
examplesフォルダでは、ライブラリの一般的なユースケース向けチュートリアルを提供しているcustom_llm.pyは、OpenAI API互換の言語モデルとエンベッダーを別々に設定する簡単な例であるcheckpointing.ipynbは、元に戻せないデータ破損を避けるためのチェックポイントの使い方を扱うquery_parameters.ipynbはさまざまなクエリパラメータを扱い、with_references=Trueによって回答に使用情報の参照を含める方法を示す
設計哲学と探索方式
- 目標は成功するGenAIアプリケーションの数を増やすことであり、そのためにLLMアプリが複雑なエージェントワークフローの設定や保守なしで特化型検索パイプラインを活用できるメモリとデータツールを作るとしている
- Fast GraphRAGは、現在のクエリに答えるために最も関連性の高い情報を見つけるため、personalized PageRankアルゴリズムでグラフを探索する
- このアプローチが機能する理由の概要として、参考資料に HippoRAG paper を挙げている
オープンソースとマネージドサービス
- リポジトリは MIT License で提供されており、詳細は LICENSE.txt にある
- 高速かつ信頼性高く始める方法として、マネージドサービスを提供している
- マネージドサービスでは毎月最初の 100リクエスト が無料で、その後は従量課金となる
- マネージドサービスについてさらに知るには demo を予約するか、docs を参照できる
- コントリビューション案内は CONTRIBUTING.md にあり、質問は Discord でできる
1件のコメント
Hacker News の意見
PageRank 以外にも、構造化データで RAG に影響を与え得る興味深い中心性指標がいくつかある
その中でも Triangle Centrality は、ノード周辺の三角形を数えて中心性を計算するもので、三角形は関係を強く閉じ、開いた接続は中心から重みを奪って中心性を薄める、という考え方に基づいている
https://arxiv.org/abs/2105.00110
論文では PageRank のような他の中心性より効率が高いとしているが、GraphBLAS を使った研究では、18億エッジ規模までの複数の疎グラフで、TC は我々の疎 PageRank 実装より遅かった
ただしグラフが大きくなるほど TC の方がうまくスケールするようで、兆単位のエッジ領域ではより効率的である可能性が高い
https://fossies.org/linux/SuiteSparse/GraphBLAS/Doc/The_Grap...
いずれにせよ回答生成では、LLM がパースする部分がボトルネックになるはず
PageRank は最初のステップだが、より正確な代替案も試してみたい
ここではパーソナライズド PageRankを使っていて、特定のノード集合に初期重みを与えているので、Triangle Centrality もこれをサポートしているのか気になる
またエッジ重みも見ているので、その部分も可能なのか知りたい
https://link.springer.com/content/pdf/10.1007/978-3-030-6097...
この領域ではかなり多くの作業をしてきて、いくつか学んだことがある
この3つを組み合わせて、似たような知識の分解/抽出ステップを作り、そこにメタプロンプターを付けて、ドメイン/エンティティタイプを事実上自動生成させた
LLM は基本的に、分解された知識の適切な粒度をうまく捉えられない
ひとつのコツは、LLM に mermaid.js のマインドマップを出力させて入力を階層的なツリーに分けさせ、最後にどのレベルが知識ノードの適切なルートなのかを言わせること
その後、そのノード内の知識で答えられる質問を生成し、この質問テキストをインデックス化し、埋め込みも行う
ユーザーのクエリをこれらの質問と純粋な BM25 で直接マッチングしても良い結果が出るし、ハイブリッドアプローチはさらに良いが、差はそれほど大きくない
クエリ時点で LLM を使わない場合は、埋め込み類似度を巡回コスト関数として使い、ルートからより深いノードへ階層的に降りていくこともできる
最終的には、ツリーの一般化としてグラフへ移行することにした
グラフを「歩く」のに埋め込み類似度を使うという考え方が核心だと見ており、FastGraphRAG にもクエリに応じてエッジ重みを付ける方式で積極的に統合している
複数の解法が似た設計に収束していくのを見るのは興味深い
クエリから仮想回答を生成した後、その回答で埋め込み検索するアイデアは興味深く、実験リストに追加してみようと思う
今では、コーパスに合わせてファインチューニングした LLM で仮想回答を生成すれば、さらにうまく機能するのかも気になる
仮想回答を作るときも「チャンクサイズ」に合わせた応答をプロンプトしているのか知りたい
より良い中心性のために PageRank を使うのはよさそうだが、RAG のおそらく解決不可能な欠陥、つまり RAG が基本的にうまく機能しにくい理由は、依然として解決していない
すべての RAG DB が期待より低い性能しか出せない理由は、RAG がユーザーの求める情報を見つけるのに必要な単語間の関係を根本的に見つけられないからだ
奇妙に聞こえるかもしれないが、本来「アテンション」メカニズムはこういうことを得意とするはずではないかと思っても、実際には十分ではない
例えば、ある文章に「Sharon」という人物が複数の物理化学の学会に参加したという内容はあるが、職業は明示されていないとする
「Sharon の職業は何か?」を探すと、ほぼすべての RAG アプローチは「職業」、学会参加、学会の種類を結びつけて「化学者」だと推論できない可能性が高い
こうした誤りは、RAG で情報検索を行う際、さまざまな種類の情報全体に広がっている
結局、上のような解法は SQL や PageRank のような別のクエリ方法を、より多くの段階で再発明しているように見え、その時点ではベクトル化の意味はあまりない
RAG コンポーネントは、大きなデータセットから Sharon 関連の記事を見つけて、全体をコンテキストとして LLM に渡せばよい
元記事で引用されている HippoRAG 論文を見ると、動機づけの例がほぼ同じで、評価もおおむねこの種のマルチホップ質問応答に合わせられている
Sharon というエンティティを取得し、追加コンテキストとして Sharon に近いノードとエッジを受け取ればよい
その後は LLM の役割であり、与えられたコンテキストに職業がなければ「与えられたコンテキストでは Sharon の職業を見つけられません」と伝えるべきだ
興味を引かれたので登録して、ダッシュボードにPDF文書をいくつかアップロードしてみた
ユースケースは、AIスタートアップで製造関連のコンプライアンス文書を分析する作業だが、これが自分たちに役立つには、どの程度の規模まで動くのか、コストモデルがどうなっているのかを理解する必要がある
クライアントごとに約30万件のPDFがあり、毎月文書集合の約10%が変わると見込んでいる
どんなGraphRAGシステムでも文書を大規模に処理する必要があり、S3を取り込みメカニズムとして使うことはできるが、次の時点でシステムが利用可能になるまでのコストと処理時間を知る必要がある
もっと詳しく話したいので、antonio [at] circlemind.co まで連絡してほしい
興味深いが、有用な知識グラフを得るには、ドメイン特化のテキストコーパスがどのくらい大きい必要があるのか気になる
Aiderは以前からコードリポジトリのコールグラフにPageRankを適用してきた
重要なコードにはどれもPageRankを支えるグラフ構造が十分にあるので、現在の作業に関連するプロジェクト内で最も関連性の高いコンテキストを見つけるのに非常にうまく機能する
https://aider.chat/docs/repomap.html#optimizing-the-map
より多くの人が使い始めたら、フィードバックを聞きたい
repo mapを強制的に生成して検査できるようにする計画があるのか気になる
すばらしい
グラフがどのように保存され、クエリされるのか気になる
グラフデータベースには慣れているが、依存関係には見えない
抽出にはsciphi triplexモデルを試したことがあるのかも気になる
以前抽出を試したとき、同じチャンクを連続して複数回抽出すると結果に一貫性がなかった
コードベースは、軽量なラッパーを書けばどんなグラフDBでも簡単に統合できるよう設計しており、近い将来neo4jのようなものをサポートする予定
triplexはまだ試していない。gpt4o-miniが現時点では十分に速く正確だったため
エンティティと関係の抽出だけでなく、説明生成や競合解決にもgpt4o-miniを使っている
ファインチューニングすれば結果は確実に良くなるはず
グラフクエリは、与えられたクエリに関連する初期ノード集合を見つけたうえで、それらのノードからパーソナライズドPageRankを実行し、他の関連パッセージを見つける方式
現在はクエリ全体とクエリから抽出したエンティティの両方について意味検索で初期ノードを選んでいるが、この方式にいくつか興味深い追加機能も計画している
良いアイデアだ
個人的には、RAGには従来型の情報検索が進むべき道だと思う
ベクトル検索は良いが遅く高価で、人々が魔法の粉のように使いがちだ
非構造化データにはうまく機能するが、構造化データに必ずしもそれほど合うわけではない
かなりうまくチューニングしない限り、ベクトル検索がよくチューニングされた従来型クエリよりはるかに優れているわけでもない
構造化データを非構造化データに変換してからベクトル検索やプロンプトエンジニアリングをしようとする実務を見たことがあるが、全体として少し逆行している感じがする
ある程度は機能するが、同じ結果を得るもっと賢い方法がある可能性が高い
Graph RAGの本質はデータ構造を活用することだ
それがSQLのJOINであれグラフDBクエリであれ、大きな違いはない
LLMにクエリ方法を教えたり、既存の検索/クエリAPIとインターフェースさせたりすることにも価値があるはず
ランキングの悪さは、より大きなコンテキストサイズで補い、複数のクエリで数百件以上の結果を取得すればよい
そのようにスケールさせるほうが、ベクトル検索よりはるかに速く安価なはずだ
良さそうだが、LangChainのような他の抽象化レイヤーで痛い目を見たことがあるので、過度な単純化が心配だ
同じ過ちを繰り返さないためにどうするつもりなのか気になる
検索と生成に関する評価指標のスコアがあるのか気になる
たとえばKILTやNQデータセットのようなものだ
ベンチマークデータセットがすべてではないが、ある程度良いスコアと推論時間を示せれば、フレームワークを説得したりエンジニアが選んだりするうえで大きな助けになるはず
フリーランスの自然言語処理エンジニアとしてRAGパイプラインを多く作ってきたので、これは実際に使ってみるつもりだ
現在Q&Aチャットボットを作っているが、次のシナリオの処理に苦労している
ユーザーが「さっき言った前の文ではどういう意味?」と尋ねたとき、このフレームワークは正しい小さなサブセットの生の知識をどのように検索し、LLMに統合して関連性のある応答を作れるのか気になる
外部フレームワークに依存せずにこの問題を解決するのは難しかった
https://www.reddit.com/r/LocalLLaMA/comments/1gtzdid/d_optim...
このフレームワークがこの問題をどのように解決し、プロセスを単純化できるのか知りたい
これがないと、ユーザーが「2番目の項目をもっと詳しく説明して」や「上の内容の詳しい例を出して」のように質問したときに、しばしば失敗した
現在の実装ではインデックスを3つ用意し、クエリと過去メッセージを提供したうえで、LLMに次のように分解させている
リクエスト全体、BM25最適化質問、キーワード、意味検索最適化質問
その後RAGと再ランキングを行い、上位N件のパッセージをリクエスト全体とともに2回目のLLM呼び出しに渡す
オーケストレーション段階に集中すべき
ReActエージェントを調べればよく、LangGraphやBedrock Agentsで作れる