社内AI基盤で複数モデルを同時運用する際は、API互換性、GPUメモリの割り当て、推論サーバーの管理を検討する必要があります。DigitalBaseでの構築知見をもとに、Ollama から vLLM へ移行する際の設計と手順を整理します。
アーキテクチャ比較
Ollamaのアーキテクチャ
Ollamaは、llama.cppをバックエンドに持つ統合型エンジンです。
┌─────────────────────────────────────────┐ │ Ollama Server │ │ ┌─────────────────────────────────┐ │ │ │ Model Manager │ │ │ │ (pull / run / list / ps) │ │ │ ├─────────────────────────────────┤ │ │ │ Inference Engine │ │ │ │ (llama.cpp / ggml) │ │ │ ├─────────────────────────────────┤ │ │ │ REST API │ │ │ │ /api/chat /api/generate │ │ │ │ /api/embed /api/tags │ │ │ └─────────────────────────────────┘ │ │ │ │ ・1プロセスで全機能を提供 │ │ ・モデルの自動ダウンロード・管理 │ │ ・GGUFフォーマット(量子化対応) │ │ ・単一モデルの逐次推論が基本 │ └─────────────────────────────────────────┘
特徴
- シングルサーバー構成:1つの
ollama serveが全リクエストを処理 - 独自API:
/api/chat、/api/generate、/api/embedなど(別途/v1配下に OpenAI 互換エンドポイントも提供) - モデル管理の統合:
ollama pullで自動ダウンロード、Modelfileでカスタマイズ - メモリ管理:モデルをロード/アンロードし、
OLLAMA_NUM_PARALLELで並列数を制御
vLLMのアーキテクチャ
vLLMは、GPUメモリ効率を重視するPython製の推論エンジンです。
┌───────────────────────────────────────────────────────┐ │ vLLM Architecture │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Chat Server │ │ Embed Server │ │Vision Server │ │ │ │ :8080 │ │ :8081 │ │ :8082 │ │ │ │ │ │ │ │ (optional) │ │ │ │ Qwen2.5 │ │ E5-large │ │ Qwen2-VL │ │ │ │ -1.5B-Inst │ │ -instruct │ │ │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ │ ┌──────┴─────────────────┴─────────────────┴───────┐ │ │ │ GPU Memory (PagedAttention) │ │ │ │ ┌─────────────┐ ┌──────────┐ ┌───────────────┐ │ │ │ │ │ Chat: 55% │ │Embed:35% │ │ Vision: 10% │ │ │ │ │ │ GPU VRAM │ │GPU VRAM │ │ GPU VRAM │ │ │ │ │ └─────────────┘ └──────────┘ └───────────────┘ │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ ・モデルごとに独立プロセス │ │ ・OpenAI互換API (/v1/chat/completions) │ │ ・GPUメモリの割合を個別に制御 │ │ ・Continuous Batchingで高スループット │ └───────────────────────────────────────────────────────┘
特徴
- マルチサーバー構成:用途ごとに独立したサーバープロセスを起動
- OpenAI互換API:
/v1/chat/completions、/v1/embeddings、/v1/models - PagedAttention:GPUメモリをページ単位で管理し、KVキャッシュの無駄を最小化
- Continuous Batching:複数リクエストを動的にバッチ処理し、スループットを最大化
- HuggingFaceモデルの直接利用:ダウンロードからロードまで自動
OllamaとvLLMの比較
Ollamaの特性
| 観点 | 内容 |
|---|---|
| セットアップ | brew install ollama → ollama pull qwen2.5 で完了。導入が容易 |
| モデル管理 | ollama list で一覧、ollama rm で削除。Docker的な操作感 |
| 量子化 | GGUF形式で4bit/8bit量子化モデルを標準サポート。VRAM 8GBでも7Bモデルが動作 |
| CPU推論 | llama.cppベースのため、GPUなしでも動作する(速度は低下する) |
| Modelfile | FROM qwen2.5:7b + SYSTEM "..." でカスタムモデルを定義可能 |
| 制約 | OpenAI 互換は一部機能に限られる、GPUメモリの細かな制御が難しい、マルチモデル同時利用が制限的 |
vLLMの特性
| 観点 | 内容 |
|---|---|
| スループット | PagedAttention + Continuous Batchingにより、同時リクエストの処理能力が高い |
| マルチモデル | モデルごとに独立サーバー。Chat + Embedding + Visionを同時に安定運用 |
| GPUメモリ制御 | --gpu-memory-utilization 0.55 のようにモデルごとのVRAM使用率を指定可能 |
| API互換性 | OpenAI APIと互換。既存のOpenAIクライアントコードをそのまま利用可能 |
| HuggingFace統合 | Qwen/Qwen2.5-1.5B-Instruct のようにHuggingFace IDを直接指定してロード |
| 制約 | 実運用では GPU 前提(CPU ビルドは存在するが性能が出ない)、セットアップがやや複雑、メモリ消費が大きい |
比較表
| 項目 | Ollama | vLLM |
|---|---|---|
| セットアップ時間 | 5分程度 | 30分〜1時間 |
| GPU要否 | なくても動作 | 必須 |
| API形式 | 独自 (/api/chat) | OpenAI互換 (/v1/chat/completions) |
| モデル形式 | GGUF(量子化) | HuggingFace(FP16/BF16) |
| 同時モデル数 | 1〜2(メモリ次第) | 用途別に複数プロセス |
| GPUメモリ制御 | 自動(制御困難) | --gpu-memory-utilization で精密制御 |
| バッチ処理 | 逐次 | Continuous Batching |
| Embedding | 同一サーバー | 別サーバー(専用ポート) |
| 推論速度(単発) | 高速(ggml最適化) | 高速(CUDA最適化) |
| 推論速度(並列) | 低下しやすい | 高スループットを維持 |
| Tensor Parallel | 非対応 | 対応(マルチGPU) |
OllamaからvLLMへの移行
DigitalBaseの社内AI基盤の本番化で実装した移行作業を、5つのステップに整理します。
Step 1: APIクライアント層の変更
最も大きな変更は、Ollama独自APIからOpenAI互換APIへの切り替えです。
主な変更点
| Ollama | vLLM | 備考 |
|---|---|---|
/api/chat | /v1/chat/completions | OpenAI互換エンドポイント |
/api/generate | /v1/completions | テキスト補完 |
/api/embed | /v1/embeddings | Embedding API |
/api/tags | /v1/models | モデル一覧 |
num_predict | max_tokens | パラメータ名の差異 |
repeat_penalty | repetition_penalty | パラメータ名の差異 |
| NDJSON stream | SSE (Server-Sent Events) | ストリーミング形式の差異 |
Step 2: Embeddingサーバーの分離
Ollamaでは1つのサーバーでChatもEmbeddingも処理しますが、vLLMではEmbeddingを専用サーバーとして分離します。
サーバー分離には次のメリットがあります。
- メモリの独立管理:Chat 55%、Embedding 35%のようにGPUメモリを用途別に割り当て
- 独立したスケーリング:Embeddingの負荷が高い場合、そのサーバーだけスケールアウト可能
- 障害の分離:Chatサーバーがクラッシュしても、Embedding処理を継続できる
RAGパイプラインでは、検索のためのEmbedding生成とChat推論が同時に走ります。この分離は、社内ドキュメント検索を伴う用途で特に効果が大きい設計です。
Step 3: Vision APIの移行
画像認識もAPIフォーマットが異なります。
Ollama版
# Ollama: imagesフィールドにbase64画像を配列で渡す response = await client.post( f"{OLLAMA_BASE_URL}/api/chat", json={ "model": vision_model, "messages": [{ "role": "user", "content": prompt, "images": [image_b64] # Ollama独自形式 }], "stream": False } )
vLLM版
# vLLM: OpenAI形式のcontent配列にimage_urlブロックを含める content = [ {"type": "text", "text": prompt}, { "type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_b64}"} # OpenAI形式 }, ] response = await client.post( f"{VLLM_BASE_URL}/v1/chat/completions", json={ "model": vision_model, "messages": [{"role": "user", "content": content}], "max_tokens": 4096, } )
Step 4: インフラ層(プロセス管理)の変更
Ollamaは ollama serve の1プロセスで完結しますが、vLLMは用途別にプロセスを起動します。
実装上の要点は起動順序です。vLLMはモデルロード時にGPUメモリを確保するため、メモリ使用量の大きいChatサーバーを先に起動して完了を待ち、その後にEmbeddingサーバーを起動する必要があります。順序を誤るとメモリ確保が競合し、起動に失敗します。
Step 5: SSEストリーミングパーサーの実装
OllamaはNDJSON(1行1JSON)でストリーミングしますが、vLLMはSSE(Server-Sent Events)形式です。パーサーの差し替えが必要になります。
vLLMサーバーの起動コマンド
移行後のvLLMサーバーの起動コマンドを示します。
Chatサーバー
python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-1.5B-Instruct \ --host 0.0.0.0 \ --port 8080 \ --gpu-memory-utilization 0.55 \ --tensor-parallel-size 1
Embeddingサーバー
# vLLM 0.15.0以降: --convert embed を使用(旧 --task embed) python -m vllm.entrypoints.openai.api_server \ --model intfloat/multilingual-e5-large-instruct \ --host 0.0.0.0 \ --port 8081 \ --gpu-memory-utilization 0.35 \ --convert embed
Visionサーバー(オプション)
python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2-VL-7B-Instruct \ --host 0.0.0.0 \ --port 8082 \ --gpu-memory-utilization 0.10
--gpu-memory-utilization の合計が単一GPUの容量を超えないよう、各サーバーの割り当てを設計時に確定させておく点が重要です。
エンジンの使い分け
Ollamaが適するケース
| シーン | 理由 |
|---|---|
| 低リソース環境 | GGUF量子化でメモリ使用量を最小化 |
| プロトタイピング | モデル切り替えが容易。Modelfileでカスタムプリセットを作成 |
vLLMが適するケース
| シーン | 理由 |
|---|---|
| 本番APIサービス | Continuous Batchingで安定した同時接続処理 |
| 複数モデルの同時利用 | Chat + Embedding + Visionを独立プロセスで並行運用 |
| RAGパイプライン | Chat推論とEmbedding生成を同時に高速処理 |
| マルチGPU環境 | Tensor Parallelで複数GPUにモデルを分散 |
| GPU効率の最大化 | --gpu-memory-utilization でVRAMを精密制御 |
| OpenAI互換が必要 | 既存のOpenAIクライアントコードをそのまま流用 |
| 高スループット | 複数ユーザーからの同時リクエストを効率よく処理 |
まとめ
OllamaからvLLMへの移行は、次のステップで進められます。
- APIエンドポイントの変更:独自API → OpenAI互換API
- Embeddingの分離:同一サーバー → 専用サーバー
- Vision APIの変更:images配列 → OpenAI content配列
- プロセス管理の変更:単一プロセス → マルチプロセス(起動順序に注意)
- ストリーミング形式の変更:NDJSON → SSE
移行時は、APIエンドポイントとストリーミング形式の変更に加え、Embedding・Visionを含む各サーバーのGPUメモリ割り当てと起動順序を確認します。
