本番環境のRAGパイプラインにおけるレイテンシのボトルネック
検索レイテンシは、検索拡張生成(RAG)システムにおいてユーザー体験を損なう最大の要因です。一般的なクエリのライフサイクルを考えてみましょう。バックエンドがリモートのEmbedding APIにテキストを送信し、ベクトルデータベースを検索し、上位のチャンクをクラウドのRerankerに転送して、最後にLLMへプロンプトを渡します。各ステップでインターネットの往復通信が発生するため、LLMが最初のトークンを生成し始めるまでに、ユーザーは1.5〜3秒ほど待たされることになります。
サードパーティのAPIは、ボトルネックをさらに悪化させます。OpenAIやCohereなどのエンドポイントを介してEmbeddingやRerankerを実行すると、ネットワークのジッター(揺らぎ)、厳格なレート制限、トークンごとの従量課金が発生します。
1日あたり100,000回の検索で、クエリごとに50件のドキュメントをリランキングすると、毎月のクラウド費用は容易に1,500ドルを超えてしまいます。さらに重要なのは、パブリックインターネット経由で社内ドキュメントや顧客のクエリを送信することにより、サードパーティの処理基盤にデータが露出するリスクがある点です。推論をローカル環境で実行すれば、これらのリスクを完全に排除できます。
そこで役立つのがInfinityです。Infinityは、Transformer Encoder向けにRustとPythonで構築された専用の推論エンジンです。ネイティブの動的バッチ処理、FP16およびINT8量子化、さらにEmbeddingとCross-Encoder Reranker向けにそのまま置き換え可能なOpenAI互換REST APIを提供します。
アプローチの比較:EmbeddingおよびReranking戦略
適切な推論エンジンの選択は、トラフィックパターンとハードウェア構成に直接左右されます。
| アプローチ | スループットとレイテンシ | インフラオーバーヘッド | OpenAI API互換性 | Cross-Encoder Reranking |
|---|---|---|---|---|
| クラウドAPI(OpenAI, Cohere) | p95レイテンシ 180〜450ms(ネットワーク依存) | なし(フルマネージド) | ネイティブ標準 | Cohere、Voyage、Jinaなどの個別エンドポイントが必要 |
| インプロセス SentenceTransformers | シングルスレッドは高速(約25ms)だが、並行アクセス時にGILが飽和 | アプリケーションとCPU・メモリを共有 | なし(カスタムラッパーが必要) | 手動のバッチループ処理。CPU枯渇リスクが高い |
| vLLM / TGI | 高スループットだが、16GB〜24GB以上のVRAMが必要 | 過重(自己回帰型のDecoderモデル向け設計) | 一部対応 | Cross-Encoderの統合が不十分または非サポート |
| Infinity推論サーバー | p95レイテンシ 8〜15ms。単一GPUで1,200文/秒以上 | 低(4 vCPUまたは手頃な8GB GPUで動作可能) | /v1/embeddings および /v1/rerank に完全対応 |
Cross-Encoder向けのネイティブ継続的バッチ処理 |
セルフホストにおけるInfinityの評価
推論環境を社内へ移行することで圧倒的な高速化が図れますが、同時に運用の責任もチームが担うことになります。
メリット
- 15ms未満の低レイテンシ:ローカルコンテナはUnixソケットやDockerのブリッジネットワークを介して通信するため、パブリックインターネットのハンドシェイクを完全に排除できます。
- 予測可能なコンピュートコスト:ハードウェア費用は一定です。急な料金高騰やティアのアップグレードに悩まされることなく、5億トークン規模の埋め込みも処理できます。
- データ漏洩リスクゼロ:機密データはプライベートサブネットやVPC内にとどまります。SOC 2、HIPAA、GDPRなどの厳格なデータ隔離要件も容易にクリアできます。
- 容易なリプレイス:LangChain、LlamaIndex、あるいは素のHTTPクライアントにおいて、ベースURLとAPIキーの2行を変更するだけでエンドポイントを切り替えられます。
- 複数モデルの同一ホスト運用:
BAAI/bge-small-en-v1.5のようなDense Embedderと、BAAI/bge-reranker-baseのようなRerankerを、単一コンテナかつ4GB未満のVRAMで同時に実行できます。
トレードオフ
- GPUのキャパシティプランニング:InfinityはONNX Runtime経由でCPU上でも動作しますが、高並行環境(50+ RPS)では最低8GBのVRAMを備えたGPUが必要です。
- メンテナンスのオーバーヘッド:コンテナのヘルスチェック、VRAM消費量の監視、サーバー更新時の再起動対応などを管理する必要があります。
- ディスクストレージ:EmbeddingおよびRerankingモデルのチェックポイント(重みとトークナイザー)を保存するために、2GB〜6GBの高速なNVMeストレージが必要です。
推奨アーキテクチャとハードウェア要件
秒間100〜250リクエスト程度を処理する環境の場合、以下の最小スペックを推奨します:
- GPU環境(推奨):8GB以上のVRAMを搭載したNVIDIA GPU(RTX 3060、RTX 4060 Ti、またはクラウドのT4/L4)×1、4 CPUコア、16GBシステムメモリ。
- CPU構成(代替案):INT8量子化を利用した8 vCPUコア(AVX-512拡張対応のIntel Xeon Ice LakeまたはAMD EPYC)、16GB RAM。
- ホストOS:Docker EngineおよびDocker Compose v2が導入されたUbuntu 22.04 LTSまたは24.04 LTS。
- ドライバ構成:NVIDIA Driver 535以上およびNVIDIA Container Toolkit。
- 推奨モデル構成:
- Embedding:超高速なベクトル検索には
BAAI/bge-small-en-v1.5(384次元、重み約133MB)。多言語対応が必須の場合はBAAI/bge-m3(1024次元)を採用。 - Reranker:
BAAI/bge-reranker-base(重み約1.1GB)またはmixedbread-ai/mxbai-rerank-base-v1。
- Embedding:超高速なベクトル検索には
Docker Composeを使ったデプロイ手順
ステップ1:NVIDIA Container Toolkitのセットアップ
CPUのみで実行する場合はこの手順をスキップしてください。GPUアクセラレーションを使用する場合は、NVIDIAリポジトリを登録し、Dockerのデフォルトランタイムを設定します:
# NVIDIA Container Toolkitリポジトリの追加
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
ステップ2:Docker Compose構成の定義
Infinity用の作業ディレクトリを作成し、新しいCompose設定ファイルを開きます:
mkdir -p ~/infinity-stack && cd ~/infinity-stack
nano docker-compose.yml
以下のサービス定義を貼り付けます。これにより、EmbeddingモデルとCross-Encoderモデルの両方が、半精度(FP16)を使用して共有エンジンに読み込まれます:
services:
infinity:
image: michaelf34/infinity:latest
container_name: infinity-inference
restart: unless-stopped
ports:
- "7997:7997"
environment:
- INFINITY_MODEL_ID=BAAI/bge-small-en-v1.5;BAAI/bge-reranker-base
- INFINITY_BATCH_SIZE=64
- INFINITY_API_KEY=sk-inf-local-secret-key-9923
- INFINITY_DTYPE=float16
volumes:
- ./cache:/root/.cache/huggingface
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
CPUで動作させる場合は、deploy ブロック全体を削除し、INFINITY_DTYPE を int8 または float32 に変更してください。
ステップ3:サービスの起動とヘルスチェック
バックグラウンドでコンテナを起動し、ダウンロードの進行状況をモニタリングします:
docker compose up -d
docker compose logs -f infinity
初回の実行時、InfinityはHugging Faceからモデルの重みを ./cache にダウンロードします。モデルのコンパイルとウォームアップが完了すると、ログに準備完了のメッセージが出力されます:
INFO: Started server process on http://0.0.0.0:7997
INFO: Application startup complete. Ready for requests.
ステップ4:ローカルエンドポイントへの問い合わせ
まず、標準的なOpenAIのペイロード構造を使用して、ベクトル生成をテストします:
curl http://localhost:7997/v1/embeddings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-inf-local-secret-key-9923" \
-d '{
"model": "BAAI/bge-small-en-v1.5",
"input": ["セルフホストされたEmbeddingにより、ネットワークレイテンシはほぼゼロになります。"]
}'
次に、取得した候補ドキュメントのバッチをRerankerに渡します。エンドポイントが関連性スコアを算出し、ソートされたインデックスを返します:
curl http://localhost:7997/v1/rerank \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-inf-local-secret-key-9923" \
-d '{
"model": "BAAI/bge-reranker-base",
"query": "ベクトル検索の応答時間を短縮するにはどうすればよいですか?",
"documents": [
"Infinity内部の継続的な動的バッチ処理により、GPU使用率が最適化されます。",
"水出しコーヒーは室温で16時間抽出する必要があります。",
"HNSWインデックスは近似最近傍探索を高速化します。"
],
"top_n": 2
}'
ステップ5:Pythonアプリケーションとの接続
InfinityはOpenAIのスキーマに完全準拠しているため、標準の openai パッケージをそのまま使用できます。カスタムのアダプターコードを書く必要はありません。
from openai import OpenAI
# クライアントの接続先をローカルのInfinityサーバーに設定
client = OpenAI(
base_url="http://localhost:7997/v1",
api_key="sk-inf-local-secret-key-9923"
)
def embed_documents(texts: list[str]) -> list[list[float]]:
response = client.embeddings.create(
model="BAAI/bge-small-en-v1.5",
input=texts
)
return [record.embedding for record in response.data]
sample_chunks = [
"セルフホスト型の推論により、p95検索時間を12msまで短縮できます。",
"Cross-Encoderは、誤検出されたベクトルの一致を正確に除外します。"
]
vectors = embed_documents(sample_chunks)
print(f"{len(vectors)} 件のEmbeddingを生成 | ベクトルの次元数: {len(vectors[0])}")
データベースの近接環境でInfinityを実行することにより、検索時間を10〜15msまで短縮できます。サードパーティAPIへの依存をなくし、機密データを保護しながら、RAGのパフォーマンスを完全にコントロールすることが可能になります。

