Guía Llama.cpp: Capítulo 3 — Ejecución y optimización del servidor
llama-server es el componente integrado de llama.cpp que expone una API HTTP compatible con OpenAI. Es la pieza que convierte tu modelo en un servicio: los clientes hablan con la API de la familia /v1/* y no notan la diferencia. En este capítulo lo arrancamos, lo afinamos y lo dejamos listo para producción.
1. Arranque básico
./llama-server -m models/modelo.gguf -ngl 99 --host 127.0.0.1 --port 8080
En seguida tendrás disponible:
- API REST:
http://127.0.0.1:8080/v1/chat/completions,/v1/completions,/v1/embeddings... - WebUI integrada: abre
http://127.0.0.1:8080en el navegador y charla directamente con tu modelo.
🔒 Por defecto escucha en
127.0.0.1. Solo cámbialo a0.0.0.0cuando el servidor esté expuesto por red y añade autenticación (capítulo 5).
2. Configuración de servidor con decodificación especulativa
Este es el comando de ejecución de referencia con el que se configuró el entorno del autor, tal cual se lanzó en una máquina Windows. Utilízalo como plantilla para el ajuste fino de tu propio despliegue:
llama-server.exe ^
-m E:\Llama-cpp\gguf\Gemma-4-E2B\gemma-4-E2B-it-qat-UD-Q4_K_XL.gguf ^
--model-draft "E:\Llama-cpp\gguf\Gemma-4-E2B\mtp-gemma-4-E2B-it-Q4_0.gguf" ^
--mmproj "E:\Llama-cpp\gguf\Gemma-4-E2B\mmproj-BF16.gguf" ^
--main-gpu %igpu_id% ^
--fit off ^
--reasoning on ^
--spec-type draft-mtp ^
--spec-draft-n-max 2 ^
--ctx-size 131072 ^
--parallel 1 ^
--cache-type-k q8_0 ^
--cache-type-v q8_0 ^
--temp 1.0 ^
--top-p 0.95 ^
--top-k 64 ^
--log-verbosity 4 ^
--alias Gemma-4-E2B
En Linux, el equivalente (sustituyendo ^ por \ y adaptando las rutas):
llama-server \
-m /ruta/a/gguf/gemma-4-E2B/gemma-4-E2B-it-qat-UD-Q4_K_XL.gguf \
--model-draft "/ruta/a/gguf/gemma-4-E2B/mtp-gemma-4-E2B-it-Q4_0.gguf" \
--mmproj "/ruta/a/gguf/gemma-4-E2B/mmproj-BF16.gguf" \
--main-gpu $igpu_id \
--fit off \
--reasoning on \
--spec-type draft-mtp \
--spec-draft-n-max 2 \
--ctx-size 131072 \
--parallel 1 \
--cache-type-k q8_0 \
--cache-type-v q8_0 \
--temp 1.0 \
--top-p 0.95 \
--top-k 64 \
--log-verbosity 4 \
--alias Gemma-4-E2B
Desglose de cada flag:
| Flag | Significado | Por qué |
|---|---|---|
-m |
Ruta del modelo principal | Cuantización QAT en formato UD al estilo Unsloth |
--model-draft |
Especifica el modelo draft MTP | Segundo GGUF dedicado al speculative decoding |
--mmproj |
Proyector multimodal | Carga los pesos del codificador de visión |
--main-gpu %igpu_id% |
Selecciona la GPU principal | Ancla la inferencia a un dispositivo concreto vía variable |
--fit off |
Desactiva el auto-ajuste de capas en la memoria | Deja el reparto GPU/CPU tal cual definido |
--reasoning on |
Modo reasoning activado | Habilita los tokens de razonamiento del modelo |
--spec-type draft-mtp |
Speculative decoding draft-MTP | Genera varios tokens por ciclo reduciendo la latencia |
--spec-draft-n-max 2 |
Máximo de tokens por ronda del draft | Límite del número de tokens que propone el borrador en cada paso |
--ctx-size 131072 |
Contexto de 128K tokens | RAG gigante y documentos completos; exige KV-cache cuantizada |
--parallel 1 |
Un solo slot | Uso mono-usuario |
--cache-type-k/v q8_0 |
KV-cache cuantizada a 8 bits | Libera ~50 % de la KV-cache a coste casi nulo de calidad |
--temp 1.0 |
Temperatura por defecto | Balance entre determinismo y creatividad |
--top-p 0.95 |
Nucleus sampling por defecto | Descarta la cola de probabilidad más baja |
--top-k 64 |
Top-k por defecto | Limita el vocabulario candidatado |
--log-verbosity 4 |
Verbosidad de logs 4 | Facilita el diagnóstico del arranque |
--alias Gemma-4-E2B |
Alias del modelo | Nombre desplegado en la API y en /v1/models |
⚠️ Si al arrancar con esta configuración ves errores de memoria, baja
--ctx-size 131072a un valor ajustado a tu VRAM (p. ej.8192o16384) o desactiva la KV-cache cuantizada; ver el capítulo 5.
3. Parámetros clave
3.1 Contexto (-c)
El contexto es lo que más agota la memoria. Cada turno de conversación, cada documento de RAG, cada entrada rodeada del prompt vive en la KV-cache:
-c 4096— chat ligero y prototipos.-c 8192— equilibrio ágil para la mayoría de modelos de 8B.-c 16384–32768— RAG serio o código del tamaño de un repositorio; exige KV-cache cuantizada o FlashAttention.
3.2 Threads (-t) y CPUs
En inferencia CPU, -t casi lo es todo. Reglas:
- Usa cores físicos (habitualmente la mitad de los lógicos con Hyper-Threading).
- Más hilos que cores → contención → peor rendimiento.
- Complemento útil:
--threads-batchpara separar los hilos del batch del prompt.
3.3 Batch y chunks (-b, -ub, --chunks)
-b(logical batch): cuántos tokens procesa de golpe; el rango sano está entre256y1024.-ub(physical/u-batch): micro-batch real de cómputo; por defecto512. Unubdemasiado grande ocupa la VRAM.--chunks: número de textos en paralelo para los endpoints de embedding y rerank.
3.4 Muestreo y predeterminados del servidor
llama-server también expone los parámetros clásicos de generación (--temp, --top-p, --top-k, --repeat-penalty, -n, --seed) como valores por defecto que se usan si el cliente no los envía. Define aquí tus preferencias y deja que cada cliente los sobrescriba cuando quiera.
4. La API compatible con OpenAI
4.1 Chat completions (curl)
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-mi-clave-local" \
-d '{
"model": "local-model",
"messages": [
{"role": "system", "content": "Eres un asistente técnico que responde en español."},
{"role": "user", "content": "¿Cómo cuantizo un modelo GGUF?"}
],
"temperature": 0.7,
"max_tokens": 512
}'
4.2 Stream ("stream": true)
Añade "stream": true y recibirás token a token en formato SSE, igual que la API de OpenAI. La integración es idéntica con los SDKs.
4.3 Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8080/v1",
api_key="sk-mi-clave-local", # cualquier string no vacío si no hay --api-key
)
resp = client.chat.completions.create(
model="local",
messages=[{"role": "user", "content": "Resume en 3 puntos el capítulo 2 de esta guía."}],
stream=False,
)
print(resp.choices[0].message.content)
4.4 WebUI y otras rutas útiles
/— WebUI de chat integrada./health— ping de vida ({"status":"ok"})./props— información del modelo (plantilla de chat, herramientas)./v1/models— listado estilo OpenAI./slots— estado interno de ranuras de inferencia (con--slots).
5. Concurrency: ranuras y streaming en paralelo
llama-server gestiona peticiones en slots paralelos. El flag -np N (parallel slots) y -c interactúan: el contexto total se divide. Ecuación mental: contexto por slot = -c / -np.
./llama-server -m models/modelo.gguf -ngl 99 -c 8192 -np 2 -fa --parallel 2
-np 2 -c 8192→ 2 usuarios concurrentes con 4096 tokens de contexto cada uno.- Para cargas críticas: mide con
llama-benchantes de decidir el número de slots.
💡 Si el equipo reporta lentitud al compartir el servidor, probablemente estás saturando la VRAM; prueba más KV-cache cuantizada o FlashAttention, y solo después revisa la concurrencia.
6. Lanzamiento como servicio
Windows (NSSM o Task Scheduler)
nssm install llama-server "C:\llama.cpp\build\bin\Release\llama-server.exe" "-m C:\models\modelo.gguf -ngl 99 -c 16384 -fa --host 127.0.0.1 --port 8081"
nssm start llama-server
Linux (systemd)
# ~/.config/systemd/user/llama-server.service
[Unit]
Description=llama.cpp server
After=network.target
[Service]
ExecStart=%h/llama.cpp/build/bin/llama-server -m %h/models/modelo.gguf -ngl 99 -c 16384 -fa --host 127.0.0.1 --port 8081
Restart=on-failure
[Install]
WantedBy=default.target
systemctl --user enable --now llama-server
7. Checklist de rendimiento
-
-nglal máximo que entra en VRAM con margen. - Contexto suficiente y no excesivo; dimensiona con tu carga real.
- KV-cache cuantizada y
-fasi hay streams/paralelismo. - Hilos coherentes con los cores físicos (en inferencia CPU).
-
--api-keyconfigurado en cualquier servidor no estrictamente local. - Token/seg medidos con tu carga real de prompt (no con benchmarks sintéticos).
En el capítulo 4 entraremos en la artillería pesada: cuantización fina, speculative decoding y el resto de la caja de herramientas de optimización.