クエリ拡張に使うLLMの違いは、検索性能にどれくらい効くのか

こんにちは。 Legalscape Labsチームの薄羽です。

検索性能を上げるためにLLMを使うとき、「どのモデルを使うべきか」は意外と悩ましい問題です。今回はその中でも、実装しやすい クエリ拡張 に絞って、モデル選びが検索結果にどれくらい効くのかを見てみます。

背景

RAGの文脈において、「クエリを拡張させるとrecallが上がる」という話はもはや手垢のついた定番のテクニックになっています。検索クエリをLLMに渡し、関連語や言い換え、補足的な観点を生成させて検索に投げ込むことで、ユーザーの素朴なクエリだけでは拾いきれないドキュメントを取りこぼさずに済む、というアプローチです。様々な検索システムに組み込みやすく、単語ベースの検索システムでもLLMの力を活かして性能向上を狙うには、お手軽な手法です。 ただ、実務でこれを組み込もうとした時に、ひとつ素朴な疑問が湧いてきます。

このクエリ拡張は、どのレベルのLLMでやる必要があるのか? という問いです。

クエリ拡張というタスクが本質的にシンプルなものなのであれば、軽量で安価なモデルでも十分こなせるはずです。一方で、ドメイン知識や文脈理解を要する難しいタスクなのだとすれば、大きめのLLMを使う価値が出てくるかもしれませんが、処理時間もコストも増大します。

今回は、このトレードオフを実践的に探ってみることにしました。利用しやすい大手のLLM APIを実際に叩いて、モデル規模と検索性能の関係を見てみます。

実際に実務上での性能を評価するなら、各自が実サービスのデータで検証するのが一番です。とはいえ、社外に公開しづらいデータだったり、そもそも評価セットの構築自体が難しかったりと、再現可能な形で共有するにはハードルは高くなりがちです。今回は公開データを使った一例として、皆さんが自社のシステムでクエリ拡張のモデル選定を検討する際の参考になれば幸いです。

どうやって測るか

ここでは、FRAMESというデータセットを使用して、いくつかのLLMでクエリ拡張を行い、クエリ拡張有無の比較・LLMごとの性能比較を行います。

使用するデータセット:FRAMES

FRAMESは Krishna et al. による NAACL 2025 の論文 Fact, Fetch, and Reason: A Unified Evaluation of Retrieval-Augmented Generation で提案されたデータセットです。Factuality, Retrieval, And reasoning MEasurement Set の略で、RAGシステムが「必要な事実を検索し、複数の情報を統合し、正しく推論して答える」能力をまとめて評価するためのデータセットです。

FRAMES の特徴は、質問が単純な一問一答ではないことです。多くの問題では、複数の Wikipedia 記事を参照し、それぞれから得られる事実を組み合わせないと答えに到達できません。質問には質問のタイプとして reasoning type というラベルが付与されており、複数の制約の交差で答えを絞る Multiple Constraints、計数・比較・算術を含む Numerical Reasoning、時系列上の関係を扱う Temporal Reasoning、infobox や表から値を読む Tabular Reasoning、最後にローマ数字化などの変換を行う Post-Processing があります。なお、各質問は単一カテゴリに排他的に分類されるわけではなく、複数の reasoning type を同時に持つことがあります。

例えば、データセットには次のような質問があります。

How many years earlier would Punxsutawney Phil have to be canonically alive to have made a Groundhog Day prediction in the same state as the US capitol?

Punxsutawney Phil とはウッドチャック(Groundhog)という動物の個体の名前で、ペンシルベニア州におり、どうも天気予報をするらしい(?)です。 このため、この問題に答えるには、Punxsutawney Phil に関する記事と United States Capitol に関する記事を参照する必要があります。Punxsutawney Phil の最初の Groundhog Day prediction が 1887 年であること、また米国議会が 1800 年までペンシルベニア州フィラデルフィアに置かれていたことを結びつけ、1887 - 1800 = 87 という差を計算します。つまり、単にキーワードが一致する記事を1本見つければよいのではなく、複数記事の参照、時系列の解釈、数値計算が同時に必要になります。

公開されている FRAMES の test split には 824 問が含まれています。各問には、人手で付与された正解回答に加えて、その回答に必要な Wikipedia 記事のURLリスト(平均は約 3.20 本)が付与されており、今回はこのリストをクエリに対して検索されるべき文書(適合文書)として扱います。

論文中の実験

論文自体の主眼は、検索コンポーネント単体の検索指標を測ることではなく、最終回答まで含めた end-to-end なRAG性能の評価にあり、論文ではクエリ拡張やmulti-stepな検索をしていますが、検索ステップの性能は見ていません。

論文中では、Gemini-Pro-1.5-0514 が、検索なしの Naive Prompt で 0.408、BM25で上位2記事を入れた場合で 0.452、上位4記事を入れた場合で 0.474、gold Wikipedia 記事をすべて与える Oracle Prompt で 0.729 と報告されています。さらに、LLMに複数回検索クエリを生成させる設定では、5回の検索ステップを入れることで 0.66 まで改善しています。

今回は、FRAMES の最終回答の正誤を評価するのではなく、各質問と gold Wikipedia ページの対応を使って、クエリ拡張によって検索段の性能がどの程度変わるかを見ます。具体的には、LLMごとに生成した拡張クエリを検索に投入し、Recall@k、Hit@k、nDCG といった検索指標で比較します。論文が主に扱っている end-to-end の回答性能ではなく、その手前にある検索段の数字を切り出して見る、という位置づけです。

なぜこれを選んだのか

FRAMES は正解のwikipediaページは人手で作られたもので、かつ質問が複雑です。 質問が複雑であれば、検索意図をdecomposeするようなクエリ拡張が効果を発揮しやすいだろうということと、「質問の回答に必須な情報ソースが複数ある」というのは、我々が普段扱う法律ドメインの質問に近い設定であるため、選定しました。

実験方法・設定

今回の検索実験で使うデータは、次のとおりです:

項目 内容 件数
検索対象 英語版 Wikipedia のページダンプ 約650万ページ
クエリ FRAMES の質問文 824問
適合文書集合 各質問に紐づく gold Wikipedia page list 2〜11件/問(平均約3.20件)

タスクとしては、クエリを入力として、検索対象から適合文書集合を検索するというタスクになります。 今回は、適合文書集合中の適合度(qrel)は1として扱い、各種検索指標を計算します。

今回は実験を単純化するため、1-hop のクエリ拡張のみを扱います。FRAMES 論文で検証されているような、検索結果を見て次の検索クエリを再生成する multi-step search planning は使いません。各質問に対してLLMで拡張クエリを一度だけ生成します。

検索器はBM25に固定します。ここでは「同じ単語ベース検索に対して、クエリ拡張に使うLLMを変えると何が変わるか」に絞って見ます。

比較するLLMモデルは以下の6つです。

サイズ Gemini OpenAI
gemini-3.5-flash openai-gpt-5.4
gemini-3-flash openai-gpt-5.4-mini
gemini-3.1-flash-lite openai-gpt-5.4-nano

これに、ベースラインとしてクエリ拡張を行わない手法 bm25-only を加えて実験します。

当初は gemini-3.1-pro も候補にしていましたが、Google公式ブログでは gemini-3.5-flashGemini 3.1 Pro を一部のエージェント・推論系ベンチマークでも上回り、かつgemini-3.5-flash の方が低価格であるためgemini-3.5-flash を採用しました。

実装

プロンプトは論文の search planning 設定を参考に設計しました。few-shotの例示と多様性・重複の指示、reasoningを行なっています。 全てのLLMの入力には同じプロンプト、スキーマを使用しています。実際に使用したプロンプトとStructured Outputのスキーマは以下のとおりです:

使用したプロンプト

You are a search query planner for a BM25 retriever over Wikipedia. The user's
question is multi-hop: it requires combining facts from multiple Wikipedia
articles. Your job is to output a SET of {n} keyword queries that, taken
together, will retrieve every fact needed to answer the question.

# Examples of good query sequences

Example 1
Question: Who directed the highest-grossing film of 2000?
Reasoning: I first need to find the highest-grossing film of 2000 (one fact),
then that film's director (another fact). Two queries — each on a different
sub-fact.
Queries:
- highest-grossing films of 2000
- Cast Away 2000 director

Example 2
Question: When was the country that hosted the 2014 FIFA World Cup founded?
Reasoning: I need (a) the host country, (b) its founding/independence date,
and possibly (c) general history. Three different sub-facts.
Queries:
- 2014 FIFA World Cup host country
- Independence of Brazil
- history of Brazil founding

Example 3
Question: How old was the second US president's wife when she died?
Reasoning: Identify the second US president, then his wife, then her birth
and death dates. Distinct entities, distinct queries.
Queries:
- list of presidents of the United States
- John Adams biography
- Abigail Adams birth death

# Counter-examples (DO NOT produce queries like these)

BAD (paraphrases of each other — they all hit the same article):
- Dewey Decimal Classification Jane Eyre
- Dewey Decimal Classification number for Jane Eyre
- Jane Eyre Dewey Decimal code

GOOD (each targets a distinct sub-fact):
- Jane Eyre Charlotte Brontë publication year
- Dewey Decimal Classification fiction
- Library of Congress classification Jane Eyre

# Current task

Question:
{question}
{context_section}{prev_queries_section}
First, in the `reasoning` field, enumerate the sub-facts you still need to
retrieve in order to answer the question, and explain why each query targets
a distinct sub-fact (2-4 sentences).
Then, in the `queries` field, output exactly {n} short keyword queries that
together cover those sub-facts.

Diversity requirements (HARD constraints — the {n} queries form a SET):
- Each query MUST target a DIFFERENT sub-fact / entity / constraint than the
  other {n_minus_1} queries. If two queries would resolve to the same Wikipedia
  article or the same attribute, REPLACE one with a query about another sub-fact.
- Do NOT paraphrase, rephrase, or restate the same idea in different words.
- Do NOT repeat or paraphrase any query already listed under "Queries you have
  already issued" above, nor target articles already listed under "Articles
  already retrieved".
- Together, the {n} queries should COVER as many of the question's sub-facts
  as possible.

Style:
- Use canonical Wikipedia-style entity names.
- Use plain keywords (no full sentences, no question marks).

使用したスキーマ

{
    "type": "object",
    "properties": {
        "reasoning": {
            "type": "string",
            "description": (
                "観点を列挙。質問のどの sub-fact / entity / constraint を "
                "それぞれのクエリで引きたいか、なぜそれが distinct なのかを "
                "短くまとめる (1-4 文)。"
            ),
        },
        "queries": {
            "type": "array",
            "description": (
                f"BM25 で検索する {n} 個のキーワードクエリ。互いに別の "
                "sub-fact を狙うこと。Wikipedia の正式表記を使い、疑問符は不要。"
            ),
            "items": {"type": "string"},
            "minItems": n,
            "maxItems": n,
        },
    },
    "required": ["reasoning", "queries"],
    "propertyOrdering": ["reasoning", "queries"],
    "additionalProperties": False,
}

今回は、以下の3つの問いを立て、実験・分析をしてみます。

  1. クエリ拡張に使うLLMによって検索性能に差が出るか

    評価指標は Recall@k、Hit@k、nDCG@k です。特に、FRAMES では各質問に複数の gold Wikipedia ページが付与されているため、必要な記事をどれだけ検索結果に含められるかを見る Recall@k を重視します。

  2. 拡張クエリの多様性に差が出るか

    テキスト上の多様性として Distinct-n や Self-BLEU を見ます。また、意味的な多様性として拡張クエリ埋め込み間の平均ペアワイズ cosine 類似度を計算します。さらに、拡張クエリごとに検索された文書集合の重複率も確認します。

  3. 各推論タイプごと検索性能に差が出るか

    FRAMES には Multiple Constraints、Numerical Reasoning、Temporal Reasoning、Tabular Reasoning、Post-Processing などの推論タイプが付与されています。全体平均だけでなく、推論タイプごとにも検索指標を集計し、特定の問題タイプでモデル差が大きくなるかを見ます。

結果

1. クエリ拡張に使うLLMによって検索性能に差が出るか

前提として、全てのケースで、クエリ拡張ありの手法の方がなし手法を上回っています。これはデータセットの設計上期待通りです。 加えて、全てのモデルで Recall は@10まで増やしていくと順調に伸びていくことがわかります。つまり簡単すぎて上位4件くらいで取り切れてしまうような質問ばかりではないと言えそうです。 その上で、特に@10において最も性能の高い手法はgemini-3.5-flashでした。 gemini-3.5-flash だけでなく、gemini系統のモデルは大体近い性能をしていそうですが、openai 系のモデルとは差が見て取れます。 Recall@10では、openai-5.4-mini, nano はほぼ同等の性能であり、gemini系統のモデルと比較して大きく差が開いています。

コストパフォーマンス

CloudベースのLLMを使う上で、料金も重要な要素です。ここはあまり研究では語りにくい部分であり、せっかくなのでコストを考慮した時のパフォーマンスを比較してみましょう。 図は、横軸が推定APIコスト、縦軸が Recall@10 を表しています。丸の大きさはクエリ拡張1回あたりの平均 latency です。ただし latency は実行環境やタイミング等の影響を受けやすいため、厳密な速度比較ではなく、今回の実行ログにおける参考値として見てください。

これを見ると、gemini-3.1-flash-lite の優秀さが際立ちます。 同価格帯である gpt-5.4-nano よりも性能として一回り上で、約3倍のコストがかかっている gemini-3-flash に近い性能を出せています。 本当は検索のコストというのは費用だけで語られることは少なく、今回は行っていませんが、速度による比較も入れて評価したいところです(一方で、gemini-3.1-flash-lite は出力までが早いモデルであるため、gemini-3.1-flash-lite の優秀さが際立つ結果になるのではないかと期待できますが)。

これはあくまで今回のタスク(クエリ拡張(生成数3)を使ったBM25の検索)の結果ということであり、タスクの種類・難易度によってパフォーマンスの評価は大きく変わり、従ってコストパフォーマンスの結果も大きく変わるであろう点に注意が必要です。

2. 拡張されるクエリの多様性に差が出るか

ここでは、生成されたクエリの多様性の指標として、Distinct-1, 2、Self-BLEU, 埋め込みのcosine類似度を計算しています。 埋め込みには gemini-embedding-2を使用しました。

gemini-3.5-flash が検索の性能としては最も高く出ていましたが、多様性評価の結果を見ると、必ずしも gemini-3.5-flash が最も高くなるという結果にはなりませんでした。 一方で、5.4-nano, 5.4-mini の多様性が低く出ていることからもわかるように、性能が一回り変わると、多様性の指標の部分でも違いが見て取れそうです。

加えて、生成されたクエリでの検索結果の重複を測ったものが "Doc overlap ratio" です。 これは高いほど検索結果の重複度が高いことを示しています。 これを見ると、5.4-nano, 5.4-mini が重複が多いことは他の指標と整合しますが、gemini-3-flashが最も重複が低くなり文書集合的な多様性が高くなる結果となりました。 生成されたクエリの多様性指標ではそこまで目立っていないことから、このあたりは誤差なのかもしれません。

3. 各推論タイプごと検索性能に差が出るか

最後に、今回クエリに対して推論タイプというラベルが付与されていました。 このラベルごとに Recall@10 を集計し、差が出るかを見てみます。

このグラフを見ると、どの推論タイプでも、特別性能順位は大きく変わっていないことが見て取れます。 ここでは、さらにLLMごとの性能差に加えて、クエリ拡張あり vs クエリ拡張なし という視点で見てみます。 以下の表は、各手法ごとに クエリ拡張なし から何% recall@10 が改善したのかを推論タイプごとに示した表です:

bm25-only を基準とした gain% (recall@10) (avg = クエリ拡張各手法の gain% の平均)

reasoning type bm25-only recall@10 gemini-3.1-flash-lite gain% gemini-3-flash gain% gemini-3.5-flash gain% openai-5.4-nano gain% openai-5.4-mini gain% openai-5.4 gain% avg gain%
Overall 0.2974 +31.0% +38.5% +41.9% +15.7% +17.8% +32.2% +29.5%
Tabular reasoning 0.2166 +56.7% +76.6% +64.7% +38.9% +37.8% +60.6% +55.9%
Multiple constraints 0.2798 +35.4% +48.9% +47.9% +18.1% +19.7% +38.4% +34.7%
Temporal reasoning 0.2747 +31.4% +36.6% +39.7% +16.6% +17.8% +34.3% +29.4%
Post processing 0.3007 +24.6% +32.2% +35.2% +11.4% +13.6% +31.2% +24.7%
Numerical reasoning 0.3090 +24.9% +28.7% +33.4% +10.9% +9.0% +23.0% +21.7%

"avg gain%" はクエリ拡張あり時の平均改善率ですが、これを見ると "Tabular reasoning"が目立って改善していることがわかります。 具体的に、クエリ拡張で何が起きているのか、この"Tabular reasoning"の質問を例に見てみましょう。 以下はTabular reasoningのクエリとその時の拡張クエリ例です:

質問: I am thinking of a Ancient Roman City. The city was destroyed by volcanic eruption. The eruption occurred in the year 79 AD. The volcano was a stratovolcano. Where was the session held where it was decided that the city would be named a UNESCO world heritage site? (自動翻訳:古代ローマの都市を一つ思い浮かべています。その都市は火山の噴火によって滅びました。噴火が起きたのは西暦79年のことで、火山は成層火山でした。さて、その都市がユネスコ世界遺産に登録されることが決定された会議は、どこで開催されたのでしょうか?)

生成されたクエリ

  • gemini-3.1-flash-lite
    • Pompeii UNESCO World Heritage Site
    • UNESCO World Heritage Committee session locations
    • Pompeii eruption 79 AD history
  • gemini-3-flash
    • Archaeological Areas of Pompeii, Herculaneum and Torre Annunziata
    • 21st session of the World Heritage Committee
    • List of World Heritage Committee sessions
  • gemini-3.5-flash
    • Pompeii UNESCO World Heritage
    • List of World Heritage Committee sessions
    • 21st session of the World Heritage Committee
  • openai-5.4-nano
    • Pompeii UNESCO World Heritage session held at
    • Pompeii destroyed by eruption 79 AD
    • UNESCO World Heritage Committee 1979 session held at
  • openai-5.4-mini
    • Pompeii
    • UNESCO World Heritage Sites in Italy
    • World Heritage Committee session
  • openai-5.4
    • Pompeii AD 79 eruption ancient Roman city
    • Archaeological Areas of Pompeii Herculaneum and Torre Annunziata UNESCO
    • World Heritage Committee 21st session Naples 1997

この質問では、最終的に "World Heritage Committee" のページから、Pompeii が世界遺産に指定された会議の開催地を抜き出す必要があります。

生成されたクエリを見ると、どのモデルも「言及されている古代ローマ都市 = Pompeii」までは内部知識で補えているようでした。ただし、その知識の使い方には差があります。gemini-3.1-flash-liteopenai-5.4 は Pompeii 自体や噴火の背景を調べるクエリも生成している一方、gemini-3.5-flashgemini-3-flash は、より直接的に世界遺産登録や World Heritage Committee の会議に向かうクエリを生成していました。pompeii自体は全てのllmの内部知識にはあるようですが、質的に見るとその知識の使い方のような面でやや差が出ているように見えます。

一方で、この違いは検索指標には大きく出ていません。これは、FRAMES の gold Wikipedia page list には、推論過程で参照されることを想定した Pompeii や噴火関連のページも含まれているためだと思われます。このような生成されるクエリの質的な違いはあるものの、今回の検索指標だけではその差が見えにくいケースもありそうです。

まとめ

今回の実験では、BM25に対する1-hopのクエリ拡張の実験を行い、どのLLMを使ってもクエリ拡張なしよりRecall@10を改善しました。 一方で、モデルごとの差は小さくなく、Gemini系のモデルは検索性能・コストパフォーマンスの両面で良い結果になりました。

今回はBM25に限定して実験しましたが、dense retriever や hybrid search では クエリ拡張の効き方が変わる可能性があります。特に dense retriever では、語彙の追加よりも意味的な焦点のずれが効きやすいため、別途検証が必要です。

また、今回は検索性能とAPI料金を中心に見ましたが、実サービスではレイテンシも重要です。検索前段で毎回LLMを呼ぶ以上、モデルごとの応答速度や並列化のしやすさも含めて評価する必要があります。加えて、今回は1-hopのクエリ拡張に絞りましたが、FRAMESのような複雑な質問では multi-step search planning の方が本質的に向いている可能性があります。

We Are Hiring!

Legalscapeでは、単に汎用的なLLMを導入するにとどまらず、リーガルという「一分の隙も許されない」高度な専門領域において、AIの限界を特定し、それを克服するための挑戦を続けています。法制度の複雑さに技術で挑み、信頼できるリーガルAIを社会に実装していく。この技術的挑戦を共に楽しんでくれる仲間を募集しています!