こんにちは!「蠢動する赤
」です
LLM と AI をもぞもぞ学んでいる蛰伏系エンジニアです。気づいたら急に強くなっている……そんな存在を目指してます![]()
毎回のお知らせ
本記事は、【10 Days Challenge】論文解説AI「Paper Copilot」開発ログ——RAGからAgentまでシリーズの記念すべき第2日目です。具体的なコードは以下の GitHub リンクをご参照ください。
どのような形のコメントでも歓迎します。皆さんからのフィードバックが学習の助けになりますので、ぜひよろしくお願いいたします。![]()
はじめに
Day 1では、LangChainを用いて基本的なRAGパイプラインを構築しました。
プロトタイプとしては十分に機能しますが、実運用や複雑なドキュメントを扱うようになると、以下のような課題に直面することがあります。
- キーワードは一致しているのに、文脈が異なるドキュメントがヒットする
- 意味的には近いが、特定の専門用語が含まれていないため、回答の精度が落ちる
単純なベクトル検索(Vector Search)だけでは、ユーザーの意図を完全に汲み取るには限界があります。
本記事では、この課題に対する解として、「ハイブリッド検索(Hybrid Search)」 と 「Re-ranking(再ランク付け)」 を導入し、検索精度をより堅牢なものにする方法を解説します。
Day 1の振り返りと課題:ベクトル検索の限界
Day 1で実装したのは、文章の意味をベクトル化し、類似度に基づいて検索を行うSemantic Search(意味検索)でした。
ベクトル検索の強みと弱み
- 強み: 「PC」と「パソコン」のように、単語が異なっても意味が近ければ検索できる。
- 弱み: 特定の型番や固有名詞(例: "GPT-4.1")など、完全一致が求められるキーワード検索において、意味的な類似性に引きずられてノイズを拾ってしまうことがある。
例えば、「2025年の予算」を知りたい場合、ベクトル検索では「2024年の予算」も「予算の話をしている」という点で類似度が高くなり、上位にランクインしてしまう可能性があります。これでは、正確な情報抽出は困難です。
解決策:Hybrid SearchとRe-ranking
この問題を解決するために、以下の2つのアプローチを組み合わせます。
1. Hybrid Search(ハイブリッド検索)
ベクトル検索(Semantic Search) とキーワード検索(Keyword Search / BM25) を組み合わせる手法です。
- Vector Search: 文脈や意味の広がりをカバー。
- Keyword Search (BM25): クエリに含まれるキーワードの出現頻度に基づき、正確な一致を重視。
これらをアンサンブル(重み付け統合)することで、意味的な関連性を保ちつつ、キーワードの欠落を防ぐことができます。
2. Re-ranking(再ランク付け)
Retriever(検索器)が広めに収集したドキュメント候補を、より高精度なモデル(Cross-Encoderなど)を用いて再評価し、並べ替えるプロセスです。
- Retriever: 計算コストの低い手法で、多めの候補(例: 10〜20件)を高速に取得。
- Re-ranker: 取得した候補とクエリのペアを詳細に分析し、本当に重要度の高い順に並べ替え、上位(例: 3〜5件)のみをLLMに渡す
この二段階構成(Two-stage Retrieval)により、計算リソースを抑えつつ、最終的なコンテキストの質を大幅に向上させることができます。
実装
それでは、day2_advanced_rag.pyの実装詳細を見ていきます。
Step 1: BM25(キーワード検索)の準備
まず、キーワード検索の標準的なアルゴリズムであるBM25を導入します。
rank_bm25ライブラリを使用します。
from langchain_community.retrievers import BM25Retriever
# ドキュメント(splits)からBM25レトリーバーを作成
bm25_retriever = BM25Retriever.from_documents(splits)
bm25_retriever.k = 10 # 候補として上位10件を取得
Step 2: Ensemble Retriever(ハイブリッド検索)
Day 1で作成したvector_retrieverと、上記のbm25_retrieverを統合します。
EnsembleRetrieverを使用することで、両者の検索結果を重み付けして統合できます。
from langchain_classic.retrievers import EnsembleRetriever
# weights=[0.5, 0.5] でベクトル検索とキーワード検索を等価に評価
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.5, 0.5],
)
バージョンによって内部のスコア正規化の仕様が異なる点には注意。
この段階で、意味とキーワードの両面からアプローチ可能な検索器となりました。
Step 3: Re-ranking(精度向上)
最後に、検索結果の質を担保するためのRe-ranking層を追加します。
ここでは、HuggingFaceのBAAI/bge-reranker-baseモデルを採用します。多言語対応かつ軽量で、高い性能を示します。
from langchain_classic.retrievers import ContextualCompressionRetriever
from langchain_classic.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
# Re-rankerモデルの読み込み
model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-base")
# 上位3つに絞り込む設定
compressor = CrossEncoderReranker(model=model, top_n=3)
# アンサンブルRetrieverと組み合わせる
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=ensemble_retriever
)
これにより、「広めに拾って(Hybrid)、厳密に選ぶ(Re-rank)」というパイプラインが完成しました。
実行結果の検証
実際に、RAGに関する論文を対象に、主な貢献について質問を行いました。
ユーザーの質問
この論文「Retrieval-Augmented_Generation_for_Knowledge-Intensive_NLP_Tasks」の主な貢献は何ですか?簡潔な言葉でまとめてください。
AIの回答(Day1の手法)
この論文の主な貢献は、事前学習済みの生成型言語モデルに外部知識(非パラメトリックなドキュメント集合)への検索機構(リトリーバル)を組み合わせた「Retrieval-Augmented Generation(RAG)」アーキテクチャを提案し、知識集約型NLPタスクにおいて高 い性能と柔軟性を実現した点です。これにより、モデルの知識更新や根拠提示が容易になり、従来のパラメトリックモデルの限界を克服しています。
検索された関連項目
[Source 1] Page 2: by θthat generates a current token based on a context of the previous i−1 tokens y1:i−1, the origina...
[Source 2] Page 6: in 71% of cases, and a gold article is present in the top 10 retrieved articles in 90% of cases.
4.5...
[Source 3] Page 2: the complete sequence. Technically, it treats the retrieved document as a single latent variable tha...
[Source 4] Page 1: the non-parametric memory can be replaced to update the models’ knowledge as the world changes.1
2 M...
AIの回答 (Advanced RAG)
この論文の主な貢献は、**Retrieval-Augmented Generation (RAG)** という新しいアーキテクチャを提案したことです。RAGは、大規模な事前学習済み生成言語モデルに、外部知識ベースから関連文書を検索・参照する「リトリーバル」機構を組み合わせることで、知識集約型NLPタスク(例:質問応答など)において高い性能を実現します。さらに、RAGは単一のアーキテクチャで多様なタスクに適応でき、モデルの知識の更新や根拠の提示も可能にする点が特徴です。
検索された関連項目
[Source 1] Page 0: Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks Patrick Lewis†‡, Ethan Perez⋆, Alek...
[Source 2] Page 8: General-Purpose Architectures for NLP Prior work on general-purpose architectures for NLP tasks has ...
[Source 3] Page 8: architecture, by learning a retrieval module to augment pre-trained, generative language models. Lea...
[Source 4] Page 18: in less informative gradients for the retriever. Perez et al.[46] also found spurious retrieval resu...
[Source 5] Page 17: documents for questions that are less likely to benefit from retrieval, suggesting that null document...
結果の分析:なぜAdvanced RAGが優れているのか
出力結果の「参照元(Source)」に注目してください。
-
Day 1の手法(Vector Searchのみ):
Page 2やPage 6がヒットしています。これらはモデルの詳細な動作原理や実験結果の一部であり、論文全体の「主な貢献」を直接的に記述している箇所ではありません。LLMは断片的な情報から答えを構成する必要がありました。 -
Advanced RAG(Hybrid + Re-ranking):
Page 0(タイトル・要旨) がトップにランクインしています。
これは非常に重要な差です。「主な貢献」というクエリに対して、論文の要約が書かれているPage 0が最も適切であることは自明です。Hybrid Searchがキーワード("contribution"や論文タイトルなど)を捉え、Re-rankerが「このドキュメントこそが質問に対する直接的な答えを含んでいる」と正しく判断し、順位を押し上げた結果です。
「なんとなく答えが合っている」から「根拠となるドキュメントが適切である」へ。
この信頼性の向上が、実務におけるRAGシステムの品質を左右します。
雑談
なお、本来であれば精度などの定量的な評価も行うべきですが、それはまた後の回で詳しく取り上げる予定です。どうぞご期待ください。
(※今回は記事の分量の都合上、私が手元で行った定量評価の結果は割愛させていただきました。データをお見せできず申し訳ありません!)
もし興味があれば、ぜひご自身でもコードを少し変更して、「BM25のみの場合」や「Re-rankingを行わない場合」の結果を試してみてください。また、参照するドキュメント数(kやtop_n)を増減させてみるのも面白いでしょう。パラメータひとつで検索結果がガラリと変わるのを体験するのは、RAGの挙動を理解する上で非常に有益です。
実務への示唆
実運用(Production)に向けた重要なポイントを3点挙げます。
-
小規模データこそHybrid Search
データが少ない場合や専門用語が多い環境ほど、ベクトル検索の曖昧さがノイズになりがちです。キーワード検索(BM25)を併用することで、ユーザーの意図を正確に拾い、UXを安定させることができます。 -
Re-rankingは「絞り込み」と「キャッシュ」が鍵
Re-rankerは高精度ですが計算コストがかかります。Retrieverで上位数十件に絞った後に適用するのが鉄則です。また、同一の質問に対する計算を省くため、キャッシュ(Caching) の実装も必須です。 -
ベクトルDBの選定
本番環境ではWeaviate, Qdrant, Milvusなどの専用DBが推奨されます。各DBでHybrid Searchの実装(RRFなど)が異なるため、自社のデータ特性に合うか検証が必要です。
まとめと次回予告
Day 2では、Hybrid SearchとRe-rankingを導入し、検索精度を物理的に向上させるアプローチを取りました。
しかし、ドキュメント同士の「関係性」や、複数のドキュメントにまたがる複雑な推論が必要な場合、単純な検索だけでは限界があります。
次回 Day 3 では、現在最も注目されている技術の一つである 「GraphRAG」 に挑戦します。
テキストデータをナレッジグラフ(知識グラフ)に変換し、構造化された知識として検索することで、従来のRAGでは到達できなかった深い洞察を引き出す方法を解説します。
それでは、また次回。