Sudachi (日本語形態素解析) と Milvus (Zilliz Cloud) を組み合わせ、日本語の表記ゆれやドキュメント特有のノイズに強い「ハイブリッド検索 (Dense + Sparse)」を実装するための実践的ハンズオンリポジトリです。
RAG (Retrieval-Augmented Generation) システム構築において、日本語特有の課題(分かち書き、表記ゆれ、同義語)を解決し、検索精度を最大化する手法を学びます。
- Sudachiによる高度な正規化:
- 「サーバー/サーバ」「第1条/第一条」などの表記ゆれ統一。
- PDF抽出時に発生する不自然なスペース(「第 一 条」)や記号ノイズの除去。
- ハイブリッド検索 (Hybrid Search):
- Dense Vector (意味検索): 文脈や意味的類似性を捉える (AWS Titan Embeddings)。
- Sparse Vector (キーワード検索): 固有名詞や正確な品番、条文番号を捉える (Milvus BM25)。
- Reciprocal Rank Fusion (RRF):
- 異なるアルゴリズム(ベクトルとキーワード)の検索結果を公平に統合・再ランク付けする手法。
- Vector Database: Zilliz Cloud (Milvus) - フルマネージドMilvus。BM25機能を標準サポート。
- NLP / Tokenizer: SudachiPy - 高精度な日本語形態素解析器。
- Embedding Model: AWS Bedrock (
amazon.titan-embed-text-v2)。 - Package Manager:
uv- 高速なPythonパッケージ管理ツール。
実務に近い難易度の高いドキュメントとして、金融庁の公開資料を使用しています。
- ソース: 金融商品取引業者等向けの総合的な監督指針 (PDF)
- 範囲: 冒頭約150ページ分。
- 収録データ:
assets/embedded_data.json- すでに チャンク化、Sudachi正規化、ベクトル埋め込み が完了したデータを含んでいます。
- メリット: Embedding API のコストや時間をかけずに、検索ロジックの学習からすぐに開始できます。
git clone https://github.com/izawaeisuke/rag-with-sudachi.git
cd rag-with-sudachi本プロジェクトは uv を推奨していますが、標準の pip でも動作します。
uv を使用する場合 (推奨):
# uvのインストール (未導入の場合)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 依存関係の同期
uv syncpip を使用する場合:
# 仮想環境の作成と有効化
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# インストール
pip install pymilvus[milvus-lite,model] sudachipy sudachidict-core boto3 python-dotenv jupyter.env.example をコピーして .env ファイルを作成し、必要なAPIキーを設定してください。
cp .env.example .env.env の設定項目:
# Zilliz Cloud (Milvus) 接続情報
ZILLIZ_CLOUD_URI="https://in03-xxxxxxxx.api.aws-us-west1.zillizcloud.com"
ZILLIZ_CLOUD_API_KEY="your-api-key"
# AWS Bedrock (Embedding用)
# ※ AWS CLI (`~/.aws/credentials`) の設定がある場合は省略可能
AWS_BEARER_TOKEN_BEDROCK=bedrock-api-key-xxxxxxx以下のJupyter Notebookで、ステップバイステップで実装を解説しています。
👉 notebooks/hybrid_search_with_bm25.ipynb
主な内容:
- SudachiAnalyzerの実装:
normalized_form()を使った正規化処理の詳細。 - Milvusスキーマ定義:
Function機能を使った BM25 Sparse Vector の自動生成設定。 - データインポート: JSONデータセットの読み込みと挿入。
- 検索比較実験: Dense単体、Sparse単体、Hybridの検索結果の違いを体感。
Notebookの内容をまとめたPythonスクリプトも用意しています。コンソールで素早く結果を確認したい場合に便利です。
uv run run_hybrid_search.py本リポジトリのコードでは、Dense検索とSparse検索の結果がどれくらい重複しているか(Jaccard係数)や、Hybrid検索結果への寄与率を算出します。
出力例:
Query: 『 指定ADR機関が存在しない場合の苦情処理措置 』
----------------------------------------
[ベクトル検索 (Dense)]
- [0.7214] 金融ADR制度の概要...
- [0.6890] 苦情処理措置の内部態勢...
[全文検索 (BM25)]
- [4.2105] 指定ADR機関が存在しない場合の苦情処理措置... (← 正確にヒット)
- [3.1022] 苦情処理紛争解決手続...
[ハイブリッド検索]
- [0.0322] 指定ADR機関が存在しない場合の苦情処理措置...
...
[定量比較分析]
- Dense vs Sparse Jaccard類似度: 0.20
=> DenseとSparseで異なる検索結果が得られています。Hybrid検索はこれらを補完し合っています。
このアーキテクチャは以下のようなケースに最適です。
- 社内規定・マニュアル検索: 「第◯条」や「型番」での検索が必要だが、自然言語での曖昧な質問にも答えたい場合。
- 法的文書・契約書RAG: 表記の厳密さと文脈理解の両方が求められる場合。
- カスタマーサポートBot: ユーザーの入力揺らぎ(「スマホ」「スマートフォン」)を吸収しつつ、専門用語(エラーコード等)を正確に捉える場合。
License: MIT