このプロジェクトの9,586チャンクはnumpy配列内積+pickle BM25で十分です。検索遅延が100ms未満であり、メモリ使用量も約29MB(埋め込み14MB+BM25インデックス7.1MB+トークン化コーパス7.6MB)レベルである。しかし、規模が大きくなると:
| チャンク数 | 埋め込みサイズ(384d) | 内的検索時間 | 問題 |
|---|---|---|---|
| 10K | 14MB | <100ms | なし |
| 100K | 140MB | ~500ms | メモリー負担開始 |
| 1M | 1.4GB | 〜5秒 | メモリ制限、遅延不許可 |
| 10M | 14GB | 不可能 | numpyでは不可 |
**変更最小化アプローチ。**現在のコード構造を維持しながらパフォーマンスのみを改善します。
| コンポーネント | 現在 | 変更 |
|---|---|---|
| ベクトル検索 | numpy 内積 | FAISS IndexFlatIP(exact, but optimized) |
| BM25 | rank-bm25 pickle | 同じ(50Kまでin-memory可能) |
| メタデータ | JSONLファイル | SQLite(chunks.db) |
| 埋め込みの作成 | PyTorch SentenceTransformer | ONNX変換(変換スクリプト準備済み:convert_to_onnx.py) |
用語注:
# FAISS 적용 예시 (embed.py 변경 부분만)
import faiss
# 빌드 시
index = faiss.IndexFlatIP(384) # Inner Product = cosine (정규화 후)
index.add(embeddings)
faiss.write_index(index, "data/faiss.index")
# 검색 시
index = faiss.read_index("data/faiss.index")
scores, indices = index.search(query_embedding, top_k) # GPU도 가능
**近似検索(ANN)の導入。**精度をわずかに犠牲にして速度を大幅に確保:
| コンポーネント | オプションA(セルフホスティング) | オプションB(マネージド) |
|---|---|---|
| ベクトル検索 | FAISS IndexIVFFlat(クラスタベース) |
Qdrant(Docker) |
| BM25 | Elasticsearch(Docker) | OpenSearch Serverless |
| メタデータ | PostgreSQL | Supabase(PostgreSQL + REST API) |
| 埋め込みの作成 | GPUサーバーでのバッチ処理 | OpenAI text-embedding-3-small API |
| リランカー | ローカルbge-reranker | Cohere Rerank API |
# FAISS IVF 적용 (100K+ 청크에 효과적)
nlist = 100 # 클러스터 수 (sqrt(N) 정도)
quantizer = faiss.IndexFlatIP(384)
index = faiss.IndexIVFFlat(quantizer, 384, nlist, faiss.METRIC_INNER_PRODUCT)
index.train(embeddings) # 클러스터 학습
index.add(embeddings)
index.nprobe = 10 # 검색 시 탐색할 클러스터 수 (정확도↔속도 트레이드오프)
専用ベクトルDB +検索エンジンクラスタ:
| コンポーネント | オプション | 特徴 |
|---|---|---|
| ベクトル検索 | Pinecone | 完全マネージド、サーバーレス、自動スケーリング |
| Weaviate | ハイブリッド検索内蔵(BM25+Denseシングルクエリ) | |
| Qdrant | Rustベースの高性能、セルフホスティング/クラウド | |
| pgvector + PostgreSQL | 既存のRDBにベクトル検索を追加する | |
| キーワード検索 | Elasticsearchクラスタ | BM25 + 形態素分析内蔵 (nori/ik) |
| 埋め込み | APIサービス(OpenAI/Cohere) | ローカルGPU不要、コストはトークンあたりの課金 |
| オーケストレーション | LangChain/LlamaIndex | 検索→リランキング→LLMチェーン自動構成 |
現在、paraphrase-multilingual-MiniLM-L12-v2(384次元)は軽量ですが、最新モデルと比較して精度が低いです。
| モデル | 次元 | サイズ | 特徴 | 適切なスケール |
|---|---|---|---|---|
| MiniLM-L12-v2(現在) | 384 | 120MB | ローカル実行、50+言語 | ~50K |
bge-m3(BAAI) |
1024 | 2.2GB | Dense+Sparse+ColBERT 3-in-1、多言語最強 | 50K~500K |
multilingual-e5-large-instruct |
1024 | 2.2GB | ディレクティブクエリに最適化 | 50K~500K |
text-embedding-3-small(OpenAI) |
1536 | API | 低コストAPI、優れた多言語 | 100K+ |
embed-multilingual-v3(Cohere) |
1024 | API | 100+言語、検索特化 | 100K+ |
交換時の影響範囲:
embed.pyのモデル名変更+バッチサイズ変更embeddings.npy 再生成(次元変更→ファイルサイズ増加)search.pyは変更不要(numpy内積は次元無関係)| 方法 | 利点 | 欠点 | 適切な状況 |
|---|---|---|---|
| フルリビルド | シンプルで一貫性を確保 | 規模が大きくなると時間↑ | <50Kチャンク、1日1回 |
| 増分追加 | 高速(変更分のみ処理) | 削除/修正管理の複雑さ | 50K~500K、リアルタイム性が必要 |
| 増分+サイクルリビルド | リアルタイム+品質 | 両方のシステム管理 | 500K+、本番 |
このプロジェクトは9,586チャンクで全体のリビルドが3〜5分なので、全体のリビルドで十分です。しかし、100Kチャンクを超えると増分インデックス付けが必須だ。
現在のシステムはすべてローカルで動作します。これを外部サービスに拡張したり、チームで共有したりするときは、各段階でどのようなオプションがあるかを整理します。
| オプション | 説明 | 適切な環境 |
|---|---|---|
| ファイルシステムウォッチング | watchdog/inotifyによるディレクトリ変更の検出→自動再処理 |
ローカル、小規模 |
| Gitウェブフック | ドキュメントレポプッシュ時にCI / CDから自動再構築 | 技術文書、IaC |
| Confluence/Notion API 同期 | REST APIで変更されたページ検出→増分処理 | 企業環境 |
| S3 イベント + Lambda | S3にドキュメントをアップロードするとき、Lambdaでチャンキング+埋め込み | AWS環境、サーバーレス |
| Unstructured.io | PDF/DOCX/PPTX/HTML → 構造化テキストの自動変換 | さまざまなファイル形式 |
| オプション | 説明 | 適切な環境 |
|---|---|---|
| 直接実装(現在) | chunk.py:512文字、段落境界を尊重 |
ドメインカスタム制御が必要な場合 |
| LangChain TextSplitter | RecursiveCharacterTextSplitter: マークダウンヘッダ認識、コードブロック保存 |
汎用、クイックスタート |
| LlamaIndex SentenceSplitter | 文章境界尊重、メタデータの自動抽出 | 汎用 |
| Unstructured.io | 文書構造の自動解析後の要素ベースのチャンキング(タイトル、本文、表、画像キャプションの分離) | 非定型文書 |
| Semantic Chunking | 埋め込み類似度に基づいて意味が切り替わる点での分割 | 構造のない長いテキスト |
| オプション | コスト | 遅延 | 適切な環境 |
|---|---|---|---|
| ローカルSentenceTransformer(現在) | 無料 | 配置3~5分 | ローカル開発、<100K |
| ローカルONNX(変換スクリプト準備済み) | 無料 | 配置〜2分 | ローカル、CPU最適化 |
| GPUサーバー | インスタンスコスト | バッチ~30秒 | 100K+、頻繁なリビルド |
| OpenAI Embedding API | $0.02/1Mトークン | リアルタイム | プロダクション、管理負担↓ |
| Cohere Embed API | $0.10/1Mトークン | リアルタイム | 多言語特化 |
| Amazon Bedrock Titan | $0.02/1Mトークン | リアルタイム | AWS環境 |
| オプション | BM25 | Dense | ハイブリッド | 適切な環境 |
|---|---|---|---|---|
| ファイルベース(現在) | rank-bm25 pickle (2ファイル: bm25_index + tokenized_corpus) | numpy .npy | 手動合計 | ローカル、<50K |
| FAISS + Elasticsearch | Elasticsearch | FAISS | 別途加算ロジック | セルフホスティング、50K~1M |
| Weaviate | 内蔵BM25 | 内蔵HNSW | alphaパラメータで自動 |
オールインワン、50K~10M |
| Qdrant | (別途ESが必要) | 内蔵HNSW | FastEmbed 連動 | 高性能ベクトル検索 |
| Pinecone | (別途必要) | 組み込み | Sparse+Dense サポート | 完全マネージド、スケール |
| pgvector + PostgreSQL | pg_trgm/FTS | pgvector | SQLクエリで合計 | 既存のRDBの活用 |
| オプション | コスト | パフォーマンス | 適切な環境 |
|---|---|---|---|
| bge-reranker-v2-m3(現在) | 無料 | 40候補/500ms | ローカル、多言語 |
| Cohere Rerank | $2/1K検索 | 40候補/200ms | 本番、APIベース |
| Jina Reranker | 無料〜有料 | 40候補/300ms | 多言語、API/ローカル |
| ColBERT v2 | 無料 | トークン単位マッチング | 長い文書、精密マッチング |
| LLMベースのリランキング | トークン費用 | 遅いが最高の精密 | 少量の高価値検索 |
RAGで管理すると効果的なデータ:
| データ型 | RAG適合度 | 理由 |
|---|---|---|
| サービス企画書 | 高い | 頻繁な変更、バージョン管理の必要性、チーム間の共有 |
| API ドキュメント | 非常に高い | 正確な用語マッチング必須、バージョン別の違い |
| オンボーディングガイド | 高い | 新規入社者の様々な質問に対応 |
| 障害対応マニュアル | 非常に高い | 緊急時のクイック検索必須 |
| コードレビューガイドライン | 中 | コード自体はIDE検索に適しています |
| 会議録 | 低 | 非定型、決定事項のみ抽出後構造化が必要 |
| デイリースタンドアップメモ | 非常に低い | 短寿命、TTLベースの有効期限処理 |
┌──────────────────────────────────────────────────┐
│ 데이터 소스 │
│ Confluence │ Notion │ Google Docs │ Git (MD) │
└──────┬───────────┬────────────┬──────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────┐
│ 수집 + 정제 레이어 │
│ - API 동기화 (변경분 감지) │
│ - HTML→Markdown 변환 │
│ - 메타데이터 추출 (작성자, 수정일, 라벨, 버전) │
│ - 이전 버전 아카이브 (검색 대상에서 제외) │
│ - 구조 정규화 (헤딩 레벨 통일, 섹션 구분선 삽입) │
└──────────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ 청킹 + 인덱싱 │
│ - 헤딩 기반 청킹 (## 단위로 분할) │
│ - 메타데이터 보존 (문서 제목, 스페이스, 태그) │
│ - 증분 인덱싱 (변경분만 재처리) │
│ - 하이브리드 인덱스 (BM25 + Dense) │
└──────────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ 검색 + 활용 │
│ - Slack/Teams 봇: "결제 API 타임아웃 몇 초?" │
│ - AI Agent: 기획서 기반 코드 생성 │
│ - 온보딩 봇: 신규 입사자 질문 대응 │
│ - 장애 대응: 에러 메시지로 해결 방법 검색 │
└──────────────────────────────────────────────────┘
社主プロジェクトと企業環境は構造は同じですが、運営要件が異なります。
1。アクセス権(ACL)
文書ごとにアクセス権が異なる。 HR文書をエンジニアが検索できないこと。
→チャンクメタデータにaccess_groupフィールドを追加、検索時のフィルタリング
2。監査ログ
誰が何を検索したかを追跡する必要があります。
→検索クエリ+戻り結果+ユーザーIDログ
3。 PII(個人情報)マスキング
企画書に含まれる個人情報は、RAGの結果として露出してはならない。
→チャンキング前PII検出+マスキングパイプラインを追加
4。マルチテナンシー
チームごとに独立したコーパスまたは共有コーパス+チーム固有のコーパス構造。
→ ネームスペース(namespace)でコーパス分離、検索時のネームスペースフィルタ