論文概要(Abstract)
LightRAGは、GraphRAGの2つの根本的課題—単一レベル検索とインクリメンタル更新不可—を解決する軽量・高速なグラフRAGフレームワークである。デュアルレベル検索(エンティティ粒度のLow-Level + 関係粒度のHigh-Level)と差分グラフ更新機構を導入し、5ドメインの実験でGraphRAGを含む既存手法を上回る性能を達成した。香港大学のチームが開発し、GitHubで14,000以上のスターを獲得しているOSSプロジェクトである。
この記事は Zenn記事: LlamaIndex v0.14実践ガイド:AgentWorkflowで本番RAGを構築する の深掘りです。
情報源
- arXiv ID: 2412.15605
- URL: https://arxiv.org/abs/2412.15605
- 著者: Zirui Guo, Lianghao Xia, Yanhua Yu, Tu Ao, Chao Huang (University of Hong Kong)
- 発表年: 2024
- 分野: cs.IR, cs.AI
背景と動機(Background & Motivation)
GraphRAG(Microsoft)はナレッジグラフとコミュニティ構造を活用してRAGのグローバルな回答能力を大幅に向上させたが、実用上2つの大きな課題を抱えている。
課題1: 単一レベル検索の制約 GraphRAGはLocal Search(エンティティ近傍)とGlobal Search(コミュニティ要約)を提供するが、この2つは独立した検索モードであり、クエリの性質に応じて事前に選択する必要がある。実際のユースケースでは「特定のエンティティについて知りたいが、関連するトレンドも知りたい」というように、複数粒度の情報を同時に求めるクエリが多い。
課題2: インクリメンタル更新の困難 GraphRAGではコーパスを更新するたびにグラフ全体を再構築する必要がある。大規模コーパスでは構築に数時間〜数日かかるため、動的に更新されるナレッジベースには不向きである。
LightRAGはこの2つの課題を同時に解決する。Zenn記事のPropertyGraphIndex(Stage 3)を検討する際、GraphRAGの代替実装として検討する価値が高い。
主要な貢献(Key Contributions)
- 貢献1: デュアルレベル検索(Low-Level: エンティティ粒度、High-Level: 関係/概念粒度)とHybridモードを設計し、クエリ性質に応じた柔軟な検索を実現
- 貢献2: 差分グラフ更新機構により、新規ドキュメント追加時にグラフ全体の再構築を不要にした
- 貢献3: 5ドメイン(Agriculture, CS, Legal, Mix, General)の実験でGraphRAGを含む既存手法を上回る性能を達成
- 貢献4: Neo4j, PostgreSQL, Milvus等の外部DBに対応し、本番環境への統合を容易にした
技術的詳細(Technical Details)
アーキテクチャ概要
LightRAGのアーキテクチャは、インデックスパイプラインと検索エンジンの2つの主要コンポーネントで構成される。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌─────────────────────────────────────────────────┐
│ LightRAG Core │
│ │
│ ┌──────────────┐ ┌─────────────────────────┐│
│ │ Indexing │ │ Retrieval Engine ││
│ │ Pipeline │ │ ││
│ │ │ │ ┌───────────────┐ ││
│ │ Text→Chunk │ │ │ Low-Level │ ││
│ │ →Extract │ │ │ (Entity) │ ││
│ │ →Graph │ │ ├───────────────┤ ││
│ │ →Embed │ │ │ High-Level │ ││
│ │ │ │ │ (Relation) │ ││
│ └──────┬───────┘ │ ├───────────────┤ ││
│ │ │ │ Hybrid │ ││
│ ┌──────▼───────┐ │ │ (LL+HL) │ ││
│ │ Graph Storage │ │ ├───────────────┤ ││
│ │ + Vector DB │ │ │ Naive │ ││
│ └──────────────┘ │ └───────────────┘ ││
│ └─────────────────────────┘│
└─────────────────────────────────────────────────┘
デュアルレベル検索メカニズム
LightRAGの核心は、検索対象をエンティティ(ノード)と関係(エッジ)の2つのレベルに分け、それぞれに独立したベクトルインデックスを構築する点にある。
Low-Level Retrieval(低レベル: エンティティ粒度)
クエリに対して、エンティティの埋め込みベクトルとの類似度でtop-kエンティティを検索し、その近傍サブグラフを取得する。
\[\mathcal{E}_q = \text{top-k}\left(\text{sim}(\mathbf{h}_q, \mathbf{h}_{e_i}) \mid e_i \in \mathcal{V}\right)\]ここで、
- $\mathcal{E}_q$: クエリ$q$に最も関連するエンティティ集合
- $\mathbf{h}_q$: クエリの埋め込みベクトル
- $\mathbf{h}_{e_i}$: エンティティ$e_i$の埋め込みベクトル
- $\mathcal{V}$: グラフの全ノード集合
- $\text{sim}$: コサイン類似度
適用例: 「LlamaIndexのAgentWorkflowとは何か?」「PropertyGraphIndexの内部実装は?」
High-Level Retrieval(高レベル: 関係/概念粒度)
クエリに対して、関係(エッジ)の埋め込みベクトルとの類似度で検索する。関係はエンティティ間の意味的つながりを表すため、より抽象的・概念的な検索が可能。
\[\mathcal{R}_q = \text{top-k}\left(\text{sim}(\mathbf{h}_q, \mathbf{h}_{r_j}) \mid r_j \in \mathcal{E}\right)\]ここで、
- $\mathcal{R}_q$: クエリ$q$に最も関連する関係集合
- $\mathbf{h}_{r_j}$: 関係$r_j$の埋め込みベクトル
- $\mathcal{E}$: グラフの全エッジ集合
適用例: 「RAGフレームワークの最近のトレンドは?」「マルチエージェントとRAGの関係性は?」
Hybrid Mode(ハイブリッド: 推奨デフォルト)
Low-LevelとHigh-Levelの両方を実行し、結果を統合する。クエリの性質が事前に分からない場合に最適。
\[\mathcal{C}_q = \text{Merge}(\mathcal{E}_q, \mathcal{R}_q)\]インクリメンタル更新メカニズム
GraphRAGの最大の弱点であるグラフ再構築問題を解決する。
既存手法(GraphRAG)の問題: \(\text{Cost}(\text{update}) = O(|\mathcal{D}|) \quad \text{(全コーパス再処理)}\)
LightRAGの解決策: \(\text{Cost}(\text{update}) = O(|\mathcal{D}_{\text{new}}|) \quad \text{(新規ドキュメントのみ処理)}\)
更新アルゴリズム:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def incremental_update(
graph: KnowledgeGraph,
new_documents: list[str]
) -> KnowledgeGraph:
"""差分更新アルゴリズム"""
for doc in new_documents:
# 1. 新チャンクのみ処理
chunks = chunk_text(doc)
for chunk in chunks:
# 2. エンティティ・関係抽出
entities, relations = extract_from_chunk(chunk)
for entity in entities:
if entity.name in graph.nodes:
# 3a. 既存エンティティ: 記述を統合
existing = graph.nodes[entity.name]
merged_desc = llm_summarize(
existing.description,
entity.description
)
graph.update_node(entity.name, merged_desc)
else:
# 3b. 新規エンティティ: 追加
graph.add_node(entity)
for relation in relations:
if relation in graph.edges:
# 4a. 既存関係: 強度スコア更新
graph.update_edge_weight(relation)
else:
# 4b. 新規関係: 追加
graph.add_edge(relation)
# 5. ベクトルインデックスを差分更新
graph.update_vector_index(new_entities, new_relations)
return graph
GraphRAGとの機能比較
| 機能 | GraphRAG | LightRAG |
|---|---|---|
| 検索粒度 | Local/Globalの二択 | Low/High/Hybrid/Naive |
| 差分更新 | 不可(全再構築) | 可(新チャンクのみ) |
| 外部DBサポート | 限定的 | Neo4j, PostgreSQL, Milvus, Qdrant |
| ローカルLLM対応 | 限定的 | Ollama完全対応 |
| コスト | 高 | 中(30-40%削減) |
| チャンクサイズ | 2400トークン | 1200トークン |
| ライセンス | MIT | MIT |
実装のポイント(Implementation)
インストールと基本使用法
1
pip install lightrag-hku
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from lightrag import LightRAG, QueryParam
from lightrag.llm import gpt_4o_mini_complete
# 初期化
rag = LightRAG(
working_dir="./ragtest",
llm_model_func=gpt_4o_mini_complete
)
# ドキュメント挿入(インクリメンタル対応)
with open("document.txt") as f:
rag.insert(f.read())
# 追加ドキュメント(差分更新)
with open("new_document.txt") as f:
rag.insert(f.read()) # グラフ全体の再構築は不要
# 各モードでクエリ
# Low-Level: 特定エンティティの詳細
result_ll = rag.query(
"LlamaIndexのAgentWorkflowとは?",
param=QueryParam(mode="local")
)
# High-Level: 抽象的テーマ
result_hl = rag.query(
"RAGフレームワークの最近のトレンドは?",
param=QueryParam(mode="global")
)
# Hybrid: 推奨デフォルト
result_hybrid = rag.query(
"AgentWorkflowがRAGにもたらす変化とは?",
param=QueryParam(mode="hybrid")
)
外部DB設定(Neo4j)
1
2
3
4
5
6
7
8
9
10
11
12
from lightrag import LightRAG
rag = LightRAG(
working_dir="./ragtest",
graph_storage="Neo4JStorage",
log_level="DEBUG",
llm_model_func=gpt_4o_mini_complete,
# Neo4j設定
neo4j_uri="bolt://localhost:7687",
neo4j_user="neo4j",
neo4j_password="password",
)
Ollama(ローカルLLM)対応
1
2
3
4
5
6
7
8
9
10
11
12
from lightrag.llm import ollama_model_complete, ollama_embedding
rag = LightRAG(
working_dir="./ragtest",
llm_model_func=ollama_model_complete,
llm_model_name="llama3.1:8b",
embedding_func=EmbeddingFunc(
embedding_dim=768,
max_token_size=8192,
func=lambda texts: ollama_embedding(texts, embed_model="nomic-embed-text")
),
)
主要ハイパーパラメータ
| パラメータ | デフォルト値 | 推奨範囲 | 説明 |
|---|---|---|---|
chunk_token_size | 1200 | 800-1600 | チャンクサイズ(GraphRAGの半分) |
chunk_overlap_token_size | 100 | 50-200 | オーバーラップ |
entity_extract_max_gleaning | 1 | 1-3 | エンティティ抽出反復回数 |
top_k | 60 | 30-100 | 検索時の近傍数 |
max_token_for_local_context | 4096 | 2048-8192 | ローカル検索コンテキスト上限 |
max_token_for_global_context | 4096 | 2048-8192 | グローバル検索コンテキスト上限 |
Production Deployment Guide
AWS実装パターン(コスト最適化重視)
トラフィック量別の推奨構成:
| 規模 | 月間リクエスト | 推奨構成 | 月額コスト | 主要サービス |
|---|---|---|---|---|
| Small | ~3,000 (100/日) | Serverless | $60-150 | Lambda + Bedrock + S3 |
| Medium | ~30,000 (1,000/日) | Hybrid | $400-900 | ECS Fargate + Neptune + ElastiCache |
| Large | 300,000+ (10,000/日) | Container | $2,500-6,000 | EKS + Neptune + OpenSearch |
Small構成の詳細 (月額$60-150):
- Lambda: 1GB RAM, 90秒タイムアウト ($20/月)
- Bedrock: Claude 3.5 Haiku ($60/月) — エンティティ抽出・回答生成
- S3: グラフストレージ(LightRAGデフォルトのJSONファイル) ($5/月)
- CloudWatch: 基本監視 ($5/月)
GraphRAG比との差別化:
- Neptune不要(Small構成ではS3のJSONファイルで十分)→ $50/月削減
- インクリメンタル更新により再構築LLMコストが不要 → 長期的に大幅コスト削減
- チャンクサイズ半分 → エンティティ抽出のLLMコスト約30%削減
コスト試算の注意事項:
- 上記は2026年2月時点のAWS ap-northeast-1(東京)リージョン料金に基づく概算値
- インクリメンタル更新の頻度により月間Bedrockコストが変動
- 最新料金は AWS料金計算ツール で確認してください
Terraformインフラコード
Small構成 (Serverless): Lambda + Bedrock + S3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# --- S3(LightRAGグラフストレージ) ---
resource "aws_s3_bucket" "lightrag_storage" {
bucket = "lightrag-graph-storage"
}
resource "aws_s3_bucket_versioning" "lightrag_storage" {
bucket = aws_s3_bucket.lightrag_storage.id
versioning_configuration { status = "Enabled" }
}
resource "aws_s3_bucket_server_side_encryption_configuration" "lightrag" {
bucket = aws_s3_bucket.lightrag_storage.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
# --- Lambda関数(LightRAGクエリハンドラ) ---
resource "aws_lambda_function" "lightrag_query" {
filename = "lightrag_query.zip"
function_name = "lightrag-query-handler"
role = aws_iam_role.lightrag_lambda.arn
handler = "index.handler"
runtime = "python3.12"
timeout = 90
memory_size = 1024
environment {
variables = {
S3_BUCKET = aws_s3_bucket.lightrag_storage.id
BEDROCK_MODEL_ID = "anthropic.claude-3-5-haiku-20241022-v1:0"
DEFAULT_QUERY_MODE = "hybrid"
TOP_K = "60"
}
}
}
# --- EventBridge(インクリメンタル更新スケジュール) ---
resource "aws_cloudwatch_event_rule" "incremental_update" {
name = "lightrag-incremental-update"
description = "LightRAGの差分グラフ更新を定期実行"
schedule_expression = "rate(1 hour)"
}
resource "aws_cloudwatch_event_target" "update_lambda" {
rule = aws_cloudwatch_event_rule.incremental_update.name
arn = aws_lambda_function.lightrag_update.arn
}
# --- 差分更新Lambda ---
resource "aws_lambda_function" "lightrag_update" {
filename = "lightrag_update.zip"
function_name = "lightrag-incremental-update"
role = aws_iam_role.lightrag_lambda.arn
handler = "update.handler"
runtime = "python3.12"
timeout = 300 # 差分更新は5分以内を想定
memory_size = 2048
environment {
variables = {
S3_BUCKET = aws_s3_bucket.lightrag_storage.id
BEDROCK_MODEL_ID = "anthropic.claude-3-5-haiku-20241022-v1:0"
}
}
}
# --- IAMロール ---
resource "aws_iam_role" "lightrag_lambda" {
name = "lightrag-lambda-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = { Service = "lambda.amazonaws.com" }
}]
})
}
運用・監視設定
CloudWatch Logs Insights — 検索モード別レイテンシ:
1
2
3
4
5
6
fields @timestamp, query_mode, duration_ms, entity_count, relation_count
| stats avg(duration_ms) as avg_latency,
pct(duration_ms, 95) as p95_latency,
count(*) as query_count
by query_mode
| sort avg_latency desc
インクリメンタル更新監視(Python):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import boto3
cloudwatch = boto3.client('cloudwatch')
cloudwatch.put_metric_alarm(
AlarmName='lightrag-update-duration',
ComparisonOperator='GreaterThanThreshold',
EvaluationPeriods=1,
MetricName='Duration',
Namespace='AWS/Lambda',
Period=300,
Statistic='Average',
Threshold=180000, # 3分超過でアラート
AlarmDescription='LightRAG差分更新時間異常(グラフ肥大化の兆候)',
Dimensions=[{
'Name': 'FunctionName',
'Value': 'lightrag-incremental-update'
}]
)
コスト最適化チェックリスト
- Small構成ではS3ストレージを使用(Neptune不要でコスト大幅削減)
- インクリメンタル更新を活用(GraphRAGの全再構築コスト回避)
- デフォルトHybridモードを使用(Low/Highの個別呼び出しは不要)
- チャンクサイズ1200トークン(GraphRAGの半分でLLMコスト約30%削減)
- Ollama対応でローカルLLM使用(APIコストゼロ化可能)
- S3バージョニングでグラフのバックアップ自動化
- EventBridge定期更新で差分更新を自動化
- AWS Budgets月額予算設定
実験結果(Results)
データセット(5ドメイン):
- Agriculture(農業)
- CS(コンピュータサイエンス)
- Legal(法律)
- Mix(複合)
- General(汎用)
比較手法: NaiveRAG, RQ-RAG, HyDE, GraphRAG (Local/Global)
LightRAG Hybrid vs 各手法の勝率(Overall):
| 比較手法 | LightRAG Hybrid 勝率 |
|---|---|
| NaiveRAG | ~90% win |
| RQ-RAG | ~85% win |
| HyDE | ~80% win |
| GraphRAG (Global) | ~65% win |
| GraphRAG (Local) | ~72% win |
評価軸別(vs GraphRAG Global):
| 評価軸 | LightRAG Hybrid 勝率 |
|---|---|
| Comprehensiveness | 63% |
| Diversity | 67% |
| Empowerment | 65% |
| Overall | 65% |
分析ポイント:
- LightRAG HybridはGraphRAGの両モード(Local/Global)を同時に上回る
- 特にDiversity(多様性)での改善が顕著 — デュアルレベル検索により異なる粒度の情報を統合
- NaiveRAGとの差は90%勝率と圧倒的 — グラフ構造の導入効果が明確
- コスト効率はGraphRAGの30-40%削減で同等以上の性能
実運用への応用(Practical Applications)
LlamaIndex v0.14との組み合わせ
Zenn記事のStage 3(PropertyGraphIndex)の代替・補完として、LightRAGを以下のように活用できる。
| シナリオ | 推奨 | 理由 |
|---|---|---|
| 静的ドキュメント、グローバル分析重視 | GraphRAG | コミュニティレポートの品質が高い |
| 動的ドキュメント、コスト重視 | LightRAG | インクリメンタル更新・低コスト |
| 特定エンティティ詳細 | PropertyGraphIndex | LlamaIndex統合が容易 |
| マルチホップ推論 | HippoRAG | PPRベースの関連エンティティ拡張 |
導入フローチャート
1
2
3
4
5
6
7
8
9
ドキュメント更新頻度は?
├─ 低い(月1回以下)→ GraphRAGを検討
├─ 中程度(週1回程度)→ LightRAGを推奨
└─ 高い(毎日〜リアルタイム)→ LightRAGを強く推奨
クエリの性質は?
├─ 特定エンティティ → Low-Level mode
├─ 抽象的テーマ → High-Level mode
└─ 両方/不明 → Hybrid mode(推奨デフォルト)
関連研究(Related Work)
- GraphRAG (2404.16130): LightRAGの直接的な先行研究。コミュニティ構造ベースのGlobal Searchが特徴だが、差分更新が不可能
- HippoRAG (2408.08921): 海馬モデルベースのRAG。Personalized PageRankによるマルチホップ推論に強みがあるが、実装複雑度が高い
- RQ-RAG: クエリ再構成によるRAG改善。LightRAGのHigh-Level検索と相補的なアプローチ
まとめと今後の展望
LightRAGはGraphRAGの概念をより実用的な形に進化させた重要なフレームワークである。デュアルレベル検索により単一の検索モードを超え、インクリメンタル更新により動的なナレッジベースへの対応を実現した。
LlamaIndex v0.14のPropertyGraphIndex(Stage 3)を検討する際、コスト効率と更新頻度を重視する場合はLightRAGが有力な選択肢となる。特にpip install lightrag-hkuで即座に試せるアクセシビリティの高さは、プロトタイピングにおいて大きなアドバンテージである。
今後の課題として、(1) 大規模グラフ(10M+エンティティ)でのスケーラビリティ検証、(2) 日本語テキストでのエンティティ抽出精度向上、(3) LLM-as-Judge以外の客観的評価指標の確立が挙げられる。
参考文献
- arXiv: https://arxiv.org/abs/2412.15605
- Code: https://github.com/HKUDS/LightRAG (MIT License)
- Related Zenn article: https://zenn.dev/0h_n0/articles/62e946539206db
- GraphRAG (Microsoft): https://arxiv.org/abs/2404.16130