# 本番RAGはなぜ失敗するのか：精度を実用品質に上げる設計と、発注者が要求すべきこと

> デモでは動いたRAG（検索拡張生成）が、本番で「誤答する・遅い・情報が漏れる」のはなぜか。素朴なRAGが失敗する典型的な落とし穴（検索精度・チャンク化・リランク・評価・アクセス制御）と、それを実用品質に上げる設計を、専門商材の誤答を構造的に排除したRAG音声接客の実例とハイブリッド検索の実装から解説します。

- 公開日: 2026-06-25
- 著者: 友田 陽大
- タグ: 生成AI, RAG, pgvector, セキュリティ, 発注, アーキテクチャ設計
- URL: https://tomodahinata.com/blog/production-rag-pitfalls-accuracy-improvement-guide

## 要点

- RAGがデモで動いて本番で失敗するのは『検索（Retrieval）の質』が低いから。LLMの賢さではなく、渡す根拠の質が精度を決める
- 素朴なベクトル検索だけでは不十分——キーワード検索と組み合わせるハイブリッド検索＋リランクが本番の標準
- チャンク化（文書の分割）の設計が精度を大きく左右する。粗すぎても細かすぎても根拠が劣化する
- マルチテナントRAGでは『他社の文書が検索結果に混ざる』情報漏洩が起きうる——アクセス制御を検索層に組み込む
- 評価（精度測定）の仕組みがないRAGは改善できない。発注時は『精度をどう測るか』を必ず要求する

---

最初に結論を述べます。**RAG（検索拡張生成）がデモでは動くのに本番で「誤答する・遅い・情報が漏れる」のは、LLMが賢くないからではありません。「検索（Retrieval）の質」が低いからです。** RAGの精度は、AIモデルの賢さではなく、**AIに渡す「根拠（コンテキスト）」の質**でほぼ決まります。間違った根拠を渡せば、どんなに賢いモデルでも間違えます。素朴に「ベクトルDBに文書を入れて、類似検索した結果を渡す」だけのRAGは、本番では高い確率で精度不足に陥ります。

本記事は、私が**RAGで「専門商材の誤答を構造的に排除」した音声接客AI**を本番運用した経験をもとに、(1) 素朴なRAGが失敗する典型的な落とし穴、(2) それを実用品質に上げる設計（ハイブリッド検索の実装付き）、(3) 発注者が要求すべきこと、を整理します。RAGそのものを採用すべきかの判断は[RAG vs ファインチューニングの記事](/blog/rag-vs-fine-tuning-cost-effectiveness-decision-guide)を、より深い実装は[pgvectorによる本番RAG](/blog/pgvector-postgres-production-rag-hybrid-search)を参照してください。

---

## 1. なぜ「素朴なRAG」は本番で失敗するのか

RAGのプロトタイプは、驚くほど簡単に作れます。文書をベクトルDBに入れ、質問をベクトル化して類似検索し、ヒットした文書をLLMに渡す——これで「それらしく」動きます。問題は、この素朴な構成が**本番の多様な質問**に晒されたとき、精度が大きく崩れることです。

失敗は、決まった場所で起きます。

| 落とし穴 | 何が起きるか |
|---|---|
| **検索精度の不足** | ベクトル類似だけでは、固有名詞・型番・略語が拾えず、根拠が外れる |
| **チャンク化の失敗** | 文書の分割が粗い／細かいと、根拠が断片化・希釈される |
| **リランクの不在** | 検索上位が必ずしも「最も答えに役立つ」順ではない |
| **評価の不在** | 精度を測れないので、改善のしようがない |
| **アクセス制御の欠落** | マルチテナントで他社の文書が結果に混ざる（情報漏洩） |
| **鮮度の管理不足** | 古い文書が根拠になり、最新情報と矛盾する |

「LLMをもっと賢いモデルに変えれば直る」と考えがちですが、**根拠が間違っていれば、モデルを変えても直りません**。直すべきは検索層です。

---

## 2. 落とし穴①：ベクトル検索だけでは足りない → ハイブリッド検索

最も多い失敗が、「ベクトル類似検索だけ」に頼ることです。ベクトル検索は「意味的に近い」文書を見つけるのは得意ですが、**固有名詞・型番・専門用語・略語の完全一致**が苦手です。「型番 XR-200 の仕様」と聞かれたとき、ベクトル検索は「似た雰囲気の別の型番」を拾ってしまうことがあります。

本番の標準解は、**ハイブリッド検索**——ベクトル検索（意味）とキーワード/全文検索（完全一致）を組み合わせ、両者の結果を統合する設計です。

PostgreSQL（pgvector）での実装例を示します。ベクトル検索と全文検索を別々に走らせ、**Reciprocal Rank Fusion（RRF）**で順位を統合します。アクセス制御（テナント分離）を**検索クエリそのものに組み込む**のが、セキュリティ上の要点です。

```ts
interface RetrievedChunk {
  readonly id: string;
  readonly content: string;
  readonly score: number;
}

interface HybridSearchParams {
  readonly tenantId: string;          // アクセス制御：必ず検索条件に含める
  readonly queryEmbedding: number[];  // 質問のベクトル
  readonly queryText: string;         // 質問の原文（全文検索用）
  readonly limit: number;
}

const RRF_K = 60; // RRFの平滑化定数（順位の影響を緩やかにする慣行値）

/**
 * ベクトル検索と全文検索を統合するハイブリッド検索。
 * - tenant_id を WHERE に必ず含め、他テナントの文書を構造的に除外（情報漏洩を防ぐ）
 * - パラメータ化クエリのみ（SQLインジェクション対策）
 * - 2系統の順位を Reciprocal Rank Fusion で統合し、意味一致と完全一致の両取り
 */
export async function hybridSearch(
  db: Database,
  params: HybridSearchParams,
): Promise<readonly RetrievedChunk[]> {
  const { tenantId, queryEmbedding, queryText, limit } = params;

  const rows = await db.query<RetrievedChunk & { rrf: number }>(
    `
    WITH vector_hits AS (
      SELECT id, content,
             ROW_NUMBER() OVER (ORDER BY embedding <=> $2) AS rank
      FROM chunks
      WHERE tenant_id = $1                       -- アクセス制御は検索層で強制
      ORDER BY embedding <=> $2                  -- コサイン距離で近い順
      LIMIT 50
    ),
    keyword_hits AS (
      SELECT id, content,
             ROW_NUMBER() OVER (
               ORDER BY ts_rank_cd(content_tsv, plainto_tsquery('simple', $3)) DESC
             ) AS rank
      FROM chunks
      WHERE tenant_id = $1
        AND content_tsv @@ plainto_tsquery('simple', $3)  -- 全文検索（完全一致に強い）
      LIMIT 50
    )
    SELECT COALESCE(v.id, k.id) AS id,
           COALESCE(v.content, k.content) AS content,
           -- Reciprocal Rank Fusion: 1/(k+rank) を両系統で合算
           COALESCE(1.0 / ($4 + v.rank), 0) + COALESCE(1.0 / ($4 + k.rank), 0) AS rrf
    FROM vector_hits v
    FULL OUTER JOIN keyword_hits k ON v.id = k.id
    ORDER BY rrf DESC
    LIMIT $5
    `,
    [tenantId, toVector(queryEmbedding), queryText, RRF_K, limit],
  );

  return rows.map(({ id, content, rrf }) => ({ id, content, score: rrf }));
}
```

私の音声接客AIでも、専門商材の型番や固有名詞を正しく拾うために、意味検索と完全一致検索を統合する設計にしました。「誤答を構造的に排除」できたのは、モデルを賢くしたからではなく、**渡す根拠の質を検索層で担保した**からです。

---

## 3. 落とし穴②：チャンク化とリランク

### チャンク化（文書の分割）

RAGでは、長い文書を「チャンク」に分割して索引します。この分割設計が精度を大きく左右します。

- **粗すぎる**（1チャンクが長い）→ 関連箇所が無関係な文章で薄まり、根拠がぼやける。
- **細かすぎる**（1チャンクが短い）→ 文脈が失われ、断片だけでは意味をなさない。

実務では、**意味のまとまり（見出し・段落・条項）でチャンク化し、隣接チャンクと少し重ねる（オーバーラップ）**のが定石です。文書の種類（マニュアル・規程・FAQ・チャット履歴）ごとに最適な分割は変わるため、ここはチューニングが要ります。

### リランク（再順位付け）

検索の上位が、必ずしも「答えに最も役立つ順」とは限りません。そこで、検索で取った候補（例: 上位50件）を、**より精密なモデルで「質問への関連度」を測り直して並べ替える**（リランク）。これにより、LLMに渡す最終的な根拠の質が上がります。コストと精度のトレードオフですが、精度がシビアな業務では効果が大きい工程です。

---

## 4. 落とし穴③：アクセス制御という「静かな情報漏洩」

マルチテナント（複数の顧客・部門が同じ基盤を使う）RAGで、最も危険なのが**アクセス制御の欠落**です。全社・全顧客の文書を1つのベクトルDBに入れ、検索時にテナントで絞り込んでいないと、**A社の質問にB社の社外秘文書がヒットして根拠として渡される**——という情報漏洩が、静かに起こりえます。

これは「あとから気をつける」では防げません。前章のコード例のように、**テナントIDを検索クエリそのものの条件に組み込み、構造的に他テナントの文書を除外**する必要があります。さらに、ユーザーの閲覧権限に応じて見られる文書を絞る（行レベルのアクセス制御）ことも、業務システムでは必須です。

> **発注者への含意**: RAGを発注するとき、「他の顧客・部門の文書が、検索結果に混ざらない保証はどうなっていますか？」と必ず質問してください。これに「テナントIDを検索条件に組み込み、構造的に分離しています」と答えられない相手は、情報漏洩リスクを抱えています。決済における[冪等性](/blog/payment-double-charge-prevention-idempotency-procurement-guide)と同じく、正しさは「運用の注意」ではなく「構造」で担保すべきです。

---

## 5. 落とし穴④：評価がなければ改善できない

最後に、最も見落とされがちで、最も重要な落とし穴——**評価（精度測定）の仕組みがない**ことです。

「なんとなく良くなった気がする」では、RAGは改善できません。本番品質のRAGには、

- **代表的な質問と「正解の根拠・回答」のセット**（評価用データセット）を用意し、
- **検索が正しい根拠を引けているか（Retrieval精度）**と、**回答が根拠に忠実か（幻覚していないか）**を、
- **変更のたびに自動で測る**

仕組みが要ります。これがあって初めて、「チャンク化を変えたら精度が上がった／下がった」を数字で判断でき、改善が回ります。放送局向けの生成AI考査支援では、**グラウンディング由来の引用を回答に付与**し、「どの文書を根拠にしたか」を追跡可能にしました。根拠が追えることは、評価と原因究明の両方に効きます。

---

## よくある質問（FAQ）

### Q. RAGがうまく答えてくれません。LLMを賢いモデルに変えれば直りますか？

多くの場合、直りません。RAGの精度は「AIに渡す根拠の質」でほぼ決まるため、根拠が外れていれば、どんなに賢いモデルでも間違えます。直すべきは検索層です。ベクトル検索だけに頼らずキーワード検索と組み合わせるハイブリッド検索、チャンク化の見直し、リランクの導入——これらで根拠の質を上げるのが先決です。

### Q. ベクトルDBに文書を入れれば、RAGは完成ですか？

それはプロトタイプの段階です。本番品質には、ハイブリッド検索（意味＋完全一致）、適切なチャンク化、リランク、アクセス制御、評価の仕組みが必要です。特に固有名詞・型番・専門用語はベクトル検索だけでは拾えないため、全文検索との組み合わせが実用上ほぼ必須です。

### Q. マルチテナントのRAGで、他社の情報が漏れることはありますか？

設計が甘いと起こりえます。全テナントの文書を1つのDBに入れ、検索時にテナントで絞っていないと、他社の社外秘文書が検索結果に混ざります。これを防ぐには、テナントIDを検索クエリの条件に組み込み、構造的に他テナントを除外する設計が必須です。発注時は必ずこの点を確認してください。

### Q. RAGの精度はどうやって測るのですか？

代表的な質問と「正解の根拠・回答」のセット（評価用データセット）を用意し、検索が正しい根拠を引けているか（Retrieval精度）と、回答が根拠に忠実か（幻覚の有無）を、変更のたびに自動で測ります。この評価基盤がないと「良くなった気がする」で終わり、改善が回りません。発注時は「精度をどう測るか」を必ず要求してください。

### Q. RAGの導入を外注したいのですが、何を確認すべきですか？

「ハイブリッド検索を使うか」「チャンク化とリランクをどう設計するか」「マルチテナントの情報分離をどう保証するか」「精度をどう測定・改善するか」を質問してください。これらに構造で答えられる相手は信頼できます。「ベクトルDBに入れて検索するだけ」の提案は、本番で精度不足に陥るリスクが高いです。

---

## まとめ：RAGの精度は「検索の質」で決まる

RAGを実用品質で本番運用するために、押さえるべきは次の通りです。

1. **失敗の原因はLLMの賢さではなく「検索（Retrieval）の質」**——渡す根拠の質が精度を決める。
2. **ベクトル検索だけでは不十分**——キーワード検索と組み合わせるハイブリッド検索＋リランクが標準。
3. **チャンク化の設計が精度を左右する**——意味のまとまりで分割し、適度に重ねる。
4. **マルチテナントは検索層でアクセス制御**——テナントIDを検索条件に組み込み、構造的に分離する。
5. **評価の仕組みがなければ改善できない**——精度を測る基盤を最初から用意する。

「RAGを入れたが精度が出ない」「これから社内文書AIを作りたい」——その成否は、検索層の設計とアクセス制御、評価基盤で決まります。専門商材の誤答を構造的に排除した実績と同じ水準で、要件定義から精度設計・セキュリティ・運用までお引き受けします。
