* feat(backend): add vllm-cpp text-generation backend (vllm.cpp) Wrap https://github.com/mudler/vllm.cpp - the LocalAI-team from-scratch C++20 port of vLLM (paged KV cache, continuous batching, prefix caching, safetensors + GGUF loading, no Python at inference) - as a Go gRPC backend over its stable C ABI (ABI v2) via purego. Backend (backend/go/vllm-cpp): - Load -> vllm_engine_load: accepts a .gguf file or a config.json model dir (anything else is refused, satisfying the greedy-probe rule); context_size maps to max_model_len, options block_size/num_blocks/max_num_seqs size the KV cache and scheduler admission. - Predict -> vllm_complete (blocking); PredictStream -> vllm_complete_stream with the per-delta C callback bridged into the gRPC stream. The backend embeds base.Base (not SingleThread): concurrent requests batch continuously in the engine's shared AsyncLLM scheduler. - PredictOptions.Grammar -> the ABI's structured_grammar (GBNF), giving grammar-constrained tool calling at parity with llama-cpp; the ABI also exposes JSON-schema/regex/choice constraints. - Hand-mirrored POD structs with layout locked by unit tests (unsafe.Offsetof vs the C offsets) and a runtime vllm_abi_version gate. - One portable library per platform (vllm.cpp uses per-file SIMD tiers with runtime dispatch), so no avx/avx2/avx512 variant builds. Wiring: - backend-matrix: CPU amd64+arm64 (per-arch + manifest merge), CUDA 12/13 amd64 (120a;121a Blackwell fat binary), L4T arm64 (121a, GB10/DGX Spark - the runtime-proven GPU target), Vulkan amd64, and Darwin arm64 Metal. - backend/index.yaml meta + 12 image entries (latest/development x cpu, cuda12, cuda13, l4t, vulkan, metal); bump_deps registration for the VLLM_CPP_VERSION pin; root Makefile registration; test-extra runs the unit specs (pure Go, no engine build). - Importers: preference-only swaps - llama-cpp (GGUF) and vllm (safetensors) advertise vllm-cpp via AdditionalBackends and emit backend: vllm-cpp without tokenizer templating (the C ABI takes the FINAL prompt; templating and tool parsing stay LocalAI-side). No auto-detect importer. - Docs: backends list, top-level README maintained-engines table, compatibility table. Verified: 20/20 Ginkgo specs against the real pinned engine and Qwen3.5-2B-UD-Q8_K_XL.gguf on CPU - blocking + streaming parity, greedy determinism, stop words, GBNF-constrained generation, and 4 concurrent streams; plus a dlopen/ABI-gate smoke of the built gRPC server binary. Upstream ABI v2 + production structured-output wiring landed as mudler/vllm.cpp@86013f3. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(vllm-cpp): ride the autoparser code path - engine-side chat templating and tool engagement (ABI v3) The backend now implements AIModelRich (PredictRich / PredictStreamRich) over vllm.cpp's ABI v3 chat entry points, so chat and tool calling ride the SAME code path as the llama.cpp autoparser: the ENGINE renders the model's chat template, decides when a tool call engages, and parses it - LocalAI receives pre-parsed ChatDelta / ToolCallDelta protos exactly as it does from llama-cpp. - With use_tokenizer_template + structured Messages, PredictOptions lowers to ONE OpenAI chat request JSON (messages, tools, tool_choice, sampling, stream_options.include_usage) for vllm_chat / vllm_chat_stream. tool_choice auto lowers engine-side to a LAZY structural-tag decode constraint - free text until the model emits the tool trigger, then the call is grammar-constrained; required/named force a call. Tool output is parsed by the engine's streaming Hermes-style parser; each chat.completion.chunk maps onto ChatDeltas (content / reasoning_content / tool_calls) which the host already prefers over Go-side tag extraction. Without structured messages the plain path (LocalAI templating + optional GBNF grammar) applies unchanged. - The engine resolves the chat template from the GGUF tokenizer.chat_template metadata (or tokenizer_config.json); templates beyond its minja subset - e.g. the full Qwen3.5 namespace()/macro template - degrade engine-side to a Hermes-aware fallback prompt (tools schemas + <tool_call> instruction) with a stderr witness, so structural-tag engagement keeps working. - Importers now emit the same config shape as llama-cpp for vllm-cpp (use_tokenizer_template: true, no-grammar autoparser flow); only the llama-cpp-specific use_jinja option and the vllm-python parser options are dropped. - Pin bumped to mudler/vllm.cpp@aaed7ec (ABI v3 + chat-prompt resolution). Verified against the real engine and Qwen3.5-2B-UD-Q8_K_XL.gguf on CPU: full suite green - blocking chat, streaming deltas concatenating byte-equal to the blocking answer, a REQUIRED tool call returning schema-valid arguments JSON, and an AUTO run where the engine itself engages get_weather and streams parsed tool deltas; plus unit specs for the request lowering, chunk->ChatDelta mapping, and the C struct mirrors (ABI gate now v3). Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(vllm-cpp): ABI v5 - engine-side parser selection for 30 tool dialects + reasoning Bump the vllm.cpp pin to the autoparser-parity engine: 30 tool-call dialects (every pure-text parser in the pinned vLLM registry, each ported 1:1 with its upstream tests), 7 reasoning parsers, google/minja as the template renderer (the full Qwen3.5 template now renders engine-side), per-family structural tags (tool_choice required/named compiles the model's NATIVE syntax where expressible), and template auto-detection for both parser axes. Backend changes: - cModelParams mirrors ABI v5 (tool_parser + reasoning_parser fields, layout-locked by the offset tests; ABI gate now v5). - New model options tool_parser:<name> / reasoning_parser:<name> pass through to the engine; unset means template auto-detection (18-row tool marker table; [THINK]->mistral, <think>->think_auto for reasoning); "none" disables the reasoning split; unknown names fail the first chat call. - Chat chunks parse the `reasoning` field (the pin renamed reasoning_content), flowing into ChatDelta.ReasoningContent which the host already prefers. Live e2e against Qwen3.5-2B-UD-Q8_K_XL.gguf on CPU, full suite green: the real chat template renders (no more fallback), reasoning auto-detection picks think_auto so markerless answers stay pure content (the live run caught the deepseek_r1 content-swallow upstream and drove the think_auto fix), required tool_choice returns schema-valid arguments, auto tool_choice engages engine-side and streams parsed deltas, and blocking/streaming stay byte-identical. Turn latency also dropped (proper template EOS behavior). Upstream program landed as mudler/vllm.cpp 86013f3..5fffe7e (ABI v2-v5, minja, parser waves B1/B2/B4, reasoning seam, structural-tag registry, think_auto). Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * chore(vllm-cpp): bump the engine pin to the ENG-wave close-out mudler/vllm.cpp@df8909b: the six engine-backed vLLM tool-parser families (qwen3-coder/xml/mimo, kimi_k2, glm45/47, minimax_m2, gemma4, seed_oss) text-reimplemented from their wire formats and held to the upstream test suites - 39 registered dialects; the pinned vLLM registry is now covered except the three Rust/Harmony-backed families, descoped by decision. kimi_k2 also gains a full native structural-tag builder; four new template auto-detection rows land with test-pinned ordering. Full backend e2e re-run green against Qwen3.5-2B-UD-Q8_K_XL.gguf on CPU. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(vllm-cpp): add the vllm-cpp-development gallery meta The gallery grew the twelve latest/development image entries but was missing the separate vllm-cpp-development meta (own capabilities map targeting the -development image names), which every backend ships so the development gallery resolves per-platform. Validated: all capability targets in both metas resolve to existing entries, and every image URI's tag suffix matches a backend-matrix build. Also full-stack verified in this change's context (single-node local-ai from this branch, locally-built backend under --backends-path, Qwen3.5-2B GGUF): /v1/chat/completions non-stream (clean content + usage), streaming (SSE deltas), tool_choice auto engaging get_weather engine-side with schema-valid arguments and finish_reason=tool_calls, and streamed tool-call deltas in the standard name-first cadence. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(vllm-cpp): repair the CI backend builds - gcc-14 -Werror + fat-arch Triton Two distinct failures took down all five vllm-cpp backend builds on the PR: 1. gcc-14 (ubuntu:24.04 CI images; the local toolchain is gcc-13) fails the engine build with -Werror=maybe-uninitialized in InputBatch::condense - a false positive through a staging std::optional's raw storage. Fixed upstream (mudler/vllm.cpp@61f3e85) by moving slot-to-slot directly; verified BOTH ways under dockerized g++-14.2 (unfixed reproduces CI's two diagnostics exactly, fixed compiles clean) with the engine's behavior suites green. Pin bumped to that sha. 2. The amd64 CUDA builds died at CMake configure: the vendored Triton-AOT cubin trees are per-arch and the engine refuses -DVLLM_CPP_TRITON=ON on a multi-arch (120a;121a) fat build unless pinned to one tree, which would be unsound for the other arch. Triton is now enabled only on the single-arch arm64/GB10 build (where the cubins matter); the fat amd64 binary uses the engine's non-AOT GDN path. Backend e2e re-run green at the new pin (Qwen3.5-2B on CPU, full suite). Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(vllm-cpp): cuda-12 images cannot compile compute_121a - target 120a only The second CI round surfaced a CUDA-version constraint: the cuda-12 (12.8) image's nvcc rejects 'compute_121a' (GB10 arch support landed with CUDA 13), killing the amd64 cuda-12 build at nvcc. Gate the architecture list on CUDA_MAJOR_VERSION (exported by Dockerfile.golang): cuda-12 builds consumer Blackwell 120a only, cuda-13 keeps the 120a;121a fat binary, arm64/l4t (cuda-13) keeps single-arch 121a with the Triton cubins. GB10 is arm64, so the amd64 cuda-12 image never served it - no capability change. Verified by Makefile dry-run variable dumps for all three combinations (cuda12 -> 120a; cuda13 -> 120a;121a; cpu -> CUDA off). Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(vllm-cpp): drop the cuda-12 variant - the engine needs the CUDA 13 toolchain Third CI round, third layer: with the arch list already narrowed to 120a, the cuda-12 (12.8) build still dies in ptxas compiling the sm_120a NVFP4 MMA kernels ("Vector type too large, exceeds 128 bit limit") - the Blackwell fp4 path genuinely requires the CUDA 13 toolchain, and vllm.cpp supports Blackwell-family GPUs only. Shipping a cuda-12 image without the fp4 kernels would be a crippled build of an engine whose whole GPU story is fp4, so the variant is dropped instead: - backend-matrix: cuda-12 vllm-cpp entry removed (cuda-13 amd64, l4t arm64, cpu, vulkan, metal remain). - gallery: cuda12 image entries removed; the nvidia capability now resolves to the cuda13 image in both metas; the nvidia-cuda-12 key is dropped so older-driver hosts fall back to the CPU image instead of an unrunnable one. - backend Makefile: BUILD_TYPE=cublas under CUDA_MAJOR_VERSION=12 now fails fast with a clear message; cuda-13 keeps the 120a;121a fat binary and arm64/l4t keeps 121a with the Triton cubins. Verified: Makefile branch dumps for all four combinations (cuda12 loud error, cuda13 fat, arm64 121a+Triton, cpu off), YAML parses, matrix filter tests green, gallery capability targets all resolve. Assisted-by: Claude Code:claude-fable-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(vllm-cpp): forward multi-turn tool identity and reasoning to the engine chatRequestJSON dropped Message.ToolCallId and Message.Name on role="tool" replies and Message.ReasoningContent on assistant history, so a second turn after tool execution reached the engine's chat template without the fields that bind a tool result to the call it answers. Forward all three (present-only, matching the OpenAI wire shape) and pin vllm.cpp to 6a0bd3e7, where ChatMessage parses/round-trips tool_calls, tool_call_id, name and reasoning and the minja adapter exposes them to the template context. Adds the round-trip request-lowering spec (user -> assistant tool_call -> tool reply -> lowered request) and re-ran the gated e2e suite against the new engine pin with a real Qwen3.5 GGUF: chat, reasoning split, streaming parity, required-tool and auto-tool cases all green. Assisted-by: Claude Code:claude-fable-5 [Bash] [Edit] [Read] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(vllm-cpp): bump vllm.cpp for the darwin arm64 i8mm build fix The darwin-metal CI job was the first build to compile the engine's arm CPU-quant files on macOS and hit their Linux-only <asm/hwcap.h> / <sys/auxv.h> includes. vllm.cpp 9e1c9025 detects i8mm per-OS (auxv on Linux, sysctl on Apple Silicon) with kernels untouched. Gated e2e suite re-run green against the new pin with a real Qwen3.5 GGUF. Assisted-by: Claude Code:claude-fable-5 [Bash] [Read] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(vllm-cpp): darwin build - bound cmake parallelism when nproc is absent The macOS runners have no nproc, so JOBS evaluated empty and `cmake --build -j$(JOBS)` became bare `-j`: unlimited clang jobs on a 3-core/7GB Mac, which swap-thrashed until the 6h GHA timeout (the log shows "nproc: Command not found" and 7+ concurrent clang processes being reaped at the cutoff). Use the same portable fallback chain as the other darwin backends: nproc, then sysctl hw.ncpu, then 4. Assisted-by: Claude Code:claude-fable-5 [Bash] [Edit] [Read] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
6.0 KiB
title, description, weight, url
| title | description | weight | url |
|---|---|---|---|
| Backends | Learn how to use, manage, and develop backends in LocalAI | 80 | /backends/ |
LocalAI supports a variety of backends that can be used to run different types of AI models. There are core Backends which are included, and there are containerized applications that provide the runtime environment for specific model types, such as LLMs, diffusion models, or text-to-speech models.
Available Backends
LocalAI ships 60+ backends covering text generation, speech-to-text, text-to-speech, music and sound generation, image and video generation, vision and object detection, audio processing, reranking, fine-tuning, and more. Each one is published as an on-demand OCI image with the appropriate acceleration variants (CPU, CUDA 12/13, ROCm, Intel SYCL, Vulkan, Metal, Jetson L4T).
For the complete list of backends, the model families they support, and their acceleration targets, see the [Backend & Model Compatibility Table]({{%relref "reference/compatibility-table" %}}). The authoritative source is backend/index.yaml, and the same catalog is browsable in the web UI under the Backends section.
Managing Backends in the UI
The LocalAI web interface provides an intuitive way to manage your backends:
- Navigate to the "Backends" section in the navigation menu
- Browse available backends from configured galleries
- Use the search bar to find specific backends by name, description, or type
- Filter backends by type using the quick filter buttons (LLM, Diffusion, TTS, Whisper)
- Install or delete backends with a single click
- Monitor installation progress in real-time
Each backend card displays:
- Backend name and description
- Type of models it supports
- Installation status
- Action buttons (Install/Delete)
- Additional information via the info button
Backend Galleries
Backend galleries are repositories that contain backend definitions. They work similarly to model galleries but are specifically for backends.
Adding a Backend Gallery
You can add backend galleries by specifying the Environment Variable LOCALAI_BACKEND_GALLERIES:
export LOCALAI_BACKEND_GALLERIES='[{"name":"my-gallery","url":"https://raw.githubusercontent.com/username/repo/main/backends"}]'
The URL needs to point to a valid yaml file, for example:
- name: "test-backend"
uri: "quay.io/image/tests:localai-backend-test"
alias: "foo-backend"
Where URI is the path to an OCI container image.
Backend Gallery Structure
A backend gallery is a collection of YAML files, each defining a backend. Here's an example structure:
name: "llm-backend"
description: "A backend for running LLM models"
uri: "quay.io/username/llm-backend:latest"
alias: "llm"
tags:
- "llm"
- "text-generation"
Pre-installing Backends
You can pre-install backends when starting LocalAI using the LOCALAI_EXTERNAL_BACKENDS environment variable:
export LOCALAI_EXTERNAL_BACKENDS="llm-backend,diffusion-backend"
local-ai run
Creating a Backend
To create a new backend, you need to:
- Create a container image that implements the LocalAI backend interface
- Define a backend YAML file
- Publish your backend to a container registry
Backend Container Requirements
Your backend container should:
- Implement the LocalAI backend interface (gRPC or HTTP)
- Handle model loading and inference
- Support the required model types
- Include necessary dependencies
- Have a top level
run.shfile that will be used to run the backend - Pushed to a registry so can be used in a gallery
Getting started
For getting started, see the available backends in LocalAI here: https://github.com/mudler/LocalAI/tree/master/backend .
- For Python based backends there is a template that can be used as starting point: https://github.com/mudler/LocalAI/tree/master/backend/python/common/template .
- For Golang based backends, you can see the
piperbackend as an example: https://github.com/mudler/LocalAI/tree/master/backend/go/piper - For C++ based backends, you can see the
llama-cppbackend as an example: https://github.com/mudler/LocalAI/tree/master/backend/cpp/llama-cpp
Publishing Your Backend
-
Build your container image:
docker build -t quay.io/username/my-backend:latest . -
Push to a container registry:
docker push quay.io/username/my-backend:latest -
Add your backend to a gallery:
- Create a YAML entry in your gallery repository
- Include the backend definition
- Make the gallery accessible via HTTP/HTTPS
Backend Types
LocalAI supports various types of backends:
- LLM Backends: For running language models (e.g., llama.cpp, vLLM, vllm.cpp, SGLang, transformers, MLX)
- Speech-to-Text Backends: For transcription and speaker diarization (e.g., whisper.cpp, parakeet.cpp, moss-transcribe.cpp, faster-whisper, NeMo)
- Text-to-Speech Backends: For speech synthesis (e.g., piper, Kokoro, VibeVoice, Qwen3-TTS)
- Sound Generation Backends: For music and audio generation (e.g., ACE-Step)
- Sound Classification Backends: For sound-event classification / audio tagging - identifying everyday sounds like baby cry, glass breaking, alarms (e.g., ced.cpp)
- Image & Video Generation Backends: For diffusion and audio-conditioned avatar models (e.g., stable-diffusion.cpp, diffusers, vLLM-Omni, [LongCat-Video]({{%relref "features/video-generation" %}}))
- Vision & Detection Backends: For object detection, segmentation, depth, and face/voice recognition (e.g., rf-detr.cpp, locate-anything.cpp, sam3.cpp, insightface)
- Audio Processing Backends: For voice activity detection and audio enhancement (e.g., Silero VAD, LocalVQE)
- Utility Backends: For reranking, PII/NER token classification, fine-tuning, quantization, and vector storage (e.g., rerankers, privacy-filter.cpp, TRL, local-store)
See the [Backend & Model Compatibility Table]({{%relref "reference/compatibility-table" %}}) for the full catalog.