digital base
プロダクトドキュメント最新情報コンテンツ会社概要

お問い合わせ

ご質問やご相談など、お気軽にお問い合わせください。

デジタルベース株式会社

〒106-0047
東京都港区南麻布3-20-1 5階

サイトメニュー

  • トップページ
  • プロダクト
  • ドキュメント
  • 最新ニュース
  • 記事一覧
  • 会社情報

お問い合わせ

  • info@digital-base.co.jp

NVIDIA Inception Program / Intel Partner ISV /
NTTPC Innovation LAB / IT導入補助金 対象

© デジタルベース株式会社. All rights reserved.
一覧に戻る

2026年2月23日

·

AI

·
958 文字

OllamaからvLLMへの移行設計|ローカルLLMで複数モデルを同時運用する構成

ローカルLLM推論エンジンとして広く使われるOllamaとvLLMを比較し、社内AI基盤を本番運用へ移行する設計指針を整理します。API互換性、Embeddingサーバーの分離、起動順序など、実装レベルの移行手順を具体的に解説します。

OllamaからvLLMへの移行設計|ローカルLLMで複数モデルを同時運用する構成

ローカルLLMの導入は、まず手軽なエンジンで検証を始め、要件が固まった段階で本番向けのエンジンへ移行する流れが一般的です。本稿では、検証フェーズで広く使われる Ollama から、本番運用に適した vLLM へ移行する際の設計と実装手順を、DigitalBaseでの構築知見をもとに整理します。複数モデルの同時運用、OpenAI互換API、GPUメモリの精密制御といった本番要件にどう対応するかを、コードレベルで具体的に扱います。


オープンソースLLM推論エンジンの動向

軽量化とローカル推論の民主化

LLM推論のオープンソース化は、ここ数年で急速に進みました。

時期できごとインパクト
2023年前半llama.cpp登場CPU推論の実用化。ggml/GGUF量子化により、消費者向けGPUでの動作が現実に
2023年後半Ollama登場ollama pull → ollama run の2コマンドでローカルLLMを起動。Docker的なUX
2024年vLLM普及PagedAttentionによるGPUメモリの効率化。サーバー用途で高スループットを実現
2025年量子化・軽量モデルの成熟Qwen2.5(1.5B〜72B)、Gemma3、Llama3.2などが実用レベルに。VRAM 8GBでも実用的に動作

エンジン選択の現状

2026年時点で、ローカルLLM推論エンジンは大きく3つの系統に整理できます。

[llama.cpp系] [Python系] [CUDA最適化系] llama.cpp vLLM TensorRT-LLM Ollama SGLang TGI LM Studio ...
  • llama.cpp系:CPU/GPU対応、GGUF量子化、セットアップが容易
  • Python系(vLLM等):PagedAttentionによるGPU効率化、OpenAI互換APIを標準装備
  • CUDA最適化系:最大性能だがセットアップが複雑、NVIDIA環境に限定

一般的な導入ステップとしては、「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 など(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なしでも動作する(速度は低下する)
ModelfileFROM qwen2.5:7b + SYSTEM "..." でカスタムモデルを定義可能
制約独自API(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推論不可)、セットアップがやや複雑、メモリ消費が大きい

比較表

項目OllamavLLM
セットアップ時間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という棲み分けが基本となります。


OllamaからvLLMへの移行

ここからは、実際の移行作業を5つのステップに分けて解説します。いずれもDigitalBaseの社内AI基盤を本番化する過程で実装した内容です。

Step 1: APIクライアント層の変更

最も大きな変更は、Ollama独自APIからOpenAI互換APIへの切り替えです。

Ollama版(chat/service.py)

# Ollama: /api/chat エンドポイント(独自フォーマット) async with client.stream( "POST", f"{OLLAMA_BASE_URL}/api/chat", json={ "model": request.model, "messages": messages, "stream": True, "options": { "temperature": request.temperature, "num_predict": request.max_tokens, # Ollama独自パラメータ名 } }, ) as response: async for line in response.aiter_lines(): chunk = json.loads(line) text = chunk.get("message", {}).get("content", "")

vLLM版(chat/service.py)

# vLLM: /v1/chat/completions エンドポイント(OpenAI互換) async for chunk in stream_chat_completions( client, model=request.model, messages=messages, temperature=request.temperature, max_tokens=request.max_tokens, # OpenAI標準パラメータ名 top_p=request.top_p, top_k=request.top_k, # vLLM拡張パラメータ repetition_penalty=request.repeat_penalty, # vLLM拡張パラメータ thinking=request.thinking, stream=request.stream, ): text = chunk.get("text", "")

主な変更点

OllamavLLM備考
/api/chat/v1/chat/completionsOpenAI互換エンドポイント
/api/generate/v1/completionsテキスト補完
/api/embed/v1/embeddingsEmbedding API
/api/tags/v1/modelsモデル一覧
num_predictmax_tokensパラメータ名の差異
repeat_penaltyrepetition_penaltyパラメータ名の差異
NDJSON streamSSE (Server-Sent Events)ストリーミング形式の差異

Step 2: Embeddingサーバーの分離

Ollamaでは1つのサーバーでChatもEmbeddingも処理しますが、vLLMではEmbeddingを専用サーバーとして分離します。

Ollama版(chat/service.py)

async def embed_text_with_ollama(text: str, model: str = None) -> List[float]: """Ollama /api/embed で埋め込み生成""" async with httpx.AsyncClient(timeout=60.0) as client: resp = await client.post( f"{OLLAMA_BASE_URL}/api/embed", # 同じサーバー json={"model": "embeddinggemma:latest", "input": text}, ) data = resp.json() return data.get("embeddings", [[]])[0]

vLLM版(common/vllm.py)

async def embed_text(text: str, model: str = None) -> List[float]: """vLLM /v1/embeddings で埋め込み生成(専用サーバー)""" async with httpx.AsyncClient(timeout=60.0) as client: resp = await client.post( f"{VLLM_EMBED_BASE_URL}/v1/embeddings", # 別サーバー (:8081) json={ "model": "intfloat/multilingual-e5-large-instruct", "input": text, }, ) data = resp.json() return data.get("data", [{}])[0].get("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は用途別にプロセスを起動します。

# Ollama版 infrastructure.py def start_ollama() -> bool: subprocess.Popen(['ollama', 'serve'], ...) # 1プロセス def stop_ollama() -> bool: subprocess.run(['ollama', 'stop'], ...) # 1コマンド
# vLLM版 infrastructure.py def start_vllm() -> bool: # 1. Chatサーバーを起動(GPUメモリを先に確保) _start_vllm_server("chat", "Qwen/Qwen2.5-1.5B-Instruct", 8080) _wait_for_server(VLLM_BASE_URL, ...) # 起動待ち # 2. Embeddingサーバーを起動(残りのGPUメモリを使用) _start_vllm_server("embed", "intfloat/multilingual-e5-large-instruct", 8081, convert="embed") _wait_for_server(VLLM_EMBED_BASE_URL, ...) # 3. Visionサーバーを起動(オプション) if DEFAULT_VISION_MODEL: _start_vllm_server("vision", DEFAULT_VISION_MODEL, 8082)

実装上の要点は起動順序です。vLLMはモデルロード時にGPUメモリを確保するため、メモリ使用量の大きいChatサーバーを先に起動して完了を待ち、その後にEmbeddingサーバーを起動する必要があります。順序を誤るとメモリ確保が競合し、起動に失敗します。

Step 5: SSEストリーミングパーサーの実装

OllamaはNDJSON(1行1JSON)でストリーミングしますが、vLLMはSSE(Server-Sent Events)形式です。パーサーの差し替えが必要になります。

# vLLM SSEストリーミングパーサー(common/vllm.py) async with client.stream("POST", f"{VLLM_BASE_URL}/v1/chat/completions", json=payload) as response: async for line in response.aiter_lines(): if not line.startswith("data: "): continue data_str = line[6:] # "data: " プレフィックスを除去 if data_str == "[DONE]": yield {"text": "", "done": True, "usage": final_usage} return chunk = json.loads(data_str) delta = chunk["choices"][0].get("delta", {}) yield { "text": delta.get("content", ""), "done": False, "reasoning_content": delta.get("reasoning_content"), # 思考モデル対応 }

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が適するケース

シーン理由
個人の開発・実験ollama pull → ollama run で即座に試せる
GPUなし環境CPU推論に対応。Apple Silicon搭載のMacでも快適に動作
デスクトップアプリLM Studio等のUI付きアプリとの統合
低リソース環境GGUF量子化でメモリ使用量を最小化
プロトタイピングモデル切り替えが容易。Modelfileでカスタムプリセットを作成
エッジデバイスRaspberry Pi等の軽量デバイスでも動作可能

vLLMが適するケース

シーン理由
本番APIサービスContinuous Batchingで安定した同時接続処理
複数モデルの同時利用Chat + Embedding + Visionを独立プロセスで並行運用
RAGパイプラインChat推論とEmbedding生成を同時に高速処理
マルチGPU環境Tensor Parallelで複数GPUにモデルを分散
GPU効率の最大化--gpu-memory-utilization でVRAMを精密制御
OpenAI互換が必要既存のOpenAIクライアントコードをそのまま流用
高スループット複数ユーザーからの同時リクエストを効率よく処理

段階的導入の推奨パス

Phase 1: Ollama(開発・検証) ↓ 本番要件が固まったら Phase 2: vLLM(本番運用) ↓ さらなるスケールが必要なら Phase 3: TensorRT-LLM / SGLang(最大性能)

実践的な判断基準

  • 同時接続ユーザー数 5人未満 → Ollamaで十分
  • 同時接続ユーザー数 5〜50人 → vLLMを検討
  • GPUメモリの使用率を最適化したい → vLLMを推奨
  • GPUがない、またはMacBook Airで動かしたい → Ollamaが適切

まとめ

OllamaからvLLMへの移行は、次のステップで進められます。

  1. APIエンドポイントの変更:独自API → OpenAI互換API
  2. Embeddingの分離:同一サーバー → 専用サーバー
  3. Vision APIの変更:images配列 → OpenAI content配列
  4. プロセス管理の変更:単一プロセス → マルチプロセス(起動順序に注意)
  5. ストリーミング形式の変更:NDJSON → SSE
  6. フロントエンド互換性の維持:レスポンスフィールド名の統一

両エンジンとも開発が活発に続いており、いずれかが優れているという話ではありません。Ollamaで手軽に検証を始め、本番要件が固まった段階でvLLMへ移行してスケールさせるという2段階のアプローチが、現時点でのオープンソースLLM構築における実践的な戦略です。

DigitalBase データ連携フロー
DigitalBase

社内データを、ネットワーク不要で
“使えるAI”に。

エンタープライズに必要なAI機能を1つに集約した、ライセンス型のオンプレミスLLM基盤。 機密データを外部に出さず、完全オフライン環境で運用できます。

  • ✓ 専用AIチャット / ドキュメントAgent(RAG)
  • ✓ 文字起こし・ベンチマーク測定
  • ✓ 管理者・共有・権限管理機能
無料で試す製品の詳細を見る

資料請求・導入のご相談は お問い合わせ から。

ニュースリリース

最新のお知らせやプレスリリースをご覧いただけます

お知らせ
「AI NATIVE EXPO 2026」(6月10日〜12日 @ 幕張メッセ) に出展いたします
Interop Tokyo 併設の総合展「AI NATIVE EXPO 2026」に出展いたします。社内データを自動連携・加工し、BI・AIエージェントへ繋ぐ一連のフローを展示します。
2026年6月8日
プレスリリースPR TIMES
台湾AIインフラ企業Spingence Technologyと社内データ連携AIプラットフォームを共同開発
4月15日〜17日開催「NexTech Week 2026【春】第10回 AI・人工知能 EXPO」に出展 ~社内データをAIに接続し、業務フローに組み込む企業向けAI基盤~
2026年4月6日
お知らせ
「AI Frontier 2026」にスポンサー出展
AI技術の最前線を発信するカンファレンス「AI Frontier 2026」にスポンサーとして出展いたします。
2026年3月4日
一覧に戻る