Szybki start przełącznika modeli llama.swap dla lokalnych LLM kompatybilnych z OpenAI
Gorące wymiana lokalnych modeli LLM bez konieczności zmiany klientów.
Wkrótce będziesz balansować między vLLM, llama.cpp i innymi rozwiązaniami – każdy stos na własnym porcie. Wszystko w dalszym ciągu oczekuje jednego podstawowego adresu URL /v1; inaczej ciągle będziesz przesuwać porty, profile i skrypty ad-hoc. llama-swap jest proxy /v1 przed tymi stosami.
llama-swap zapewnia jeden kompatybilny z OpenAI i Anthropic punkt wejścia, z plikiem YAML, który mapuje każdą nazwę model na polecenie uruchamiające odpowiedni upstream. Poproś o model, a proxy go uruchomi lub przełączy się na niego; skonfiguruj TTL i grupy, gdy VRAM jest ograniczony lub wiele modeli musi współistnieć. Ten przewodnik obejmuje ścieżki instalacji, praktyczny config.yaml, powierzchnię HTTP oraz tryby awaryjne, które pojawiają się, gdy do gry wchodzą strumieniowanie i serwery odwrotne.
Aby uzyskać szersze porównanie opcji hostingu LLM, zobacz LLM Hosting in 2026: Local, Self-Hosted & Cloud Infrastructure Compared
Przegląd przełącznika modeli llama-swap dla lokalnych API LLM kompatybilnych z OpenAI
llama-swap to lekki serwer proxy oparty na prostym modelu operacyjnym: jeden plik binarny, jeden plik konfiguracyjny YAML, brak zależności. Jest napisany w języku Go, co oznacza pojedynczy statyczny plik binarny obok reszty stosu – bez konieczności uruchamiania Pythona czy aplikacji desktopowej. Znajduje się przed dowolnym upstreamem kompatybilnym z OpenAI i Anthropic jako warstwa przełączania modeli.
W koncepcji rozwiązuje to bardzo praktyczne pytanie, które pojawia się w lokalnych stosach LLM:
Jak przełączać modele z klientem kompatybilnym z OpenAI?
Z llama-swap nadal używasz normalnych żądań /v1/..., ale zmieniasz model, którego żądasz. llama-swap odczytuje tę wartość model, ładuje odpowiadającą mu konfigurację serwera i jeśli „błędny" upstream jest uruchomiony, zamienia go na właściwy.
Kilka szczegółów projektowych ma znaczenie dla środowisk produkcyjnych:
llama-swap jest licencjonowany na MIT z brakiem telemetrii – wciąż warto to potwierdzić dla każdego hosta, który widzi prawdziwe prompty.
Został zbudowany dla uruchamiania backendów na żądanie, takich jak llama.cpp, vLLM, Whisper i stable-diffusion.cpp, a nie dla przywiązania do jednego silnika inferencji.
Domyślnie (bez specjalnych grup) uruchamia jeden model na raz: poproś o inny model i zatrzyma bieżący upstream oraz uruchomi właściwy. Dla więcej niż jednego modelu rezydenta lub bardziej precyzyjnej kontroli współistnienia, skonfiguruj groups.
Oto model mentalny, który większość programistów uważa za użyteczny:
flowchart LR
C[Twoja aplikacja lub SDK\nKlient kompatybilny z OpenAI] -->|/v1/chat/completions\nmodel = qwen-coder| LS[llama-swap proxy\npojedynczy punkt końcowy]
LS -->|uruchamia lub przekierowuje do| U1[Serwer upstream A\nllama-server]
LS -->|uruchamia lub przekierowuje do| U2[Serwer upstream B\nvLLM OpenAI server]
LS --> M[Punkty końcowe zarządzania\nrunning, unload, events, metrics]
To też dlatego, że proxy przełącznika modeli różni się od „po prostu uruchamiania modelu": to orkiestracja i routing na jednym lub więcej serwerach inferencji.
llama-swap vs Ollama vs LM Studio vs serwer llama.cpp
Wszystkie cztery opcje mogą zapewnić Ci „lokalne API LLM", ale optymalizują one różne przepływy pracy. Najszybszym sposobem na wybór jest decyzja, czy chcesz runtime (pobieranie modelu + wykonanie), czy router/proxy (przełączanie i orkiestracja między runtime’ami).
llama-swap
llama-swap skupia się na byciu przezroczystym proxy, które obsługuje punkty końcowe kompatybilne z OpenAI (w tym /v1/chat/completions, /v1/completions, /v1/embeddings oraz /v1/models) i przekierowuje żądania do poprawnego upstreamu na podstawie żądanego modelu. Zapewnia również punkty końcowe operacyjne nie związane z inferencją, takie jak /running, /logs/stream oraz interfejs WWW pod adresem /ui.
Ollama
Ollama wystawia własne API HTTP (POST /api/chat, POST /api/generate, oraz standardowy port lokalny 11434).
keep_alive kontroluje, jak długo model pozostaje załadowany, w tym 0 dla natychmiastowego rozładowania.
Pasuje użytkownikom, którzy chcą pobrać model i czatować z minimalną konfiguracją. llama-swap pasuje do polecenia per model, mieszanych backendów i jednego URL w kształcie OpenAI dla każdego klienta – orkiestracja vLLM obok llama-server z różnymi flagami dla każdego modelu jest poza zakresem celów Ollamy.
LM Studio
LM Studio to aplikacja desktopowa z lokalnym serwerem API z zakładki Deweloper (localhost lub LAN), w tym tryby kompatybilne z OpenAI i Anthropic, oraz lms server start z terminala.
Pasuje do pętli opartej na GUI: przeglądaj modele, klikaj, testuj. llama-swap pasuje do roli stylu serwera: YAML, nadzór procesów, mieszane upstreamy, bez sesji desktopowej.
Serwer llama.cpp
llama-server wystawia /v1/completions, /v1/chat/completions, /v1/responses, a typowym wzorcem jest skierowanie klienta OpenAI do niego za pomocą base_url.
llama.cpp dostarcza również tryb routera: uruchom llama-server jako router, --models-dir, a następnie POST /models/load i POST /models/unload, aby balansować modelami GGUF bez osobnego proxy. Aby uzyskać pełny przewodnik konfiguracji, zobacz llama-server router mode: dynamic model switching without restarts.
Jeśli każdy model znajduje się pod jednym routerem llama.cpp, dodatkowe proxy jest często zbędne. Kiedy llama.cpp musi siedzieć obok vLLM lub innych serwerów w kształcie OpenAI, llama-swap zapewnia jedną powierzchnię /v1 i wiele procesów za nią.
Dla podobnych rozwiązań hostingu kompatybilnych z OpenAI zobacz LocalAI QuickStart: Run OpenAI-Compatible LLMs Locally lub SGLang QuickStart: Install, Configure, and Serve LLMs via OpenAI API
Instalacja przełącznika modeli llama-swap z Docker, Homebrew, WinGet lub plikami binarnymi
Linux, macOS i Windows są traktowane z równą uwagą: Docker, Homebrew, WinGet, pliki binarne z GitHuba lub kompilacja ze źródeł. Popularne wybory: Docker na serwerach bez interfejsu użytkownika, Homebrew lub WinGet na stacjach roboczych, samodzielne pliki binarne, gdy ślad instalacji powinien być minimalny.
Instalacja Docker
Pobierz obraz pasujący do Twojego sprzętu. Obrazy śledzą upstream bardzo blisko (budowania nocne) i obejmują CUDA, Vulkan, Intel, MUSA oraz CPU – wybierz ten, który pasuje do tego, jak faktycznie przyspieszasz, a nie „latest" z przyzwyczajenia.
# Przykładowe pobrań platform
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
Wolę warianty obrazów nieadministratora (non-root), gdy to możliwe: mniej żałuj, jeśli granica kontenera kiedyś będzie niepoprawna.
Instalacja Homebrew
Na macOS i Linux użyj tap i zainstaluj:
brew tap mostlygeek/llama-swap
brew install llama-swap
llama-swap --config path/to/config.yaml --listen localhost:8080
Instalacja WinGet
Na Windows:
winget install llama-swap
winget upgrade llama-swap
Pliki binarne i wydania
Wydania na GitHubie oferują pliki binarne dla Linux, macOS, Windows i FreeBSD, jeśli nie chcesz używać menedżera pakietów.
Numery wydzeń zmieniają się szybko (na przykład v198, v197 na początku 2026 roku) – przypinaj wersję w automatyzacji zamiast pływania z „tym, co było wczoraj".
Konfiguracja llama-swap z config.yaml dla przełączania modeli, TTL i grup
Wszystko w llama-swap jest sterowane konfiguracją. Minimalna wykonalna konfiguracja to po prostu słownik models: i cmd dla każdego modelu, często uruchamiający llama-server z ${PORT} podmienianym dla każdego modelu.
System konfiguracji idzie znacznie dalej niż „uruchomienie procesu", a kilka opcji warto zrozumieć na wczesnym etapie, ponieważ bezpośrednio odpowiadają na częste problemy typu FAQ (automatyczne rozładowywanie, bezpieczeństwo i klienci polegający na /v1/models).
Ustawienia globalne, które faktycznie użyjesz
healthCheckTimeout to czas, jaki llama-swap czeka, aż model stanie się zdrowy po uruchomieniu (domyślnie 120s, minimum 15s). Dla ładowania wielo-gigabajtowych na wolnych dyskach, zwiększ to, zanim winisz proxy.
globalTTL to sekundy bezczynności przed automatycznym rozładowaniem; domyślnie 0 oznacza „nigdy nie rozładowuj", chyba że ustawisz – wyraźnie wybierz TTL dla wszystkiego poza konfiguracją zabawową, aby VRAM nie wypełnił się zapomnianymi modelami.
startPort nasienia makro ${PORT} (domyślnie 5800); przypisanie jest deterministyczne według alfabetycznego ID modelu, co jest funkcją, gdy debugujesz „kto zajął który port" i pułapką, jeśli nieuważnie zmienisz nazwy modeli.
includeAliasesInList decyduje, czy aliasy pojawiają się jako osobne wiersze w /v1/models; włącz to, jeśli Twój interfejs użytkownika oferuje tylko wyliczone modele.
apiKeys zabezpiecza wszystko dostępne poza localhost: Basic, Bearer lub x-api-key. llama-swap usuwa te nagłówki przed przekierowaniem, więc upstreamy są mniej prawdopodobne, aby zatrzymać sekrety klienta.
Ustawienia na poziomie modelu, które odblokowują ergonomię produkcyjną
Dla każdego modelu cmd jest jedynym wymagającym polem.
proxy domyślnie to http://localhost:${PORT} – to jest cel przekierowania dla upstreamu tego modelu.
checkEndpoint domyślnie to /health; ustaw "none", gdy backend nie ma trasy zdrowia lub zimne starty przekraczają to, na co jesteś gotowy czekać – nie zostawiaj zepsutego /health i zastanawiaj się, dlaczego nic nie osiąga stanu ready.
ttl: -1 dziedziczy globalTTL, 0 nigdy nie rozładowuje, N > 0 rozładowuje po N sekundach bezczynności – użyj TTL per model, gdy jeden model powinien trwać dłużej, a inny znikać szybko.
aliases i useModelName utrzymują stabilne nazwy dla klienta, jednocześnie zaspokajając upstreamy wymagające specyficznego identyfikatora.
cmdStop jest niezbędny dla kontenerów: mapuj go na docker stop (lub odpowiednik); bez tego otrzymasz POSIX SIGTERM / Windows taskkill przeciwko PID, który llama-swap uruchomił – w porządku dla gołego pliku binarnego, źle dla nazwy kontenera.
concurrencyLimit ogranicza równoległe żądania per model z HTTP 429, gdy przekroczony – ustaw to, gdy wolisz odrzucić obciążenie niż czekać w kolejce wiecznie.
groups obejmują współistnienie (swap, exclusive) i modele zawsze włączone (persistent). Haczyki mogą preładować przy starcie; jeśli preładowujesz kilka modeli naraz bez grupy, oczekuj, że będą się walczyć – zdefiniuj grupę najpierw, aby preładowanie pasowało do tego, jak chcesz, aby modele dzieliły GPU.
Minimalny przykład config.yaml dla llama.cpp i vLLM
Ten przykład ma na celu bycie „dostatecznym", aby zilustrować najlepsze praktyki: domyślny TTL, wyraźne sprawdzanie zdrowia, stabilne aliasy i grupę, która utrzymuje mały model „zawsze włączony" podczas uruchamiania, podczas gdy większe modele czatu się przełączają.
# config.yaml
healthCheckTimeout: 180
globalTTL: 900 # 15 minut bezczynności, potem rozładuj
includeAliasesInList: true
startPort: 5800
# Opcjonalne, ale zalecane dla wszystkiego poza rozwojem lokalnym
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"
# Używa domyślnych:
# proxy: http://localhost:${PORT}
# checkEndpoint: /health
# ttl: -1 (dziedziczy globalTTL)
qwen-coder:
cmd: |
llama-server --port ${PORT} --model /models/qwen-coder.gguf
--ctx-size 8192
aliases:
- "qwen-coder-latest"
vllm-coder:
# Ilustracyjny wzorzec: zarządzanie konteneryzowanym serwerem kompatybilnym z 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 # nigdy nie rozładowuj automatycznie (np. utrzymaj na GPU)
groups:
chat-models:
swap: true
exclusive: true
members: ["llama-chat", "qwen-coder"]
always-on:
persistent: true
swap: false
exclusive: false
members: ["vllm-coder"]
Żadne z tego nie jest dekoracyjne: cmd napędza proces, proxy/checkEndpoint/ttl kontrolują routing i cykl życia, cmdStop sprawia, że upstreamy oparte na Dockerze faktycznie się zatrzymują, a groups oddzielają „jeden duży model na raz" od „te dwa modele czatu mogą współistnieć, podczas gdy serwer embeddings pozostaje przypięty".
Uruchamianie i przełączanie modeli przez punkty końcowe kompatybilne z OpenAI
Gdy llama-swap działa, interakcja z nim wygląda tak jak z dowolnym innym punktem końcowym kompatybilnym z OpenAI. Powierzchnia API obejmuje kluczowe punkty końcowe, takie jak /v1/chat/completions, /v1/completions, /v1/embeddings oraz /v1/models, a llama-swap używa żądanego model do decyzji, który upstream uruchomić i do niego przekierować.
Praktyczny przepływ szybkiego startu:
# 1) Uruchom llama-swap
llama-swap --config ./config.yaml --listen localhost:8080
# 2) Odkryj dostępne modele
curl http://localhost:8080/v1/models
Wykazanie modeli to pierwszorzędna funkcja zarządzania i obejmuje zachowania takie jak sortowanie po ID, wykluczanie modeli unlisted oraz opcjonalne uwzględnianie aliasów.
# 3) Wykonaj żądanie uzupełnienia czatu dla konkretnego modelu
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":"Napisz funkcję TypeScript, która ponawia fetch z backoffem."}]
}'
Jeśli teraz powtórzysz wywołanie z "model": "llama-chat", llama-swap przełączy procesy upstream (chyba że Twoja konfiguracja grup pozwala im współistnieć), ponieważ wyodrębnia żądany model z żądania i ładuje odpowiednią konfigurację serwera.
Jeśli używasz SDK, skieruj klienta na http://localhost:8080/v1 – ten sam trik co celowanie biblioteki Python OpenAI w llama-server, z wyjątkiem tego, że stabilny URL jest teraz llama-swap, a pole model wybiera upstream.
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": "Wyjaśnij różnicę między mutexami a semaforem."}],
)
print(resp.choices[0].message.content)
Aby przypieścić model przed pierwszym prawdziwym żądaniem (ukryć opóźnienie zimnego startu), użyj /upstream/<model> – automatycznie ładuje, jeśli to konieczne i przekierowuje bezpośrednio do tego upstreamu. Prosty sposób, aby zapewnić, że wagi są rezydentne przed benchmarkiem lub testem skryptowym.
Kontrola i monitorowanie llama-swap przez punkty końcowe API zarządzania i zdarzenia SSE
llama-swap to nie tylko „proxy"; wystawia również punkty końcowe operacyjne, które pozwalają zbudować narzędzia wokół cyklu życia modelu i obserwowalności.
Sprawdź, co działa
GET /running zwraca stan uruchomiony dla załadowanych modeli, w tym wartości stanu takie jak ready, starting, stopping, stopped i shutdown.
curl http://localhost:8080/running
Rozładuj modele, aby zwolnić VRAM
Aby rozładować wszystko natychmiast, użyj punktu końcowego POST /api/models/unload. Aby rozładować pojedynczy model (po ID lub aliasie), użyj POST /api/models/unload/<model>. Istnieje legacy GET /unload dla kompatybilności wstecznej.
# rozładuj wszystko
curl -X POST http://localhost:8080/api/models/unload
# rozładuj jeden model
curl -X POST http://localhost:8080/api/models/unload/qwen-coder
Użyj tych punktów końcowych, gdy VRAM jest potrzebny z powrotem teraz, zamiast czekać na TTL – benchmarki, szybkie przełączanie modeli lub po załadowaniu znacznie większego checkpointu niż zamierzono.
Strumień żywych zdarzeń przez SSE
GET /api/events ustanawia strumień zdarzeń wysyłanych przez serwer (Server-Sent Events) i jest zaprojektowany dla aktualizacji w czasie rzeczywistym, które obejmują zmiany statusu modelu, logi, metryki i liczbę żądań w locie.
curl -N http://localhost:8080/api/events
SSE i strumieniowanie tokenów się psują, gdy jakiekolwiek urządzenie pośredniczące buforuje – wyłącz buforowanie w nginx (lub odpowiedniku) dla /api/events i /v1/chat/completions. llama-swap ustawia X-Accel-Buffering: no w SSE; wyłącz buforowanie w proxy również – nagłówki nie zastępują poprawnej konfiguracji proxy.
Metryki i przechwytywania żądań
GET /api/metrics zwraca metryki użycia tokenów, z retencją w pamięci kontrolowaną przez metricsMaxInMemory (domyślnie 1000).
GET /api/captures/<id> może pobrać pełne przechwycone żądania/odpowiedzi, ale tylko wtedy, gdy skonfigurowano captureBuffer > 0.
Logi i interfejs WWW
llama-swap wystawia /ui dla interfejsu WWW oraz punkty końcowe logów operacyjnych, takich jak /logs i /logs/stream do monitoringu w czasie rzeczywistym.

Jeśli włączysz apiKeys, załóż obronę w głębi: /health i fragmenty /ui pozostają dostępne bez klucza – w porządku dla lokalnych granic zaufania, nie w porządku, jeśli host znajduje się w sieci współdzielonej. Umieść llama-swap za czymś, egzekwującym Twoją prawdziwą politykę; wbudowana uwierzytelnienie służy do utrzymania zwykłych klientów w ryzach, a nie dla publicznego API wielodostępowego.
Rozwiązywanie problemów z przełączaniem modeli llama-swap w produkcji
Większość problemów z llama-swap spada na mały zestaw kategorii operacyjnych: strumieniowanie przez serwer odwrotny, sprawdzanie zdrowia podczas zimnych startów, porty i cykl życia procesów oraz uwierzytelnianie.
Strumieniowanie się psuje za nginx lub innym serwerem odwrotnym
nginx z radością zbuforuje Twoje SSE i strumieniowane uzupełnienia. Wyłącz proxy_buffering (i proxy_cache) dla /api/events i /v1/chat/completions. llama-swap emituje X-Accel-Buffering: no w SSE, co pomaga – napraw proxy tak czy inaczej.
Model nigdy nie staje się gotowy
Domyślnie, checkEndpoint per model to /health i musi zwracać HTTP 200, aby proces był uważany za gotowy. Możesz ustawić checkEndpoint na inną ścieżkę lub na "none", aby całkowicie wyłączyć sprawdzanie zdrowia.
Jeśli duże modele potrzebują więcej czasu na załadowanie, zwiększ healthCheckTimeout (domyślnie 120s) lub użyj dostosowanych sprawdzania zdrowia dla Twojego specyficznego upstreamu.
Przełączanie modeli zostawia stary kontener uruchomiony
Jeśli upstream to Docker lub Podman, ustaw cmdStop – w przeciwnym razie llama-swap zatrzymuje proces opakowania, podczas gdy kontener dalej pożera VRAM w tle.
Otrzymuję odpowiedzi 401 po włączeniu bezpieczeństwa
Gdy apiKeys jest skonfigurowane, llama-swap wymaga ważnego klucza i akceptuje trzy metody (uwierzytelnianie Basic, token Bearer, x-api-key). Usuwa również nagłówki uwierzytelniania przed przekierowaniem upstream.
Otrzymuję 429 Too Many Requests
concurrencyLimit zwraca 429, gdy przekroczony – z założenia. Podnieś limit, jeśli go niedobudowałeś, lub obniż limit, jeśli nie chciałeś ograniczać przepustowości.
Konflikty portów lub dziwne problemy z routingiem
Unikaj portów twardo zakodowanych w cmd; użyj ${PORT} i przesunij startPort, jeśli 5800+ koliduje z czymś innym. Pamiętaj, że porty są przydzielane w kolejności alfabetycznej według ID modelu – zmiana nazwy modelu przesunie mapowanie portów.
Lista kontrolna debugowania operacyjnego
/running dla prawdy, /logs/stream gdy start jest niejasny, POST /api/models/unload gdy VRAM jest potrzebny z powrotem teraz. Ta trójka obejmuje większość sesji „dlaczego GPU jest pełne".