Guida introduttiva al Model Switcher di llama.swap per LLM locali compatibili con OpenAI
Hot-swap dei LLM locali senza modificare i client.
Presto ti ritroverai a gestire vLLM, llama.cpp e altri componenti, ognuno su una porta propria. Tutta l’infrastruttura a valle richiede comunque un unico /v1 come base URL; altrimenti continuerai a riordinare porte, profili e script one-off. llama-swap è il proxy /v1 da posizionare davanti a quegli stack.
llama-swap fornisce un unico punto di ingresso compatibile con OpenAI e Anthropic, con un file YAML che mappa ogni nome model al comando che avvia il backend corretto. Richiedi un modello e il proxy lo avvia o ci passa sopra; configura i TTL e i gruppi quando la VRAM è limitata o quando più modelli devono coesistere. Questa guida copre i percorsi di installazione, un config.yaml pratico, la superficie HTTP e i problemi di failure che emergono quando entrano in gioco streaming e proxy inversi.
Per un confronto più ampio delle opzioni di hosting LLM, consulta Hosting LLM nel 2026: Infrastruttura Locale, Self-Hosted e Cloud a confronto
Panoramica dello switcher di modelli llama-swap per API LLM locali compatibili con OpenAI
llama-swap è un server proxy leggero costruito attorno a un modello operativo semplice: un’unica binaria, un file di configurazione YAML, nessuna dipendenza. È scritto in Go, il che significa una singola binaria statica accanto al resto dello stack—nessun runtime Python o app desktop richiesta. Si posiziona davanti a qualsiasi upstream compatibile con OpenAI e Anthropic come layer di cambio modello (model-swapping).
Concettualmente, questo risponde a una domanda molto pratica che sorge negli stack LLM locali:
Come faccio a cambiare modello con un client compatibile con OpenAI?
Con llama-swap continui a usare normali richieste /v1/..., ma cambi il model che richiedi. llama-swap legge quel valore model, carica la configurazione del server corrispondente e, se l’upstream “sbagliato” è in esecuzione, lo sostituisce con quello corretto.
Alcuni dettagli di progettazione sono importanti per setup semi-produzione:
llama-swap è con licenza MIT e nessuna telemetria—vale comunque la pena verificarlo per qualsiasi host che vede prompt reali.
È progettato per il caricamento on-demand di backends come llama.cpp, vLLM, Whisper e stable-diffusion.cpp, non per legarti a un singolo motore di inferenza.
Di default (nessun raggruppamento speciale), esegue un modello alla volta: richiedi un model diverso e ferma l’upstream corrente per avviarne uno nuovo. Per più modelli residenti o un controllo più fine sulla coesistenza, configura i groups.
Ecco il modello mentale che la maggior parte degli sviluppatori trova utile:
Per questo motivo un proxy switcher di modelli è diverso dal “semplice eseguire un modello”: è orchestrazione e routing sopra uno o più server di inferenza.
Confronto tra llama-swap, Ollama, LM Studio e server llama.cpp
Tutte e quattro le opzioni possono darti un’ “API LLM locale”, ma ottimizzano per flussi di lavoro diversi. Il modo più rapido per scegliere è decidere se vuoi un runtime (download + esecuzione modelli) o un router/proxy (cambio + orchestrazione tra i runtime).
llama-swap
llama-swap si concentra sull’essere un proxy trasparente che supporta endpoint compatibili con OpenAI (inclusi /v1/chat/completions, /v1/completions, /v1/embeddings e /v1/models) e instrada le richieste all’upstream corretto in base al modello richiesto. Fornisce anche endpoint operativi non di inferenza come /running, /logs/stream e un’interfaccia Web a /ui.
Ollama
Ollama espone la propria API HTTP (POST /api/chat, POST /api/generate e il solito default locale sulla porta 11434).
keep_alive controlla per quanto tempo un modello resta caricato, incluso 0 per scaricarlo immediatamente.
Si adatta agli utenti che vogliono scaricare un modello e chattare con il minimo cablaggio. llama-swap si adatta a comandi per modello, backends misti e un’unica URL con forma OpenAI per ogni client—orchestrare vLLM accanto a llama-server con flag diversi per modello è al di fuori di ciò che Ollama è progettato per fare.
LM Studio
LM Studio è un’app desktop con un server API locale dalla scheda Developer (localhost o LAN), incluse le modalità compatibili con OpenAI e compatibili con Anthropic, oltre a lms server start dal terminale.
Si adatta a un ciclo di lavoro GUI-first: sfoglia i modelli, clicca, testa. llama-swap si adatta a un ruolo server-style: YAML, supervisione dei processi, upstream misti, nessuna sessione desktop.
Server llama.cpp
llama-server espone /v1/completions, /v1/chat/completions, /v1/responses e il solito pattern è puntare un client OpenAI verso di esso tramite base_url. L’installazione di quel server e dei flag che accetta effettivamente è coperta in llama.cpp quickstart.
llama.cpp include anche una modalità router: esegui llama-server come router, --models-dir, poi POST /models/load e POST /models/unload per gestire modelli GGUF senza un proxy separato. Per una guida di setup completa consulta Modalità router di llama-server: cambio modello dinamico senza riavvii.
Se ogni modello è sotto un singolo router llama.cpp, un proxy aggiuntivo è spesso inutile. Quando llama.cpp deve stare accanto a vLLM o ad altri server con forma OpenAI, llama-swap fornisce una singola superficie /v1 e molti processi dietro di essa.
Per soluzioni di hosting compatibili con OpenAI simili, consulta LocalAI QuickStart: Esegui LLM Compatibili con OpenAI in Locale o SGLang QuickStart: Installa, Configura e Servi LLM via API OpenAI
Installa lo switcher di modelli llama-swap con Docker, Homebrew, WinGet o binarie
Linux, macOS e Windows sono tutti supportati a pieno titolo: Docker, Homebrew, WinGet, binarie da GitHub o compilazione dal sorgente. Scelte comuni: Docker su server headless, Homebrew o WinGet su workstation, binarie standalone quando l’impronta di installazione deve rimanere minima.
Installazione con Docker
Scarica un’immagine che corrisponda al tuo hardware. Le immagini seguono da vicino gli upstream (build notturne) e coprono CUDA, Vulkan, Intel, MUSA e CPU—scegli quella che corrisponde a come accelera effettivamente, non quella “latest” per abitudine.
# Esempio di scaricamento piattaforme
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
Preferisci le varianti di immagine non-root quando possibile: meno di cui pentirsi se il confine del container è sbagliato.
Installazione con Homebrew
Su macOS e Linux, usa il tap e installa:
brew tap mostlygeek/llama-swap
brew install llama-swap
llama-swap --config path/to/config.yaml --listen localhost:8080
Installazione con WinGet
Su Windows:
winget install llama-swap
winget upgrade llama-swap
Binarie pre-compilate e release
Le Release di GitHub offrono binarie per Linux, macOS, Windows e FreeBSD se non vuoi un gestore di pacchetti.
I numeri delle release cambiano rapidamente (ad esempio v198, v197 intorno all’inizio del 2026)—fissa una versione nell’automazione invece di usare “quella che c’era ieri”.
Configura llama-swap con config.yaml per cambio modello, TTL e gruppi
Tutto in llama-swap è guidato dalla configurazione. La configurazione minima vitale è semplicemente un dizionario models: e un cmd per ogni modello, che spesso avvia llama-server con ${PORT} sostituito per modello.
Il sistema di configurazione va molto oltre il “avviare un processo”, e alcune opzioni vale la pena capirle presto perché rispondono direttamente a problemi comuni di tipo FAQ (scarico automatico, sicurezza e client che si basano su /v1/models).
Impostazioni globali che userai effettivamente
healthCheckTimeout è il tempo che llama-swap attende affinché un modello diventi sano dopo l’avvio (default 120s, minimo 15s). Per caricamenti multi-GB su dischi lenti, aumenta questo valore prima di dare la colpa al proxy.
globalTTL è il numero di secondi di inattività prima dello scarico automatico; default 0 significa “mai scaricare” a meno che tu non lo imposti—scegli TTL espliciti per qualsiasi setup oltre il toy in modo che la VRAM non si riempia di modelli dimenticati.
startPort inizializza la macro ${PORT} (default 5800); l’assegnazione è deterministica per ID modello alfabetico, che è un vantaggio quando debugghi “chi ha preso quale porta” e una trappola se rinomini i modelli senza cura.
includeAliasesInList decide se gli alias appaiono come righe separate in /v1/models; attivalo se la tua UI offre solo modelli enumerati.
apiKeys protegge tutto ciò che è raggiungibile da localhost: Basic, Bearer o x-api-key. llama-swap rimuove quelle header prima di inoltrare in modo che i log upstream siano meno propensi a ritenere segreti dei client.
Impostazioni a livello di modello che sbloccano l’ergonomia di produzione
Per modello, cmd è l’unico campo obbligatorio.
proxy è di default http://localhost:${PORT}—questo è il target di inoltro per l’upstream di quel modello.
checkEndpoint è di default /health; imposta "none" quando il backend non ha una rotta di salute o l’avvio a freddo supera ciò che sei disposto ad attendere—non lasciare un /health rotto e chiederti perché nulla raggiunge ready.
ttl: -1 eredita globalTTL, 0 non scarica mai, N > 0 scarica dopo N secondi di inattività—usa TTL per modello quando un modello dovrebbe restare e un altro sparire rapidamente.
aliases e useModelName mantengono nomi stabili rivolti al client soddisfando upstream che richiedono un identificatore specifico.
cmdStop non è opzionale per i container: mappalo a docker stop (o equivalente); senza di esso ottieni POSIX SIGTERM / taskkill di Windows contro il PID che llama-swap ha avviato—va bene per una binaria nuda, sbagliato per un nome di container.
concurrencyLimit limita le richieste parallele per modello con HTTP 429 quando superato—impotalo quando preferisci scaricare il carico piuttosto che fare la coda all’infinito.
I groups coprono la coesistenza (swap, exclusive) e i modelli sempre attivi (persistent). Gli hook possono precaricare all’avvio; se precarichi più modelli alla volta senza un gruppo, aspettati che si scontrino—definisci prima un gruppo in modo che il precaricamento corrisponda a come vuoi che i modelli condividano la GPU.
Esempio minimo di config.yaml per llama.cpp e vLLM
Questo esempio mira a essere “abbastanza” da illustrare le migliori pratiche: un TTL predefinito, check di salute espliciti, alias stabili e un gruppo che mantiene in esecuzione un modello piccolo “sempre attivo” mentre i modelli di chat più grandi fanno il cambio.
# config.yaml
healthCheckTimeout: 180
globalTTL: 900 # 15 minuti di inattività poi scarico
includeAliasesInList: true
startPort: 5800
# Opzionale ma raccomandato per qualsiasi cosa oltre lo sviluppo 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"
# Usa i valori di default:
# proxy: http://localhost:${PORT}
# checkEndpoint: /health
# ttl: -1 (eredita globalTTL)
qwen-coder:
cmd: |
llama-server --port ${PORT} --model /models/qwen-coder.gguf
--ctx-size 8192
aliases:
- "qwen-coder-latest"
vllm-coder:
# Schema esemplificativo: gestire un server compatibile OpenAI containerizzato
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 # mai scaricare automaticamente (es. lascia sulla GPU)
groups:
chat-models:
swap: true
exclusive: true
members: ["llama-chat", "qwen-coder"]
always-on:
persistent: true
swap: false
exclusive: false
members: ["vllm-coder"]
Nessuna di queste cose è decorativa: cmd guida il processo, proxy/checkEndpoint/ttl controllano routing e ciclo di vita, cmdStop è ciò che fa sì che gli upstream basati su Docker fermino davvero, e i groups sono ciò che separa “un grande modello alla volta” da “questi due modelli di chat possono coesistere mentre il server di embedding resta fissato”.
Esegui e cambia modelli tramite endpoint compatibili con OpenAI
Una volta che llama-swap è in esecuzione, interagisci con esso come con qualsiasi altro endpoint compatibile con OpenAI. La superficie API include endpoint principali come /v1/chat/completions, /v1/completions, /v1/embeddings e /v1/models, e llama-swap usa il model richiesto per decidere quale upstream eseguire e a quale instradare.
Un flusso di avvio pratico:
# 1) Avvia llama-swap
llama-swap --config ./config.yaml --listen localhost:8080
# 2) Scopri i modelli disponibili
curl http://localhost:8080/v1/models
L’elenco dei modelli è una funzionalità di gestione di primo piano e include comportamenti come l’ordinamento per ID, l’esclusione di modelli unlisted e l’inclusione opzionale di alias.
# 3) Esegui una richiesta di completamento chat per un modello specifico
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."}]
}'
Se ora ripeti la chiamata con "model": "llama-chat", llama-swap cambierà i processi upstream (a meno che la configurazione dei gruppi non permetta loro di coesistere) perché estrae il modello richiesto dalla richiesta e carica la configurazione del server appropriata.
Se stai usando un SDK, punta il client verso http://localhost:8080/v1—stesso trucco di puntare la libreria Python di OpenAI verso llama-server, tranne che l’URL stabile ora è llama-swap e il campo model sceglie l’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": "Explain the difference between mutexes and semaphores."}],
)
print(resp.choices[0].message.content)
Per riscaldare un modello prima della prima richiesta reale (nascondere la latenza dell’avvio a freddo), usa /upstream/<model>—si carica automaticamente se necessario e inoltta direttamente a quell’upstream. Modo semplice per garantire che i pesi siano residenti prima di un benchmark o un test scriptato.
Controlla e monitora llama-swap tramite endpoint API di gestione ed eventi SSE
llama-swap non è solo “un proxy”; espone anche endpoint di controllo operativo che ti permettono di costruire strumenti attorno al ciclo di vita del modello e all’osservabilità.
Controlla cosa è in esecuzione
GET /running restituisce lo stato di runtime per i modelli caricati, inclusi valori di stato come ready, starting, stopping, stopped e shutdown.
curl http://localhost:8080/running
Scarica i modelli per liberare VRAM
Per scaricare tutto immediatamente, usa l’endpoint con versione API POST /api/models/unload. Per scaricare un singolo modello (per ID o alias), usa POST /api/models/unload/<model>. Esiste un GET /unload legacy per la compatibilità inversa.
# scarica tutto
curl -X POST http://localhost:8080/api/models/unload
# scarica un modello
curl -X POST http://localhost:8080/api/models/unload/qwen-coder
Usa questi endpoint quando la VRAM è necessaria adesso invece di attendere il TTL—benchmark, cambi rapidi di modello o dopo aver caricato un checkpoint molto più grande di quanto inteso.
Streaming di eventi live tramite SSE
GET /api/events stabilisce uno stream di Server-Sent Events ed è progettato per aggiornamenti in tempo reale che includono cambi di stato dei modelli, log, metriche e conteggi di richieste in corso.
curl -N http://localhost:8080/api/events
SSE e streaming dei token si rompono se qualsiasi scatola intermedia fa buffering—disabilita il buffering su nginx (o equivalente) per /api/events e /v1/chat/completions. llama-swap imposta X-Accel-Buffering: no su SSE; disabilita il buffering anche nel proxy—le header non sono una sostituta per una configurazione proxy corretta.
Metriche e catture delle richieste
GET /api/metrics restituisce metriche di utilizzo dei token, con ritenzione in memoria controllata da metricsMaxInMemory (default 1000).
GET /api/captures/<id> può recuperare catture complete di richiesta/risposta, ma solo quando è configurato captureBuffer > 0.
Log e interfaccia Web
llama-swap espone /ui per un’interfaccia web, e endpoint di log operativi come /logs e /logs/stream per il monitoraggio in tempo reale.

Se abiliti apiKeys, assumi difesa in profondità: /health e parti di /ui restano raggiungibili senza chiave—va bene per confini di fiducia locali, non va bene se l’host è su una rete condivisa. Metti llama-swap dietro qualcosa che imponga la tua vera politica; l’autenticazione integrata è per mantenere i client occasionali onesti, non per un’API pubblica multi-tenant.
Troubleshooting del cambio modello llama-swap in produzione
La maggior parte dei problemi di llama-swap ricade in un piccolo set di categorie operative: streaming attraverso un proxy inverso, check di salute durante gli avvii a freddo, porte e ciclo di vita dei processi, e autenticazione.
Lo streaming si rompe dietro nginx o un altro proxy inverso
nginx farà volentieri buffering dei tuoi SSE e completamenti streammati. Disabilita proxy_buffering (e proxy_cache) per /api/events e /v1/chat/completions. llama-swap emette X-Accel-Buffering: no su SSE, il che aiuta—sistema comunque il proxy.
Un modello non diventa mai pronto
Di default, checkEndpoint per modello è /health e deve restituire HTTP 200 affinché il processo sia considerato pronto. Puoi impostare checkEndpoint su un altro percorso o su "none" per disabilitare del tutto i check di salute.
Se i grandi modelli richiedono più tempo per caricare, aumenta healthCheckTimeout (default 120s) o usa check di salute su misura per il tuo specifico upstream.
Cambiare modello lascia un vecchio container in esecuzione
Se l’upstream è Docker o Podman, imposta cmdStop—altrimenti llama-swap ferma il processo wrapper mentre il container continua a consumare VRAM in background.
Ricevo risposte 401 dopo aver abilitato la sicurezza
Quando apiKeys è configurato, llama-swap richiede una chiave valida e accetta tre metodi (autenticazione Basic, token Bearer, x-api-key). Rimuove anche le header di autenticazione prima di inoltrare upstream.
Ricevo 429 Too Many Requests
concurrencyLimit restituisce 429 quando superato—per progettazione. Alza il limite se l’hai sotto-provisionato, o abbassa il limite se non intendevi limitare.
Conflitti di porte o problemi di routing strani
Evita porte hard-codate in cmd; usa ${PORT} e sposta startPort se 5800+ collide con qualcos’altro. Ricorda che le porte sono assegnate in ordine alfabetico per ID modello—rinomina un modello e la mappatura delle porte cambia.
Checklist di debug operativo
/running per la verità, /logs/stream quando l’avvio è opaco, POST /api/models/unload quando la VRAM è necessaria adesso. Questa triade copre la maggior parte delle sessioni “perché la GPU è piena”.