llama.swap モデルスイッチャーのクイックスタート(OpenAI 互換ローカル LLM 向け)
クライアントを変更せずに、ローカル LLM をホットスワップします。
まもなく、vLLM や llama.cpp、さらに多くのスタックをそれぞれのポートで並行して管理することになるでしょう。しかし、下流のシステムはすべて単一の /v1 ベース URL を望みます。そうしないと、ポート、プロファイル、ワンオフスクリプトを絶えず整理し続ける羽目になります。llama-swap は、それらのスタックの前に置かれる /v1 プロキシです。
llama-swap は、OpenAI 互換かつ Anthropic 互換のフロントドアを単一で提供し、YAML ファイルを使って各 model 名を適切なアップストリームを起動するコマンドにマッピングします。モデルをリクエストすると、プロキシはそのモデルを起動または切り替えます。VRAM が逼迫している場合や、複数のモデルが共存する必要がある場合に、TTL やグループを設定できます。このガイドでは、インストールパス、実用的な config.yaml、HTTP の機能面、そしてストリーミングやリバースプロキシが絡み始めた際に現れる障害モードについて解説します。
LLM ホスティングオプションのより広範な比較については、LLM Hosting in 2026: Local, Self-Hosted & Cloud Infrastructure Compared を参照してください。
OpenAI 互換のローカル LLM API 向けの llama-swap モデルスイッチャー概観
llama-swap は軽量なプロキシサーバーであり、シンプルな運用モデルを基に構築されています:単一のバイナリ、単一の YAML 設定ファイル、依存関係なし。Go で書かれているため、スタックの残りと共に単一の静的バイナリとして動作し、Python ランタイムやデスクトップアプリは必要ありません。これは、あらゆるOpenAI 互換かつ Anthropic 互換のアップストリームの前に立ち、モデル切り替えレイヤーとして機能します。
概念的には、これはローカル LLM スタックで頻繁に直面する非常に実用的な疑問に対する答えです。
OpenAI 互換クライアントでモデルを切り替えるにはどうすればよいですか?
llama-swap を使用すれば、通常の /v1/... リクエストを使い続けることができますが、リクエストする model を変更するだけです。llama-swap はその model 値を読み取り、一致するサーバー設定を読み込み、もし「間違った」アップストリームが実行中の場合は、正しいものに切り替えます。
本番に近い設定では、いくつかの設計詳細が重要になります。
llama-swap は MIT ライセンスでテレメトリ(計測データ送信)なしです——ただし、本番のプロンプトを見るホストでは確認する価値があります。
これは、llama.cpp、vLLM、Whisper、stable-diffusion.cpp などのバックエンドをオンデマンドで読み込むために設計されており、単一の推論エンジンに縛られるものではありません。
デフォルト(特別なグループ設定なし)では、一度に 1 つのモデルを実行します:異なる model をリクエストすると、現在のアップストリームが停止され、適切なものが起動します。1 つ以上の常駐モデルや共存に対するより細かい制御が必要な場合は、groups を設定します。
多くの開発者が役立つと感じるメンタルモデルは以下の通りです。
flowchart LR
C[Your app or SDK\nOpenAI-compatible client] -->|/v1/chat/completions\nmodel = qwen-coder| LS[llama-swap proxy\nsingle endpoint]
LS -->|starts or routes to| U1[Upstream server A\nllama-server]
LS -->|starts or routes to| U2[Upstream server B\nvLLM OpenAI server]
LS --> M[Management endpoints\nrunning, unload, events, metrics]
これが、モデル切り替えプロキシが「単にモデルを実行する」ことと異なる理由です。これは、1 つまたは複数の推論サーバーの上に構築されたオーケストレーションとルーティングです。
llama-swap と Ollama と LM Studio と llama.cpp サーバーの比較
この 4 つのオプションはすべて「ローカル LLM API」を提供できますが、最適化されているワークフローは異なります。選択する最も速い方法は、ランタイム(モデルのダウンロード+実行)が欲しいのか、ルーター/プロキシ(ランタイム間の切り替えとオーケストレーション)が欲しいのかを決定することです。
llama-swap
llama-swap は、OpenAI 互換エンドポイント(/v1/chat/completions、/v1/completions、/v1/embeddings、/v1/models など)をサポートし、リクエストされたモデルに基づいて適切なアップストリームにリクエストをルーティングする透過的なプロキシに焦点を当てています。また、推論以外の運用エンドポイント(/running、/logs/stream、/ui の Web UI など)も提供します。
Ollama
Ollama は独自の HTTP API(POST /api/chat、POST /api/generate、および通常はポート 11434 のローカルデフォルト)を公開します。
keep_alive はモデルが読み込まれたままになる時間を制御し、0 は即座にアンロードします。
これは、モデルをプルしてチャットしたいユーザーに適しており、配線は最小限です。llama-swap は、モデルごとのコマンド、混合バックエンド、すべてのクライアントに対する単一の OpenAI 形式の URLに適しています。vLLM を llama-server の隣でオーケストレーションし、モデルごとに異なるフラグを設定するのは、Ollama が狙っている範囲外です。
LM Studio
LM Studio は、Developer タブ(localhost または LAN)からローカル API サーバーを提供するデスクトップアプリで、OpenAI 互換およびAnthropic 互換モードに加え、ターミナルからの lms server start コマンドも含みます。
これは、モデルを閲覧してクリックしてテストするGUI ファーストなループに適しています。llama-swap は、YAML、プロセス管理、混合アップストリーム、デスクトップセッションなしのサーバースタイルの役割に適しています。
llama.cpp サーバー
llama-server は /v1/completions、/v1/chat/completions、/v1/responses を公開し、通常の使い方は base_url を介して OpenAI クライアントをそれへ指向させることです。
llama.cpp にはルーターモードも付属しています:llama-server をルーターとして実行し、--models-dir を指定して、POST /models/load と POST /models/unload で GGUF モデルを別プロキシなしで切り替えます。
すべてのモデルが1 つの llama.cpp ルーターの下にある場合、追加のプロキシは不要なことが多いです。llama.cpp が vLLM や他の OpenAI 形式のサーバーの隣に置かれる必要がある場合、llama-swap は単一の /v1 表面と、その背後にある多数のプロセスを提供します。
同様の OpenAI 互換ホスティングソリューションについては、LocalAI QuickStart: Run OpenAI-Compatible LLMs Locally または SGLang QuickStart: Install, Configure, and Serve LLMs via OpenAI API を参照してください。
Docker、Homebrew、WinGet、またはバイナリで llama-swap モデルスイッチャーをインストール
Linux、macOS、Windows はいずれもファーストクラスに対応しています:Docker、Homebrew、WinGet、GitHub バイナリ、またはソースからのビルドです。一般的な選択としては、ヘッドレスサーバーでは Docker、ワークステーションでは Homebrew または WinGet、インストールフットプリントを最小限に抑えたい場合はスタンドアロンバイナリです。
Docker インストール
ハードウェアに一致するイメージをプルしてください。イメージはアップストリームに密接に追従しており(Nightly ビルド)、CUDA、Vulkan、Intel、MUSA、CPU をカバーしています。習慣で「latest」ではなく、実際に使用するアクセラレーションに一致するものを選んでください。
# 例としてのプラットフォームプル
docker pull ghcr.io/mostlygeek/llama-swap:cuda
docker pull ghcr.io/mostlygeek/llama-swap:vulkan
docker pull ghcr.io/mostlygeek/llama-swap:intel
docker pull ghcr.io/mostlygeek/llama-swap:musa
docker pull ghcr.io/mostlygeek/llama-swap:cpu
可能であれば、非ルートイメージのバリアントを優先してください:コンテナの境界が誤っている場合でも、後悔する要素が少ないためです。
Homebrew インストール
macOS および Linux では、タップしてインストールします:
brew tap mostlygeek/llama-swap
brew install llama-swap
llama-swap --config path/to/config.yaml --listen localhost:8080
WinGet インストール
Windows 上では:
winget install llama-swap
winget upgrade llama-swap
事前構築済みバイナリとリリース
パッケージマネージャーを望まない場合、GitHub リリースには Linux、macOS、Windows、FreeBSD のバイナリが含まれています。
リリース番号は素早く移動します(例:2026 年初頭の v198、v197 など)——自動化では、昨日あった「何か」に依存するのではなく、バージョンをピン留めしてください。
config.yaml で llama-swap を設定してモデル切り替え、TTL、グループを管理
llama-swap のすべては設定駆動です。最小限の機能設定は、単に models: 辞書と、各モデルの cmd だけであり、通常は ${PORT} を各モデルごとに置換して llama-server を起動します。
設定システムは「プロセスを起動する」だけよりもはるかに深く、いくつかのオプションは早期に理解する価値があります。これらは、自動アンロード、セキュリティ、および /v1/models に依存するクライアントなど、一般的な FAQ 形式の問題に直接答えからです。
実際に使用するグローバル設定
healthCheckTimeout は、llama-swap がモデルの起動後に健全になるのを待つ時間です(デフォルト120 秒、最小15 秒)。スロウディスク上のマルチ GB 読み込みの場合、プロキシを非難する前にこれを増やしてください。
globalTTL は自動アンロードまでのアイドル秒数です。デフォルトの**0は「アンロードしない」を意味しますが、設定した場合のみです——VRAM が忘れられたモデルで埋まらないように、おもちゃの設定を超えたものについては明示的に TTL を選択してください。
startPort は ${PORT} マクロの種となる値です(デフォルト5800**)。割り当てはモデル ID のアルファベット順に決定論的であり、これは「どのポートを誰が占有したか」をデバッグする際の機能ですが、モデル名を不注意に変更すると足かせになります。
includeAliasesInList は、エイリアスが /v1/models に別行として表示されるかどうかを決定します。UI が列挙されたモデルのみを提供する場合は、オンにしてください。
apiKeys は、localhost 以外の到達可能なものをゲートキーします:Basic、Bearer、または x-api-key。llama-swap はこれらのヘッダーを転送前に削除するため、アップストリームログがクライアントの秘密を保持する可能性が低くなります。
本番環境の使い勝手を解き放つモデルレベルの設定
モデルごとに cmd は必須フィールドのみです。
proxy はデフォルトで http://localhost:${PORT} であり、そのモデルのアップストリームの転送ターゲットです。
checkEndpoint はデフォルトで /health です。バックエンドにヘルスルートがない場合、またはコールドスタートが待つのに耐えられない場合、"none" に設定します——壊れた /health を残して「なぜ ready にならないのか」と不思議がるべきではありません。
ttl: -1 は globalTTL を継承し、0 はアンロードされず、N > 0 は N 秒のアイドル後にアンロードします——あるモデルは残っておき、あるモデルはすぐに消えたい場合にモデルごとの TTL を使用します。
aliases と useModelName は、クライアント向けの安定した名前を保ちつつ、特定の識別子を必要とするアップストリームに対応します。
cmdStop はコンテナにとって必須です:docker stop(または同等のもの)にマッピングします。それがない場合、llama-swap が起動した PID に対して POSIX SIGTERM / Windows taskkill が発行されます——裸のバイナリには問題ありませんが、コンテナ名に対しては誤っています。
concurrencyLimit はモデルごとの並行リクエスト数を制限し、超過時に HTTP 429 を返します——永遠にキューに並べるよりも負荷を捨てたい場合に設定します。
groups は共存(swap、exclusive)と常時オンモデル(persistent)をカバーします。フックは起動時にプリロードできます。グループなしで複数のモデルを一度にプリロードすると、互いに競合するのを期待してください——まずグループを定義して、プリロードがモデルを GPU と共有する望ましい方法に一致するようにしてください。
llama.cpp と vLLM 向けの最小限の config.yaml 例
この例は、ベストプラクティスのノブを説明するのに「ちょうど良い」ことを目指しています:デフォルトの TTL、明示的なヘルスチェック、安定したエイリアス、そして小さな「常時オン」モデルを実行し続けながら大きなチャットモデルを切り替えるグループです。
# config.yaml
healthCheckTimeout: 180
globalTTL: 900 # 15 分アイドルしたらアンロード
includeAliasesInList: true
startPort: 5800
# localhost 開発を超えたものにはオプションだが推奨
apiKeys:
- "${env.LLAMASWAP_API_KEY}"
models:
llama-chat:
cmd: |
llama-server --port ${PORT} --model /models/llama-chat.gguf
--ctx-size 8192
aliases:
- "llama-chat-latest"
# デフォルトを使用:
# proxy: http://localhost:${PORT}
# checkEndpoint: /health
# ttl: -1 (globalTTL を継承)
qwen-coder:
cmd: |
llama-server --port ${PORT} --model /models/qwen-coder.gguf
--ctx-size 8192
aliases:
- "qwen-coder-latest"
vllm-coder:
# 例示パターン:コンテナ化された OpenAI 互換サーバーを管理
proxy: "http://127.0.0.1:${PORT}"
cmd: |
docker run --name ${MODEL_ID} --init --rm -p ${PORT}:8000 vllm/vllm-openai:latest
cmdStop: docker stop ${MODEL_ID}
checkEndpoint: "none"
ttl: 0 # 自動アンロードしない(例:GPU 上に保持)
groups:
chat-models:
swap: true
exclusive: true
members: ["llama-chat", "qwen-coder"]
always-on:
persistent: true
swap: false
exclusive: false
members: ["vllm-coder"]
これらは装飾的なものではありません:cmd がプロセスを駆動し、proxy/checkEndpoint/ttl がルーティングとライフサイクルを制御し、cmdStop が Docker ベースのアップストリームを実際に停止させ、groups が「1 つの大きなモデルを一度に」から「これらの 2 つのチャットモデルは共存しつつ埋め込みサーバーは固定される」を区別します。
OpenAI 互換エンドポイント経由でモデルを実行して切り替え
llama-swap が実行されると、他の OpenAI 互換エンドポイントと同様に操作します。API 表面には /v1/chat/completions、/v1/completions、/v1/embeddings、/v1/models などのコアエンドポイントが含まれ、llama-swap はリクエストされた model を使って実行およびルーティングするアップストリームを決定します。
実用的なクイックスタートフロー:
# 1) llama-swap を起動
llama-swap --config ./config.yaml --listen localhost:8080
# 2) 利用可能なモデルを検出
curl http://localhost:8080/v1/models
モデルリストはファーストクラスの管理機能であり、ID によるソート、unlisted モデルの除外、およびオプションのエイリアス包含などの動作を含みます。
# 3) 特定のモデルのチャット完了リクエストを実行
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${LLAMASWAP_API_KEY}" \
-d '{
"model": "qwen-coder",
"messages": [{"role":"user","content":"Write a TypeScript function that retries fetch with backoff."}]
}'
ここで "model": "llama-chat" で呼び出しを繰り返すと、llama-swap はアップストリームプロセスを切り替えます(グループ設定が共存を許可しない限り)——これはリクエストからリクエストされたモデルを抽出し、適切なサーバー設定を読み込むからです。
SDK を使用している場合、クライアントを http://localhost:8080/v1 に向けさせます——llama-server に向ける OpenAI Python ライブラリと同じトリックですが、安定した URL は今や llama-swap であり、model フィールドがアップストリームを選ぶのです。
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="sk-your-llamaswap-key"
)
resp = client.chat.completions.create(
model="qwen-coder",
messages=[{"role": "user", "content": "Explain the difference between mutexes and semaphores."}],
)
print(resp.choices[0].message.content)
最初の実際のリクエスト前にモデルをウォームアップ(コールドスタートの遅延を隠す)するには、/upstream/<model> を使用します——必要に応じて自動ロードされ、そのアップストリームに直接転送します。ベンチマークやスクリプトテスト前にウェイトが常駐していることを確認するシンプルな方法です。
管理 API エンドポイントと SSE イベントで llama-swap を制御・監視
llama-swap は単なる「プロキシ」ではなく、モデルのライフサイクルと可視性周りのツールを構築するための運用制御エンドポイントも公開します。
実行中のものを確認
GET /running は、読み込まれたモデルのランタイム状態を返し、ready、starting、stopping、stopped、shutdown などの状態値を含みます。
curl http://localhost:8080/running
VRAM を解放するためにモデルをアンロード
すべてを即座にアンロードするには、API バージョン付きエンドポイント POST /api/models/unload を使用します。単一のモデル(ID またはエイリアスで)をアンロードするには、POST /api/models/unload/<model> を使用します。後方互換性のためにレガシーな GET /unload も存在します。
# すべてアンロード
curl -X POST http://localhost:8080/api/models/unload
# 1 つのモデルをアンロード
curl -X POST http://localhost:8080/api/models/unload/qwen-coder
TTL を待つ代わりに、VRAM を今すぐ必要とする場合にこれらのエンドポイントを使用します——ベンチマーク、素早いモデル切り替え、または意図よりもはるかに大きなチェックポイントをロードした後など。
SSE を経由してライブイベントをストリーミング
GET /api/events は Server-Sent Events ストリームを確立し、モデル状態の変更、ログ、メトリック、および進行中のリクエスト数を含むリアルタイム更新用に設計されています。
curl -N http://localhost:8080/api/events
SSE とトークンストリーミングは、ミドルボックスがバッファリングするときに破断します——nginx(または同等のもの)で /api/events と /v1/chat/completions に対してバッファリングを無効にしてください。llama-swap は SSE に X-Accel-Buffering: no を設定しますが、プロキシ設定も無効にしてください——ヘッダーは正しいプロキシ設定の代わりにはなりません。
メトリックとリクエストキャプチャー
GET /api/metrics はトークン使用率のメトリックを返し、metricsMaxInMemory(デフォルト 1000)で制御されるメモリ内保持を行います。
GET /api/captures/<id> は完全なリクエスト/レスポンスキャプチャーを取得できますが、captureBuffer > 0 が設定された場合のみです。
ログと Web UI
llama-swap は Web インターフェースのための /ui を公開し、リアルタイム監視のための /logs と /logs/stream のような運用ログエンドポイントも提供します。

apiKeys を有効にする場合、多層防御を想定してください:/health と /ui の一部はキーなしで到達可能です——ローカルな信頼境界には問題ありませんが、共有ネットワーク上のホストでは問題外です。llama-swap を実際にポリシーを強制するものの後ろに置いてください。組み込み認証はカジュアルなクライアントを正直にさせるためのもので、パブリックなマルチテナント API 用ではありません。
本番環境での llama-swap モデル切り替えのトラブルシューティング
llama-swap の問題のほとんどは、いくつかの運用カテゴリに分類されます:リバースプロキシを通じたストリーミング、コールドスタート中のヘルスチェック、ポートとプロセスライフサイクル、認証です。
nginx や他のリバースプロキシの背後でストリーミングが破断する
nginx は SSE とストリーミング完了を喜んでバッファリングしてしまいます。/api/events と /v1/chat/completions に対して proxy_buffering(および proxy_cache)を無効にしてください。llama-swap は SSE に X-Accel-Buffering: no を発しますが、それでもプロキシを修正してください。
モデルが ready にならない
デフォルトでは、モデルごとの checkEndpoint は /health であり、プロセスが ready と見なされるには HTTP 200 を返す必要があります。checkEndpoint を別のパスまたは "none" に設定してヘルスチェックを完全に無効にできます。
大きなモデルの読み込みに時間がかかる場合は、healthCheckTimeout を増やしてください(デフォルト 120 秒)または、特定のアップストリームに適したヘルスチェックを使用してください。
モデル切り替えが古いコンテナを稼働させたままにする
アップストリームが Docker または Podman の場合、cmdStop を設定してください——そうしないと、llama-swap はラッパープロセスを停止しますが、コンテナはバックグラウンドで VRAM を消費し続けます。
セキュリティを有効にした後、401 レスポンスを取得する
apiKeys が設定されている場合、llama-swap は有効なキーを必要とし、3 つの方法(Basic 認証、Bearer トークン、x-api-key)を受け付けます。また、アップストリームへ転送前に認証ヘッダーを削除します。
429 Too Many Requests を取得する
concurrencyLimit は超過時に 429 を返します——設計通りです。過小評価した場合は上限を引き上げ、意図しないスロットリングをした場合は制限を下げてください。
ポート競合または奇妙なルーティング問題
cmd でハードコードされたポートを避け、${PORT} を使用し、5800+ が他のものと衝突する場合は startPort を移動してください。ポートはモデル ID のアルファベット順に割り当てられることを覚えておいてください——モデル名を変更するとポートマッピングがシフトします。
運用デバッグチェックリスト
真実には /running、起動が不透明な場合は /logs/stream、VRAM を今すぐ必要とする場合は POST /api/models/unload を使用します。この 3 つの組み合わせが、多くの「なぜ GPU が満杯なのか」セッションをカバーします。