LLaMA Factory:推理、LLaMA Board 与 OpenAI API
本系列第 10/17 章。第 9 章把样本送进 Trainer 并写出 checkpoint。本章说明训练完成后的三条出口:程序与终端推理、LLaMA Board,以及 OpenAI 风格 HTTP API。基线是 0.9.6.dev0 的 v0。v1 没有 api、webui、export,不能把本章命令加上 USE_V1=1 指望原样工作。
三条出口共用同一扇门:ChatModel。Board 的聊天页在 Web 进程里构造它,API 进程在启动时构造它,终端 chat 命令也构造它。真正分叉的是 infer_backend,以及 Board 训练页会不会再去拉起一条 CLI 子进程。把“界面”和“训练实现”当成两套系统,是本章最需要先拆掉的误解。
可以先用一句教科书写法记住分工:训练改变权重,推理消费权重,Board 把两者的命令拼出来,API 把推理包装成 HTTP。权重如何更新,仍然回到第 9 章的五个 dataclass 与 stage workflow;权重如何被问话,则全部经过本章的引擎门面。界面上的按钮如果看起来“也能训练、也能聊天”,只是因为它同时调用了这两条已经存在的路径。
1. 推理:一个门面,三种后端
ChatModel 先调用 get_infer_args(),再按 infer_backend 选择引擎。合法值只有三个:
| 取值 | 引擎 | 进程模型 | 打分 |
|---|---|---|---|
huggingface |
HuggingfaceEngine |
本进程 Transformers | 支持 get_scores() |
vllm |
VllmEngine |
本进程 AsyncLLMEngine |
不支持 |
sglang |
SGLangEngine |
子进程 HTTP 服务 | 不支持 |
训练 parser 拒绝非 HF 后端。因此同一字段出现在训练 YAML 与推理 YAML 中,含义并不对称:训练里写 vllm 会失败,推理里它才是合法加速路径。HF 引擎在 stage == sft 时才能生成;非 SFT 会加载 value head,此时 chat 被拒绝,只保留打分。vLLM 与 SGLang 没有这条打分路径。
门面对上提供同步与异步两套方法:chat、stream_chat、get_scores,以及对应的 a* 形式。异步方法直接 await 引擎,FastAPI 走这条路。同步方法把协程提交到后台 event loop 线程,再阻塞等待。对象没有显式 close(),后台线程随进程退出;反复新建 ChatModel 会累积 daemon 线程,服务进程应当复用单例。
三个后端的实现差异大于接口差异。HF 非流式调用 model.generate(),流式再用 TextIteratorStreamer 加生成线程。vLLM 只让 LLaMA Factory 负责模板编码,执行交给 AsyncLLMEngine;存在 adapter 时通常只取第一个做成 LoRARequest。SGLang 则拉起 sglang.launch_server 子进程,请求发到 /generate,同样只加载第一个 LoRA。HF 当前会忽略请求级 stop 字符串并打警告;vLLM 与 SGLang 支持 stop。SGLang 不支持 n > 1。不要仅凭方法签名判断多模态是否真正进入引擎:SGLang 路径发送的是 input_ids。
终端入口使用推理配置,而不是训练配置:
1 | llamafactory-cli chat examples/inference/qwen3_lora_sft.yaml |
2. Board:生成 CLI,而不是另一套 Trainer
1 | llamafactory-cli webui |
webchat 只装配聊天界面,适合已经写好推理 YAML、只想对话的场合。完整 Board 包含 Train、Evaluate & Predict、Chat、Export。默认监听地址是 0.0.0.0,可用 GRADIO_SERVER_NAME 修改;端口走 Gradio 自身默认值或 GRADIO_SERVER_PORT。GRADIO_SHARE=1 会打开 Gradio 的 share。这些都是界面进程的部署参数,不改变训练实现。
Board 的训练能力来自 Runner:把页面字段收成参数字典,再启动 llamafactory-cli train 子进程并监控日志。它是 CLI 的参数生成器与过程监视器,不是第二套 Trainer。Chat 在 Web 进程内构造 ChatModel;Export 在 Web 进程内直接调用 export_model(),要求提供 export_dir。刷新页面后的“恢复”,只是重新挂接当前 Python 进程里还活着的子进程。关掉 Web 进程再打开,并不会从磁盘自动复活一次训练;断点续训由输出目录和训练参数完成。
Evaluate & Predict 最容易与旧评测命令混淆。它仍然走训练入口,强制 stage=sft 且 predict_with_generate=true;勾选预测则 do_predict,否则 do_eval,并始终设置 eval_dataset。因此它是数据集上的生成式评估,沿用第 9 章那条 SFT workflow,不是独立评测框架。与此同时,llamafactory-cli eval 在 launcher 里直接抛出 NotImplementedError,源码注明将来弃用。这条命令不会“警告一下再继续跑”。需要指标时,用 Board 的 Evaluate,或在训练 YAML 里写 do_eval / do_predict。
Board 顶部的模型、模板、量化选项由四个 Tab 共享。量化对 LoRA/OFT 开放;Chat 页的后端同样是 huggingface|vllm|sglang。演示模式可以显示训练页,但 Runner 会拒绝真正启动任务。把 Board 理解成“给 CLI 填表”,比理解成“图形化训练框架”更接近源码。
界面内部按三层协作。interface.py 只负责装配 Tab 与事件;Engine 持有组件索引、Runner 和进程内聊天模型;Manager 把控件登记成稳定 ID,例如 train.dataset 或 infer.chat_box。新增一个输入框时,必须同时改组件注册、参数解析、恢复逻辑和文案,否则页面上看得到、启动训练时却读不到。Train 页的 extra_args 必须是 JSON 对象,并且最后覆盖 Board 生成的同名字段。它适合补齐界面没有画出的项,不适合把整份训练契约都藏进一个文本框。
HF 后端的 MAX_CONCURRENT 只是并发信号量,不会自动做 continuous batching。把它调大可能提高峰值显存,却不会变成 vLLM 的调度器。需要吞吐时,应换 infer_backend,而不是在 Board 里把并发数字调到很大还继续用 Transformers 生成。这与第 9 章“训练拒绝非 HF 后端”并不矛盾:训练要的是可反传的模块,推理要的是生成调度。
3. API:三条 OpenAI 风格路由
1 | llamafactory-cli api examples/inference/qwen3_lora_sft.yaml |
默认监听 0.0.0.0:8000,可用 API_HOST、API_PORT、API_KEY 覆盖。run_api() 自行创建 ChatModel,再交给 Uvicorn。应用启用宽松 CORS;公网部署应在反向代理收紧,不要把默认值当成安全基线。
当前只注册三条路由:
| 方法 | 路径 | 何时可用 |
|---|---|---|
GET |
/v1/models |
总是 |
POST |
/v1/chat/completions |
引擎可生成;否则 405 |
POST |
/v1/score/evaluation |
引擎不可生成,走奖励打分;否则 405 |
API_KEY 非空时,三个端点都做 HTTP Bearer 校验。/v1/models 返回的模型 ID 来自 API_MODEL_NAME,默认 gpt-3.5-turbo。这是协议里的名字,不是磁盘上的权重路径。聊天与打分互斥:SFT 生成引擎只开 completions,value-head 引擎只开 score。客户端若对生成模型调用 score,或对奖励模型调用 chat,得到的是 405,而不是“自动降级”。这是协议层用状态码表达引擎能力,不要在网关里把它改写成 200 空回复。
部署时还要分清“谁在监听、谁在算、谁在训”。Board 进程负责画界面;一旦点击训练,真正占 GPU 做反传的是它拉起的 CLI 子进程。Chat 与 API 则在当前进程里加载引擎,HF 与 vLLM 占本进程显存,SGLang 再额外占一个子服务。因此同一台机器上同时开 Board 训练、Board 聊天和 API,会叠出多份模型。正确做法是:训练时关掉聊天引擎,提供服务时只留一个 ChatModel 单例。API_KEY、监听地址和 CORS 属于访问控制,不是功能开关;功能开关仍然是 stage 与 infer_backend。把安全参数和算法参数混在一起改,排错时很难判断是鉴权拒绝还是引擎能力不足。
4. 怎样选择出口
交互试错用 chat 或 Board 的 Chat,二者都是 ChatModel。要把已有 OpenAI SDK 接过来,用 api,只依赖上述三条路径。需要改超参并启动训练,用 Board 的 Train,但要清楚最终仍是 llamafactory-cli train。需要生成式指标,用 Board Evaluate 或训练配置里的 do_eval/do_predict,不要调用已经拆除的 eval 命令。导出合并走 export 或 Board 的 Export,不要在量化模型上再合并 adapter。选出口时先问“要改权重还是只用权重”,答案会直接指向 Train 或 Chat/API。
下一章把对齐算法、多卡进程模型和 v1 边界放到同一张地图上。请继续阅读:LLaMA Factory:对齐训练、分布式与进阶能力。
正在加载留言…