Skip to main content
The quickest way to build a chat experience on llama.cpp is llama-server. It applies the model’s chat template, exposes an OpenAI-compatible /v1/chat/completions endpoint, streams tokens over server-sent events, and reuses the KV cache across turns. Any OpenAI client library becomes your app-side API. For in-process use (mobile, or a desktop app that must not spawn a helper process) the same loop is a few dozen lines of the C API β€” see Native C API.

Start the server

  • -hf downloads the GGUF from Hugging Face on first run; :Q4_K_M selects the quantization. Use -m path/to/model.gguf for a local file.
  • -c is the context length. Larger contexts cost memory linearly; check the model page for the supported maximum.
  • --jinja uses the chat template embedded in the GGUF. It is required for tool calling and recommended for everything else.
  • -ngl 99 offloads all layers to the GPU (Metal, CUDA, Vulkan) when one is available.
  • -np 4 serves up to four requests concurrently; each slot gets -c / 4 tokens of context.
GET /health returns {"status":"ok"} once the model is loaded.

Sampling parameters

Every LFM checkpoint has validated sampling defaults. Use them; placeholder values such as temperature=0.7 degrade output quality.
llama-server reads the penalty as repeat_penalty in the request body (matching the --repeat-penalty CLI flag). top_k, min_p, and repeat_penalty are not part of the OpenAI schema, so pass them through extra_body in the OpenAI Python client. The exact values for any checkpoint are on its Hugging Face model card.

Send a message

Stream tokens

Set stream: true and consume the delta.content chunks as they arrive.

Multi-turn conversations

The API is stateless: send the whole messages history on every request and append the assistant’s reply before the next turn.
Re-sending the history is cheap: llama-server keeps the KV cache of the previous request in its slot and only prefills the new suffix (cache_prompt defaults to true). Two flags make this more effective:
  • --cache-reuse 256 β€” reuse cached chunks even when an earlier part of the prompt changed (for example, a trimmed history), by shifting KV entries instead of recomputing them.
  • -np N with --slot-prompt-similarity β€” with multiple slots, route each request to the slot whose cached prompt matches best; useful when several users share one server.
To trim history, drop the oldest user/assistant pairs but keep the system message first. Long system prompts and RAG preambles are exactly what the prompt cache is for β€” keep them byte-identical across requests so the prefix stays cached.

Generation controls

Native C API

In-process, the conversation loop is the same as in iOS & Android, with three additions:
  1. Format only the new suffix. Keep the message history and the formatted prompt string. For each turn, format the full history with the LFM2 chat template and tokenize only the part that was not already decoded. The KV cache still holds the earlier tokens, so prefill cost is proportional to the new turn.
  2. Close the assistant turn. The loop stops when llama_vocab_is_eog() fires, before the end token is decoded. Feed the tokens for <|im_end|>\n (with parse_special = true) after each reply so the cache matches what the template produces on the next turn.
  3. Reset with llama_memory_clear(llama_get_memory(ctx), true) to start a new conversation without reloading the model.
examples/simple-chat/simple-chat.cpp is the reference implementation of this pattern. If you need the full Jinja template (for example, tool definitions), link the common library and use common_chat_templates_init() / common_chat_templates_apply() from common/chat.h instead of formatting by hand.