🐸 青蛙编程网
首页 / AI / 微调 LLaMA-Factory / 6. 导出与部署

6. 导出与部署

这是什么:导出(export)= 把训练好的 LoRA 补丁和基座模型揉成一个完整的模型目录;部署 = 用 vLLM 起一个 OpenAI 格式的 HTTP 服务。

为什么用:训练产物是个几十 MB 的「补丁」,推理时还得背着基座模型一起加载。合并成一个目录才能丢给 vLLM、量化工具或者别的框架随便用。

如何用:本章按「合并 → 量化 → 起服务 → 验证」四步走,最后给你一张上线检查清单。

6.1 为什么要先合并

LoRA 训完产出的是一个适配器(adapter),几十 MB 到几百 MB:

saves/qwen3-4b/lora/sft/
├── adapter_config.json
├── adapter_model.safetensors
└── ...

它本身不是模型,离开基座就没意义。合并之后得到的是一个自包含的目录:

saves/qwen3_sft_merged/
├── config.json
├── generation_config.json
├── model-00001-of-00002.safetensors
├── model-00002-of-00002.safetensors
├── model.safetensors.index.json
├── tokenizer.json
└── ...

合并的好处:推理端只需要一个目录、加载快一步、能直接给 vLLM / SGLang / Transformers 用,也方便上传到 HuggingFace 分享。

6.2 第一步:合并权重

官方示例 examples/merge_lora/qwen3_lora_sft.yaml:

### model
model_name_or_path: Qwen/Qwen3-4B-Instruct-2507
adapter_name_or_path: saves/qwen3-4b/lora/sft
template: qwen3_nothink
trust_remote_code: true

### export
export_dir: saves/qwen3_sft_merged
export_size: 5
export_device: cpu  # choices: [cpu, auto]
export_legacy_format: false

跑起来:

llamafactory-cli export examples/merge_lora/qwen3_lora_sft.yaml

你会看到(示意):

[INFO] Merging LoRA adapters to model: saves/qwen3_sft_merged
[INFO] Saving model to disk... Done.

四个导出参数的意思:

配置项 含义
export_dir 合并后模型放哪儿
export_size 每个分片文件多大(GB)。5 表示按 5GB 切;填 0 表示不切分
export_device cpu 更稳(不占显存),auto 会用 GPU 快一点
export_legacy_format 是否导出旧格式权重,保持 false 即可

⚠️ 官方明确警告:合并 LoRA 时不要用量化模型,也不要设 quantization_bit。量化底座 + LoRA 合并出来的权重会有精度损失。要量化请走 6.3 的导出流程。

6.3 第二步:导出量化版(可选)

想要一个更小的模型,可以顺手导出一份 GPTQ 4bit 版本:

### model
model_name_or_path: Qwen/Qwen3-4B-Instruct-2507
template: qwen3_nothink
trust_remote_code: true

### export
export_dir: saves/qwen3_gptq
export_quantization_bit: 4
export_quantization_dataset: data/c4_demo.jsonl
export_size: 5
export_device: cpu
export_legacy_format: false
llamafactory-cli export examples/merge_lora/qwen3_gptq.yaml

export_quantization_dataset 是量化时用来校准的语料,几百条样本就够了,仓库里的 data/c4_demo.jsonl 可以直接用。量化后体积大概是原来的四分之一。

6.4 第三步:起一个 OpenAI 兼容 API

LLaMA-Factory 自带 API 服务,后端可以选 vLLM 或 SGLang:

API_PORT=8000 llamafactory-cli api examples/inference/qwen3.yaml infer_backend=vllm vllm_enforce_eager=true

你会看到(示意):

INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000
Visit http://localhost:8000/docs for API document.

几个要点:

项目 说明
API_PORT 监听端口,默认 8000
API_HOST 监听地址,默认 0.0.0.0(所有网卡)
API_KEY 设了就必须带 Authorization: Bearer <key>,适合公网暴露时用
API_MODEL_NAME 对外报告的模型名,默认 gpt-3.5-turbo,方便兼容 OpenAI SDK 的老代码

infer_backend 的可选值是 huggingface / vllm / sglang / ktransformers,生产环境用 vllm 并发能力最好。vllm_enforce_eager=true 会关掉 CUDA Graph 加速(省显存、启动快,但吞吐略低),显存紧张时很有用。其他可调项还有 vllm_maxlen、vllm_gpu_util、vllm_max_lora_rank、vllm_config。

也可以直接用自己的配置指向合并后的模型:

model_name_or_path: saves/qwen3_sft_merged
template: qwen3_nothink
infer_backend: vllm
trust_remote_code: true

6.5 第四步:验证

浏览器打开 http://localhost:8000/docs,那是自动生成的交互式接口文档(Swagger UI)。命令行测一发:

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [{"role": "user", "content": "用一句话介绍你自己"}],
    "max_tokens": 128
  }'

你会看到(示意):

{
  "id": "chatcmpl-8f2a...",
  "object": "chat.completion",
  "model": "gpt-3.5-turbo",
  "choices": [{"index": 0, "message": {"role": "assistant", "content": "我是一个专注于回答问题的 AI 助手。"}, "finish_reason": "stop"}],
  "usage": {"prompt_tokens": 21, "completion_tokens": 24, "total_tokens": 45}
}

因为接口是 OpenAI 格式,现成的 OpenAI SDK 改个 base_url 就能直接用:

from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
resp = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "你好"}],
)
print(resp.choices[0].message.content)

你会看到(示意):

我是一个专注于回答问题的 AI 助手,可以帮你解答各类知识与生活问题。

6.6 上线检查清单

检查项 怎么确认
合并用的基座和训练时是同一个 model_name_or_path 对得上
推理的 template 和训练一致 两份 YAML 都检查一遍
合并时没用量化底座 合并配置里没有 quantization_bit
服务能扛住并发 压测一下,或换 infer_backend: vllm
公网暴露要设 API_KEY API_KEY=xxx llamafactory-cli api ...
显存够 vLLM 用 vllm_gpu_util 调小一点试试

动手改

  1. 把合并配置里的 export_device 从 cpu 改成 auto,对比耗时差别
  2. 用 llamafactory-cli export examples/merge_lora/qwen3_gptq.yaml 导一份 GPTQ 版,然后看看两个目录各有多大
  3. 给 API 加一个 API_KEY,不带 key 再 curl 一次,看看是不是真的被拦住

小结

  • LoRA 只是补丁,合并后才能当完整模型用
  • 合并配置只有四个关键项:export_dir / export_size / export_device / export_legacy_format
  • 合并时绝对不要用量化底座或 quantization_bit
  • 要量化就单独导一份:export_quantization_bit + export_quantization_dataset
  • 起服务:API_PORT=8000 llamafactory-cli api examples/inference/qwen3.yaml infer_backend=vllm,文档在 /docs
  • 环境变量 API_PORT / API_HOST / API_KEY / API_MODEL_NAME 控制监听和鉴权

全书完结

从「微调是什么」到「API 上线」,六章走完了一条完整链路:

理解原理 → 算清显存 → 备好数据 → 跑通 SFT → 偏好对齐 → 合并部署

接下来你可以做的事:把自己的业务数据按第 3 章的格式整理一份,跑一遍第 4 章的 LoRA,再用第 6 章把结果发成一个 API。提示词能解决的事就别微调,微调解决不了的事,记得先想想 RAG。

回到 教程总览 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。