Inicio rápido de llama.swap Model Switcher para modelos LLM locales compatibles con OpenAI
Intercambio en caliente de LLMs locales sin necesidad de modificar los clientes.
Pronto estarás manejando vLLM, llama.cpp y más, cada stack en su propio puerto. Todo lo que viene aguas abajo aún quiere una URL base /v1; de lo contrario, seguirás moviendo puertos, perfiles y scripts de una sola vez. llama-swap es el proxy /v1 antes de esos stacks.
llama-swap proporciona una puerta de entrada compatible con OpenAI y Anthropic, con un archivo YAML que asigna cada nombre de modelo al comando que inicia el upstream correcto. Solicita un modelo y el proxy lo inicia o cambia a él; configura TTLs y grupos cuando la VRAM es limitada o varios modelos deben coexistir. Esta guía cubre las rutas de instalación, un config.yaml práctico, la superficie HTTP y los modos de fallo que aparecen una vez que entran en juego la transmisión en 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
Resumen del conmutador de modelos llama-swap para APIs de LLM locales compatibles con OpenAI
llama-swap es un servidor proxy ligero construido alrededor de un modelo operativo simple: un binario, un archivo de configuración YAML, sin dependencias. Está escrito en Go, lo que significa un único binario estático junto al resto del stack: no se requiere runtime de Python ni una aplicación de escritorio. Se sitúa frente a 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 los stacks locales de LLM:
¿Cómo cambio de modelos con un cliente compatible con OpenAI?
Con llama-swap sigues usando solicitudes normales /v1/..., pero cambias el modelo que solicitas. llama-swap lee ese valor de modelo, carga la configuración del servidor coincidente y, si el upstream “incorrecto” está ejecutándose, lo cambia por el correcto.
Algunos detalles de diseño importan para configuraciones tipo producción:
llama-swap tiene licencia MIT y no tiene telemetría; todavía vale la pena confirmarlo para cualquier host que vea prompts reales.
Está diseñado para la carga bajo demanda de backends como llama.cpp, vLLM, Whisper y stable-diffusion.cpp, no para encerrarte en un motor de inferencia único.
De fábrica (sin agrupación especial), ejecuta un modelo a la vez: solicita un modelo diferente y detiene el upstream actual e inicia el correcto. Para más de un modelo residente o un control más fino sobre la coexistencia, configura groups.
Aquí está el modelo mental que la mayoría de los desarrolladores encuentran útil:
flowchart LR
C[Tu app o SDK\nCliente compatible con OpenAI] -->|/v1/chat/completions\nmodel = qwen-coder| LS[Proxy llama-swap\nendpoint único]
LS -->|inicia o enruta a| U1[Servidor upstream A\nllama-server]
LS -->|inicia o enruta a| U2[Servidor upstream B\nServidor OpenAI vLLM]
LS --> M[Endpoints de gestión\nejecutando, descargar, eventos, métricas]
Esto es también por qué un proxy conmutador de modelos es diferente de “ejecutar simplemente 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 de modelo + ejecución) o un router/proxy (conmutación + orquestación entre runtimes).
llama-swap
llama-swap se enfoca en ser un proxy transparente que soporta endpoints compatibles con OpenAI (incluyendo /v1/chat/completions, /v1/completions, /v1/embeddings y /v1/models) y enruta solicitudes al upstream correcto basado en el modelo solicitado. También proporciona endpoints operativos no relacionados con 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 local por defecto en el puerto 11434).
keep_alive controla cuánto tiempo permanece cargado un modelo, incluido 0 para descargar inmediatamente.
Se adapta a usuarios que quieren descargar un modelo y chatear con cableado mínimo. llama-swap se adapta a comandos por modelo, backends mixtos y una URL con forma de OpenAI para cada cliente: orquestar vLLM junto a llama-server con banderas diferentes por modelo está fuera de lo que Ollama apunta.
LM Studio
LM Studio es una aplicación de escritorio con un servidor API local desde la pestaña Developer (localhost o LAN), incluyendo modos compatibles con OpenAI y compatibles con Anthropic, además de lms server start desde la terminal.
Se adapta a un bucle primero GUI: navegar modelos, hacer clic, probar. llama-swap se adapta a un rol de tipo 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 OpenAI a él vía base_url.
llama.cpp también incluye un modo router: ejecuta llama-server como router, --models-dir, luego POST /models/load y POST /models/unload para manejar 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 cada modelo está bajo un router de llama.cpp, un proxy extra a menudo es innecesario. Cuando llama.cpp debe estar junto a vLLM u otros servidores con forma de OpenAI, llama-swap proporciona una superficie /v1 y muchos procesos detrás de ella.
Para soluciones de alojamiento compatibles con OpenAI similares, consulta Inicio Rápido de LocalAI: Ejecuta LLMs Compatibles con OpenAI Localmente o Inicio Rápido de SGLang: Instala, Configura y Sirve LLMs vía API OpenAI
Instala llama-swap conmutador de modelos con Docker, Homebrew, WinGet o binarios
Linux, macOS y Windows son todos de primera clase: Docker, Homebrew, WinGet, binarios de GitHub o compilar desde el código fuente. Elecciones comunes: Docker en servidores headless, Homebrew o WinGet en estaciones de trabajo, binarios independientes cuando la huella de instalación debe mantenerse mínima.
Instalación con Docker
Extrae una imagen que coincida con tu hardware. Las imágenes siguen de cerca el upstream (compilaciones nocturnas) y cubren CUDA, Vulkan, Intel, MUSA y CPU: elige la que coincida con cómo aceleras realmente, no “latest” por costumbre.
# Ejemplos de extracción de 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
Prefiere las variantes de imagen no root cuando puedas: menos de qué arrepentirse 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 lanzamientos
GitHub Releases distribuye binarios para Linux, macOS, Windows y FreeBSD si no quieres un gestor de paquetes.
Los números de lanzamiento avanzan rápido (por ejemplo v198, v197 alrededor de principios de 2026): fija una versión en automatización en lugar de flotar “lo que haya estado allí ayer”.
Configura llama-swap con config.yaml para conmutación de modelos, TTL y grupos
Todo en llama-swap está impulsado 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 simplemente “iniciar un proceso”, y unas pocas opciones valen la pena entender temprano porque responden directamente a problemas de estilo FAQ (descarga automática, seguridad y clientes que dependen de /v1/models).
Ajustes globales que realmente usarás
healthCheckTimeout es cuánto tiempo llama-swap espera para que un modelo se vuelva saludable después del inicio (por defecto 120s, mínimo 15s). Para cargas de varios GB en discos lentos, aumenta esto antes de culpar al proxy.
globalTTL es segundos de inactividad antes de la descarga automática; por defecto 0 significa “nunca descargar” a menos que lo configures: elige explícitamente TTLs para cualquier cosa más allá de una configuración de juguete para que la VRAM no se llene con modelos olvidados.
startPort siembra la macro ${PORT} (por defecto 5800); la asignación es determinista por ID de modelo alfabético, lo cual es una característica cuando depuras “quién agarró qué puerto” y una trampa si renomas modelos descuidadamente.
includeAliasesInList decide si los alias aparecen como filas separadas en /v1/models; actívalo on si tu UI solo ofrece modelos enumerados.
apiKeys bloquea cualquier cosa accesible fuera de localhost: Basic, Bearer o x-api-key. llama-swap elimina esos encabezados antes de reenviar para que los logs del upstream sean menos propensos a retener secretos del cliente.
Ajustes a nivel de modelo que desbloquean ergonomía de producción
Por modelo, cmd es el único campo requerido.
proxy por defecto es http://localhost:${PORT}: ese 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 inicio en frío excede lo que estás dispuesto a esperar: no dejes un /health roto y preguntes por qué nada llega a ready.
ttl: -1 hereda globalTTL, 0 nunca descarga, N > 0 descarga después de N segundos inactivos: usa TTL por modelo cuando un modelo debe permanecer y otro debe desaparecer rápidamente.
aliases y useModelName mantienen nombres estables orientados al cliente mientras satisfacen upstreams que requieren un identificador específico.
cmdStop es no opcional para contenedores: mápalo a docker stop (o equivalente); sin él obtienes POSIX SIGTERM / Windows taskkill contra cualquier PID que llama-swap inició: bien para un binario desnudo, mal para un nombre de contenedor.
concurrencyLimit limita solicitudes paralelas por modelo con HTTP 429 cuando se excede: configúralo cuando prefieras descartar carga que hacer cola para siempre.
groups cubren coexistencia (swap, exclusive) y modelos siempre activos (persistent). Los hooks pueden precargar al inicio; si precargas varios modelos a la vez sin un grupo, espera que 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 “justo lo suficiente” para ilustrar los controles de mejores prácticas: un TTL por defecto, verificación de salud explícita, alias estables y un grupo que mantiene un modelo “siempre activo” pequeño ejecutándose mientras los modelos de chat más grandes cambian.
# config.yaml
healthCheckTimeout: 180
globalTTL: 900 # 15 minutos inactivos luego descarga
includeAliasesInList: true
startPort: 5800
# Opcional pero recomendado para cualquier cosa más allá del desarrollo 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 defectos:
# proxy: http://localhost:${PORT}
# checkEndpoint: /health
# ttl: -1 (heredar 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 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 ciclo de vida, cmdStop es lo que hace que los upstreams basados en Docker realmente detengan, y groups son lo que separa “un modelo grande a la vez” de “estos dos modelos de chat pueden coexistir mientras el servidor de embedding permanece fijo”.
Ejecuta y cambia modelos vía endpoints compatibles con OpenAI
Una vez que llama-swap está ejecutándose, interactúas con él como con cualquier otro endpoint compatible con OpenAI. La superficie de la API incluye endpoints centrales como /v1/chat/completions, /v1/completions, /v1/embeddings y /v1/models, y llama-swap usa el modelo solicitado para decidir qué upstream ejecutar y enrutar.
Un flujo de inicio rápido práctico:
# 1) Inicia llama-swap
llama-swap --config ./config.yaml --listen localhost:8080
# 2) Descubre modelos disponibles
curl http://localhost:8080/v1/models
La lista de modelos es una característica de gestión de primera clase e incluye comportamientos como ordenar por ID, excluir modelos unlisted e incluir opcionalmente alias.
# 3) Haz una solicitud de finalización de chat 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":"Escribe una función TypeScript que reintente fetch con backoff."}]
}'
Si ahora repites la llamada con "model": "llama-chat", llama-swap cambiará los procesos upstream (a menos que tu configuración de grupo permita que coexistan) porque extrae el modelo solicitado de la solicitud 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 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": "Explica la diferencia entre mutex y semáforos."}],
)
print(resp.choices[0].message.content)
Para calentar un modelo antes de la primera solicitud real (ocultar latencia de inicio en frío), usa /upstream/<modelo>—carga automáticamente si es necesario y reenvía directamente a ese upstream. Forma directa de asegurar que los pesos estén residentes antes de un benchmark o prueba scriptada.
Controla y monitorea llama-swap vía endpoints de API de gestión y eventos SSE
llama-swap no es solo “un proxy”; también expone endpoints de control operativo que te permiten construir herramientas alrededor del ciclo de vida del modelo y la observabilidad.
Verifica qué está ejecutándose
GET /running devuelve el estado de runtime para 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 endpoint versionado de API POST /api/models/unload. Para descargar un solo modelo (por ID o alias), usa POST /api/models/unload/<modelo>. Existe un GET /unload legacy para compatibilidad hacia atrás.
# descarga todo
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 endpoints cuando la VRAM sea necesaria de vuelta ahora en lugar de esperar al TTL: benchmarks, cambios rápidos de modelo o después de cargar un checkpoint mucho más grande del previsto.
Transmite eventos en vivo vía SSE
GET /api/events establece un flujo de Eventos Enviados por Servidor y está diseñado para actualizaciones en tiempo real que incluyen cambios de estado del modelo, logs, métricas y conteos de solicitudes en vuelo.
curl -N http://localhost:8080/api/events
SSE y streaming de tokens se rompen cuando cualquier caja intermedia hace buffer: desactiva la bufferización en nginx (o tu equivalente) para /api/events y /v1/chat/completions. llama-swap establece X-Accel-Buffering: no en SSE; desactiva la bufferización en el proxy también: los encabezados no son un sustituto para 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 (por defecto 1000).
GET /api/captures/<id> puede recuperar capturas completas de solicitud/respuesta, pero solo cuando captureBuffer > 0 está configurado.
Logs y la Interfaz Web
llama-swap expone /ui para una interfaz web, y endpoints de logs operativos como /logs y /logs/stream para monitoreo en tiempo real.

Si habilitas apiKeys, asume defensa en profundidad: /health y partes de /ui permanecen accesibles sin una clave: bien para límites de confianza locales, no bien si el host está en una red compartida. Pon llama-swap detrás de algo que haga cumplir tu política real; la autenticación integrada es para mantener a los clientes casuales honestos, no para una API multiinquilino pública.
Solución de problemas de 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 inicios en frío, puertos y ciclo de vida del proceso, y autenticación.
El streaming se rompe detrás de nginx u otro proxy inverso
nginx felizmente bufferizará tu SSE y finalizaciones en streaming. 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, checkEndpoint por modelo es /health y debe devolver HTTP 200 para que el proceso sea considerado listo. Puedes establecer checkEndpoint a otra ruta o a "none" para desactivar las verificaciones de salud por completo.
Si los modelos grandes tardan más en cargar, aumenta healthCheckTimeout (por defecto 120s), o usa verificaciones de salud a medida para tu upstream específico.
Cambiar modelos deja un contenedor antiguo ejecutándose
Si el upstream es Docker o Podman, establece cmdStop—de lo contrario llama-swap detiene el proceso envoltorio mientras el contenedor sigue consumiendo VRAM en segundo plano.
Obtengo respuestas 401 después de habilitar 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 los encabezados de autenticación antes de reenviar upstream.
Obtengo 429 Demasiadas Solicitudes
concurrencyLimit devuelve 429 cuando se excede: por diseño. Sube el límite si lo subdimensionaste, o baja el límite si no querías limitar.
Conflictos de puertos o problemas de enrutamiento extraños
Evita puertos codificados en duro en cmd; usa ${PORT} y mueve startPort si 5800+ choca con algo más. 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 verificación de depuración operativa
/running para la verdad, /logs/stream cuando el inicio es opaco, POST /api/models/unload cuando la VRAM es necesaria de vuelta ahora. Esa trío cubre la mayoría de sesiones de “por qué está la GPU llena”.