本番運用に耐えるRAG社内検索
社内に散らばったドキュメントを、2秒以内に出典付きで92%の精度で答える即答エンジンへ変える。

担当領域
エンジニアリングをリード。ハイブリッド検索パイプラインの設計、評価ゲート付きCI/CDの実装、ストリーミングUIの構築、そして1クエリ$0.02までのコスト最適化を担当した。
期間
4か月
年
2025
技術スタック
ステータス
稼働中社内に散らばったドキュメントを、2秒以内に出典付きで92%の精度で答える即答エンジンへ変える。
500ページを超える社内規程、散らばったNotionのページ、古いPDFの山を抱えた企業には、正確な答えをすぐ引き出す手段がない。従業員は制度を探すのに30分以上を費やし、新しく入った人が立ち上がるまでには数週間かかる。汎用のChatGPTを使う方法では3割以上の確率で誤った内容を返し、出典を検証することもできない。
BM25のキーワード検索、密ベクトル検索、ColBERTによるリランキングを組み合わせ、F1で92%の精度を出す本番品質のRAGパイプラインを構築した。ドキュメントはUnstructured.ioとLlamaParseで解析して表を抽出し、Sentence Transformersで埋め込んでpgvectorへ格納する。DeepEvalを組み込み、精度が92%を下回るとデプロイを止める。本番運用に本当に耐えると言えるRAGを届けられた、私たちにとって最初の案件になった。
ハイブリッド検索エンジン
BM25のキーワード検索、密ベクトルの類似度、MMRによる多様性スコアを組み合わせ、さらにColBERTでリランキングする。ドメイン固有の問い合わせでは、純粋な意味検索を18%上回った。
評価ゲート付きのデプロイ
CI/CDがpushごとにDeepEvalのテストスイートを実行し、F1が0.92を下回るとデプロイを自動で止める。精度の劣化が本番へ届かない。
出典付きのストリーミング応答
PydanticAIがすべての応答を構造化し、該当ページへの出典リンクを本文中に埋め込む。ユーザーはワンクリックで原典と突き合わせられる。
ドラッグ&ドロップでの取り込み
PDF、Notionのエクスポート、Google Driveのファイルを画面から投入するだけでよい。チャンク分割、表の抽出、埋め込みは非同期で進み、進捗も表示される。
コストの追跡ダッシュボード
クエリ単価(平均$0.02)、トークン使用量、検索レイテンシをリアルタイムに監視し、運用コストを完全に把握できる。
このプロジェクトを形づくった技術選定と、それぞれを選んだ理由。
pgvector + BM25 Hybrid
データ検索と構造化データを1つのデータベースに収めたかったため、Pineconeではなくpgvectorを選んだ。BM25相当のキーワード一致にはpg_trgmを足した。技術文書ではハイブリッド検索が、純粋なベクトル検索より18%高い精度を出した。
ColBERT Reranker
AI・ML精度が同等でありながら3倍速いため、cross-encoderによるリランキングではなくColBERTを採用した。late interactionのスコアリングはトークン単位の粒度を保ちつつ、full cross-attentionのレイテンシを避けられる。
FastAPI + Streaming
バックエンド非同期のストリーミングを標準で扱えるため、DjangoではなくFastAPIを選んだ。Server-Sent Eventsでトークンを逐次フロントエンドへ送り、WebSocketの複雑さなしにChatGPTと同じ体験を実現している。
DeepEval
インフラCI/CDにそのまま組み込めるテストランナーを持つため、RAGASではなくDeepEvalを採用した。評価スイートをpytestのフィクスチャとして定義するだけで、独自の基盤を作らずに精度の劣化でデプロイを止められる。
ハイブリッド検索、リランキング、評価ゲート付きデプロイからなる多段の検索パイプライン。
取り込み
アップロード → Unstructured.io(PDFの解析)とLlamaParse(表の抽出) → 文単位のチャンク分割
埋め込み
Sentence Transformers(all-MiniLM-L6-v2) → BM25インデックス付きでpgvectorへ格納
検索
クエリ → ハイブリッド検索(密ベクトル + BM25 + MMR) → 上位20件の候補
リランキング
ColBERTが上位20件を再スコアリング → 最も関連する5件を選抜
応答生成
Claude 3.5 SonnetがPydanticAIで構造化した出典付きの回答を生成
配信
FastAPIのSSEでストリーミング → Next.jsのUIに出典リンクを埋めて表示
開発中にぶつかった難所と、どう乗り越えたか。
表の抽出精度
一般的なPDFパーサーは表の構造を壊してしまい、財務や制度の表が意味の通らないチャンクになっていた。規程に関する問い合わせの35%が表データを含んでおり、その部分が崩れていた。
表が多いページに限ってLlamaParseを使い、そのビジョンモデルで表構造を復元した。加えて、行と列の対応関係を埋め込み空間でも保つ、表を意識したチャンク分割を導入した。
表に関する問い合わせの精度は61%から89%へ上がった。経理チームからは、ようやく報酬テーブルを「理解している」と評価された。
規模拡大にともなう検索レイテンシ
チャンクが5万件を超えると、ハイブリッド検索に4.2秒かかっていた。2秒以内の応答を期待される対話的な検索体験には遅すぎる。
pgvectorにHNSWインデックスを張り、ef_construction=200、m=16に調整した。さらに繰り返される質問に備えてRedisのクエリキャッシュを置き、本番トラフィックの40%をここで処理している。
P95の検索レイテンシは4.2秒から380msへ下がった。キャッシュに当たるクエリは50ms未満で返る。

