Szybki start: Przełącznik modeli llama.swap dla lokalnych modeli LLM zgodnych z OpenAI

Gorąca wymiana lokalnych modeli LLM bez konieczności zmiany klientów.

Page content

Wkrótce będziesz jugglingować vLLM, llama.cpp i innymi – każdy stos na własnym porcie. Wszystko w dalszym ciągu oczekuje jednej bazowej URL /v1; inaczej ciągle będziesz przesuwać porty, profile i skrypty jednorazowe. llama-swap to proxy /v1 przed tymi stosami.

llama-swap zapewnia jedno kompatybilne z OpenAI i Anthropic wejście, z plikiem YAML, który mapuje każdą nazwę model na polecenie uruchamiające odpowiedni upstream. Zażądaj modelu, a proxy go uruchomi lub przełączy; skonfiguruj TTL-i i grupy, gdy VRAM jest ograniczona lub gdy kilka modeli musi współistnieć. Ten przewodnik obejmuje ścieżki instalacji, praktyczny config.yaml, powierzchnię HTTP oraz tryby awarii, które pojawiają się, gdy do gry wchodzą strumienie i serwery odwrotne.

llama swap llm infographic Dla szerszego porównania 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 zbudowany wokół prostego modelu operacyjnego: jeden binarnik, jeden plik konfiguracyjny YAML, brak zależności. Jest napisany w Go, co oznacza pojedynczy statyczny binarnik obok reszty stosu – bez wymogu środowiska Python lub aplikacji desktopowej. Umieszcza się przed każdym kompatybilnym z OpenAI i Anthropic upstreamem jako warstwa przełączania modeli.

Pojęciowo rozwiązuje to bardzo praktyczne pytanie pojawiające 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 żądany model. llama-swap czyta tę wartość model, ładuje pasującą konfigurację serwera i jeśli „zły" upstream jest uruchomiony, podmienia go na poprawny.

Kilka szczegółów projektowych ma znaczenie dla konfiguracji przybliżonych do produkcji:

llama-swap jest licencjonowany na MIT z brakiem telemetrii – nadal warto to potwierdzić dla każdego hosta widzącego prawdziwe prompty.
Został zbudowany dla ładowania backendów na żądanie, takich jak llama.cpp, vLLM, Whisper i stable-diffusion.cpp, a nie do blokowania Cię na jednym silniku inferencji.
Domyślnie (bez specjalnych grup) uruchamia jeden model na raz: żądanie innego model zatrzymuje bieżący upstream i uruchamia właściwy. Dla więcej niż jednego modelu rezydenta lub dokładniejszej 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 również dlatego, że proxy przełącznika modeli różni się od „po prostu uruchamiania modelu": to orkiestracja i routing nad jednym lub więcej serwerami inferencji.

llama-swap vs Ollama vs LM Studio vs serwer llama.cpp

Wszystkie cztery opcje mogą zapewnić „lokalne API LLM", ale optymalizują dla różnych workflow. Najszybszy sposób na wybór to decyzja, czy chcesz środowisko uruchomieniowe (pobranie modelu + wykonanie) czy router/proxy (przełączanie + orkiestracja między środowiskami).

llama-swap
llama-swap skupia się na byciu przejrzystym proxy, które obsługuje punkty końcowe kompatybilne z OpenAI (w tym /v1/chat/completions, /v1/completions, /v1/embeddings i /v1/models) oraz przekierowuje żądania do poprawnego upstreamu na podstawie żądanego modelu. Zapewnia również operacyjne punkty końcowe niezwiązane z inferencją, takie jak /running, /logs/stream oraz interfejs Web UI pod /ui.

Ollama
Ollama wystawia własne API HTTP (POST /api/chat, POST /api/generate oraz standardowe lokalne domyślne na porcie 11434).
keep_alive kontroluje, jak długo model pozostaje załadowany, w tym 0 do natychmiastowego odł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 per model jest poza celem Ollama.

LM Studio
LM Studio to aplikacja desktopowa z lokalnym serwerem API z zakładki Developer (localhost lub LAN), w tym tryby kompatybilne z OpenAI i kompatybilne z Anthropic, plus lms server start z terminala.
Pasuje do pętli skupionej na GUI: przeglądaj modele, klikaj, testuj. llama-swap pasuje do roli serwerowej: YAML, nadzór nad procesami, mieszane upstreamy, brak sesji desktopowej.

Serwer llama.cpp
llama-server wystawia /v1/completions, /v1/chat/completions, /v1/responses, a standardowy wzorzec to wskazanie klienta OpenAI na niego przez base_url.
llama.cpp dostarcza również tryb routera: uruchom llama-server jako router, --models-dir, następnie POST /models/load i POST /models/unload, aby jugglingować modele GGUF bez osobnego proxy.
Jeśli każdy model znajduje się pod jednym routerem llama.cpp, dodatkowe proxy często nie jest konieczne. Gdy 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 nim.

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 binarnikami

Linux, macOS i Windows są traktowane równo: Docker, Homebrew, WinGet, binarniki z GitHub lub kompilacja ze źródeł. Powszechne wybory: Docker na serwerach bez GUI, Homebrew lub WinGet na stacjach roboczych, samodzielne binarniki, gdy ślad instalacji ma być minimalny.

Instalacja Docker

Pobierz obraz pasujący do Twojego sprzętu. Obrazy śledzą upstream blisko (budowy 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

Preferuj warianty obrazów nie-root, gdy możesz: mniej żalów, jeśli granica kontenera kiedyś będzie błędna.

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

Gotowe binarniki i wydania

Wydania na GitHub dostarczają binarniki dla Linux, macOS, Windows i FreeBSD, jeśli nie chcesz menedżera pakietów.
Numery wydań zmieniają się szybko (np. v198, v197 pod koniec 2026) – przypisz wersję w automatyzacji zamiast pływania na „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 podstawiąnym ${PORT} per model.

System konfiguracji idzie znacznie dalej niż tylko „uruchom proces", a kilka opcji warto zrozumieć wczesnie, ponieważ bezpośrednio odpowiadają na częste problemy typu FAQ (automatyczne odładowywanie, bezpieczeństwo i klienci polegający na /v1/models).

Globalne ustawienia, które faktycznie użyjesz

healthCheckTimeout to czas, jaki llama-swap czeka, aż model stanie się zdrowy po starcie (domyślnie 120s, minimum 15s). Dla wielo-GB ładowań na wolnych dyskach, zwiększ to, zanim zawinisz proxy.
globalTTL to sekundy bezczynności przed automatycznym odładowaniem; domyślnie 0 oznacza „nigdy nie odładowuj", chyba że ustawisz – wyraźnie wybierz TTL dla wszystkiego poza zabawkową konfiguracją, aby VRAM nie zapełniła się zapomnianymi modelami.
startPort nasienia makro ${PORT} (domyślnie 5800); przypisanie jest deterministyczne wg alfabetycznego ID modelu, co jest funkcją, gdy debugujesz „kto zajął który port", a miną, jeśli bezmyślnie zmienisz nazwy modeli.
includeAliasesInList decyduje, czy aliasy pojawią się jako osobne wiersze w /v1/models; włącz to, jeśli Twój UI oferuje tylko wyliczone modele.
apiKeys blokuje wszystko osiągalne poza localhostem: Basic, Bearer lub x-api-key. llama-swap usuwa te nagłówki przed przesyłaniem, więc upstreamy logują mniej prawdopodobnie zachowują sekrety klienta.

Ustawienia na poziomie modelu, które odblokowują ergonomię produkcyjną

Per model, cmd jest jedynym wymaganym polem.
proxy domyślnie to http://localhost:${PORT} – to cel przesyłania dla upstreamu tego modelu.
checkEndpoint domyślnie to /health; ustaw "none", gdy backend nie ma trasy zdrowia lub zimny start przekracza to, co jesteś gotów czekać – nie zostawiaj zepsutego /health i pytaj, dlaczego nic nie osiąga ready.
ttl: -1 dziedziczy globalTTL, 0 nigdy nie odładowuje, N > 0 odładowuje po N sekundach bezczynności – użyj TTL per model, gdy jeden model ma się zalegać, a inny szybko zniknąć.
aliases i useModelName utrzymują stabilne nazwy widoczne dla klienta, podczas gdy spełniają upstreamy wymagające specyficznego identyfikatora.
cmdStop jest nieopcjonalny dla kontenerów: mapuj na docker stop (lub odpowiednik); bez niego otrzymujesz POSIX SIGTERM / Windows taskkill przeciwko dowolnemu PID, który llama-swap uruchomił – w porządku dla gołego binarnika, źle dla nazwy kontenera.
concurrencyLimit ogranicza równoległe żądania per model z HTTP 429 przy przekroczeniu – ustaw to, gdy wolisz odrzucić obciążenie niż czekać w kolejce na zawsze.

groups pokrywają współistnienie (swap, exclusive) i modele zawsze-włączone (persistent). Haki mogą preładować przy starcie; jeśli preładowujesz kilka modeli naraz bez grupy, oczekuj, że będą się walkować – 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 celuje w „just enough", aby zilustrować najlepsze praktyki: domyślny TTL, jawne sprawdzanie zdrowia, stabilne aliasy i grupa, która utrzymuje mały model „zawsze-włączony" podczas gdy większe modele czatu się przełączają.

# config.yaml
healthCheckTimeout: 180
globalTTL: 900            # 15 minut bezczynności, potem odładowanie
includeAliasesInList: true
startPort: 5800

# Opcjonalne, ale zalecane dla wszystkiego poza rozwojem 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"
    # 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 odł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"]

Nic 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 to to, co oddziela „jeden duży model na raz" od „te dwa modele czatu mogą współistnieć, podczas gdy serwer wektorów pozostaje przypięty".

Uruchamianie i przełączanie modeli przez punkty końcowe kompatybilne z OpenAI

Po uruchomieniu llama-swap, interagujesz z nim jak z dowolnym innym punktem końcowym kompatybilnym z OpenAI. Powierzchnia API obejmuje główne punkty końcowe takie jak /v1/chat/completions, /v1/completions, /v1/embeddings i /v1/models, a llama-swap używa żądanego model, aby zdecydować, który upstream uruchomić i do którego 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

Wykaz modeli to funkcja zarządzania pierwszego rzędu 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 powtarza fetch z backoff."}]
  }'

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ż ekstrahuje żądany model z żądania i ładuje odpowiednią konfigurację serwera.

Jeśli używasz SDK, wskaż klienta na http://localhost:8080/v1 – ten sam trik co celowanie biblioteki OpenAI Python na llama-server, z wyjątkiem tego, że stabilny URL to 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 semaforami."}],
)
print(resp.choices[0].message.content)

Aby rozgrzać model przed pierwszym prawdziwym żądaniem (ukryć opóźnienie zimnego startu), użyj /upstream/<model> – automatycznie ładuje, jeśli potrzebne, i przekierowuje bezpośrednio do tego upstreamu. Prosty sposób na zapewnienie, że wagi są rezydentne przed testem benchmarkowym lub 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ż operacyjne punkty końcowe kontroli, które pozwalają budować narzędzia wokół cyklu życia modelu i obserwowalności.

Sprawdź, co działa
GET /running zwraca stan uruchomieniowy dla załadowanych modeli, w tym wartości stanu takie jak ready, starting, stopping, stopped i shutdown.

curl http://localhost:8080/running

Odladowuj modele, aby zwolnić VRAM
Aby odładować wszystko natychmiast, użyj punktu końcowego z wersją API POST /api/models/unload. Aby odładować pojedynczy model (po ID lub aliasie), użyj POST /api/models/unload/<model>. Legacy GET /unload istnieje dla kompatybilności wstecznej.

# odładowanie wszystkich
curl -X POST http://localhost:8080/api/models/unload

# odładowanie jednego modelu
curl -X POST http://localhost:8080/api/models/unload/qwen-coder

Użyj tych punktów końcowych, gdy VRAM jest potrzebna z powrotem teraz, zamiast czekać na TTL – benchmarki, szybkie przełączenia 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 psują się, gdy jakiekolwiek pośrednie urządzenie buforuje – wyłącz buforowanie na nginx (lub odpowiedniku) dla /api/events i /v1/chat/completions. llama-swap ustawia X-Accel-Buffering: no dla 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 odzyskać pełne przechwyconia żądań/odpowiedzi, ale tylko gdy captureBuffer > 0 jest skonfigurowane.

Logi i interfejs Web UI

llama-swap wystawia /ui dla interfejsu webowego oraz punkty końcowe logów operacyjnych, takie jak /logs i /logs/stream dla monitoringu w czasie rzeczywistym.

llama-swap web UI for switching models

Jeśli włączysz apiKeys, zakładaj obronę w głębi: /health i części /ui pozostają osiągalne 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ś, co egzekwuje Twoją prawdziwą politykę; wbudowane uwierzytelnienie służy do utrzymywania przypadkowych klientów uczciwych, 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 wpada do małej kategorii operacyjnej: strumieniowanie przez serwer odwrotny, sprawdzanie zdrowia podczas zimnych startów, porty i cykl życia procesów oraz uwierzytelnianie.

Strumieniowanie psuje się za nginx lub innym serwerem odwrotnym
nginx z przyjemnoś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 dla SSE, co pomaga – napraw proxy tak czy inaczej.

Model nigdy nie staje się gotowy
Domyślnie, per-model checkEndpoint to /health i musi zwrócić 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 zajmują dłuższy czas ładowania, zwiększ healthCheckTimeout (domyślnie 120s) lub użyj dostosowanych sprawdzania zdrowia dla Twojego specyficznego upstreamu.

Przełączanie modeli pozostawia stary kontener uruchomiony
Jeśli upstream to Docker lub Podman, ustaw cmdStop – inaczej llama-swap zatrzyma proces opakowania, podczas gdy kontener będzie dalej zużywał 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 przesyłaniem upstream.

Otrzymuję 429 Too Many Requests
concurrencyLimit zwraca 429 przy przekroczeniu – z założenia. Zwiększ limit, jeśli niedoinwestowałeś, lub zmniejsz, jeśli nie miałeś zamiaru throttlować.

Konflikty portów lub dziwne problemy z routingu
Unikaj hardkodowanych portów w cmd; użyj ${PORT} i przesuń startPort, jeśli 5800+ koliduje z czymś innym. Pamiętaj, że porty są przypisywane w porządku alfabetycznym wg ID modelu – zmień nazwę modelu i mapowanie portów się przesunie.

Lista kontrolna debugowania operacyjnego
/running dla prawdy, /logs/stream gdy start jest niejasny, POST /api/models/unload gdy VRAM jest potrzebna z powrotem teraz. Ta trójka pokrywa większość sesji „dlaczego GPU jest pełne".