ナレッジベース検索で関連性のない結果が返される:チャンク戦略・Embeddingモデル・Top-K/Score閾値の連携チューニング
はじめに
Dify のナレッジベースに「確かにドキュメントは入っている」のに、ユーザーの質問に対して的外れな回答が返ってくる――これはエンタープライズ導入現場で最も頻繁に報告される問題の一つである。多くのチームはまずプロンプトを修正しようとするが、実際にはプロンプト以前の 検索レイヤー に根本原因があることが大半だ。
本記事では、Dify のナレッジベース検索における Top-K、Score Threshold、Rerank モデルの三要素を中心に、チャンク分割戦略や Embedding モデル選定まで含めた総合的なチューニング手法を解説する。
症状
以下のような挙動が見られる場合、検索レイヤーの調整が必要である可能性が高い。
| 症状 | 典型的な表面化パターン |
|---|---|
| ドキュメントに書いてあるのに「情報が見つかりません」と返される | Score Threshold が高すぎる、またはチャンク分割で文脈が切断されている |
| 質問とまったく関係ない段落が引用される | Top-K が大きすぎてノイズが混入、Rerank 未使用 |
| 似た内容が複数ヒットし、肝心の情報が埋もれる | 複数ナレッジベース間の重複、Embedding モデルの精度不足 |
| 日本語の質問に対して英語ドキュメントの断片が返る | 多言語 Embedding の精度問題、言語別ナレッジベース未分離 |
| 同じ質問でも検索結果が毎回微妙に変わる | 検索モード設定の不整合、ベクトル検索の近似探索による揺れ |
原因分析
検索パイプラインの全体構造を理解する
Dify のナレッジベース検索は、単一のパラメータで制御されるものではない。以下の多層構造を理解することが前提となる。
flowchart TD
A[ユーザーの質問] --> B[クエリ前処理]
B --> C{検索モード選択}
C -->|ベクトル検索| D[Embedding → ANN検索]
C -->|全文検索| E[キーワードマッチング]
C -->|ハイブリッド検索| F[ベクトル + 全文 並列]
D --> G[候補チャンク群 Top-N]
E --> G
F --> G
G --> H{Rerank有効?}
H -->|Yes| I[Rerank モデルで再スコアリング]
H -->|No| J[スコア順でそのまま返却]
I --> K[Top-K + Score Threshold でフィルタ]
K --> L[LLM に渡すコンテキスト]
J --> L
第1層:チャンク分割の問題
検索精度の根本はチャンクの品質にある。どれだけ検索パラメータを調整しても、チャンク自体が壊れていれば意味がない。
よくある失敗パターン:
- チャンクサイズが大きすぎる(2000トークン超):一つのチャンクに複数のトピックが混在し、Embedding ベクトルが曖昧になる
- チャンクサイズが小さすぎる(100トークン未満):文脈が失われ、単独では意味をなさない断片になる
- オーバーラップなし:段落の境界でちょうど重要な情報が切断される
- 自動分割に頼りきり:PDFの改行位置やHTMLタグの都合で意味的に不自然な位置で切れる
推奨チャンク設定:
| パラメータ | 推奨値 | 備考 |
|---|---|---|
| チャンクサイズ | 500〜1000トークン | 日本語は1文字あたり約1〜2トークン |
| オーバーラップ | 50〜100トークン | 段落境界の情報損失を防ぐ |
| 分割方式 | 段落ベース優先 | 自動(改行ベース)よりセマンティック分割を推奨 |
第2層:Embedding モデルの選定
Embedding モデルはチャンクをベクトル空間に写像する役割を担う。日本語コンテンツにおいては、モデル選定が検索精度に直結する。
日本語対応 Embedding モデル比較:
| モデル | 日本語精度 | 次元数 | 備考 |
|---|---|---|---|
text-embedding-3-large (OpenAI) | 高 | 3072 | 多言語対応、コスト高 |
text-embedding-3-small (OpenAI) | 中〜高 | 1536 | コストパフォーマンス良好 |
multilingual-e5-large | 高 | 1024 | オープンソース、自前ホスト可 |
bge-m3 (BAAI) | 高 | 1024 | 多言語・長文対応 |
cl-nagoya/sup-simcse-ja-large | 日本語特化 | 1024 | 日本語単一言語なら高精度 |
注意:Embedding モデルを変更した場合、既存のナレッジベースは再インデックスが必要である。モデル変更は既存チャンクのベクトルを自動更新しない。
第3層:検索モードの選択
Dify は高品質インデックスモードで以下の検索方式をサポートしている:
- ベクトル検索:意味的な類似度に基づく検索。口語的・曖昧な質問に強い
- 全文検索:キーワードマッチング。型番・エラーコードなど正確な文字列検索に強い
- ハイブリッド検索:ベクトル検索と全文検索を併用し、Rerank で統合する
# ナレッジベース検索設定の例
retrieval_mode: hybrid # hybrid / vector / fulltext
top_k: 5 # 最終的にLLMに渡すチャンク数
score_threshold: 0.5 # この値未満のチャンクは除外
reranking_model:
provider: cohere
model: rerank-multilingual-v3.0
第4層:Top-K・Score Threshold・Rerank の連携
ここが最も誤解されやすいポイントである。Dify 公式ドキュメントおよび GitHub Discussion(#3171)で明確に説明されている通り:
Top-K と Score Threshold は、Rerank モデルが有効な場合、Rerank 後のフィルタリングに適用される。
つまり、Rerank を有効にしている場合と無効にしている場合で、これらのパラメータの挙動が異なる。
Rerank 無効時:
ベクトル検索 → Top-K 件取得 → Score Threshold で足切り → LLM へ
Rerank 有効時:
ベクトル検索 → 初期候補 N 件取得 → Rerank で再スコアリング →
Top-K 件に絞り込み → Score Threshold で足切り → LLM へ
この違いを理解していないと、パラメータ調整が意図通りに機能しない。
典型的な誤設定パターンと診断
パターン1:Top-K が小さすぎる(Top-K = 1〜2)
問題:ユーザーの表現とドキュメントの表現にギャップがある場合、
正解チャンクが候補に入らずに漏れる
対策:Top-K を 5〜8 に拡大し、Rerank で絞り込む
パターン2:Score Threshold が高すぎる(0.8以上)
問題:「該当する情報が見つかりません」が頻発する
実際にはスコア 0.6〜0.7 の有用なチャンクが存在している
対策:閾値を 0.3〜0.5 に下げてから徐々に調整
パターン3:Rerank なしで Top-K を大きくしている
問題:類似度スコアの低いノイズチャンクが大量に LLM に渡される
コンテキストウィンドウが無関係な情報で埋まる
対策:Top-K を大きくするなら必ず Rerank を有効にする
パターン4:ハイブリッド検索で Rerank なし
問題:ベクトル検索と全文検索の結果がスコア体系の異なるまま混在
統合的なランキングができず、結果の質が不安定
対策:ハイブリッド検索には Rerank を必ず併用する
解決策
ステップ1:チャンクの品質を確認する
まず Dify のナレッジベース管理画面で、実際のチャンク内容を目視確認する。
確認ポイント:
- 一つのチャンクが一つのトピックに対応しているか
- 重要な情報が途中で切断されていないか
- ヘッダーやフッターなどの不要なテキストが混入していないか
問題がある場合は、チャンク設定を変更して再インデックスを実行する。
ステップ2:検索モードと Rerank を設定する
推奨構成:
| シナリオ | 検索モード | Rerank | Top-K | Score Threshold |
|---|---|---|---|---|
| 社内FAQ・マニュアル検索 | ハイブリッド | 有効 | 3〜5 | 0.5 |
| 技術ドキュメント検索 | ハイブリッド | 有効 | 5〜8 | 0.4 |
| 契約書・法務文書検索 | ベクトル | 有効 | 3〜5 | 0.6 |
| エラーコード・型番検索 | 全文 | 不要 | 3 | 0.3 |
| 多言語混在ドキュメント | ハイブリッド | 有効 | 8〜10 | 0.4 |
ステップ3:Rerank モデルを選定する
# Cohere Rerank(多言語対応、日本語精度高)
reranking_model:
provider: cohere
model: rerank-multilingual-v3.0
# Jina Rerank(軽量、コスト低)
reranking_model:
provider: jina
model: jina-reranker-v2-base-multilingual
ステップ4:段階的にパラメータを調整する
推奨チューニング手順:
- Top-K を大きめに設定(8〜10)して、候補が十分に入ることを確認
- Score Threshold を低め(0.3)に設定して、足切りが厳しすぎないことを確認
- Rerank を有効化して、再スコアリング後の上位結果の品質を確認
- Top-K を徐々に絞る(5〜6)
- Score Threshold を徐々に上げる(0.4〜0.5)
- 実際のユーザー質問でテストし、精度とノイズのバランスを確認
ステップ5:Workflow ノード内の検索設定を確認する
Workflow 内のナレッジ検索ノードでは、ナレッジベース本体の設定とは別にパラメータを上書きできる。この二重設定が矛盾していると、意図しない挙動になる。
# Workflow ナレッジ検索ノードの設定例
knowledge_retrieval:
dataset_ids:
- "dataset_abc123"
retrieval_mode: "multiple" # single / multiple
top_k: 5
score_threshold: 0.5
reranking:
enabled: true
model: "rerank-multilingual-v3.0"
予防策
1. ナレッジベース設計のガイドライン
- 1ナレッジベース = 1ドメインの原則を守る。異なるドメインのドキュメントを1つのナレッジベースに混在させない
- ドキュメントアップロード前に、不要なヘッダー・フッター・目次ページを除去する前処理を実施する
- 定期的にチャンク品質を抜き取り検査し、分割の妥当性を確認する
2. Embedding モデル選定チェックリスト
- 対象コンテンツの主要言語に対応しているか
- 日本語の専門用語・固有名詞を適切にベクトル化できるか
- チャンクサイズに対して最大入力トークン数が十分か
- コストと精度のバランスが運用要件に合っているか
3. 検索品質モニタリング
検索結果の品質を継続的に監視する仕組みを構築する。
# 検索品質テストスクリプトの例
test_queries = [
{"query": "有給休暇の申請方法は?", "expected_doc": "就業規則_休暇.pdf"},
{"query": "VPN接続がタイムアウトする", "expected_doc": "IT_FAQ_ネットワーク.pdf"},
{"query": "経費精算の締め日はいつ?", "expected_doc": "経理マニュアル.pdf"},
]
for test in test_queries:
results = dify_api.knowledge_retrieval(
query=test["query"],
dataset_id="your_dataset_id",
top_k=5
)
# 期待するドキュメントが上位に含まれているか確認
hit = any(test["expected_doc"] in r["document_name"] for r in results)
print(f"Query: {test['query']} -> {'PASS' if hit else 'FAIL'}")
4. 運用時のトラブルシューティングチェックリスト
- ナレッジベースのチャンク粒度は適切か(粗すぎ・細かすぎの両方を確認)
- チャンク分割で完全な文脈が切断されていないか
- Embedding モデルは対象言語に適しているか
- 複数ナレッジベース間で類似コンテンツが重複していないか
- Workflow ノードの検索設定がナレッジベース本体の設定と矛盾していないか
- Rerank モデルが有効になっているか(特にハイブリッド検索時)
- Score Threshold が厳しすぎて有効な結果を除外していないか
まとめ
検索結果が不適切な場合、「モデルがなぜ間違えたか」ではなく「システムが何を検索して何を見つけたか」を最初に確認すべきである。Dify のナレッジベース検索は、チャンク分割 → Embedding → 検索モード → Rerank → Top-K/Score Threshold の多層パイプラインであり、いずれか一つのレイヤーだけを調整しても十分な効果は得られない。
特に重要なのは、Top-K と Score Threshold が Rerank との連携で挙動が変わるという点である。この仕様を理解した上で、チャンク品質の確認から始めて段階的にチューニングすることが、安定した検索精度への最短経路となる。