llama.swap Guía rápida del conmutador de modelos para LLMs locales compatibles con OpenAI
Intercambia modelos LLM locales en caliente sin modificar los clientes.
Pronto estarás gestionando vLLM, llama.cpp y más—cada pila en su propio puerto. Todo lo que hay aguas abajo sigue requiriendo una única URL base /v1; de lo contrario, seguirás intercambiando puertos, perfiles y scripts de un solo uso. llama-swap es el proxy /v1 que se sitúa antes de esas pilas.
llama-swap proporciona una única puerta de entrada compatible con OpenAI y Anthropic, con un archivo YAML que asigna cada nombre de model al comando que inicia el upstream correcto. Al solicitar un modelo, el proxy lo inicia o realiza el cambio hacia él; configura TTLs y grupos cuando la VRAM sea limitada o varios modelos deban coexistir. Esta guía cubre las rutas de instalación, una config.yaml práctica, la superficie HTTP y los modos de fallo que aparecen cuando entran en juego el streaming y los proxies inversos.
Para una comparación más amplia de las opciones de alojamiento de LLM, consulta Alojamiento de LLM en 2026: Local, Autoalojado e Infraestructura en la Nube Comparados
Visión general del conmutador de modelos llama-swap para APIs locales de LLM compatibles con OpenAI
llama-swap es un servidor proxy ligero construido en torno a un modelo operativo simple: un único binario, un archivo de configuración YAML, sin dependencias. Está escrito en Go, lo que significa un único binario estático junto al resto de la pila—sin necesidad de un runtime de Python ni una aplicación de escritorio. Se sitúa delante de cualquier upstream compatible con OpenAI y Anthropic como la capa de conmutación de modelos.
Conceptualmente, esto responde a una pregunta muy práctica que surge en las pilas de LLM locales:
¿Cómo cambio de modelos con un cliente compatible con OpenAI?
Con llama-swap sigues utilizando solicitudes normales /v1/..., pero cambias el model que solicitas. llama-swap lee ese valor de model, carga la configuración del servidor correspondiente y, si el upstream “incorrecto” está en ejecución, lo sustituye por el correcto.
Algunos detalles de diseño son importantes para configuraciones tipo producción:
llama-swap tiene licencia MIT y no tiene telemetría—aún así, vale la pena confirmarlo para cualquier host que reciba prompts reales.
Está diseñado para la carga bajo demanda de backends como llama.cpp, vLLM, Whisper y stable-diffusion.cpp, no para encerrarte con un único motor de inferencia.
De serie (sin agrupación especial), ejecuta un modelo a la vez: solicita un model diferente y detiene el upstream actual para iniciar el correcto. Para más de un modelo residente o un control más fino sobre la coexistencia, configura groups.
Este es el modelo mental que la mayoría de los desarrolladores encuentran útil:
Por eso, también, un proxy con conmutador de modelos es diferente a “simplemente ejecutar un modelo”: es orquestación y enrutamiento sobre uno o más servidores de inferencia.
llama-swap vs Ollama vs LM Studio vs servidor llama.cpp
Las cuatro opciones pueden darte una “API de LLM local”, pero optimizan para flujos de trabajo diferentes. La forma más rápida de elegir es decidir si quieres un runtime (descarga + ejecución de modelos) o un router/proxy (conmutación + orquestación entre runtimes).
llama-swap
llama-swap se centra en ser un proxy transparente que soporta puntos de terminación compatibles con OpenAI (incluyendo /v1/chat/completions, /v1/completions, /v1/embeddings y /v1/models) y enruta las solicitudes al upstream correcto en función del modelo solicitado. También proporciona puntos de terminación operativos de no inferencia, como /running, /logs/stream y una interfaz web en /ui.
Ollama
Ollama expone su propia API HTTP (POST /api/chat, POST /api/generate y el puerto local predeterminado habitual en 11434).
keep_alive controla durante cuánto tiempo un modelo permanece cargado, incluyendo 0 para descargarlo inmediatamente.
Se adapta a usuarios que quieren obtener un modelo y chatear con un cableado mínimo. llama-swap se adapta a comandos por modelo, backends mixtos y una única URL con formato OpenAI para cada cliente—orquestrar vLLM junto a llama-server con diferentes banderas por modelo está fuera de lo que Ollama persigue.
LM Studio
LM Studio es una aplicación de escritorio con un servidor de API local desde la pestaña Developer (localhost o LAN), incluyendo modos compatibles con OpenAI y compatibles con Anthropic, más lms server start desde la terminal.
Se adapta a un ciclo centrado en la GUI: navegar por modelos, hacer clic, probar. llama-swap se adapta a un rol estilo servidor: YAML, supervisión de procesos, upstreams mixtos, sin sesión de escritorio.
servidor llama.cpp
llama-server expone /v1/completions, /v1/chat/completions, /v1/responses, y el patrón habitual es apuntar un cliente de OpenAI a él mediante base_url. La instalación de ese servidor y las banderas que realmente respeta se cubren en la Introducción rápida a llama.cpp.
llama.cpp también incluye un modo router: ejecuta llama-server como router, usa --models-dir, y luego POST /models/load y POST /models/unload para gestionar modelos GGUF sin un proxy separado. Para una guía de configuración completa, consulta Modo router de llama-server: conmutación dinámica de modelos sin reinicios.
Si todos los modelos se encuentran bajo un router de llama.cpp, un proxy extra a menudo es innecesario. Cuando llama.cpp debe situarse junto a vLLM u otros servidores con formato OpenAI, llama-swap proporciona una única superficie /v1 y muchos procesos detrás de ella.
Para soluciones de alojamiento compatibles con OpenAI similares, consulta LocalAI QuickStart: Ejecuta LLMs Compatibles con OpenAI Localmente o SGLang QuickStart: Instala, Configura y Sirve LLMs vía API de OpenAI
Instala el conmutador de modelos llama-swap con Docker, Homebrew, WinGet o binarios
Linux, macOS y Windows son de primera clase: Docker, Homebrew, WinGet, binarios de GitHub o compilar desde el código fuente. Opciones comunes: Docker en servidores sin interfaz gráfica, Homebrew o WinGet en estaciones de trabajo, binarios independientes cuando la huella de instalación debe mantenerse mínima.
Instalación con Docker
Obtén una imagen que coincida con tu hardware. Las imágenes siguen de cerca a los upstream (compilaciones nocturnas) y cubren CUDA, Vulkan, Intel, MUSA y CPU—elige la que coincida con cómo aceleras en realidad, no “latest” por costumbre.
# Ejemplo de obtención de imágenes por plataforma
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
Preferencia por las variantes de imagen no raíz cuando sea posible: menos de lo que lamentar si el límite del contenedor alguna vez es incorrecto.
Instalación con Homebrew
En macOS y Linux, usa el tap e instala:
brew tap mostlygeek/llama-swap
brew install llama-swap
llama-swap --config path/to/config.yaml --listen localhost:8080
Instalación con WinGet
En Windows:
winget install llama-swap
winget upgrade llama-swap
Binarios precompilados y versiones
GitHub Releases ofrece binarios para Linux, macOS, Windows y FreeBSD si no quieres usar un gestor de paquetes.
Los números de versión se mueven rápido (por ejemplo v198, v197 alrededor de principios de 2026)—fija una versión en la automatización en lugar de flotar “lo que estaba allí ayer”.
Configura llama-swap con config.yaml para conmutación de modelos, TTL y grupos
Todo en llama-swap está dirigido por configuración. La configuración mínima viable es simplemente un diccionario models: y un cmd para cada modelo, a menudo lanzando llama-server con ${PORT} sustituido por modelo.
El sistema de configuración va mucho más allá de solo “iniciar un proceso”, y algunas opciones valen la pena entender temprano porque responden directamente a problemas comunes de tipo FAQ (descarga automática, seguridad y clientes que dependen de /v1/models).
Configuraciones globales que realmente usarás
healthCheckTimeout es cuánto tiempo llama-swap espera a que un modelo se vuelva saludable tras el arranque (predeterminado 120s, mínimo 15s). Para cargas de varios GB en discos lentos, aumenta esto antes de culpar al proxy.
globalTTL es los segundos en espera antes de la descarga automática; el predeterminado 0 significa “nunca descargar” a menos que lo configures—elige TTLs explícitos para cualquier cosa más allá de una configuración de juguete para que la VRAM no se llene con modelos olvidados.
startPort inicializa la macro ${PORT} (predeterminado 5800); la asignación es determinista por ID de modelo alfabético, lo cual es una función cuando depuras “quién se llevó cuál puerto” y un error si renombras modelos descuidadamente.
includeAliasesInList decide si los alias aparecen como filas separadas en /v1/models; actívalo si tu interfaz solo ofrece modelos enumerados.
apiKeys restringe cualquier cosa accesible fuera de localhost: Basic, Bearer o x-api-key. llama-swap elimina esas cabeceras antes de reenviar para que los registros del upstream sean menos propensos a retener secretos del cliente.
Configuraciones a nivel de modelo que desbloquean ergonomía de producción
Por modelo, cmd es el único campo obligatorio.
proxy por defecto es http://localhost:${PORT}—eso es el objetivo de reenvío para el upstream de ese modelo.
checkEndpoint por defecto es /health; establece "none" cuando el backend no tiene ruta de salud o el arranque en frío excede lo que estás dispuesto a esperar—no dejes un /health roto y te preguntes por qué nada alcanza el estado ready.
ttl: -1 hereda globalTTL, 0 nunca descarga, N > 0 descarga después de N segundos en espera—usa TTL por modelo cuando un modelo debería permanecer y otro debería desaparecer rápidamente.
aliases y useModelName mantienen nombres estables para el cliente mientras satisfacen upstreams que requieren un identificador específico.
cmdStop no es opcional para contenedores: mápalo a docker stop (o equivalente); sin él obtienes POSIX SIGTERM / Windows taskkill contra el PID que llama-swap inició—bien para un binario desnudo, incorrecto para un nombre de contenedor.
concurrencyLimit limita las solicitudes paralelas por modelo con HTTP 429 cuando se excede—establece esto cuando prefieras descarte de carga antes que encolarse para siempre.
groups cubren la coexistencia (swap, exclusive) y los modelos siempre activos (persistent). Los hooks pueden precargar al inicio; si precargas varios modelos a la vez sin un grupo, espera que se peleen—define un grupo primero para que la precarga coincida con cómo quieres que los modelos compartan la GPU.
Ejemplo mínimo de config.yaml para llama.cpp y vLLM
Este ejemplo apunta a ser “lo suficiente” para ilustrar los ajustes de mejores prácticas: un TTL predeterminado, verificación de salud explícita, alias estables y un grupo que mantiene un modelo “siempre activo” pequeño en ejecución mientras los modelos de chat más grandes se intercambian.
# config.yaml
healthCheckTimeout: 180
globalTTL: 900 # 15 minutos en espera y luego descarga
includeAliasesInList: true
startPort: 5800
# Opcional pero recomendado para cualquier cosa más allá del desarrollo en 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 predeterminados:
# proxy: http://localhost:${PORT}
# checkEndpoint: /health
# ttl: -1 (hereda globalTTL)
qwen-coder:
cmd: |
llama-server --port ${PORT} --model /models/qwen-coder.gguf
--ctx-size 8192
aliases:
- "qwen-coder-latest"
vllm-coder:
# Patrón ilustrativo: gestionar un servidor compatible con OpenAI empaquetado en contenedor
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 # nunca descargar automáticamente (ej. mantener en GPU)
groups:
chat-models:
swap: true
exclusive: true
members: ["llama-chat", "qwen-coder"]
always-on:
persistent: true
swap: false
exclusive: false
members: ["vllm-coder"]
Nada de esto es decorativo: cmd impulsa el proceso, proxy/checkEndpoint/ttl controlan el enrutamiento y el ciclo de vida, cmdStop es lo que hace que los upstreams basados en Docker realmente se detengan, y groups es lo que separa “un modelo grande a la vez” de “estos dos modelos de chat pueden coexistir mientras el servidor de embeddings permanece fijado”.
Ejecuta y cambia modelos mediante puntos de terminación compatibles con OpenAI
Una vez que llama-swap está en ejecución, interactúas con él como con cualquier otro punto de terminación compatible con OpenAI. La superficie de la API incluye puntos de terminación principales como /v1/chat/completions, /v1/completions, /v1/embeddings y /v1/models, y llama-swap utiliza el model solicitado para decidir qué upstream ejecutar y al cual enrutar.
Un flujo práctico de inicio rápido:
# 1) Inicia llama-swap
llama-swap --config ./config.yaml --listen localhost:8080
# 2) Descubre los modelos disponibles
curl http://localhost:8080/v1/models
La lista de modelos es una función de gestión de primera clase e incluye comportamiento como ordenar por ID, excluir modelos unlisted e incluir opcionalmente alias.
# 3) Realiza una solicitud de chat completion para un modelo específico
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."}]
}'
Si ahora repites la llamada con "model": "llama-chat", llama-swap intercambiará los procesos upstream (a menos que tu configuración de grupo les permita coexistir) porque extrae el modelo solicitado de la petición y carga la configuración del servidor apropiada.
Si estás usando un SDK, apunta el cliente a http://localhost:8080/v1—el mismo truco que apuntar la librería de Python de OpenAI a llama-server, excepto que la URL estable ahora es llama-swap y el campo model elige el 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)
Para calentar un modelo antes de la primera solicitud real (ocultar la latencia de arranque en frío), usa /upstream/<model>—lo carga automáticamente si es necesario y reenvía directamente a ese upstream. Es la forma sencilla de asegurar que los pesos estén residentes antes de una prueba de rendimiento o una prueba con guion.
Controla y monitorea llama-swap mediante puntos de terminación de la API de gestión y eventos SSE
llama-swap no es solo “un proxy”; también expone puntos de terminación de control operativo que te permiten construir herramientas en torno al ciclo de vida del modelo y la observabilidad.
Revisa lo que está en ejecución
GET /running devuelve el estado de tiempo de ejecución para los modelos cargados, incluyendo valores de estado como ready, starting, stopping, stopped y shutdown.
curl http://localhost:8080/running
Descarga modelos para liberar VRAM
Para descargar todo inmediatamente, usa el punto de terminación con versión de API POST /api/models/unload. Para descargar un modelo individual (por ID o alias), usa POST /api/models/unload/<model>. Existe un GET /unload legado para compatibilidad hacia atrás.
# descarga todos
curl -X POST http://localhost:8080/api/models/unload
# descarga un modelo
curl -X POST http://localhost:8080/api/models/unload/qwen-coder
Usa estos puntos de terminación cuando se necesite la VRAM de vuelta ahora en lugar de esperar al TTL—pruebas de rendimiento, cambios rápidos de modelos o después de cargar un punto de control mucho mayor de lo previsto.
Transmite eventos en vivo vía SSE
GET /api/events establece un flujo de Server-Sent Events y está diseñado para actualizaciones en tiempo real que incluyen cambios de estado del modelo, registros, métricas y conteos de solicitudes en curso.
curl -N http://localhost:8080/api/events
SSE y el streaming de tokens fallan cuando cualquier caja intermedia almacena en búfer—desactiva el almacenamiento en búfer en nginx (o tu equivalente) para /api/events y /v1/chat/completions. llama-swap establece X-Accel-Buffering: no en SSE; desactiva el almacenamiento en búfer en el proxy también—las cabeceras no son un sustituto de una configuración de proxy correcta.
Métricas y capturas de solicitudes
GET /api/metrics devuelve métricas de uso de tokens, con retención en memoria controlada por metricsMaxInMemory (predeterminado 1000).
GET /api/captures/<id> puede recuperar capturas completas de solicitud/respuesta, pero solo cuando captureBuffer > 0 está configurado.
Registros y la interfaz web
llama-swap expone /ui para una interfaz web, y puntos de terminación de registros operativos como /logs y /logs/stream para monitoreo en tiempo real.

Si activas apiKeys, asume defensa en profundidad: /health y partes de /ui permanecen accesibles sin clave—bien para límites de confianza locales, no bien si el host está en una red compartida. Coloca llama-swap detrás de algo que aplique tu política real; la autenticación integrada es para mantener a los clientes casuales honestos, no para una API pública multiinquilino.
Solución de problemas de la conmutación de modelos llama-swap en producción
La mayoría de los problemas de llama-swap caen en un pequeño conjunto de categorías operativas: streaming a través de un proxy inverso, verificaciones de salud durante arranques en frío, puertos y ciclo de vida del proceso, y autenticación.
El streaming falla detrás de nginx u otro proxy inverso
nginx almacenará en búfer tu SSE y completaciones transmitidas. Desactiva proxy_buffering (y proxy_cache) para /api/events y /v1/chat/completions. llama-swap emite X-Accel-Buffering: no en SSE, lo cual ayuda—arregla el proxy de todos modos.
Un modelo nunca se vuelve listo
Por defecto, el checkEndpoint por modelo es /health y debe devolver HTTP 200 para que el proceso se considere listo. Puedes establecer checkEndpoint en otra ruta o en "none" para desactivar las verificaciones de salud por completo.
Si los modelos grandes tardan más en cargarse, aumenta healthCheckTimeout (predeterminado 120s), o usa verificaciones de salud a la medida para tu upstream específico.
Cambiar de modelos deja un contenedor viejo en ejecución
Si el upstream es Docker o Podman, establece cmdStop—de lo contrario llama-swap detiene el proceso contenedor mientras el contenedor sigue consumiendo VRAM en segundo plano.
Obtengo respuestas 401 después de activar la seguridad
Cuando apiKeys está configurado, llama-swap requiere una clave válida y acepta tres métodos (autenticación Basic, token Bearer, x-api-key). También elimina las cabeceras de autenticación antes de reenviar al upstream.
Obtengo 429 Too Many Requests (Demasiadas solicitudes)
concurrencyLimit devuelve 429 cuando se excede—por diseño. Sube el límite si lo provisionaste insuficientemente, o baja el límite si no pretendías regular.
Conflictos de puertos o problemas de enrutamiento extraños
Evita puertos codificados en cmd; usa ${PORT} y mueve startPort si 5800+ colisiona con otra cosa. Recuerda que los puertos se asignan en orden alfabético por ID de modelo—renombra un modelo y el mapeo de puertos cambia.
Lista de comprobación de depuración operativa
/running para la verdad, /logs/stream cuando el arranque es opaco, POST /api/models/unload cuando se necesita la VRAM de vuelta ahora. Ese trío cubre la mayoría de las sesiones de “¿por qué la GPU está llena?”.