四个推理后端:huggingface、vllm、sglang、ktransformers
本文所有事实以
hiyouga/LlamaFactory官方仓库 2026-08-09 的内容为准。我们没有安装、训练或部署过任何模型,文中所有参数名与默认值都是从仓库源码和示例配置里读出来的。
先说结论性的那一行:infer_backend 这个字段的合法取值就四个,写在 examples/inference/qwen3_lora_sft.yaml 的行内注释里,原文是 infer_backend: huggingface # choices: [huggingface, vllm, sglang, ktransformers]。
这一行值得单独拎出来,是因为它是这四个名字在我们读到的仓库内容里最直白的一处集中出处。README 的 changelog 和命令行示例里也会零散撞见其中某一个(比如 infer_backend: sglang、infer_backend=vllm),但要一次看全四个合法取值,就得回到这份示例 YAML 的这行注释。
这个字段坐在哪一层
infer_backend 定义在 src/llamafactory/hparams/model_args.py 里,源码默认值是 EngineName.HF。
注意这个位置。它不在 finetuning_args.py(微调方式那一层),也不在 generating_args.py(采样参数那一层),而在模型加载参数这一层。同一个文件里挨着它的还有 use_kv_cache(默认 True)和 infer_dtype(默认 "auto")这类同样服务于推理的字段。
这个分层带来的一个直接后果是:改 infer_backend 和改 temperature 是两件互不相干的事,前者在 model_args.py,后者在 generating_args.py(那组默认值另有一篇专门讲,那里有两个数字和大多数人凭印象记的不一样)。你把后端换了,采样参数不会跟着变;反过来也一样。
还有一点从默认值直接能读出来:源码默认就是 HF 这条路。也就是说,如果你的 YAML 里压根没写 infer_backend 这一行,跑的就是 huggingface 后端。示例文件里把它显式写成 huggingface,写的是与源码默认一致的值。
怎么切:两条路径,一条环境变量
第一条路径是改 YAML,把 infer_backend 那一行的值换成四个之一。
第二条路径是命令行覆盖。README 里部署 OpenAI 风格 API 的原文命令长这样:
API_PORT=8000 llamafactory-cli api examples/inference/qwen3.yaml infer_backend=vllm vllm_enforce_eager=true
这条命令里有三个容易被略过的细节:
- 端口走
API_PORT环境变量,不是命令行参数。README 这条原文命令就是把API_PORT=8000写在命令最前面的,端口没有以选项形式出现在命令行里。 infer_backend=vllm是追加在配置文件路径后面的 key=value。也就是说 YAML 里的字段可以在命令行上被就地覆盖,不必为了试一个后端另存一份配置。- 同一条命令里还顺手覆盖了
vllm_enforce_eager=true,而这个字段在model_args.py里的默认值是False。README 的示例命令里显式把它改成了true,源码默认是False——两处口径不同,这是可核实的差异,至于为什么示例要这么写,我们不推断。
顺带一提,llamafactory-cli 有个官方短别名 lmf,写在 launcher.py 的 USAGE 提示行里:Hint: You can use lmf as a shortcut for llamafactory-cli.。八个子命令里跟推理直接相关的有三个:chat(CLI 里的对话界面)、webchat(Web UI 里的对话界面)、api(OpenAI 风格 API 服务)。这三条命令读的都是同一类推理配置。
四个后端在参数表里各占几格
比”哪个快”更能落地的一个视角是:这四个名字在 model_args.py 里各自带了多少专属字段。这是能直接数出来的:
| 后端取值 | 专属参数 | 默认值 |
|---|---|---|
huggingface | 我们读到的 model_args.py 里没有 hf_ 前缀的专属字段;同文件里的通用推理项是 use_kv_cache / infer_dtype | use_kv_cache=True、infer_dtype="auto" |
vllm | vllm_maxlen / vllm_gpu_util / vllm_enforce_eager / vllm_max_lora_rank / vllm_config | 4096 / 0.7 / False / 32 / None |
sglang | sglang_maxlen / sglang_mem_fraction / sglang_tp_size / sglang_lora_backend / sglang_config | 4096 / 0.7 / -1 / "triton" / None |
ktransformers | use_kt / kt_weight_path / kt_expert_checkpoint_path / kt_use_lora_experts / kt_lora_expert_num / kt_lora_expert_intermediate_size | False / 其余五个全是 None |
这张表能帮你少踩一类困惑:vllm_ / sglang_ / kt_ 这三组字段从命名上就各自绑定了一个后端。你在 YAML 里同时写满这三组,从字段名就能看出它们不属于同一条路——至于运行时具体怎么取用、会不会报错,源码里那段逻辑我们没有读过,不替它下结论。
vllm 与 sglang 这两列的对称性很明显——最大长度都默认 4096,显存占用比例都默认 0.7,都留了一个 *_config 的逃生口,差异只落在各自那两个不对称的字段上。这条对照我们另有一篇专门展开,这里点到为止。
ktransformers 那一列的形状不一样
上表最后一行和前两行不是一个形状。vLLM 和 SGLang 的字段里有具体数值默认(4096、0.7、32、"triton"),而 KTransformers 这一组除了开关 use_kt 默认 False 以外,其余五个字段的默认值全是 None:kt_weight_path、kt_expert_checkpoint_path、kt_use_lora_experts、kt_lora_expert_num、kt_lora_expert_intermediate_size。
从字段名能读到的就到这里:它需要你自己指定权重路径与若干专家相关的取值,源码没有替你预设。这些值该填什么、填多少,取决于你的模型和硬件,我们读到的仓库内容里没有给出通用值,也不会替官方编一个。
另有一处 kt 出现的位置值得记一笔,但它属于训练侧而不是推理侧:launcher.py 里触发分布式训练的判断条件是「命令是 train,且(FORCE_TORCHRUN 被启用,或者(检测到的设备数大于 1 且没在用 ray 且没在用 kt))」。也就是说 kt 这个条件出现在分布式启动的判断链条上。这是源码里的条件表达式,我们如实转述,不解释它为什么这么写。
一处不该顺手脑补的数字关系
model_args.py 里 vllm_max_lora_rank 默认是 32;finetuning_args.py 里 lora_rank 默认是 8。
这两个数字很容易被联系起来读,但它们分别属于两层:一个是推理后端参数,一个是微调参数。它们之间的约束关系官方在我们读到的地方没有写明,所以我们只陈述这两个默认值本身,不推断”训练时 rank 超过多少就得改另一个”。 真要确认,去看 llamafactory-cli train -h 与对应后端的实际报错,比看一篇文章可靠。
那么该选哪个:按官方给了什么倒推
这是本文唯一算得上”选型”的一节,但它的依据只有一条——官方在什么地方主动用了哪个后端、为哪个后端提供了什么。除此之外的横向比较,我们没有数据。
- 你只是想先把训完的模型拉起来对几句话:什么都不用改。源码默认就是
EngineName.HF,示例examples/inference/qwen3_lora_sft.yaml写的也是huggingface。README 的 Quickstart 三条命令里,推理那条是llamafactory-cli chat examples/inference/qwen3_lora_sft.yaml,走的就是这条默认路。 - 你要照 README 那条 API 命令部署 OpenAI 风格服务:README 原文示例里写的是
infer_backend=vllm。这是官方示例的选择,不是我们的推荐。 - 你想用 SGLang:README 的 changelog 记载 [25/03/15] 支持 SGLang 作为推理后端,用
infer_backend: sglang。changelog 只说明它在那个日期被记录为支持,不说明它今天在你的环境里是否可用、是否稳定。 - 你在看 KTransformers:先准备好上面那六个字段里你要填的那几个,因为源码没给默认值。
至于四者之间的吞吐、延迟、显存表现谁更好——这一点官方没在我们读到的 README、示例配置和 hparams/ 源码里给出任何横向数据,我们不比,也不建议你根据任何一篇没跑过基准的文章去比。
什么情况说明问题不在后端
最后补一步,这一步比前面所有内容都省时间:如果你换了 infer_backend 之后行为没变,先确认三件事,都不属于后端本身。
一是这个字段有没有真的被读到。它写在推理用的那份 YAML 里,而不是训练那份;命令行上的 key=value 覆盖如果拼错了字段名,也只是多传了一个无关键值。
二是你改的是不是采样层。输出的随机性、长度这些由 generating_args.py 那一组控制,跟后端不是一层,换后端不会让它们变。
三是对话模板对没对齐。template 需要训练侧与推理侧一致,这件事和你选哪个后端无关,我们另有一篇专门讲。
把这三项排除掉之后,再回头怀疑后端本身,会少走很多冤枉路。
本文依据 LlamaFactory 官方仓库(github.com/hiyouga/LlamaFactory)的 README、data/README.md、examples/ 下的配置与 src/llamafactory/hparams/ 的参数定义整理,核对日 2026-08-09。本文内容为仓库源码与文档口径,我们没有安装、训练或部署过任何模型,文中显存数字均为官方标注的估算值(README 原文标 * estimated)而非实测占用。参数与默认值随版本变动,请以 llamafactory-cli train -h 的实际输出为准。安全相关做法请结合自身环境评估,本文不构成安全方案建议。