RAGの精度改善手法10選【2025年最新版】
はじめまして、
株式会社dotConfにて、AIエンジニアをしている森です!
この度、会社としてZennでの発信をスタートすることになりました。
私たちは、「テクノロジーを民主化する。」というミッションのもと、AIソリューション事業とAI教育事業を行っている会社です。
日々、様々な企業のAI導入をサポートしている中で、最近特に多くご相談いただくのが RAG(Retrieval-Augmented Generation:検索拡張生成) の活用についてです。「ChatGPTのような生成AIに社内文書を学習させて、精度の高い回答システムを作りたい」というニーズが急速に高まっています。
しかし実際には、RAGの仕組みを導入しただけでは十分な精度が得られないケースが非常に多く、社内PoC(実証実験)で期待した結果を見込めないことも少なくありません。
そこで今回は、私たちがこれまでの支援経験で蓄積してきた「RAGの精度を劇的に改善する10の手法」を、基礎から応用まで具体的な実装例と合わせて解説していきます!
1. RAGとは何か?
RAG(Retrieval-Augmented Generation、検索拡張生成)とは、
「知識を探す仕組み(検索)」と「答えを文章にする仕組み(生成AI)」を組み合わせた技術です。
通常の生成AI(例:ChatGPT)だけに任せると、以下のような弱点があります:
- 学習時点の知識にしか答えられない
- 根拠のない内容(幻覚)を自信満々に答えてしまうことがある
そこで登場するのがRAGです。
AIが答える前に、まず社内文書やデータベースなどから「関連する情報」を検索して持ってきます。
その情報をもとに回答を作るため、次のようなメリットがあります:
- 最新の情報を反映できる
- 専門知識や社内固有の情報も活用できる
- 回答の根拠を示しやすい
2. なぜRAGの精度改善が重要なのか
ただし、RAGを導入したからといって自動的に正しい答えが出るわけではありません。
私たちがサポートしてきた企業でも、以下のような課題がよく発生します:
これらの問題は、検索(Retriever) と 生成(Generator) のどちらか、または両方に起因します。検索で正しい情報を取得できても、生成側が情報をうまく参照できなければ「幻覚(Hallucination)」が発生してしまうのです。
つまり、検索と生成の両方をバランスよく最適化することが、RAGを実務で活用するためには不可欠なのです。
3. RAGの基本構成と改善アプローチ
RAGの基本構成
基本的なRAGの構成は、主に以下の4つのステップです。
事前準備: 社内のPDF・Word・ナレッジベース等を事前にEmbedding(ベクトル化)して、ベクターデータベースに保存しておきます。
Step 1: 質問(検索クエリ)
ユーザーが質問をします。
➡ ここで質問文をEmbedding(ベクトル化)して、ベクターデータベースから検索する準備をします。
Step 2: ベクターデータベース(関連文書の検索)
ベクトル化した質問と、事前に準備されたベクターデータベースを比較し、意味的に近い文書を特定します。
Step 3: 検索結果(関連文書の取得)
意味的に近い文書を取り出し、質問に関連する情報を抽出します。
Step 4: 生成AI(回答の生成)
検索結果をコンテキストとして生成AIに渡し、それをもとに自然な文章で回答を作成します。
RAGの基本的なアーキテクチャ:4つのステップの流れ
RAG改善の4つのポイント
RAGの改善は、それぞれの段階で工夫することができます:
1. 質問の工夫
質問をどう表現するかで、検索精度は大きく変わります。
2. ベクターデータベース作成の工夫
文書の分割方法(チャンク化)やEmbeddingモデルの選定が検索精度に直結します。
3. 検索結果の工夫
検索手法や再ランク付けなどで、より適切な文書を取得する工夫が必要です。
4. 生成の工夫
取得した文書をどう参照し、どのように答えを構成させるかで、幻覚(Hallucination)を減らせます。
つまり、RAGの精度改善は この4つのステップでどこを改善するかを意識すること が大切です。
本記事での手法分類と構成
本記事では、実装難易度と効果を考慮して10の手法を2つのレベルに分類して紹介します:
- 【すぐ始められる改善】: 既存システムの大きな変更なしに効果が期待できる5つの手法
- 【本格的な改善】: より高い効果を得るための高度な手法5つ
なお、各手法がRAGのどの部分を改善するかも明記していますので、問題の原因に応じて優先的に取り組む手法を選択してください。
改善対象別の手法一覧
改善対象 | 手法 |
---|---|
質問 | Query Rewriting(手法7) |
ベクターデータベース | チャンクサイズ最適化(手法3)、Embeddingモデル活用(手法4) |
検索結果 | Top-k拡大(手法5)、Reranking(手法6)、Hybrid Search(手法8)、Multi-Stage Retrieval(手法9) |
生成AI | プロンプト設計(手法1)、Structured Output(手法2) |
全体最適化 | RAGAS評価自動化(手法10) |
4. 【すぐ始められる改善】実装コスト低・効果高の5つの手法
まずは既存システムを大きく変更せずに、すぐに試せる改善手法から始めましょう。
1. プロンプト設計の工夫
改善対象: 生成
実装難易度: ★☆☆☆☆ | 期待効果: 幻覚の大幅減少 | 実装時間: 1-2日
なぜ必要?
RAGシステムでも生成AIが参照文書を無視して、学習データから「想像で」回答してしまう問題が頻発します。
- 参考文書があるのに無関係な回答をする
- 文書にない情報を「確信を持って」答える
- 根拠を示さず信頼性が低い回答になる
どう改善?
プロンプトに明確な制約を組み込み、参照情報のみを使って回答するよう指示します。
プロンプト実装例
改善前のプロンプト:
質問: {query}
参考情報: {retrieved_docs}
回答してください。
改善後のプロンプト:
あなたは正確性を重視するAIアシスタントです。以下の制約を必ず守ってください:
制約:
- 提供された参考情報のみを使用して回答してください
- 情報が不足している場合は「提供された情報では回答できません」と回答してください
- 回答の根拠となる文書を必ず引用してください(例:[文書1]より)
質問: {query}
参考情報: {retrieved_docs}
回答:
プロンプトエンジニアリングについて、より体系的で実践的な内容を学びたい方は、こちらの記事もぜひご覧ください:
RAGシステムでのプロンプト改善と合わせて学ぶことで、より効果的なAI活用が可能になります!
2. Structured Outputと根拠提示
改善対象: 生成
実装難易度: ★☆☆☆☆ | 期待効果: 品質管理効率の大幅向上 | 実装時間: 1日
なぜ必要?
RAGの回答品質を人間が毎回チェックするのは現実的ではなく、自動的な品質管理が必要です。
- 回答の確信度が分からず判断が困難
- どの文書を参考にしたか不明
- 品質の悪い回答を自動で検出できない
どう改善?
回答を決められたJSON形式で出力するよう強制し、ハルシネーションを抑制しながら品質管理を自動化します。
Structured Outputの実装例
from openai import OpenAI
client = OpenAI()
# 構造化された出力形式を定義
response_format = {
"type": "json_schema",
"json_schema": {
"name": "rag_response",
"schema": {
"type": "object",
"properties": {
"answer": {"type": "string", "description": "回答内容"},
"confidence": {"type": "number", "description": "確信度(0-1)"},
"sources": {"type": "array", "items": {"type": "string"}},
"reasoning": {"type": "string", "description": "判断根拠"}
}
}
}
}
# RAGシステムでの使用例
def generate_structured_response(query, retrieved_docs):
messages = [
{"role": "system", "content": "あなたは正確性を重視するAIアシスタントです。"},
{"role": "user", "content": f"質問: {query}\n参考情報: {retrieved_docs}"}
]
response = client.chat.completions.create(
model="gpt-4o", # Structured Output対応モデル
messages=messages,
temperature=0.1,
response_format=response_format
)
return response.choices[0].message.content
3. 文書チャンクサイズの最適化
改善対象: データベース作成
実装難易度: ★☆☆☆☆ | 期待効果: 検索精度の明確な向上 | 実装時間: 半日
なぜ必要?
文書を適切なサイズに分割しないと、検索で関連性の低い大きなブロックが取得されたり、重要な情報が分散してしまいます。
- 長すぎる:無関係な情報も含んで検索精度が下がる
- 短すぎる:文脈が失われて意味が不明になる
- 境界が不適切:重要な情報が分割されてしまう
どう改善?
文書の特性に応じて最適なチャンクサイズを設定し、自然な境界で分割します。
チャンクサイズ最適化の実装例
# LangChainでの実装例
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=800, # 文字数(日本語の場合)
chunk_overlap=100, # オーバーラップ
separators=["。", "\n\n", "\n", "、"] # 日本語に最適化
)
チャンクサイズの選び方
- 短い(150-300文字): FAQ、製品仕様など具体的質問向け
- 中程度(400-800文字): 一般的な業務文書、マニュアル向け
- 長い(1000-1500文字): 技術文書、研究論文など文脈重視の内容向け
4. 高性能Embeddingモデルの活用
改善対象: データベース作成
実装難易度: ★☆☆☆☆ | 期待効果: 検索精度の大幅向上 | 実装時間: 半日
なぜ必要?
古いEmbeddingモデルでは、日本語の微妙なニュアンスや専門用語の意味を正確に捉えられず、検索精度が低下します。
- 類似した概念なのに全く違うベクトルになる
- 専門用語や固有名詞の理解が不十分
- 文脈を考慮した検索ができない
どう改善?
最新の高性能Embeddingモデルに切り替えることで、より精密な意味理解を実現します。
推奨モデル
モデル | 精度 | 速度 | コスト | 日本語対応 |
---|---|---|---|---|
OpenAI text-embedding-3-large | ★★★★★ | ★★★☆☆ | 高 | ★★★★☆ |
OpenAI text-embedding-3-small | ★★★★☆ | ★★★★☆ | 中 | ★★★★☆ |
OpenAI text-embedding-ada-002 | ★★★☆☆ | ★★★★★ | 低 | ★★★☆☆ |
Embeddingモデルの実装例
from openai import OpenAI
client = OpenAI()
def get_embedding(text):
response = client.embeddings.create(
model="text-embedding-3-large",
input=text,
dimensions=1024 # 次元数調整で速度向上可能
)
return response.data[0].embedding
5. 複数文書検索(Top-k最適化)
改善対象: 検索
実装難易度: ★☆☆☆☆ | 期待効果: 回答精度の安定化 | 実装時間: 半日
なぜ必要?
1つの文書だけに依存すると、その文書が部分的な情報しか含まない場合に不完全な回答になってしまいます。
- 重要な情報が複数の文書に分散している
- 1つの文書だけでは文脈が不十分
- 検索順位1位が必ずしも最適とは限らない
どう改善?
複数の候補文書を取得し、より豊富な情報から回答を生成します。
Top-k最適化の実装例
# 検索設定の最適化
retrieval_settings = {
"top_k": 5, # 取得文書数(3-5件が最適)
"score_threshold": 0.7, # 類似度閾値
"max_tokens": 4000 # 合計トークン上限
}
# 実装例
results = vector_store.similarity_search_with_score(
query,
k=retrieval_settings["top_k"],
score_threshold=retrieval_settings["score_threshold"]
)
設定値の目安
- 取得文書数3-5件: 一般的な用途(推奨)
- 類似度0.7以上: 品質フィルタとして有効
5. 【本格的な改善】より高い効果を狙う5つの手法
基本的な改善で効果を実感できたら、より高度な手法に挑戦してさらなる精度向上を目指しましょう。
6. Rerankingモデルの導入
改善対象: 検索結果
実装難易度: ★★☆☆☆ | 期待効果: 検索精度の顕著な向上 | 実装時間: 3-5日
なぜ必要?
ベクトル検索だけでは、質問と文書の微妙な関連度の違いを正確に判断できず、重要な文書が下位に埋もれてしまうことがあります。
- ベクトル検索の順位と実際の関連度にズレがある
- 質問の意図に最も適した文書が上位に来ない
- 文脈を考慮した詳細な関連度評価ができない
どう改善?
Rerankerモデルで検索結果を再評価し、質問により適した順序に並び替えます。
仕組み
- 通常の検索で10件程度を取得
- Rerankingで関連度を再計算
- 上位3-5件を最終的に使用
Rerankingモデルの実装例
from sentence_transformers import CrossEncoder
# Rerankingモデルの初期化
reranker = CrossEncoder('bge-reranker-v2-m3')
def rerank_search_results(query, documents):
# 1. 通常検索で多めに取得(例:10件)
initial_results = vector_store.similarity_search(query, k=10)
# 2. Rerankingで関連度を再評価
pairs = [[query, doc.page_content] for doc in initial_results]
scores = reranker.predict(pairs)
# 3. スコア順に並び替えて上位を選択
ranked_results = sorted(
zip(scores, initial_results),
key=lambda x: x[0],
reverse=True
)
return [doc for score, doc in ranked_results[:3]]
推奨モデル
- Cohere Rerank API: 高精度、日本語対応良好、商用利用向け
- jina-reranker-v1-base-en: 無料、高性能(英語特化)
- bge-reranker-v2-m3: 無料、多言語対応(日本語は限定的)
7. Query Rewriting(質問の書き換え)
改善対象: 質問
実装難易度: ★★☆☆☆ | 期待効果: 検索カバレッジの向上 | 実装時間: 2-3日
なぜ必要?
ユーザーの質問は曖昧で抽象的なことが多く、そのまま検索しても適切な文書を見つけられないことがあります。
- 「最新の情報は?」など抽象的な質問が多い
- 略語や表記ゆれで検索漏れが発生
- ユーザーの意図と検索キーワードにギャップがある
どう改善?
質問を検索に最適化された複数の表現に書き換えて、検索漏れを防ぎます。
アプローチ
- 同義語展開: 略語や表記ゆれに対応
- 複数視点: 異なる角度から同じ内容を検索
- LLM活用: 動的なクエリ生成
Query Rewritingの実装例
from openai import OpenAI
client = OpenAI()
def rewrite_query_with_llm(original_query):
"""LLMを使った高度なクエリ書き換え"""
prompt = f"""
以下の質問を検索に最適化された3つの異なる表現に書き換えてください:
元の質問: {original_query}
条件:
- 具体的なキーワードを含める
- 異なる視点から表現する
- 検索しやすい形に変換する
出力形式: JSON
{{"queries": ["書き換え1", "書き換え2", "書き換え3"]}}
"""
response = client.chat.completions.create(
model="gpt-5",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)["queries"]
def multi_query_search(original_query, vector_store):
# 1. クエリを複数パターンに展開
expanded_queries = rewrite_query_with_llm(original_query)
# 2. 各クエリで検索実行
all_results = []
seen_content = set()
for query in expanded_queries:
results = vector_store.similarity_search(query, k=3)
# 重複除去しながら結果を統合
for result in results:
content_hash = hash(result.page_content)
if content_hash not in seen_content:
all_results.append(result)
seen_content.add(content_hash)
return all_results[:5] # 上位5件を返す
8. Hybrid Search(ベクトル+キーワード検索)
改善対象: 検索結果
実装難易度: ★★★☆☆ | 期待効果: 検索精度の安定化 | 実装時間: 5-7日
なぜ必要?
ベクトル検索だけでは固有名詞や専門用語の完全一致を見逃し、キーワード検索だけでは意味的な類似性を捉えられません。
- ベクトル検索:固有名詞や専門用語に弱い
- キーワード検索:同義語や類似概念を見つけられない
- どちらか一方では検索精度に限界がある
どう改善?
両方の検索手法を組み合わせ、それぞれの長所を活用します。
なぜ効果的?
- ベクトル検索: 意味的類似性に強い(「車」→「自動車」)
- キーワード検索: 完全一致に強い(固有名詞、専門用語)
- 組み合わせ: 両方の長所を活用して検索漏れを防ぐ
Hybrid Searchの実装例
from rank_bm25 import BM25Okapi
from sentence_transformers import SentenceTransformer
import numpy as np
class HybridRetriever:
def __init__(self, documents):
self.documents = documents
self.embedder = SentenceTransformer('all-MiniLM-L6-v2')
self.bm25 = BM25Okapi([doc.split() for doc in documents])
self.doc_embeddings = self.embedder.encode(documents)
def search(self, query, alpha=0.7):
# ベクトル検索スコア
query_embedding = self.embedder.encode([query])
vector_scores = np.dot(self.doc_embeddings, query_embedding.T).flatten()
# キーワード検索スコア
bm25_scores = self.bm25.get_scores(query.split())
# スコア統合(0-1に正規化)
vector_norm = (vector_scores - vector_scores.min()) / (vector_scores.max() - vector_scores.min() + 1e-8)
bm25_norm = (bm25_scores - bm25_scores.min()) / (bm25_scores.max() - bm25_scores.min() + 1e-8)
# 重み付きスコア
combined_scores = alpha * vector_norm + (1 - alpha) * bm25_norm
# 上位5件を返す
top_indices = np.argsort(combined_scores)[::-1][:5]
return [(self.documents[i], combined_scores[i]) for i in top_indices]
# 使用例
retriever = HybridRetriever(documents)
results = retriever.search("RAGの改善方法", alpha=0.7)
重み調整の目安
- alpha=0.8: 意味的検索重視(技術文書、概念的な質問)
- alpha=0.5: バランス重視(一般的な用途)
- alpha=0.3: キーワード重視(固有名詞、専門用語が多い)
9. Multi-Stage Retrieval(段階的検索)
改善対象: 検索結果
実装難易度: ★★★☆☆ | 期待効果: 大規模データベース検索の効率化 | 実装時間: 4-6日
なぜ必要?
大量の文書がある環境では、全文書に対して高精度な検索を行うと処理時間とコストが膨大になってしまいます。
- 数万件以上の文書で全件Embeddingは処理時間が長い
- リアルタイム検索では応答速度が要求される
- 高精度モデルの計算コストを抑えたい
どう改善?
粗い検索→詳細検索の2段階で処理し、効率と精度を両立します。
Multi-Stage Retrievalの実装例
from sklearn.feature_extraction.text import TfidfVectorizer
from sentence_transformers import SentenceTransformer
class MultiStageRetrieval:
def __init__(self, documents):
self.documents = documents
self.tfidf = TfidfVectorizer()
self.tfidf_matrix = self.tfidf.fit_transform(documents)
self.embedder = SentenceTransformer('all-MiniLM-L6-v2')
def search(self, query):
# Stage 1: TF-IDFで候補を絞り込み
query_vec = self.tfidf.transform([query])
tfidf_scores = (self.tfidf_matrix * query_vec.T).toarray().flatten()
top_20_idx = tfidf_scores.argsort()[-20:][::-1]
# Stage 2: 上位候補をEmbeddingで再ランク
candidates = [self.documents[i] for i in top_20_idx]
embeddings = self.embedder.encode([query] + candidates)
query_emb = embeddings[0]
candidate_embs = embeddings[1:]
# 類似度計算して上位5件を返す
scores = [query_emb @ emb for emb in candidate_embs]
final_idx = sorted(range(len(scores)), key=lambda i: scores[i], reverse=True)[:5]
return [(candidates[i], scores[i]) for i in final_idx]
# 使用例
retriever = MultiStageRetrieval(documents)
results = retriever.search("RAGの改善手法")
適用場面
- 10,000件以上の文書: 全件Embeddingは処理時間が長い
- リアルタイム検索: 応答速度を重視する場合
- コスト最適化: 高精度モデルの使用を最小限に抑えたい場合
10. 評価・改善の自動化(RAGAS)
改善対象: 全体最適化
実装難易度: ★★★★☆ | 期待効果: 継続的改善の効率化 | 実装時間: 7-10日
なぜ必要?
RAGシステムの品質を継続的に管理するには、主観的な判断ではなく客観的な評価指標が必要です。
- 手動での品質チェックは現実的ではない
- 品質劣化を早期に発見できない
- 改善の優先順位が不明確
- データに基づかない改善は非効率
どう改善?
自動評価システムを導入し、定期的な品質測定と改善点の特定を行います。
RAGAS評価の実装例
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy
# テストデータの準備(10-20件程度から開始)
test_data = {
'question': [
"RAGの改善方法は?",
"プロンプト設計のコツは?"
],
'answer': [
"チャンクサイズ最適化とプロンプト改善が効果的です。",
"制約を明確にし、根拠の引用を求めることが重要です。"
],
'contexts': [
["RAG改善には10の手法があります...", "チャンクサイズは500-1000文字が最適..."],
["プロンプトには制約を含めましょう...", "参考文書の引用が重要です..."]
]
}
# 評価実行
results = evaluate(test_data, metrics=[faithfulness, answer_relevancy])
print(f"忠実性スコア: {results['faithfulness']:.2f}")
print(f"関連性スコア: {results['answer_relevancy']:.2f}")
6. 継続的改善のポイント
RAG改善は一度で終わるものではありません。以下の3つのポイントを意識して継続的に改善していきましょう。
1. 計画的に小さく始める
- 1つの手法から段階的に導入(一度に複数は避ける)
- 実装コストが低く効果の高い手法から優先的に着手
- 基本的な改善(プロンプト・チャンク等)→高度な改善(Hybrid Search等)の順で進める
2. 効果の測定
- 改善前後の比較を必ず実施(定量・定性の両面)
- ユーザーフィードバックの定期的な収集
- 忠実性・関連性などの客観的指標で品質を評価
3. 継続的な監視
- 月1回程度の品質チェック実施
- 「分からない」回答や検索失敗の増加を監視
- 品質低下時の原因分析と迅速な対応策実行
7. まとめ
実装優先度マトリックス
推奨順序 | 改善手法 | 実装コスト | 期待効果 | 優先度 |
---|---|---|---|---|
1 | プロンプト設計 | 低 | 高 | 🔴最優先 |
2 | チャンクサイズ最適化 | 低 | 中 | 🟡重要 |
3 | Embedding更新 | 低 | 高 | 🔴最優先 |
4 | Structured Output | 低 | 中 | 🟡重要 |
5 | Top-k調整 | 低 | 中 | 🟡重要 |
6 | Reranking導入 | 中 | 高 | 🟠次段階 |
7 | Hybrid Search | 高 | 高 | 🟠次段階 |
8 | Query Rewriting | 中 | 中 | 🔵長期 |
9 | Multi-Stage | 高 | 中 | 🔵長期 |
10 | RAGAS評価 | 高 | 中 | 🔵長期 |
今回ご紹介した10の手法を段階的に実装することで、最小のコストで最大の効果 を実現できます。まずはPhase 1から始めて、効果を確認しながら次の段階に進んでいきましょう!
次世代RAG手法への展望
基本的な改善を完了した後は、以下の先進的手法も検討できます:
AgenticRAG(エージェント型RAG)
- LLMが自律的に検索戦略を決定
- 複数回の検索・推論を組み合わせ
- 複雑な質問に対する高精度回答が可能
GraphRAG(グラフ型RAG)
- 文書間の関係性をグラフ構造で管理
- エンティティ間の関連性を活用した検索
- 構造化された知識の効率的活用
これらの手法は実装コストが高いため、基本的な改善で十分な効果を得た後の次段階として検討することをおすすめします。
最後に
最後まで読んでくださり、ありがとうございました!
この記事が少しでも皆さんの学びや気づきにつながれば嬉しいです ✨
ぜひ「いいね」と共有をお願いします!🚀
📬 仕事の相談はこちら 📬
お仕事のご相談やご依頼は、下記のフォームよりお気軽にお問い合わせください。
👉 お問い合わせフォーム
メールでのご連絡をご希望の方は、こちらまでお願いいたします。
📧 info@dotconf.co.jp
⭐ お知らせ ⭐
私たちは AI学習サービス「aipass」 も運営しています。
実践的なAIプログラミング学習や副業案件獲得支援をお届けしていますので、ぜひこちらもご覧ください!
Discussion