様々なRAGを組み、比較してみる

## 1. はじめに

### 趣旨・背景

近年AIエージェントが注目されてきており、エージェントによって呼び出されるツールとしてRAG（Retrieval-Augmented Generation）システムが有力な候補の1つとして挙げられると思います。そして、RAGが今後一層本格的に企業で利用されるようになることも考えられます。そういった背景から、RAGについての基礎を理解したいと思い、RAGの様々な手法を組んで比較してみました。本記事では、そのプロセスと結果を共有します。

## 2. 利用したツール・構成

* **LLM API, モデル**:
    * OpenAI API（RAGの推論に利用）
        * gpt-4o-mini
        * text-embedding-3-small
    * GCP VertexAI（PDFのテキスト化に利用）
        * gemini-2.0-flash
* **LLM Pythonライブラリ**:
    * LangChain
    * Ragas
* **PDFテキスト抽出**:
    * Langchain PyPDFLoader
    * Gemini-2.0-flashを使った画像からのテキスト抽出
* **開発環境**:
    * WSL2
    * Ubuntu
    * Docker
    * VSCode (Cursor)
* **使用言語**:
    * Python
* **DB**:
    * PostgreSQL pgvector
    * Elastic Search（Hybrid RAGに使用）
    * neo4j（Graph RAGに使用）

## 3. 検証した手法と開発・評価プロセス

### 試した手法
* シンプルなRAG（参考：[いまさら基本的なRAGを構築する](https://qiita.com/mrsd/items/2269caf36bb5531ba25a)）
* Dense X
* Parent Document
* RAPTOR
* Hybrid RAG
* RAG Fusion
* Graph RAG（参考：[github.com/tomasonjo/blogs/blob/master/llm/enhancing_rag_with_graph.ipynb](https://github.com/tomasonjo/blogs/blob/master/llm/enhancing_rag_with_graph.ipynb?ref=blog.langchain.dev))
* Microsoft Graph RAG（参考：[https://microsoft.github.io/graphrag/](https://microsoft.github.io/graphrag/)）

参考：[RAG入門: 精度改善のための手法28選](https://qiita.com/FukuharaYohei/items/0949aaac17f7b0a4c807#rag-fusion):

### プロセス
* Vector DBはコンテナを立てて（参考：[いまさら基本的なRAGを構築する](https://qiita.com/mrsd/items/2269caf36bb5531ba25a)）構築し、それぞれのRAGシステムを構築する
* 構築したRAGシステムを[Ragas](https://docs.ragas.io/en/stable/getstarted/)に接続し、評価する

## 4. Ragas評価（ご参考までに）
※[データセット](https://huggingface.co/datasets/allganize/RAG-Evaluation-Dataset-JA?row=0)を使って評価をしましたが、API利用料を抑えるために[^1]一部のみを使用してRagasで評価していますので、正確なものではありません。あくまでも参考程度にご確認ください。
[^1]: target_file_nameが01.pdf,1c202401.pdf,DP2023-2.pdf,eval_datasets.pdf,FILP_Report2022.pdfのデータセットを使用

### Langchain PyPDFLoader
| ドキュメント(PDF)のテキスト抽出方法 | context_recall | factual_correctness | faithfulness | semantic_similarity |
|---|---|---|---|---|
| シンプルなRAG | 0.7917 | 0.3952 | 0.6263 | 0.6187 |
| Dense X | 0.8148 | 0.3596 | 0.4724 | 0.565 |
| Parent Document | 0.8086 | 0.3459 | 0.5515 | 0.593 |
| ハイブリッド検索 | 0.8491 | 0.4248 | 0.6453 | 0.6435 |
| クエリ翻訳 | 0.875 | 0.3022 | 0.6552 | 0.5009 |
| RAG Fusion | 0.8352 | 0.3181 | 0.5703 | 0.5738 |

次に、上記で結果の良かった「シンプルなRAG」「Parent Document」「ハイブリッド検索」に加え、Graph検索を取り入れたGraph RAGを、下記方法でテキスト抽出したPDFを使って再度評価

### Gemini 2.0-flash を使った画像からのテキスト抽出
| ドキュメント(PDF)のテキスト抽出方法 | context_recall | factual_correctness | faithfulness | semantic_similarity |
|---|---|---|---|---|
| シンプルなRAG | 0.9 | 0.4622 | 0.6601 | 0.6821 |
| Parent Document | 0.821 | 0.4078 | 0.5492 | 0.6854 |
| ハイブリッド検索 | 0.8657 | 0.4552 | 0.6591 | 0.6928 |
| Graph RAG | 0.8873 | 0.4356 | 0.6889 | 0.6853 |
| MS Graph RAG | 0.3185 | 0.2307 | 0.2562 | 0.4465 |

### 検証結果まとめ
* **PDFのテキスト抽出プロセスの改善**: Gemini-2.0-flashを用いたテキスト抽出により、大幅な性能向上が見られました
* **検索方法の拡張**: Graph検索や全文検索の導入も精度向上に貢献しました
* **階層構造のDBの再帰検索処理**: こちらも有効でしたが、Dense Xは今回の検証ではあまり精度向上に繋がりませんでした

## 5. 学んだこと

* RAGをどのように評価、改善するのかが難しい
    * 個別具体的な利用シーンや環境を定義してそこに最適化することはできるとは思いますが、汎用的な利用を想定した評価・改善は特に難しいことがわかりました
* Ragas検証結果について
    * （Ragas評価が正確なものではないにしても）シンプルなRAGが比較的高い精度を出したことから、RAGの精度向上の難易度が高いことがわかりました
    * 上記でも述べた通り、今回はAPIの利用料を抑えるために使用するモデルも軽いものを選択したため、モデルを最新のものにするだけでも精度は大幅に向上することが考えられる



## 参考文献

https://qiita.com/FukuharaYohei/items/0949aaac17f7b0a4c807#rag-fusion

https://docs.ragas.io/en/stable/getstarted/

https://github.com/tomasonjo/blogs/blob/master/llm/enhancing_rag_with_graph.ipynb?ref=blog.langchain.dev

https://qiita.com/mrsd/items/2269caf36bb5531ba25a

https://huggingface.co/datasets/allganize/RAG-Evaluation-Dataset-JA?row=0

https://gigazine.net/news/20250210-ingesting-pdf-gemini-2-0/