2025年12月19日
RAG
RAG構築におけるEmbedding選定|OpenAI APIとOllama(ローカルLLM)の実装差と運用設計
RAG構築でEmbeddingモデルをOpenAI APIで動かすかOllamaでローカル運用するかは、性能・コスト・データ主権を左右する設計判断です。本稿ではバッチ処理やメタデータ設計、コスト比較を含む実装上の差異を、業務AI基盤の観点で整理します。

概要
RAG(Retrieval-Augmented Generation)システムを構築する際、Embeddingモデルの選択は、システムの性能・コスト・運用体制を大きく左右する重要な意思決定です。クラウドAPIを使うか、ローカルLLMで完結させるかによって、実装の組み方も運用負荷も変わってきます。
本稿では、DigitalBaseでの構築知見をもとに、OpenAI API と Ollama(ローカルLLM) それぞれでRAGを構築する際の実装上の違いと、プロダクション環境で実際に直面する課題を整理します。バッチ処理の扱い、ベクトルDBへの格納とメタデータ設計、コスト構造の差まで、選定の判断材料となる観点を体系的に解説します。
Embeddingモデルの選択
OpenAI API
OpenAIでは2026年6月時点で text-embedding-3-small が標準的な選択肢です。主な特徴は以下のとおりです。
- 次元数: 1536次元(
dimensionsパラメータで256〜1536の範囲に調整可能) - コスト: $0.02 / 1M tokens
- 性能: MTEB(Massive Text Embedding Benchmark)で高いスコアを記録
- コンテキスト長: 8,191トークンまで対応
次元数を削減することで、ベクトルDBのストレージコストを抑えつつ、検索性能の大幅な低下を避けられます。たとえば512次元に削減しても、多くのユースケースで実用的な精度を維持できます。より高精度を求める場合は text-embedding-3-large(3072次元)も選択肢になりますが、コストとストレージが増える点に留意が必要です。
Ollama(ローカルLLM)
Ollamaでは以下のオープンソースモデルが利用可能です。
- nomic-embed-text: 768次元、コンテキスト長8,192トークン
- mxbai-embed-large: 1024次元、高精度だがリソース消費が大きい
- all-minilm: 384次元、軽量で高速
ローカル実行のため、API利用料が発生せず、データの外部送信が不要という利点があります。医療・金融・製造業など、機密性の高いデータを扱う場合に特に有効です。
バッチ処理の実装上の違い
最も注意すべき違いは、Embedding生成時のバッチ処理の仕組みです。
OpenAI APIの実装
OpenAIはバッチ入力をサポートしており、複数テキストを1回のAPI呼び出しで処理できます。
from openai import OpenAI client = OpenAI() # 100チャンクを一度に処理 response = client.embeddings.create( model="text-embedding-3-small", input=chunks, # List[str]で最大2048要素まで dimensions=512 # オプション ) embeddings = [data.embedding for data in response.data]
この実装による利点は以下のとおりです。
- レイテンシの削減: 100チャンクでも1回のリクエストで完結する
- レート制限の効率的な利用: リクエスト数ベースの制限(例: 3,000 RPM)を無駄なく使える
- 通信オーバーヘッドの削減: バッチ化により1件あたりの通信コストを抑えられる
検証では、100チャンクの処理で約2〜3秒程度でした(ネットワーク環境に依存します)。
Ollamaの実装
Ollamaの埋め込みAPIは1リクエストあたり単一プロンプトを基本とするため、各テキストを順次処理する構成になります。
import ollama embeddings = [] for chunk in chunks: response = ollama.embeddings( model='nomic-embed-text', prompt=chunk ) embeddings.append(response['embedding'])
この実装の特性は次のとおりです。
- ローカル処理: ネットワーク遅延がなく、データは外部送信されない
- リソース依存: CPU/GPUの性能に大きく依存する(GPU使用時は大幅に高速化)
- 並列化が可能: 非同期処理やマルチスレッドで実効スループットを高められる
検証では、M1 Mac(GPU使用)で1チャンクあたり約50〜100ms、100チャンクで5〜10秒程度でした。
並列化による最適化
Ollamaでは、同時実行数を制御しながら並列化することでスループットを改善できます。サーバー側の負荷を考慮し、セマフォ等で同時実行数を絞るのが実務上のポイントです。
import asyncio from ollama import AsyncClient client = AsyncClient() semaphore = asyncio.Semaphore(8) # 同時実行数を制限 async def get_embedding(chunk): async with semaphore: response = await client.embeddings( model='nomic-embed-text', prompt=chunk ) return response['embedding'] embeddings = await asyncio.gather(*[ get_embedding(chunk) for chunk in chunks ])
ベクトルDBへの格納とメタデータ設計
どちらのアプローチでも、効率的なデータ管理のためにメタデータ設計が重要です。Embedding生成の方式に関わらず、ここを最初に固めておくことが運用フェーズでの手戻りを減らします。
推奨メタデータ構造
metadata = { "document_id": "doc_12345", # 必須 "chunk_index": 0, "source": "product_manual.pdf", "created_at": "2026-06-15T10:30:00Z", "page_number": 5, "section": "第3章" }
document_id を含めることで、次のような運用が容易になります。
- 差分更新: 特定ドキュメントのチャンクのみを再生成・更新できる
- 削除操作: ドキュメント単位での一括削除が容易になる
- 追跡性: 検索結果の出典追跡とトラブルシューティングが簡単になる
実装例(ChromaDB)
import chromadb client = chromadb.Client() collection = client.create_collection("documents") # ドキュメント更新時は既存チャンクを削除 collection.delete( where={"document_id": "doc_12345"} ) # 新しいチャンクを追加 collection.add( embeddings=embeddings, documents=chunks, metadatas=metadatas, ids=[f"doc_12345_chunk_{i}" for i in range(len(chunks))] )
業務システムでの本番運用では、PostgreSQL拡張の pgvector(HNSWインデックス)のように、既存のRDBインフラと統合できるベクトルストアを採用するケースも増えています。検索だけでなく、権限管理や監査ログとの連携を考えると、運用済みのデータ基盤と地続きにできる利点は小さくありません。
コストとパフォーマンスの比較
OpenAI API
メリット
- 高精度な検索結果
- インフラ管理が不要
- スケーラビリティが高い
コスト例
- 10万ページのドキュメント初期Embedding: 約$32
- 月間100万クエリ(平均200トークン/クエリ): 約$40
- 合計: 初期費用約40程度
デメリット
- 従量課金のため利用量増に比例してコストが増える
- データを外部に送信する
- APIレート制限の考慮が必要
Ollama
メリット
- API利用料が発生しない(サーバーコストのみ)
- データの外部送信が不要
- レート制限がない
コスト例
- GPU搭載サーバー(例: AWS g4dn.xlarge): 約$150/月
- ストレージ: 約$10/月
- 合計: 月額約$160程度(固定費)
デメリット
- インフラ運用が必要
- モデルによってはOpenAIより精度が劣る可能性がある
- スループット拡大にはハードウェア投資が必要
コスト構造の本質的な違いは、従量課金(OpenAI)か固定費(Ollama)か にあります。クエリ量が少ない初期フェーズではOpenAIが有利ですが、月間数百万クエリを超える安定運用ではローカル運用の固定費が相対的に有利になる損益分岐点が存在します。
選択基準とユースケース
OpenAI APIが適しているケース
- スタートアップ・小規模運用: 初期投資を抑えたい
- 可変ワークロード: 月ごとの利用量が大きく変動する
- 高精度が要件: カスタマーサポートなど検索精度が直接成果に影響する
- 開発リソースが限られる: インフラ管理に人員を割けない
Ollamaが適しているケース
- 大規模・安定運用: 月間数百万クエリ以上で従量課金が高コストになる
- データ主権の重視: 医療・金融・製造業など機密データを外に出せない
- オフライン・閉域環境: インターネット接続が制限される環境
- カスタマイズ重視: モデルの選定・ファインチューニングを自社で行いたい
ハイブリッドアプローチ
実務では、両者を組み合わせる構成も有効です。
- 開発環境: OpenAI APIで迅速にプロトタイプを構築する
- 本番環境: Ollamaで運用コストを抑える
- フォールバック: ローカル基盤の障害時にOpenAI APIへ一時的に切り替える
ただし、OpenAIとOllamaではEmbeddingのベクトル空間が異なるため、両者を混在させる場合は同一インデックス内でモデルを混ぜないことが前提です。モデルを切り替える際は、原則として全チャンクの再Embeddingが必要になる点に注意してください。
まとめ
RAGシステムでのEmbedding選定は、単なる技術選定ではなく、ビジネス要件・コスト構造・データ主権のバランスを取る意思決定です。OpenAI APIは開発速度と精度を優先する場合に、Ollamaはコスト管理とデータ主権を重視する場合に適しています。実装面ではバッチ処理の差が初期構築のスループットに、メタデータ設計が運用フェーズの保守性に直結します。
プロジェクトの成熟度に応じて段階的に移行する柔軟なアプローチも検討に値します。重要なのは最初から完璧を目指すことではなく、実装・測定・改善のサイクルを回しながら、自社の要件に合った構成へ収束させていくことです。
