llama.cpp Engine Guide
llama.cpp (llama-server) serves GGUF models on CPU, GPU or a mix of both. Cortex uses it
for every GGUF file: single-file, sharded (-00001-of-0000N), quantized (Q4_K_M, Q8_0, ...),
and for architectures vLLM does not support (for example GPT-OSS / Harmony).
Pinned image: ghcr.io/ggml-org/llama.cpp:server-cuda-b10731 (LLAMACPP_IMAGE in
versions.env and backend/src/config.py), CUDA 12.8 runtime, works with NVIDIA driver
= 550. server-cuda without a build number is rebuilt daily and must not be used in
production or offline packages. CPU-only hosts can set LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server-b10731.
How Cortex runs llama.cpp
The llama.cpp adapter (backend/src/engines/llamacpp.py) renders one container per model from
the field table in backend/src/engines/spec.py:
docker run --name llamacpp-model-<id> \
--label cortex.managed=1 --label cortex.model_id=<id> --label cortex.engine=llamacpp \
--network cortex_default -p 127.0.0.1::8000 --ipc host --runtime nvidia \
-e NVIDIA_VISIBLE_DEVICES=<selected_gpus> \
-v /var/cortex/models:/models:ro \
ghcr.io/ggml-org/llama.cpp:server-cuda-b10731 \
--model /models/<file>.gguf --alias <served name> --host 0.0.0.0 --port 8000 \
--api-key $INTERNAL_VLLM_API_KEY --timeout 300 --metrics --log-timestamps <fields below> <custom args>
- Ports are published on
127.0.0.1 only; clients go through the gateway, which presents
INTERNAL_VLLM_API_KEY (--api-key, both engines).
- GGUF resolution:
local_path may be a .gguf file or a folder. A shard other than
00001 is rewritten to the first shard of the same set; a folder must contain exactly one
GGUF set, otherwise the API asks you to pick the file. Multi-part files are loaded natively -
never merge them.
- GPU placement:
selected_gpus sets NVIDIA_VISIBLE_DEVICES; empty means CPU only
(ngl=0). tensor_split is regenerated as an equal split when its arity no longer matches
the GPU count.
- Managed flags (
--model, -m, --alias, -a, --host, --port, --api-key) are
rejected in custom args; the LLAMA_ARG_* / LLAMA_API_KEY env vars are protected.
- Dry-run:
POST /admin/models/dry-run (body) or POST /admin/models/{id}/dry-run returns
the redacted command plus issues[] (for example "quantized V cache requires flash attention").
Why GGUF always runs here
vLLM v0.28 ships no GGUF loader (it is an out-of-tree plugin), and llama.cpp handles sharded
files, CPU offload and every GGUF architecture. Cortex enforces the policy at validation time:
a .gguf local_path with engine_type=vllm is rejected. See
GGUF format and Multi-part GGUF.
Configuration fields
"Engine default" means Cortex does not emit the flag unless you set the field. Values in the
Default column are the documented llama-server b10731 defaults. Generated from
backend/src/engines/spec.py by python3 scripts/gen-engine-flag-tables.py.
Common fields (both engines)
Engine image & startup
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
engine_image |
(Cortex-internal, not a flag) |
Engine image. Docker image override. Leave blank for the pinned system default. |
engine default |
|
engine_version |
(Cortex-internal, not a flag) |
Engine version (reference) |
engine default |
|
engine_digest |
(Cortex-internal, not a flag) |
Engine image digest |
engine default |
|
startup_timeout_sec |
(Cortex-internal, not a flag) |
Startup timeout (s). How long the model may take to become ready before it is marked failed. |
engine default |
(min 30) |
GPU placement & parallelism
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
selected_gpus |
(Cortex-internal, not a flag) |
GPUs. GPU indices exposed to the container. Empty = CPU mode (vLLM device=cpu, llama.cpp ngl=0). |
engine default |
|
Model behaviour
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
seed |
--seed VALUE |
Seed. Random seed for sampling reproducibility. |
engine default |
|
chat_template |
--chat-template VALUE |
Chat template (inline, preset name or file under the models dir) |
engine default |
|
Custom args & environment
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
engine_startup_args_json |
(Cortex-internal, not a flag) |
Custom startup args |
engine default |
|
engine_startup_env_json |
(Cortex-internal, not a flag) |
Custom environment variables |
engine default |
|
Request defaults
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
request_defaults_json |
(Cortex-internal, not a flag) |
Request defaults |
engine default |
|
request_timeout_sec |
(Cortex-internal, not a flag) |
Request timeout (s) |
engine default |
(min 1) |
stream_timeout_sec |
(Cortex-internal, not a flag) |
Stream timeout (s) |
engine default |
(min 1) |
llama.cpp fields
GPU placement & parallelism
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
ngl |
--n-gpu-layers VALUE |
GPU layers (-ngl). Layers to offload to GPU. Empty = auto (engine decides), 0 = CPU only, 999 = all. |
engine default |
(min 0) |
main_gpu |
--main-gpu VALUE |
Main GPU |
engine default |
(min 0) |
split_mode |
--split-mode VALUE |
Split mode |
engine default |
none, layer, row, tensor |
tensor_split |
--tensor-split VALUE |
Tensor split. Proportions per GPU, e.g. 3,1. |
engine default |
|
n_cpu_moe |
--n-cpu-moe VALUE |
MoE layers kept on CPU |
engine default |
(min 0) |
override_tensor |
--override-tensor VALUE |
Override tensor placement (-ot). pattern=buffer_type,... e.g. exps=CPU |
engine default |
|
numa_policy |
--numa VALUE |
NUMA policy |
engine default |
distribute, isolate, numactl |
Memory & KV cache
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
load_mode |
--load-mode VALUE |
Load mode. Replaces --mlock / --no-mmap / --direct-io. |
engine default |
auto, none, mmap, mlock, dio |
context_size |
--ctx-size VALUE |
Context size (-c, total across slots). Total KV context shared by all slots unless KV is unified. 0 = from model. |
engine default |
(min 0) |
kv_unified |
--kv-unified / --no-kv-unified |
Unified KV cache |
engine default |
|
kv_unified_per_slot |
--kv-unified-per-slot VALUE |
Per-slot context limit (unified KV) |
engine default |
(min 1) |
fit_memory |
--fit on|off |
Auto-fit unset args to VRAM (--fit). When on (engine default) llama.cpp adjusts UNSET -ngl / -c to fit device memory. Turn off for fully explicit configs. |
on |
|
cache_type_k |
--cache-type-k VALUE |
KV cache type K |
f16 |
f32, f16, bf16, q8_0, q4_0, q4_1, iq4_nl, q5_0, q5_1 |
cache_type_v |
--cache-type-v VALUE |
KV cache type V. Quantized V cache requires flash attention on. |
f16 |
f32, f16, bf16, q8_0, q4_0, q4_1, iq4_nl, q5_0, q5_1 |
Throughput & scheduling
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
parallel_slots |
--parallel VALUE |
Parallel slots (-np). Empty = auto. Each slot gets context_size / slots tokens unless unified KV. |
engine default |
(min 1) |
flash_attn |
--flash-attn VALUE |
Flash attention |
auto |
auto, on, off |
batch_size |
--batch-size VALUE |
Batch size (-b) |
2048 |
(min 1) |
ubatch_size |
--ubatch-size VALUE |
Micro-batch size (-ub) |
512 |
(min 1) |
threads |
--threads VALUE |
CPU threads (-t). Empty = auto. |
engine default |
(min 1) |
threads_http |
--threads-http VALUE |
HTTP threads |
engine default |
(min 1) |
cont_batching |
--no-cont-batching when off |
Continuous batching |
on |
|
cache_reuse |
--cache-reuse VALUE |
Cache reuse (min chunk) |
engine default |
(min 0) |
context_shift |
--context-shift |
Context shift |
engine default |
|
Serving mode
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
enable_embeddings |
--embeddings |
Enable embeddings endpoint |
engine default |
|
pooling |
--pooling VALUE |
Pooling |
engine default |
none, mean, cls, last, rank |
rerank |
--rerank |
Reranking endpoint |
engine default |
|
Model behaviour
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
rope_freq_base |
--rope-freq-base VALUE |
RoPE frequency base |
engine default |
|
rope_freq_scale |
--rope-freq-scale VALUE |
RoPE frequency scale |
engine default |
|
jinja_enabled |
--jinja / --no-jinja |
Jinja chat templates |
on |
|
chat_template_file |
--chat-template-file VALUE |
Chat template file Path relative to the models dir (mounted at /models). |
engine default |
|
chat_template_kwargs_json |
--chat-template-kwargs '{...}' |
Chat template kwargs (JSON). e.g. |
engine default |
|
reasoning_format |
--reasoning-format VALUE |
Reasoning format |
engine default |
auto, none, deepseek, deepseek-legacy |
reasoning_budget |
--reasoning-budget VALUE |
Reasoning budget (tokens, -1 unlimited) |
engine default |
|
n_predict |
--n-predict VALUE |
Max tokens to predict (-n) |
engine default |
|
grammar_file |
--grammar-file VALUE |
Grammar file (GBNF) Path relative to the models dir (mounted at /models). |
engine default |
|
Adapters, speculative decoding & multimodal
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
lora_adapters_json |
--lora (repeated) |
LoRA adapters (JSON list of path or {path, scale}) |
engine default |
|
lora_init_without_apply |
--lora-init-without-apply |
Load LoRAs without applying |
engine default |
|
draft_model_path |
--model-draft VALUE |
Draft model (GGUF) Path relative to the models dir (mounted at /models). |
engine default |
|
spec_type |
--spec-type VALUE |
Speculative type |
engine default |
none, draft-simple, draft-eagle3, draft-mtp, draft-dflash, draft-dspark, ngram-simple, ngram-map-k, ngram-map-k4v, ngram-mod, ngram-cache |
draft_n |
--spec-draft-n-max VALUE |
Draft tokens (max) |
3 |
(min 1) |
spec_draft_n_min |
--spec-draft-n-min VALUE |
Draft tokens (min) |
engine default |
(min 0) |
draft_p_min |
--spec-draft-p-min VALUE |
Draft acceptance p_min |
engine default |
(min 0, max 1) |
spec_draft_ngl |
--spec-draft-ngl VALUE |
Draft model GPU layers |
engine default |
(min 0) |
mmproj |
--mmproj VALUE |
Multimodal projector (GGUF) Path relative to the models dir (mounted at /models). |
engine default |
|
mmproj_offload |
--no-mmproj-offload when off |
Offload projector to GPU |
on |
|
Logging & diagnostics
| Field (API / form) |
Flag |
Meaning |
Default |
Choices / range |
verbose_logging |
--verbose |
Verbose logging |
engine default |
|
check_tensors |
--check-tensors |
Check tensors on load |
engine default |
|
skip_warmup |
--no-warmup |
Skip warmup |
engine default |
|
Removed or renamed since earlier Cortex releases
| Old field / flag |
Now |
flash_attn boolean → --flash-attn |
flash_attn is auto / on / off (--flash-attn on\|off\|auto). |
mlock, no_mmap, --direct-io |
One field: load_mode → --load-mode auto\|none\|mmap\|mlock\|dio. |
draft_n → --draft-max |
Same field, now --spec-draft-n-max; --spec-draft-n-min, --spec-draft-p-min, --spec-draft-ngl, --spec-type added. |
defrag_thold / --defrag-thold |
Removed (KV defragmentation is automatic). |
system_prompt / --system-prompt-file |
Removed; put system prompts in the chat template or the request. |
cache_type_v q8_0 as default |
Default is f16; a quantized V cache requires flash_attn=on (validated). |
LLAMACPP_DEFAULT_NGL/BATCH_SIZE/UBATCH_SIZE/THREADS/CONTEXT, LLAMACPP_MAX_PARALLEL, LLAMACPP_CONT_BATCHING, LLAMACPP_CACHE_TYPE_K/V, LLAMACPP_LOG_VERBOSE/COLORS, LLAMACPP_CHECK_TENSORS, LLAMACPP_SKIP_WARMUP, LLAMACPP_JINJA_ENABLED, LLAMACPP_DEFRAG_THOLD (gateway env) |
Removed. Defaults are the engine's; set per model. Remaining gateway settings: LLAMACPP_IMAGE, LLAMACPP_STARTUP_TIMEOUT, LLAMACPP_SERVER_TIMEOUT, LLAMACPP_METRICS_ENABLED, LLAMACPP_SLOTS_ENABLED, LLAMACPP_LOG_TIMESTAMPS. |
cortex/llamacpp-server:latest custom image |
Never existed as a product artifact; the official ghcr.io/ggml-org/llama.cpp image is used. |
-ngl 999 as Cortex default |
ngl is empty by default: llama.cpp's --fit on places as many layers as fit. |
Context, slots and KV cache sizing
context_size (-c) is the total KV context shared by all parallel_slots (-np). With
-c 16384 -np 4 each request gets 4096 tokens. Turn on kv_unified to let slots share one
pool (optionally capped per slot with kv_unified_per_slot).
KV cache memory for the whole context:
bytes = 2 x n_layer x n_ctx x n_embd_k_gqa x bytes_per_element
(K and V) (= n_head_kv x head_dim) f16 = 2, q8_0 ≈ 1.06, q4_0 ≈ 0.56
Example: Llama-3-8B (32 layers, 8 KV heads x 128 = 1024) at 32k context in f16 =
2 x 32 x 32768 x 1024 x 2 ≈ 4.3 GiB; at q8_0 ≈ 2.3 GiB. Cortex's folder inspector reports
n_layer and the head counts from the GGUF header. Weights are on top of that
(Q4_K_M ≈ 0.6 bytes/param, Q8_0 ≈ 1.07 bytes/param). If weights + KV cache exceed VRAM, lower
ngl (partial CPU offload), reduce context_size, quantize the cache
(cache_type_k/v=q8_0 with flash_attn=on) or, for MoE models, keep experts on CPU
(n_cpu_moe, override_tensor=exps=CPU). fit_memory (--fit on, the default) already
shrinks unset -ngl/-c to what fits.
Custom arguments and environment
Any llama-server flag not in the table can be passed as a custom startup arg (short aliases
such as -c, -ngl, -fa, -ctk are normalised to the long form). Custom env vars are
attached to the container; the protected list (NVIDIA_VISIBLE_DEVICES,
CUDA_VISIBLE_DEVICES, HF_HUB_OFFLINE, LLAMA_API_KEY, LLAMA_ARG_HOST/PORT/MODEL/API_KEY,
VLLM_API_KEY) is rejected. See Setting custom environment variables.
Request defaults and gateway behaviour
Sampling defaults (temperature, top_p, top_k, penalties) and custom extras in
request_defaults_json are merged by the gateway into requests that omit them and apply
immediately. They override llama-server's own --temp/--top-p defaults per request. Server-wide
generation limits (n_predict, reasoning_budget) still cap what a request can ask for.
The gateway proxies /v1/chat/completions, /v1/completions and /v1/embeddings
(enable_embeddings + pooling for embedding GGUFs, rerank for rerankers) and reads
/metrics (--metrics from LLAMACPP_METRICS_ENABLED, default on; Prometheus discovers the container by label).
Embedding-task models get --embeddings automatically.
Troubleshooting
| Symptom |
Likely cause |
Fix |
state=failed, reason container_exited: ... error loading model |
wrong file (shard 2, folder with several sets) |
pick the first shard / the exact file |
cudaMalloc failed / OOM |
weights + KV cache > VRAM |
see sizing above: lower ngl, context_size, quantize KV |
| very slow generation, GPU idle |
ngl too low or CPU-only |
set ngl=999 (all layers) and check selected_gpus |
state_reason=startup_timeout_after_300s |
large model still loading |
raise startup_timeout_sec (LLAMACPP_STARTUP_TIMEOUT default 300) |
| requests truncated at ~1k tokens |
context_size / parallel_slots too small |
raise -c, lower -np, or kv_unified=on |
quantized V cache requires flash attention |
cache_type_v set with flash_attn=off |
set flash_attn=on |
nvidia-container-cli ... cuda>=12.8 |
driver < 550 |
update the driver or use an older server-cuda-b* image as engine_image |
Related: Engine comparison, Model management,
Runbooks.