首页
/ LocalAI vllm-cpp 后端完全指南:无 Python 的 vLLM C++20 移植、安装、模型与推理配置

LocalAI vllm-cpp 后端完全指南:无 Python 的 vLLM C++20 移植、安装、模型与推理配置

2026-09-08 12:00:12作者:侯霆垣

vllm-cpp 是 LocalAI 团队基于 vLLM 用 C++20 重写的推理引擎,在推理路径上完全不依赖 Python,同样具备 continuous-batching 调度器、分页 KV 缓存与自动前缀缓存。LocalAI 通过原生 vllm-cpp 后端暴露该引擎,可加载 HuggingFace safetensors 目录或 .gguf 文件,并将聊天模板、工具调用解析与推理分段(reasoning split)全部收敛到引擎内部完成。本文以 docs/content/features/vllm-cpp.md 为主干,结合 backend/go/vllm-cpp 源码与 gallery/index.yaml 中的画廊条目,系统讲解后端的安装与硬件选型、LocalAI 内置的可直接运行模型、KV 缓存与推测解码配置要点,以及由同一后端承载的 MiniMax-H3 音视频联合生成能力。

vllm-cpp 后端是什么

vllm.cpp 是 LocalAI 团队维护的 vLLM C++20 移植:它保留了 vLLM 的核心运行时特性——连续批处理(continuous batching)、分页 KV 缓存(paged KV cache)与自动前缀缓存(automatic prefix caching),区别在于推理阶段没有任何 Python 参与,这让部署链路更简单、更可预测。

LocalAI 通过原生 vllm-cpp 后端把它接入 OpenAI 兼容 API。一个后端同时覆盖两类负载:

  • 文本生成:加载 safetensors 模型目录或 .gguf 文件,提供聊天 / 补全 / 流式输出、工具调用、推理分段;
  • MiniMax-H3 音视频联合生成:经由独立的视频引擎句柄,返回带真实 AAC 音轨的 MP4。

backend/go/vllm-cpp/backend.go 的实现看,该后端通过 purego 以 dlopen 方式加载引擎的稳定 C ABI(libvllm,ABI v20):

  • Load 对应 vllm_engine_load,接受 .gguf 文件或 HF 风格模型目录(config.json + safetensors);context_size 映射为 max_model_lenoptions 中的 block_sizenum_blocksmax_num_seqs 决定 KV 缓存与调度准入规模;
  • Predict 对应阻塞式 vllm_completePredictStream 对应 vllm_complete_stream;多个并发 gRPC 请求会持续汇入引擎共享的 AsyncLLM 调度器实现连续批处理——这正是后端内嵌 base.Base 而非单线程基类的原因。

聊天与工具调用与 llama.cpp 的 autoparser 走同一条代码路径:在 use_tokenizer_template: true 时,后端基于 ABI v3 聊天入口(vllm_chat / vllm_chat_stream)实现 PredictRich/PredictStreamRich,由引擎套用模型的聊天模板(GGUF tokenizer.chat_templatetokenizer_config.json),并自行完成工具调用触发判断、解析与推理分段。

安装后端

在任意终端执行:

local-ai backends install vllm-cpp

也可以直接在 LocalAI Web UI 的 Backends 页面点击安装。官方发布的镜像覆盖 CPU、CUDA 13、Vulkan、Metal 与 Jetson L4T 五类运行环境,按宿主机能力选择即可。

CUDA 镜像的 GPU 覆盖范围(重要前提)

当前 CUDA 镜像只为 Blackwell 系架构构建

  • x86-64:sm_120a(RTX 50 系列、RTX PRO 6000 Blackwell)与 sm_121a(GB10 / DGX Spark);
  • arm64:仅 sm_121a

由于要求 CUDA 13,不存在 CUDA 12 变体。这比 vllm.cpp 上游自己构建的十种架构要窄。在 Ampere、Ada、Hopper、Jetson Orin 或 Jetson Thor GPU 上,CUDA 后端会成功安装,但第一个请求即失败,报错为 no kernel image is available for execution on the device(无可执行内核镜像)。

在架构支持放宽之前,上述旧卡的推荐方案是改装 VulkanCPU 镜像:vulkan-vllm-cpp 以完全关闭 CUDA 的方式编译,能为这些卡提供 GPU 加速路径(代价是没有 NVFP4 与 Marlin 内核)。架构下限是选择入口模型时最需要先确认的硬约束。

LocalAI 内置的现成 vllm-cpp 模型

模型画廊(见 gallery/index.yamlqwen3.6-*qwen3-coder-*qwen3-* 系列条目)为 vllm-cpp 维护了一套精选配置。每个条目在下载时已带好引擎设置,工具调用、推理分段与推测解码开箱即用,无需手改 YAML。

画廊条目 模型 体量 硬件要求
qwen3.6-27b-nvfp4-vllm-cpp Qwen3.6-27B,NVFP4 25 GB Blackwell GPU
qwen3.6-27b-nvfp4-mtp-vllm-cpp 同上,启用 MTP 推测解码 25 GB Blackwell GPU
qwen3.6-27b-nvfp4-dflash-vllm-cpp 同上,启用 DFlash 推测解码 28 GB Blackwell GPU
qwen3.6-35b-a3b-nvfp4-vllm-cpp Qwen3.6-35B-A3B MoE,NVFP4 23 GB Blackwell GPU
qwen3.6-35b-a3b-nvfp4-mtp-vllm-cpp 同上,启用 MTP 推测解码 23 GB Blackwell GPU
qwen3-coder-30b-a3b-vllm-cpp Qwen3-Coder-30B-A3B,bf16 57 GB Blackwell GPU 或 CPU
qwen3-4b-vllm-cpp Qwen3-4B,bf16 8 GB CPU、Metal、Vulkan、Blackwell GPU
qwen3-0.6b-vllm-cpp Qwen3-0.6B,bf16 1.4 GB CPU、Metal、Vulkan、Blackwell GPU

安装任一条目:

local-ai models install qwen3-0.6b-vllm-cpp

两个小体量 bf16 条目是"后端能跑的地方它们都能跑"的选择,包括纯 CPU 环境,因此也最适合先用来验证一次 vllm-cpp 安装是否真的能对外服务(如 gallery/index.yamlqwen3-0.6b-vllm-cpp 的说明,它是一颗真实可对话、可演练工具调用与推理分段的模型,而非桩)。NVFP4 条目则需要 Blackwell 级 NVIDIA GPU,原因有二:NVFP4 在更老架构上没有对应 kernel;且 CUDA 镜像本身只针对 Blackwell 构建。

KV 缓存内存:num_blocks 不是白送的

尺寸提示:每个条目都通过 num_blocks 预留约一到四个完整上下文的 KV 缓存,这只是起点而非调优值。KV 缓存并非免费:例如 4B 条目每 token 占用 144 KiB,其 1024 个 block 意味着在权重之外还要再支付约 4.5 GB 内存。需要更高并发就调高 num_blocks,小内存机器则应调低。以 qwen3-4b-vllm-cpp 的默认配置为例(对应 gallery/index.yaml):

engine_args:
  block_size: 32
  # 一个完整上下文的 KV(32768 token),在该模型 144 KiB/token 下约 4.5 GB。
  # 这是刻意克制的大小:该条目必须能和小机器上的其他任务共存。内存够就调大。
  num_blocks: 1024
  max_num_seqs: 8

为什么 27B 条目要锁定 revision

Qwen3.6-27B 系列条目将权重固定到 HuggingFace 的某个具体 commit,而不是跟随仓库默认分支。这是有意为之,在复制这些配置前值得理解。

上游仓库后来在同名下被原地重新量化,从 NVFP4 换成了 FP8 W8A8。一个只写仓库名而不写 revision 的配置,因此会解析到完全不同的权重——不同的数值精度、不同的性能,而加载过程不会报告任何变化。锁定 revision 正是保证条目可复现的手段:

artifacts:
  - name: model
    target: model
    source:
      type: huggingface
      repo: unsloth/Qwen3.6-27B-NVFP4
      revision: 890bdef7a42feba6d83b6e17a03315c694112f2a

同样的道理适用于任何你依赖的量化社区仓库:配置一经发布,就把权重来源锁到具体 commit 上,避免"静默换芯"。

推测解码:如何在三个 27B 变体间选择

推测解码用内存换取解码吞吐。三个 Qwen3.6-27B 条目服务的是相同权重、产出相同质量,区别只在 token 如何被"提议":

条目 方法 额外权重 额外内存
qwen3.6-27b-nvfp4-vllm-cpp
qwen3.6-27b-nvfp4-mtp-vllm-cpp MTP,深度 1 无(草稿头随 checkpoint 自带) 约 3.6 GB
qwen3.6-27b-nvfp4-dflash-vllm-cpp DFlash,16-token 块 独立的 3.5 GB drafter drafter 加草稿缓存

MTP(多 token 预测)从目标 checkpoint 自带的 mtp.* 张量中取草稿头,每步起草一个 token,因此不增加任何下载量。在 27B 入口上,画廊元数据记录的实测约为散文 85%、代码 92% 的草稿接受率,相对关闭推测带来约 1.5–1.6 倍解码吞吐,且并发 2/4/8 下优势仍保持(见 gallery/index.yaml)。

DFlash 从独立 drafter 出发,在一次非自回归前向中起草整块 16 个 token,再由目标单步验证整块——是更大的吞吐收益,代价是磁盘上多一个 checkpoint。画廊记录其单并发下约为关闭推测时的 2.9 倍。

务实建议:内存紧张从普通条目起步;内存宽裕直接上 DFlash 条目。DFlash 草稿与目标共享 embed_tokenslm_head,两者不可独立互换,安装时会由画廊自动把 drafter 放到 models/Qwen3.6-27B-DFlash,这正是后端解析 speculative_config.model 时查找的位置。

engine_args:引擎级配置参考

上述画廊条目覆盖了常见用法;若需自行编写模型配置,完整参数参考见 text-generation 指南 的 vllm.cpp 小节。vllm-cpp 后端接受与 vLLM、SGLang 后端相同的 engine_args: 映射,键名与 vLLM 自身的 CLI 标志完全一致——因此为 vLLM 写好的 speculative_configkv_transfer_config 结构可以原样使用。未知键会被忽略而不会致命;引擎会校验交给它的文档并在加载时报出精确错误。

name: qwen35-a3b
backend: vllm-cpp
parameters:
  model: "Qwen/Qwen3.5-A3B"
context_size: 16384
template:
  use_tokenizer_template: true
engine_args:
  # KV 缓存容量:num_blocks * block_size 个 token 的缓存。
  block_size: 32
  num_blocks: 1024
  # 并发度与每步 chunked-prefill 的 token 预算。
  max_num_seqs: 32
  max_num_batched_tokens: 8192
  # 自动前缀缓存。省略则沿用模型自身默认
  #(稠密模型默认开,hybrid/无注意力模型默认关)。
  enable_prefix_caching: true
  # 调度准入顺序:fcfs(默认)、priority 或 lpm
  #(cache-aware 最长前缀匹配;需前缀缓存开启才生效)。
  scheduling_policy: lpm

常用键速查表

含义 默认值
block_size KV 缓存块大小(token/块) 32
num_blocks 分配的 KV 缓存块数 256
max_model_len 最大序列长度;也可用 context_size / max_model_len 设置 模型配置
max_num_seqs 调度器准入的最大并发序列数 8
max_num_batched_tokens 每步 chunked-prefill 的 token 预算 按架构(稠密 2048,MoE 4096/8192)
enable_prefix_caching 自动前缀缓存;enable_radix_attention 是接受的别名 模型默认
enable_jump_forward Jump-forward 解码:被文法强制出的 token 无需模型步进。仅影响受限请求(grammar、JSON schema)
scheduling_policy fcfsprioritylpm fcfs
tool_parser / reasoning_parser 强制指定解析器,而非聊天模板自动探测 自动
tokenizer_config 覆盖读取聊天模板所用的 tokenizer_config.json <model_dir>/tokenizer_config.json
speculative_config 推测解码(见下) 禁用
kv_transfer_config 外部 KV 连接器 / LMCache

提高 max_num_batched_tokens 能让更多 prefill 落入单步执行,代价是排在其后的请求解码延迟上升。默认值刻意不随 max_num_seqs 缩放,这是避免大并发 prefill 在 hybrid 架构上撑爆单步激活的关键设计。

enable_prefix_cachingenable_jump_forward 在引擎边界是三态:省略键会退化为默认(前缀缓存取模型自身能力、jump-forward 取环境变量),显式 false 则强制关闭。两者含义真实不同——前缀缓存在稠密模型上默认——所以只在确实需要覆盖时才写该键。

推测解码的三种方法

speculative_config: 接受与 vLLM --speculative-config 相同的 JSON 对象。需要特别注意架构限制:在当前引擎 pin 下,mtpdflash 仅支持 Qwen3.5 / Qwen3.6(引擎为这两个系列直接构建了加宽的推测 KV 缓存,而非经模型注册表),Llama、GLM、Gemma、Mistral 等其他架构即使换了 checkpoint 格式也无法生效;ngram 无需草稿权重,不受此限制。

MTP 使用目标 checkpoint 自带 mtp.* 张量中的草稿头,无需下载第二个模型,但要求 safetensors 格式(mtp.* 张量无法在 GGUF 转换中幸存,对 .gguf 模型配置 MTP 会在加载时被拒绝):

engine_args:
  speculative_config:
    method: mtp
    # 可选;默认取 checkpoint 自带草稿头深度,通常即正确值。必须是该深度的倍数。
    num_speculative_tokens: 1

DFlash 使用独立的分块扩散 drafter,一次非自回归前向提出整块 token。与 MTP 不同,草稿是独立 checkpoint,因此 model: 必填:

engine_args:
  speculative_config:
    method: dflash
    model: z-lab/Qwen3.6-27B-DFlash
    num_speculative_tokens: 4

草稿与目标共享 embed_tokenslm_head,因此两者必须出自同一模型家族,且目标必须是 safetensors。引擎不会下载草稿model: 依次按"原样路径 → 以最后一段作为 LocalAI models 目录下的路径(即 LocalAI 自带下载器的产物布局)→ models 目录下的完整引用"解析。请先把 drafter 安装进 LocalAI,或给出含 config.json 的目录绝对路径;全部解析失败时加载会立刻失败,并列出所有尝试过的位置,而不是在引擎内部报告一个缺失 checkpoint。

N-gram 完全不需要草稿模型——它从提示自身的后缀历史中提议:

engine_args:
  speculative_config:
    method: ngram
    num_speculative_tokens: 4
    prompt_lookup_min: 5
    prompt_lookup_max: 5

此外,导入 safetensors 仓库时 LocalAI 会读取 config.json:若声明了 MTP 头(mtp_num_hidden_layers),会自动向生成的 engine_args 写入 speculative_config: {method: mtp};自己显式写的 speculative_config 永远不会被覆盖。导入 DFlash 草稿 仓库则会被拒绝并告警——drafter 无法独立服务,应导入目标模型并把 speculative_config.model 指向草稿。

外部 KV 缓存:LMCache

kv_transfer_config: 接受 vLLM --kv-transfer-config 的 JSON,选择外部 KV 缓存连接器。lm:// LMCache 客户端允许把 prefill 的 KV 存入共享的 lmcache.v1.server 并按需重载,使一个副本算出的前缀不必被下一个副本重算:

engine_args:
  kv_transfer_config:
    kv_connector: LMCacheConnector
    kv_role: kv_both          # 设置 kv_connector 时必填
    kv_connector_extra_config:
      host: 127.0.0.1
      port: 65432

kv_rolekv_producer(只存)、kv_consumer(只取)或 kv_both 之一。未注册的连接器名、缺失的 role 或畸形的文档都会使加载显式失败,而不是在缺少缓存时静默运行。

兼容旧的 options: 列表写法

早期版本用扁平 options: 列表配置此后端,这些配置仍然有效——上表每个键都能以 key:value 形式从 options: 读到,且键同时出现时 engine_args 优先:

options:
  - max_num_seqs:32
  - enable_prefix_caching:true

新配置应优先使用 engine_args:,它是嵌套的 speculative_config / kv_transfer_config 文档唯一能被自然书写(而非挤成单行 JSON 字符串)的位置。

工具调用与引擎内解析

上表每个条目都设置 use_tokenizer_template: true 并禁用 LocalAI 的 Go 侧文法路径,因此工具调用由引擎自带的流式解析器检测与解析,最终以 OpenAI 响应中真实的 tool_calls 到达客户端。

解析器通常根据聊天模板自动探测,但有一种情况无法自动完成:Qwen3-Coder 的工具方言在线缆上与另一模型家族的字节完全相同,模板嗅探会选错解析器。因此 qwen3-coder-30b-a3b-vllm-cpp 条目显式点名解析器——任何你自行编写的 Qwen3-Coder 配置都应照做(参见 gallery/index.yaml):

engine_args:
  tool_parser: qwen3_coder

画廊中大模型条目同时显式给出 reasoning_parser: think_auto,以保证推理分段(<think> 输出切分)在模板将来被上游修订后依旧可用。

超出文本生成:MiniMax-H3 音视频联合生成

vllm-cpp 后端同样服务 MiniMax-H3——从文本提示联合生成视频与音频,产出的是带真实音轨的 MP4(可在提示中要求语音,模型会做口型同步),详见 Video generation 指南

值得注意的实现细节:视频引擎是第二个句柄vllm_video_engine,ABI v12),而非文本引擎的一种模式。因为 H3 是一组 checkpoint(DiT、文本编码器、两个 VAE 各自独立),而 vllm.cpp 的两个加载器会互相拒绝对方的 checkpoint;Load 在模型配置携带任一视频选项时走视频分支。后端 C ABI 文档(backend/go/vllm-cpp/README.md)与画廊的 minimax-h3-fl2va-q4 条目给出了完整配置骨架:

name: minimax-h3-fl2va-q4
backend: vllm-cpp
cuda: true
known_usecases: [video]
parameters:
  model: minimax-h3/MiniMax-H3-FL2VA-Q4_K_M.gguf
options:
- video_encoder:minimax-h3/qwen3vl-32B-MiniMax-H3-Q4_K_M.gguf
- video_tokenizer:minimax-h3/tokenizer.json
- video_vae:minimax-h3/video_vae.safetensors
- video_vae_config:minimax-h3/video_vae_config.json
- audio_vae:minimax-h3/audio_vae.safetensors
- audio_vae_config:minimax-h3/audio_vae_config.json
- video_partition:fl2va
- video_device:cuda
- video_dequant_bf16:true
- video_width:1344
- video_height:768
- video_num_frames:124

三条选型须知:

  1. partition 靠声明而非探测,且不匹配不会干净失败。 FL2VA DiT 服务 t2va(文生视频)与 fl2va(首/末帧条件);ref2va 是另一个 checkpoint。社区的 GGUF/NVFP4 量化剥离了发布元数据,且两个 DiT 字节结构相同,引擎会在 video_partition 表明身份前拒绝一切生成;后端还会在调用引擎前拒绝把参考条件送入 FL2VA DiT 的组合。
  2. ffmpeg 来自宿主机。 libvllm 只负责写帧与 WAV、拼装 mux 的 argv,进程边界由上游决定;后端镜像 FROM scratch 且不带 ffmpeg,与 vibevoice-cpp 的做法一致。运行时宿主机需要提供 ffmpeg。
  3. 它很慢。 在 1344x768、20-SM 设备上约 176 秒/去噪步,50 步默认意味着数小时量级的任务。

另外可留意画廊元数据中的坐标约定:画布会截断到 32 像素网格、帧数落在 17n+5 网格,未指定画布而给定关键帧时按 768 短边由图片宽高比推导(MiniMaxH3ResolveShapeminimax_h3_planner.cpp)。

小结:如何开始

  1. 按宿主硬件选择镜像:Blackwell 新卡用 CUDA 13 镜像,旧卡与 Jetson 用 vulkan-vllm-cpp,无 GPU 走 CPU;
  2. local-ai backends install vllm-cpp 安装后端(或 Web UI Backends 页);
  3. local-ai models install qwen3-0.6b-vllm-cpp 起步验证服务,再按内存预算选择 4B bf16(通用)或 27B NVFP4 系列(Blackwell,可选 MTP/DFlash 提速);
  4. 需要自定义配置时,以 engine_args: 书写引擎参数,并牢记:KV 缓存要按并发与上下文显式预留、依赖社区量化仓库务必锁 revision、Qwen3-Coder 必须显式声明 tool_parser: qwen3_coder
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.74 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
595
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.63 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
518
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
389