Llama-server lifecycle management — used by any project that needs
to download, configure, launch, and health-check a llama-server
process running a specific GGUF model.
Capabilities
- Find or download the binary —
find_binary/1returns the absolute path, or downloads viaBotica.Batteries.LlamaServer.Installerwhen missing. - Build the args —
build_args/2produces the canonicalllama-serverflags for the given role + config. - Spawn the process —
start/2andstop/1useArrea.LongRunningso the process is supervised, restartable, and hot-swappable. - Health-check —
running?/1probes the/healthendpoint; the same function used insidestart/2to wait for readiness. - Predefined checks —
check/1returns aBotica.Checkspec suitable forBotica.Doctor.
Roles
Two roles are handled side by side (chat completion vs embeddings):
:chat— higher--parallel, larger--ctx-size,reasoning-friendly args (spec-decode, cache q8).:embedding—--embedding, smaller model, separate batchergonomics.
Both call into the same generic launcher, differing only in the role-specific args and config block they accept.
Use cases
delfos(this project's primary consumer) uses:chatand:embeddingsimultaneously via itsDelfos.LLM.InternalandDelfos.LLM.Embedadapters, each a thin wrapper that delegates to this module.- Any other Elixir app that needs a managed local LLM can reuse the same module without duplicating the lifecycle plumbing.
Summary
Functions
Builds the full arg list for llama-server. Merges
Builds a ready-to-use Botica.Check definition for :chat or
:embedding so the role can show up in Botica.Doctor.run/1
output. Pass the same config you would pass to start/3.
Finds the absolute path to llama-server, downloading a
precompiled binary if needed. Priority
Probes the /health endpoint of a running llama-server.
Spawns a llama-server subprocess and waits for it to become
ready. Returns {:ok, :started} (GPU) or {:ok, :started_cpu}
depending on the device resolved during build_args/2. Returns
:already_running if the server was already reachable before
the attempt.
Stops the server registered under the given server_id. Idempotent.
Types
@type config() :: %{ :gguf_path => String.t(), :port => pos_integer(), optional(:host) => String.t(), optional(:api_key) => String.t(), optional(:alias) => String.t(), optional(:binary) => String.t(), optional(:llama_server_path) => String.t(), optional(:hardware_plan) => %{device: :gpu | :cpu}, optional(:extra_args) => [String.t()], optional(any()) => any() }
Resolved config passed to start/2.
@type role() :: :chat | :embedding
Role selectors.
Functions
Builds the full arg list for llama-server. Merges:
- defaults for the role (
:chat/:embedding) - user overrides (in
config) - auto-resolved device (
hardware_plan.device) when:auto extra_args(always appended last)
Returns a list suitable to pass to Arrea.LongRunning.start_link/1
or Port.open/2.
Builds a ready-to-use Botica.Check definition for :chat or
:embedding so the role can show up in Botica.Doctor.run/1
output. Pass the same config you would pass to start/3.
Examples
Botica.Doctor.run(%{
app_name: "delfos",
checks: [
Botica.Batteries.LlamaServer.check(:chat, %{port: 9999, ...}),
Botica.Batteries.LlamaServer.check(:embedding, %{port: 9998, ...})
]
})
Finds the absolute path to llama-server, downloading a
precompiled binary if needed. Priority:
- Explicit override (
llama_server_path). which llama-serverin PATH (returns absolute path).- Installable via
Botica.Batteries.LlamaServer.Installer.
Options
:force_download— re-download even if a binary already exists.
@spec running?(pos_integer()) :: boolean()
Probes the /health endpoint of a running llama-server.
Examples
iex> Botica.Batteries.LlamaServer.running?(9999)
true
@spec start(role(), config(), keyword()) :: :already_running | {:ok, :started} | {:ok, :started_cpu} | {:error, term()}
Spawns a llama-server subprocess and waits for it to become
ready. Returns {:ok, :started} (GPU) or {:ok, :started_cpu}
depending on the device resolved during build_args/2. Returns
:already_running if the server was already reachable before
the attempt.
Options
:force— kill the existing server and re-spawn.:health_check— override the health probe (defaults toGET /health). Receives the port.:wait_timeout— max ms to wait for readiness (default 30 s).
@spec stop(keyword()) :: :ok
Stops the server registered under the given server_id. Idempotent.