【SIGNATE】第3回金融データ活用チャレンジ: LightRAGを試してみた

### はじめに

前回の記事に引き続き、第3回金融データ活用チャレンジについて、振り返り（主に失敗談）を共有します。今回は、通常のRAG（Retrieval-Augmented Generation）に加えて、GraphRAGなど様々な手法を調べていく中で知ったLightRAGという手法に焦点を当てます。LightRAGは、グラフ構造を活用することでRAGの性能向上を目指す新しい試みです。[参照リンク](https://lightrag.github.io/)
### LightRAGとは

LightRAGは、テキスト索引付けと検索プロセスにグラフ構造を組み込むことで、従来のRAGシステムが抱える課題の解決を目指しています。主な特徴は以下の通りです。

*   **グラフ構造の活用:** ドキュメント内のエンティティ（例：企業、人物、商品）とその関係性をグラフ構造で表現します。これにより、文脈を捉えやすくなり、より関連性の高い情報を検索できます。
*   **二段階検索:** テキスト検索とグラフ検索の二段階で検索を行います。まず、テキスト検索で関連性の高いチャンクを絞り込み、次にグラフ検索でエンティティ間の関係性を考慮しながら、より関連性の高い情報を抽出します。詳細なクエリ（例：「〇〇社の株価は？」）と抽象的なクエリ（例：「金融市場のトレンドは？」）の両方に対応できます。
*   **高速な更新:** 新しいデータが追加された際も、変更があった部分グラフのみを更新すればよく、全体の再処理が不要で、効率的に知識ベースを更新できます。

LightRAGは、GraphRAGを軽量化し、より扱いやすくするための手法と言えます。GraphRAGでは、大規模な知識グラフ全体を対象に検索を行うため、計算コストが高くなる傾向があります。一方、LightRAGでは、グラフ構造を局所的に分割し、各部分グラフに対して検索を行うことで、計算コストを削減しています。

また、LightRAGでは、テキスト埋め込みとグラフ構造を組み合わせることで、より高度な検索を実現しています。テキスト埋め込みは、単語や文の意味をベクトル空間に表現する技術であり、グラフ構造は、エンティティ間の関係性を表現する技術です。LightRAGでは、これらの技術を組み合わせることで、質問の意図をより正確に捉え、関連性の高い情報を検索することができます。
![LightRag.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635931/2747b62e-f45c-4d60-99b6-3b6314fc55fa.png)
（出所: [LightRAG: Simple and Fast Retrieval-Augmented Generation](https://arxiv.org/abs/2410.05779), Zirui Guo, Lianghao Xia, Yanhua Yu, Tu Ao, Chao Huang, Beijing University of Posts and Telecommunications, University of Hong Kong)

### サンプルコード
```python
import os

from lightrag import LightRAG, QueryParam
from lightrag.llm.openai import gpt_4o_mini_complete, openai_embed
import networkx as nx
from pyvis.network import Network

WORKING_DIR = "./dickens"
INPUT_PATH = "./documents" # ドキュメントが格納されているフォルダ

if not os.path.exists(WORKING_DIR):
    os.mkdir(WORKING_DIR)

rag = LightRAG(
    working_dir=WORKING_DIR,
    embedding_func=openai_embed,
    llm_model_func=gpt_4o_mini_complete,
    # llm_model_func=gpt_4o_complete
)

# ドキュメントを読み込み(例: 1.md, 2.md, ...19.md)
texts = []
for i in range(1, 20):
    file_path = os.path.join(INPUT_PATH, f"{i}.md")
    if os.path.exists(file_path):
        with open(file_path, encoding="utf-8") as file:
            texts.append(file.read())
    else:
        print(f"{file_path} does not exist. Skipping.")

# LightRAGにテキストを挿入
rag.insert(texts)

question = "〇〇について教えてください。" # 質問

# 検索モードを指定して質問
print(rag.query(question, param=QueryParam(mode="naive")))  # ナイーブ検索
print(rag.query(question, param=QueryParam(mode="local")))  # ローカル検索
print(rag.query(question, param=QueryParam(mode="global"))) # グローバル検索
print(rag.query(question, param=QueryParam(mode="hybrid"))) # ハイブリッド検索

# グラフ可視化
G = nx.read_graphml('./dickens/graph_chunk_entity_relation.graphml')
net = Network(notebook=True)
net.from_nx(G)
net.show('knowledge_graph.html')
```

### 実行結果について

サンプルコードを実行したところ、グラフが複雑になりすぎて、エンティティが過剰に抽出されているように感じました（新種のウィルスのよう...)。原因として、以下の点が考えられます。

*   **エンティティの過剰抽出:** LightRAGでは、テキストチャンクからエンティティを抽出する際にLLMを利用します。この際、LLMのプロンプトやパラメータ設定が適切でないと、不要なエンティティまで抽出される可能性があります。
*   **関係性の過剰な結びつき:** LightRAGでは、エンティティ間の関係性を推定する際にもLLMを利用します。この際、LLMのプロンプトやパラメータ設定が適切でないと、本来は関係性の薄いエンティティ同士が結び付けられてしまう可能性があります。

また、今回はお試しとして、PDFから抽出したデータをそのまま使用しましたが、事前処理（データクリーニングや要約処理）を適切に行えば、より有益な情報を得られる可能性があると考えています。

![LightRag1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635931/c7fe2cd0-403f-41eb-ba32-11bf8a931693.png)
![LightRag2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635931/ee3d7e74-facc-4f05-a28c-8454404a9a8a.png)


（ナレッジグラフ可視化）



### 回答精度について

LightRAGを用いて企業のESG情報や財務情報を基にした質問に回答することを試みましたが、期待していたほどスコアは伸びませんでした。原因として、以下の点が考えられます。

1.  **データ形式と質問形式のミスマッチ:**
    *   質問内容が多岐に渡るため、LightRAGが効果的にグラフ構造を活用できるようなデータ形式になっていなかった可能性があります。
    *   LightRAGは、構造化データもグラフ構造に変換して処理できます。ただし、構造化データを効果的に活用するには、適切なグラフ構造を設計する必要があります。
    *   質問内容によっては、グラフ構造を介さずに、直接構造化データを参照した方が効率的な場合があります。

2.  **グラフ構造の複雑さ:**
    *   質問内容によっては、グラフ構造が複雑になりすぎ、かえって検索効率を低下させた可能性があります。
    *   例えば、複数の企業間の関係性や、事業内容と財務情報の関係性などをグラフ構造で表現しようとすると、グラフが複雑になり、検索時にノイズが増えてしまう可能性があります。
    *   これはグラフ構造の設計に依存します。適切なグラフ構造を設計すれば、複雑な関係性を表現しつつ、検索効率を維持することができます。

3.  **質問の意図の解釈:**
    *   質問内容によっては、質問の意図を正確に解釈することが難しい場合があります。
    *   例えば、「〇〇社の強みは何か」という質問に対して、どのような情報を強みとして捉えるべきか、判断が難しい場合があります。
    *   LightRAGは、質問の意図を基にグラフ構造を検索しますが、意図の解釈が誤っていると、適切な情報を検索できない可能性があります。

正直、まだ理解が不十分な点が多いので、引き続き様々な角度から検証を進めたいと思います。

### まとめ

LightRAGは、複雑な関係性を持つ情報間のつながりを捉える上で、非常に有効な技術です。しかし、質問内容やデータ形式によっては、期待通りの性能を発揮できない場合があることが分かりました。

今回得られた知見を基に、LightRAGの更なる可能性を探求し、今後のRAGコンペで活用できるよう、引き続き試していければと思います。