RAG×「クエリリライト・クエリ拡張」設計ガイド【2026年版】——HyDE・Multi-Query・Step-Back Promptingで「ユーザーの曖昧な質問」を検索可能なクエリに変換する前処理パイプライン構築

  1. はじめに——「チャンキングを最適化したのに、検索精度が頭打ち」の原因
  2. クエリリライト・クエリ拡張とは——RAGの「前処理パイプライン」
    1. RAGパイプラインにおける位置づけ
    2. 「クエリの質を上げる」とは具体的に何か
  3. テクニック①:HyDE(Hypothetical Document Embeddings)
    1. HyDEの基本アイデア
    2. なぜHyDEは精度が上がるのか
    3. HyDEの実装例(LangChain)
    4. HyDEが効くケース・効かないケース
  4. テクニック②:Multi-Query Retrieval
    1. Multi-Queryの基本アイデア
    2. なぜMulti-Queryは精度が上がるのか
    3. Multi-Queryの実装例(LangChain)
    4. Multi-Queryのコスト
  5. テクニック③:Step-Back Prompting
    1. Step-Backの基本アイデア
    2. なぜStep-Backは精度が上がるのか
    3. Step-Backの実装パターン
  6. テクニック④:会話履歴の解決(Contextual Compression)
    1. 会話履歴解決が必要な理由
    2. 会話履歴解決の実装パターン
    3. LangChainのConversationalRetrievalChain
  7. テクニック⑤:社内用語辞書との連携(クエリ拡張)
    1. 社内俗称・略称の問題
    2. 用語辞書を使ったクエリ拡張
    3. 動的な辞書管理
  8. テクニック⑥:クエリルーティング
    1. クエリルーティングが必要な理由
    2. クエリルーティングの実装パターン
    3. LangChainのRouterChain / LlamaIndexのRouterQueryEngine
  9. 主要フレームワーク別の実装パターン比較
  10. クエリリライトのコストと精度のトレードオフ
    1. 追加コストの内訳
    2. コスト削減の打ち手
    3. 精度改善の評価方法
  11. Anthropic Contextual Retrieval——2026年の標準実装
    1. Contextual Retrievalの基本
    2. クエリリライトとの組み合わせ
  12. 実装ロードマップ——「どこから手を付けるか」
    1. フェーズ1:低コスト・高効果(まず実装)
    2. フェーズ2:中コスト・高効果
    3. フェーズ3:要評価で導入判断
    4. フェーズ4:大規模システムで標準化
  13. よくある質問(Q&A)
    1. Q1. クエリリライトは必ず効果がありますか?
    2. Q2. すべてのテクニックを同時に使うべきですか?
    3. Q3. クエリリライト用のLLMは何を使うべきですか?
    4. Q4. キャッシュ戦略はどう設計しますか?
    5. Q5. 評価データセットはどう作りますか?
  14. まとめ——「クエリの質」がRAG精度を決める
  15. 参考リンク・関連記事

はじめに——「チャンキングを最適化したのに、検索精度が頭打ち」の原因

RAG(Retrieval-Augmented Generation)の検索精度を上げるために、チャンキング戦略を見直し、ハイブリッド検索を導入し、評価フレームワークを整備した——それでもユーザーから「期待した回答が返ってこない」というフィードバックが減らない。

この壁にぶつかっているチームは少なくありません。原因の多くは、インデックス側や検索器の最適化に偏り、「ユーザーが入力した質問そのものを書き換える前処理」が抜け落ちていることです。

具体的には、こんな質問がRAGに投げられています。

  • 「それってどうだっけ?」(前のターンの代名詞を解決できない)
  • うちの会社の経費精算ルール教えて」(社内俗称が文書には載っていない)
  • 「先月のあの件、どうなった?」(曖昧で検索キーワードが抽出できない)
  • 働き方改革って何?」(抽象的すぎて、具体的な文書とマッチしない)

これらは検索器の問題ではなく、クエリの問題です。チャンキングや埋め込みモデルをどれだけ最適化しても、入力クエリが曖昧なら検索精度は上がりません。

この記事では、2026年の標準実装テクニックとなりつつある「クエリリライト・クエリ拡張」の設計パターンを、HyDE・Multi-Query・Step-Back Prompting・会話履歴解決・社内用語辞書連携・クエリルーティングの6つの観点で整理します。LangChain・LlamaIndex・Difyでの実装例、コストと精度のトレードオフ、評価方法まで、実務に必要な情報を一気通貫で解説します。


クエリリライト・クエリ拡張とは——RAGの「前処理パイプライン」

RAGパイプラインにおける位置づけ

典型的なRAGパイプラインは以下の3段階で構成されます。

  1. クエリ前処理(Query Processing):ユーザーの入力を検索可能な形に変換する
  2. 検索(Retrieval):ベクトル検索・BM25・ハイブリッド検索などで関連文書を取得
  3. 生成(Generation):取得した文書をコンテキストとしてLLMが回答を生成

多くのRAG実装は、2と3を熱心にチューニングしますが、1の前処理は「ユーザー入力をそのまま使う」ことが多いのが現状です。クエリリライト・クエリ拡張は、この1番目の段階で追加のLLM呼び出しを行い、検索クエリの質を上げるテクニックの総称です。

「クエリの質を上げる」とは具体的に何か

問題のあるクエリ変換後のクエリ使う技術
「あれってどうだっけ?」「先週議論したマーケティング戦略の予算配分はどうなったか?」会話履歴解決
「経費精算のルール」「経費精算 申請手順 承認フロー 上限金額」(複数言い換え)Multi-Query
「働き方改革って何?」「日本における労働時間規制と労働環境改善政策の概要」(抽象化)Step-Back
「うちの経費精算」「株式会社○○ 経費精算規程」(社内用語展開)用語辞書連携
「最新のRAG手法は?」「RAG手法は、コンテキスト圧縮、ハイブリッド検索、リランキングなどがある」(仮想回答生成)HyDE

これらの変換を経たクエリで検索すると、ベクトル検索の精度が大きく改善します。なぜなら、埋め込み空間では「質問」と「回答」の距離が近く、「曖昧な質問」と「具体的な文書」の距離は遠いからです。


テクニック①:HyDE(Hypothetical Document Embeddings)

HyDEの基本アイデア

HyDE(ハイド:Hypothetical Document Embeddings)は、2022年にCarnegie Mellon Universityが発表した手法で、ユーザーの質問から「仮の回答」をLLMに生成させ、その仮の回答でベクトル検索するテクニックです。

「質問→検索」ではなく、「質問→仮の回答→検索」という流れを作ります。

なぜHyDEは精度が上がるのか

埋め込みモデルは「意味的に近い文章」をベクトル空間で近くに配置します。しかし、質問文と回答文は文体・構造が異なるため、ベクトル空間では意外と離れていることがあります。

  • 質問:「東京の人口は?」
  • 正解文書:「2024年時点で東京都の人口は約1,400万人である」

この2つは意味的には対応していますが、文体が違うためベクトル距離が遠くなりがちです。一方、HyDEで生成した仮の回答「東京の人口は約1,400万人です」は、正解文書と同じ「回答形式」のため、ベクトル空間で近くなります。

HyDEの実装例(LangChain)

from langchain.chains import HypotheticalDocumentEmbedder
from langchain.embeddings import OpenAIEmbeddings
from langchain.llms import OpenAI

base_embeddings = OpenAIEmbeddings()
llm = OpenAI()

# HyDEのembedder
embeddings = HypotheticalDocumentEmbedder.from_llm(
    llm=llm,
    base_embeddings=base_embeddings,
    prompt_key="web_search"  # 用途別のプロンプトテンプレート
)

# 通常のembeddings.embed_query()と同じインターフェースで使える
query_embedding = embeddings.embed_query("東京の人口は?")
# 内部で「東京の人口は約1,400万人です」のような仮回答を生成し、その埋め込みを返す

HyDEが効くケース・効かないケース

効くケース効かないケース
事実確認系の質問(「○○とは?」「○○の数字は?」)LLMが事実誤認をする可能性が高い専門領域
一般知識でカバーできるドメイン社内固有・最新情報が中心のRAG
質問文と文書の文体が大きく異なるもともと質問形式のFAQが文書側にある

注意:HyDEはLLMが「ハルシネーション」した仮回答を作る可能性があります。社内文書RAGなど、外部知識が役に立たない領域では精度が下がることもあります。必ずA/Bテストで効果を検証してください。


テクニック②:Multi-Query Retrieval

Multi-Queryの基本アイデア

Multi-Query Retrievalは、1つの質問をLLMに「複数の言い換え」に展開させ、それぞれで検索し、結果を統合する手法です。

例えば「経費精算のルールを教えて」という質問は、以下のように展開されます。

  • 経費精算の申請手順
  • 経費精算の承認フロー
  • 経費精算の上限金額
  • 経費精算規程

各クエリで検索した結果を統合し、重複を除去して上位N件を採用します。

なぜMulti-Queryは精度が上がるのか

ユーザーの1つの質問は、文書側では複数の表現で書かれていることが多いです。1つのクエリだけだと「マッチする文書」が見落とされる可能性があります。Multi-Queryで複数の表現で検索することで、ベクトル検索の「再現率(Recall)」を大きく改善できます。

Multi-Queryの実装例(LangChain)

from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(temperature=0)

retriever = MultiQueryRetriever.from_llm(
    retriever=vector_store.as_retriever(),
    llm=llm,
    # デフォルトでは3つの言い換えを生成
)

# 内部で3つのクエリに展開し、それぞれで検索、結果を統合
docs = retriever.get_relevant_documents("経費精算のルールを教えて")

Multi-Queryのコスト

Multi-Queryは1質問あたり「LLM呼び出し1回 + 検索N回」のコストがかかります。N=3の場合、検索コストは3倍、LLMコストは1回追加です。本番運用では、以下のチューニングが必要です。

  • 言い換えの数(通常3〜5が最適)
  • 各クエリの結果統合方法(Reciprocal Rank Fusion推奨)
  • キャッシュ戦略(同じ質問は再展開しない)

テクニック③:Step-Back Prompting

Step-Backの基本アイデア

Step-Back Promptingは2023年にGoogle DeepMindが発表した手法で、「具体的すぎる質問」を一段抽象化してから検索するテクニックです。

例:

  • 具体的な質問:「2023年第3四半期のiPhone 15 Proの北米での販売台数は?」
  • Step-Backクエリ:「iPhone 15シリーズの2023年の販売実績の概要」

抽象化したクエリでまず関連文書を広く取得し、その後で具体的な情報を抽出します。

なぜStep-Backは精度が上がるのか

具体的すぎる質問は、文書中のごく一部にしかマッチしません。一方、抽象化した質問は文書の「文脈」全体にマッチしやすいため、関連度の高い文書群を取得できます。

特に、複雑な推論を必要とする質問(「なぜ?」「どのように?」)で効果的です。

Step-Backの実装パターン

step_back_prompt = """
以下の質問を一段抽象化してください。
具体的な数字や固有名詞を取り除き、より広い視点での質問に変換してください。

元の質問: {original_question}
抽象化した質問:
"""

# 1. Step-Backクエリで広く検索
abstract_query = llm.invoke(step_back_prompt.format(original_question=question))
abstract_docs = retriever.get_relevant_documents(abstract_query)

# 2. 元のクエリでも検索
original_docs = retriever.get_relevant_documents(question)

# 3. 統合してLLMに渡す
context = abstract_docs + original_docs
answer = llm.invoke(f"以下の文書を参考に質問に答えてください: {context}\n質問: {question}")

テクニック④:会話履歴の解決(Contextual Compression)

会話履歴解決が必要な理由

RAGがチャットボットとして使われる場合、ユーザーは前のターンを参照する質問を投げます。

  • ユーザー:「経費精算の上限はいくら?」
  • RAG:「出張費は1日あたり10,000円が上限です」
  • ユーザー:「それを超えた場合は?」 ← この「それ」が解決できない

「それを超えた場合は?」という単独のクエリでは、ベクトル検索は何もヒットしません。会話履歴を考慮して「出張費が1日10,000円の上限を超えた場合の処理」というクエリに再構築する必要があります。

会話履歴解決の実装パターン

history_resolution_prompt = """
以下の会話履歴と最新の質問を読み、最新の質問を「単独で意味が通る完全な質問文」に書き換えてください。
代名詞や省略された主語・目的語を、会話履歴から補完してください。

会話履歴:
{chat_history}

最新の質問: {latest_question}

書き換えた質問:
"""

resolved_query = llm.invoke(history_resolution_prompt.format(
    chat_history=conversation.get_history(),
    latest_question=user_input
))

docs = retriever.get_relevant_documents(resolved_query)

LangChainのConversationalRetrievalChain

LangChainには、この処理を自動化するConversationalRetrievalChainが用意されています。

from langchain.chains import ConversationalRetrievalChain

chain = ConversationalRetrievalChain.from_llm(
    llm=llm,
    retriever=retriever,
    # 内部でcondense_question_promptを使い、会話履歴と新質問から
    # スタンドアロンな質問を生成してから検索する
)

result = chain({"question": user_input, "chat_history": history})

テクニック⑤:社内用語辞書との連携(クエリ拡張)

社内俗称・略称の問題

企業のRAGで頻発するのが、「社内で使われる略称・俗称が、正式文書に載っていない」問題です。

ユーザーの入力(俗称)文書側の表記(正式名称)
「マネ会」「マネジメント会議」
「経費シス」「経費精算システム」
「○○本部」「○○事業本部」(正式名称)
「ICT統」「情報通信技術統括部」

これらは社内の人にしか分からない表現で、ベクトル検索でもマッチしにくいです。

用語辞書を使ったクエリ拡張

社内用語辞書({"マネ会": "マネジメント会議", "経費シス": "経費精算システム", ...})を用意し、クエリに含まれる俗称を正式名称に展開(または併記)します。

def expand_query_with_glossary(query: str, glossary: dict) -> str:
    """社内用語辞書でクエリを拡張"""
    expanded = query
    for slang, formal in glossary.items():
        if slang in query:
            # 俗称を正式名称に置換、または併記
            expanded = expanded.replace(slang, f"{slang}({formal})")
    return expanded

# 使用例
query = "マネ会の議事録ある?"
expanded = expand_query_with_glossary(query, company_glossary)
# → "マネ会(マネジメント会議)の議事録ある?"
docs = retriever.get_relevant_documents(expanded)

動的な辞書管理

辞書は手作業ではなく、以下のような自動化が望ましいです。

  • 社内Wiki・Slackから略称・正式名称のペアを抽出
  • 「検索失敗(0件ヒット)したクエリ」をログ化し、辞書追加候補とする
  • LLMで「このクエリに含まれる略称・俗称を抽出してください」と前処理する

テクニック⑥:クエリルーティング

クエリルーティングが必要な理由

すべての質問をベクトル検索に投げるのは非効率です。質問の種類によって、最適な検索手段は異なります。

質問の種類最適な検索手段
「経費精算のルールは?」(概念検索)ベクトル検索
「ID 12345の注文ステータスは?」(ID検索)SQL / API直接呼び出し
「2024年の売上トップ10は?」(集計)SQL(DB直接クエリ)
「○○という固有名詞を含む文書」BM25(キーワード検索)
「最新の天気は?」(リアルタイム情報)API呼び出し(外部)

クエリルーティングは、LLMに質問内容を分類させ、適切な検索手段を選択する仕組みです。

クエリルーティングの実装パターン

routing_prompt = """
以下の質問を分類してください。

選択肢:
- VECTOR_SEARCH: 概念や説明を求める質問
- SQL_QUERY: 集計・統計・特定IDを参照する質問
- BM25_SEARCH: 固有名詞や特定の用語を含む文書検索
- API_CALL: リアルタイム情報や外部データが必要な質問

質問: {question}

分類(VECTOR_SEARCH/SQL_QUERY/BM25_SEARCH/API_CALL のいずれか):
"""

route = llm.invoke(routing_prompt.format(question=user_query))

if route == "VECTOR_SEARCH":
    docs = vector_retriever.get_relevant_documents(user_query)
elif route == "SQL_QUERY":
    docs = sql_agent.query(user_query)
elif route == "BM25_SEARCH":
    docs = bm25_retriever.get_relevant_documents(user_query)
elif route == "API_CALL":
    docs = api_tool.invoke(user_query)

LangChainのRouterChain / LlamaIndexのRouterQueryEngine

主要フレームワークには、ルーティング機能が組み込まれています。

  • LangChainMultiPromptChainRouterChain
  • LlamaIndexRouterQueryEngineSubQuestionQueryEngine
  • Dify:ワークフロー機能の「Question Classifier」ノード

主要フレームワーク別の実装パターン比較

機能LangChainLlamaIndexDify
HyDEHypotheticalDocumentEmbedderHyDEQueryTransformカスタムノードで実装
Multi-QueryMultiQueryRetrieverQueryRewriter並列検索ワークフロー
Step-Backカスタムプロンプトで実装StepBackQueryEngine(実験的)ワークフローで実装
会話履歴解決ConversationalRetrievalChainChatEngine会話変数 + LLMノード
クエリルーティングRouterChainRouterQueryEngineQuestion Classifierノード
ノーコード対応×△(一部)○(GUI完備)

選定の目安:

  • 細かいカスタマイズが必要 → LangChain
  • RAG特化で高度な機能 → LlamaIndex
  • 非エンジニアと協業・GUI重視 → Dify

クエリリライトのコストと精度のトレードオフ

追加コストの内訳

クエリリライト・拡張は、必ず追加のLLM呼び出しが発生します。本番運用では、以下のコスト試算が必要です。

テクニック追加LLM呼び出し追加検索回数レイテンシ増加
HyDE1回0回(検索クエリは1つ)+0.5〜1秒
Multi-Query (N=3)1回2回追加(合計3回)+1〜2秒
Step-Back1回1回追加(元 + Step-Back)+0.5〜1秒
会話履歴解決1回0回+0.5〜1秒
用語辞書拡張0回(辞書置換のみ)0回ほぼ0
クエリルーティング1回0回(1つの手段に振り分け)+0.5〜1秒

すべて組み合わせると、1質問あたりLLM呼び出しが3〜5回追加される可能性があります。GPT-4クラスを使うと、1クエリあたり0.05〜0.1ドル程度のコストになります。

コスト削減の打ち手

  • 用語辞書拡張は最優先:LLM呼び出しゼロでクエリ品質が改善
  • クエリリライト用は軽量モデル:GPT-4ではなくGPT-4o-mini、Claude Haiku、Gemini Flashなど
  • キャッシュ戦略:同じ質問は前処理結果をRedisにキャッシュ
  • 分岐実装:シンプルな質問は前処理スキップ(短い・代名詞なし・固有名詞ありなら直接検索)

精度改善の評価方法

クエリリライトの効果は、必ず定量的に評価してください。評価指標の例:

  • Hit Rate@K:上位K件に正解文書が含まれる割合
  • MRR (Mean Reciprocal Rank):正解文書の順位の逆数の平均
  • NDCG:順位を考慮した関連度スコア
  • End-to-End評価:最終的な回答の正確性(RAGAS、LangSmith等)

評価駆動開発(RAG Evaluation)の詳細は、こちらの記事もご参照ください。


Anthropic Contextual Retrieval——2026年の標準実装

2024年9月にAnthropicが発表した「Contextual Retrieval」も、クエリリライト・拡張の系譜にある手法です。

Contextual Retrievalの基本

各チャンクに、その文脈を説明する短い文(50〜100トークン)をLLMで生成して埋め込み、検索精度を改善する手法です。HyDEが「クエリ側を仮回答化する」のに対し、Contextual Retrievalは「文書側に文脈を付加する」発想です。

Anthropicの実験では、Contextual RetrievalとBM25を組み合わせ、さらにReranking(再ランキング)を加えることで、検索失敗率を最大67%削減できたと報告されています。

クエリリライトとの組み合わせ

Contextual Retrievalは「文書側の最適化」、クエリリライトは「入力側の最適化」であり、両者は補完関係にあります。2026年の標準実装としては、以下の組み合わせが推奨されます。

  1. 会話履歴解決でスタンドアロンな質問に変換
  2. 用語辞書で社内俗称を展開
  3. クエリルーティングで検索手段を選択
  4. 必要ならMulti-QueryまたはHyDEで検索クエリを拡張
  5. Contextual Retrieval + ハイブリッド検索(ベクトル + BM25)
  6. Rerankerで上位N件を再ランキング
  7. 取得した文書でLLMが回答生成

実装ロードマップ——「どこから手を付けるか」

すべてを一度に実装するのは現実的ではありません。投資対効果(ROI)の高い順に段階的に導入することを推奨します。

フェーズ1:低コスト・高効果(まず実装)

  • 会話履歴解決:チャットボット型RAGの必須機能。代名詞・省略の解決
  • 社内用語辞書:LLM呼び出し不要、辞書置換のみ

フェーズ2:中コスト・高効果

  • クエリルーティング:質問の種類で検索手段を分岐
  • Multi-Query Retrieval:再現率を上げたい場面で導入

フェーズ3:要評価で導入判断

  • HyDE:ドメインによって効果が分かれる。A/Bテスト必須
  • Step-Back Prompting:複雑な推論を要する質問が多いRAGで検討

フェーズ4:大規模システムで標準化

  • Contextual Retrieval:文書側最適化と組み合わせ
  • Reranker導入:CohereやBGEの再ランキングモデル

よくある質問(Q&A)

Q1. クエリリライトは必ず効果がありますか?

「必ず」効果がある手法はありません。RAGの対象ドメイン、ユーザーの質問パターン、文書の性質によって効果は異なります。必ずA/Bテストで検証してから本番投入してください。特にHyDEは、社内固有情報が中心のRAGでは精度が下がるケースもあります。

Q2. すべてのテクニックを同時に使うべきですか?

いいえ。テクニックを増やすほどコストとレイテンシが増えます。「実装ロードマップ」のフェーズ1から段階的に導入し、各段階で評価指標が改善するか確認しましょう。多くのRAGでは、フェーズ1(会話履歴解決+用語辞書)だけで体感精度が大きく改善します。

Q3. クエリリライト用のLLMは何を使うべきですか?

本回答生成には高性能モデル(GPT-4、Claude Opus等)を使い、クエリリライトには軽量・高速モデル(GPT-4o-mini、Claude Haiku、Gemini Flash等)を使うのが推奨です。クエリリライトは「文を変換するだけ」のタスクなので、軽量モデルで十分な品質が得られます。

Q4. キャッシュ戦略はどう設計しますか?

クエリリライトの結果は、入力が同じなら出力も同じになりやすいため、Redisなどのインメモリキャッシュで再利用できます。キャッシュキーには「ユーザーの元クエリ + 会話履歴のハッシュ」を使うのが一般的です。TTLは数時間〜数日で設定し、辞書更新時にはキャッシュをパージします。

Q5. 評価データセットはどう作りますか?

最低でも50〜100件の「質問+正解文書ID」のペアを作成しましょう。実際のユーザーの質問ログから抽出するのが理想です。各質問に対して「どの文書が回答に使われるべきか」を専門家が判定します。LangSmith、RAGAS、TruLensなどのツールがデータセット管理を支援します。


まとめ——「クエリの質」がRAG精度を決める

RAGの精度向上は、ついインデックス側・検索器側のチューニングに目が行きがちです。しかし、ユーザーが入力したクエリそのものが曖昧なら、どんなに高性能な検索器でも限界があります

クエリリライト・クエリ拡張は、2026年のRAG標準実装になりつつあります。重要なポイントを再掲します。

  1. 段階的に導入する:会話履歴解決と用語辞書から始め、効果を測りながら追加
  2. 必ず評価する:A/Bテストと定量指標(Hit Rate、MRR、NDCG)で検証
  3. コストを管理する:軽量モデルとキャッシュでLLM呼び出しを最適化
  4. 文書側最適化と組み合わせる:Contextual Retrievalやハイブリッド検索と併用

RAGは「インデックス×検索器×クエリ前処理×回答生成」の総合力で精度が決まります。前処理パイプラインを侮らず、ユーザー入力の質を上げることが、これからのRAG実装で差をつけるポイントです。


参考リンク・関連記事

免責事項:本記事は2026年4月時点の公開情報に基づく技術解説であり、特定のRAG実装における動作を保証するものではありません。本番環境への導入前には、必ず自社のデータと評価基準で検証を行ってください。各フレームワーク・ツールのバージョンによってAPIや動作が変わる可能性があるため、最新の公式ドキュメントを併せてご参照ください。

コメント

タイトルとURLをコピーしました