跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

Qwen3-VL 基于 Llama-Factory 的 QLoRA 微调与部署流程 (Ollama/LMDeploy)

综述由AI生成使用 Llama-Factory 对 Qwen3-VL-2B-Instruct 模型进行 QLoRA 微调的全过程,基于 Open-EQA 具身智能数据集。内容包括环境配置、训练参数设置(4bit 量化)、训练过程监控、评估指标分析(BLEU/ROUGE)、模型融合导出,以及通过 Ollama 和 LMDeploy 进行本地推理部署的具体步骤。实验在 NVIDIA Tesla T4 显卡上完成,验证了低显存环境下多模态模型微调与部署的可行性。

云间漫步发布于 2026/4/5更新于 2026/5/2128 浏览
Qwen3-VL 基于 Llama-Factory 的 QLoRA 微调与部署流程 (Ollama/LMDeploy)

1.微调训练

有 cuda 显卡可以执行 pip install unsloth 可以安装 Unsloth 加快训练和推理。

执行 pip install tensorboard 安装保存完整训练过程的数据,避免中断只能部分曲线。

创建 saves/Qwen3-VL-2B-Instruct/qlora/train_openeqa,并创建文件 training_args.yaml,内容参考,路径根据自己的情况改:

### model
model_name_or_path: model/Qwen3-VL-2B-Instruct
trust_remote_code: true

### method
stage: sft
do_train: true
finetuning_type: lora
lora_target: all
lora_rank: 8
lora_alpha: 16
lora_dropout: 0.1

### 是否使用 unsloth 加速
use_unsloth: false
# 不启用 Unsloth 加速
#unsloth_max_seq_length: 2048 # Unsloth 内部优化
flash_attn: auto # T4 自动回退到 FA1 或 sdpa

### quantization (QLoRA)
quantization_bit: 4
quantization_method: bitsandbytes
double_quantization: true #双量化/嵌套量化,进一步节省显存

### dataset
dataset: open_eqa_train_val
template: qwen3_vl_nothink
cutoff_len: 2048
max_samples: 100000
 
 


 
 
 
  
 


  
  
  
 
 
 

 
 


 

 
 
 
 
 
 
 
 


 
 
 
 
 
  
  


  



overwrite_cache:
true
preprocessing_num_workers:
8
### output
output_dir:
saves/Qwen3-VL-2B-Instruct/qlora/train_openeqa
logging_steps:
10
save_steps:
25
resume_from_checkpoint:
false
#首次用 false,断点训练用 true
overwrite_output_dir:
true
### train
per_device_train_batch_size:
2
# 如果是用 Unsloth 省显存,可以加大
gradient_accumulation_steps:
4
# 有效 batch=8
learning_rate:
5.0e-5
# Unsloth 可以用更高 LR
num_train_epochs:
3.0
lr_scheduler_type:
cosine
warmup_ratio:
0.05
#warmup_steps: 0
fp16:
true
ddp_timeout:
180000000
### optimization
optim:
adamw_torch
# group_by_length: true
report_to:
tensorboard
plot_loss:
true
video_max_pixels:
65536
video_min_pixels:
256
freeze_multi_modal_projector:
true
freeze_vision_tower:
true
image_max_pixels:
589824
image_min_pixels:
1024
### evaluation
do_eval:
true
per_device_eval_batch_size:
2
val_size:
0.125
eval_strategy:
steps
eval_steps:
25
eval_delay:
0
# 延迟多少步开始第一次评估
prediction_loss_only:
true
# 是否需要完整预测(多模态通常需要 false 以计算准确率和生成指标,除非显存不足)
### save & eval 联动(可选但推荐)
load_best_model_at_end:
true
# 训练结束后加载最佳模型
#metric_for_best_model: eval_loss # 或 eval_accuracy 等,选择监控指标
#greater_is_better: false # eval_loss 越小越好,如果是 accuracy 则设为 true
#save_total_limit: 3 # 保留最新的 3 个检查点,避免磁盘爆满

这次训练设备配置是显存 16GB 的 NVIDIA Tesla T4,执行 llamafactory-cli train saves/Qwen3-VL-2B-Instruct/qlora/train_openeqa/training_args.yaml 开始训练。

文章配图

文章配图

若出现中断,将 resume_from_checkpoint 设置为 true 恢复中断训练继续训练:

llamafactory-cli train saves/Qwen3-VL-2B-Instruct/qlora/train_openeqa/training_args.yaml

训练结束。

文章配图

观察图片。

文章配图

文章配图

从训练和验证的损失曲线与指标来看,Qwen3-VL-2B-Instruct 在 Open-EQA 多模态小样本训练 - 验证集上的表现可以这样总结:

训练阶段表现

  • 损失变化:训练损失初始值很高(约 5.5),在训练初期(前 100 步)快速下降,之后下降速度放缓,在 200 步后稳定在 1.0~1.5 区间。
  • 最终指标:最终训练损失为 1.3233,说明模型在训练集上的拟合效果良好,且后期波动很小,收敛稳定。
  • 效率:训练总耗时约 2 小时 27 分钟,共完成 453 步,计算量达 48049026 GFLOPs,显示出多模态训练的计算成本较高。

验证阶段表现

  • 损失变化:验证损失初始值约 1.8,同样在初期快速下降,100 步后趋于平缓,后期稳定在 1.25~1.3 区间。
  • 最终指标:最终验证损失为 1.2683,略低于训练损失,这表明模型在未见过的验证数据上泛化能力较好,没有出现明显的过拟合。
  • 效率:验证集共 173 个样本,耗时约 2 分钟 10 秒,批大小为 2,验证阶段的样本处理速度比训练阶段更快。

整体表现

训练和验证的损失曲线趋势高度一致,且验证损失略低于训练损失,说明模型在训练过程中不仅对训练数据拟合充分,还具备良好的泛化能力,在 Open-EQA 多模态小样本任务上表现稳定。

如果曲线不完整,可以把云服务器的 runs 目录中 tensorboard 日志文件下载到本地电脑。

文章配图

在自己电脑的 python 环境执行 uv pip install tensorboard -i http://mirrors.aliyun.com/pypi/simple 安装 tensorboard,对于纯 python 或 conda 可以直接执行 pip install tensorboard -i http://mirrors.aliyun.com/pypi/simple 安装 tensorboard。

文章配图

执行 tensorboard --logdir=/Users/Zhuanz/Downloads --port 6006 查看,--logdir 是你的 tensorboard 日志文件文件的所在目录(不是文件),port 是端口号可自己设置。

文章配图

查看网页。

文章配图

文章配图

文章配图

2.测试评估

创建 saves/Qwen3-VL-2B-Instruct/qlora/eval_openeqa 目录,并建立 eval_args.yaml,内容如下,其中 do_predict 设置为 true 代表评估测试,注意要改适配器路径 adapter_name_or_path、基座模型路径 model_name_or_path 和是融合模型路径 output_dir。

adapter_name_or_path: saves/Qwen3-VL-2B-Instruct/qlora/train_openeqa/ #最佳 checkpoint
cutoff_len: 2048
dataset_dir: data
ddp_timeout: 180000000
do_predict: true
eval_dataset: open_eqa_test
finetuning_type: lora
flash_attn: auto
max_new_tokens: 128
max_samples: 99999
model_name_or_path: model/Qwen3-VL-2B-Instruct
output_dir: saves/Qwen3-VL-2B-Instruct/qlora/eval_openeqa
per_device_eval_batch_size: 2
predict_with_generate: true
preprocessing_num_workers: 4
report_to: none
stage: sft
temperature: 0.2
template: qwen3_vl_nothink
top_p: 1.0
trust_remote_code: true

执行 llamafactory-cli train saves/Qwen3-VL-2B-Instruct/qlora/eval_openeqa/eval_args.yaml。

文章配图

测试评估结束。

文章配图

结论:Qwen3-VL-2B-Instruct 模型经 QLoRA 轻量化微调 Open-EQA 多模态具身智能数据集后,在 NVIDIA Tesla T4(16GB 显存)硬件环境下完成了全量测试集的推理评估,本次评估共涉及 258 个测试样本,且每个样本包含 8 张关联图片的多模态输入。评估过程中模型采用批大小 2 的推理配置,全程无显存溢出等异常问题,稳定完成所有样本的预测推理,验证了 QLoRA 微调方案对 16GB 显存低算力显卡的良好适配性。从生成指标来看,模型预测 BLEU-4 值达 29.4966,ROUGE 系列指标中 ROUGE-1、ROUGE-2、ROUGE-L 分别为 36.2965、7.9106、35.7659,整体指标表现表明模型经微调后具备了一定的多图关联理解能力和与任务匹配的文本生成能力,其中 ROUGE-1 和 ROUGE-L 的较好表现体现模型能有效捕捉具身智能任务中的核心信息,ROUGE-2 偏低则反映模型在短句语义衔接的细粒度生成上仍有提升空间。从推理效率来看,本次预测全程耗时约 2 小时 55 分钟,样本处理速度为 0.025 个 / 秒、步数处理速度为 0.012 个 / 秒,推理速度整体偏低,核心受单样本 8 张图片的多模态特征提取带来的高计算量影响。整体而言,模型在 16GB 显存的 Tesla T4 显卡上成功实现了 Open-EQA 具身智能多图任务的稳定推理,并取得了具备参考性的生成效果,充分验证了本次 QLoRA 微调的实际有效性,同时也为后续通过优化图片处理策略、调整推理配置来提升模型推理速度,以及针对性优化训练策略改善细粒度生成能力提供了实际参考依据。

3.融合模型导出

创建 saves/Qwen3-VL-2B-Instruct/qlora/merge 目录,并建立 merge_openeqa.yaml,路径同样需要修改,内容如下:

### model
model_name_or_path: model/Qwen3-VL-2B-Instruct
adapter_name_or_path: saves/Qwen3-VL-2B-Instruct/qlora/train_openeqa/
template: qwen3_vl_nothink
finetuning_type: lora
trust_remote_code: true

### export
export_dir: saves/Qwen3-VL-2B-Instruct/qlora/merge
export_size: 2 #导出模型分片(shard)的单文件大小上限,单位是 GB
export_device: auto
export_legacy_format: false #true:导出 .bin(旧/legacy)false:导出 .safetensors(默认/推荐)

执行 llamafactory-cli export saves/Qwen3-VL-2B-Instruct/qlora/merge/merge_openeqa.yaml。

文章配图

4.推理部署 API 服务

(1) Ollama

将融合模型下载到本地目录,比如/saves/Qwen3-VL-2B-Instruct/qlora/merge,并进入目录,打开 Modelfile 文件,可以根据需要修改。

# ollama modelfile auto-generated by llamafactory
FROM .
TEMPLATE """{{ if .System }}<|im_start|>system {{ .System }}<|im_end|> {{ end }}{{ range .Messages }}{{ if eq .Role "user" }}<|im_start|>user {{ .Content }}<|im_end|> <|im_start|>assistant {{ else if eq .Role "assistant" }}{{ .Content }}<|im_end|> {{ end }}{{ end }}"""
# PARAMETER temperature 0.7 #可设置温度
PARAMETER stop "<|im_end|>"
PARAMETER num_ctx 4096

到终端执行创建模型的命令,模型将被转换格式并放入 ollama 的模型空间中,这里是这个 qwen3-vl-2b 是在 ollama 模型空间的模型名称,可以修改。

ollama create qwen3-vl-2b -f Modelfile

文章配图

执行 ollama list 查看 ollama 的模型列表。

文章配图

调用方法

这里只列举其中三种。

1)命令行直接传入

执行 ollama run qwen3-vl-2b "问题" 图片路径,比如

ollama run qwen3-vl-2b "墙上有什么东西" ./data/open_eqa_frames/0a0c0f2b9ba65d1b/000.jpg

文章配图

2)交互式模式

先执行 ollama run qwen3-vl-2b 加载模型,进入交互模式,然后输入问题及图片路径,比如带有斑纹的椅子上有几个枕头 ./data/open_eqa_frames/0a0c0f2b9ba65d1b/000.jpg。

文章配图

3)curl 调用

执行 IMG=$(base64 -i data/open_eqa_frames/0a0c0f2b9ba65d1b/000.jpg | tr -d '\n') 转图片为 base64 格式。

文章配图

执行命令

curl http://localhost:11434/api/generate -d '{ 
  "model": "模型名称", 
  "system": "系统提示词", 
  "prompt": "用户提示词", 
  "images": ["$图片 base64 变量"], 
  "format": "格式", 
  "stream": "是否流式输出", 
  "options": {参数设置}, 
}'

比如

curl http://localhost:11434/api/generate -d '{ "model": "qwen3-vl-2b", "system": "你是机器人控制 AI。你必须输出可执行的动作序列。scene_analysis 必须包含:目标相对于当前视角的方位(左/右/前)和距离(米)。plan 中的 params 必须使用英文键名(target/type/distance/degrees)。严禁使用中文键名。", "prompt": "观察图片,为指令\"怎么关闭台灯\"输出 JSON:\n{\n \"scene_analysis\": \"目标在 [方位],距离 [X] 米\",\n \"plan\": [\n {\"action\": \"rotate\", \"params\": {\"degrees\": 角度,\"direction\": \"left|right\"}},\n {\"action\": \"navigate\", \"params\": {\"distance\": 米数}},\n {\"action\": \"interact\", \"params\": {\"type\": \"press\", \"target\": \"台灯开关\"}}\n ]\n}", "images": ["'$IMG'"], "format": "json", "stream": false, "options": {"temperature": 0.01, "num_predict": 300} }'

回答得不错,基本符合格式,实际使用最好使用解析器处理格式。

文章配图

(2) LMDeploy

切换激活环境,执行 pip install --no-cache-dir lmdeploy 安装 LMDeploy 库。

文章配图

编写测试脚本 test_offline.py。

from lmdeploy import pipeline, TurbomindEngineConfig, PytorchEngineConfig, GenerationConfig
from lmdeploy.vl import load_image
import time

MODEL_PATH = "/workspace/LlamaFactory/saves/Qwen3-VL-2B-Instruct/qlora/merge"
IMAGE_PATH = "/workspace/LlamaFactory/data/open_eqa_frames/0a0c0f2b9ba65d1b/000.jpg"

print("🚀 使用 LMDeploy PyTorch 后端加载 Qwen3-VL...")
# ⚠️ T4 必须用 PyTorch 后端(TurboMind 不支持 Qwen3-VL)
# T4 只有 16GB,限制并发和序列长度
engine_config = PytorchEngineConfig(
    tp=1, # 单卡
    session_len=4096, # 最大序列长度(T4 显存限制)
    max_batch_size=4, # 最大批处理大小
    cache_max_entry_count=0.6, # KV Cache 占用显存比例(T4 建议 0.5-0.6)
    eager_mode=True, # T4 必须禁用 CUDA Graph
)

if __name__ == '__main__':
    #freeze_support() # 创建 pipeline(会自动检测无 Flash Attn,fallback 到 native)
    pipe = pipeline(MODEL_PATH, backend_config=engine_config)
    print("✅ 模型加载成功!")
    # 加载图片
    image = load_image(IMAGE_PATH)
    # 测试单张图片
    print("\n🎯 单图推理测试...")
    prompts = [
        ("描述这张图片", image),
    ]
    start = time.time()
    # 使用 GenerationConfig 对象而非 dict
    response = pipe(prompts, gen_config=GenerationConfig(max_new_tokens=256, temperature=0.7))
    latency = time.time() - start
    print(f"⏱️ 延迟:{latency:.2f} s")
    print(f"📝 输出:{response[0].text}")
    # 测试 batch 加速效果(LMDeploy 的核心优势)
    print("\n🎯 Batch 推理测试(4 张相同图片,体现 continuous batching)...")
    prompts_batch = [
        ("描述这张图片", image),
        ("图中有几个人?", image),
        ("这是什么场景?", image),
        ("图片主色调是什么?", image),
    ]
    start = time.time()
    responses = pipe(prompts_batch, gen_config=GenerationConfig(max_new_tokens=128))
    batch_latency = time.time() - start
    print(f"⏱️ Batch 总延迟:{batch_latency:.2f} s")
    print(f"⚡ 平均每个请求:{batch_latency/4:.2f} s")
    print("📊 throughput 提升:{:.1f}x".format(4 / (batch_latency / latency)))

文章配图

结果分析:

a. 功能层面:完美打通,输出质量优秀

  • 单图推理能精准描述图片细节(深蓝色沙发、条纹扶手椅、装饰画文字 Live, Travel, Explore、绿植 / 百叶窗等),无遗漏关键视觉信息;
  • Batch4 个不同问题的推理均能正确响应,模型对视觉问答的语义理解符合预期,多模态能力完全正常发挥;
  • 全程无报错、无 OOM(显存溢出),说明 LMDeploy 对 Qwen3-VL 的 PyTorch 后端适配完善,图片加载 / 提示构造 / 推理流程全链路通畅。

b. 单图推理性能:符合 T4+PyTorch 后端的预期

单图延迟 9.63s,这个数值在当前约束下是合理且可接受的:多模态推理的耗时主要来自视觉特征提取(Qwen3-VL 的视觉分支需要处理图片张量)+ 文本生成,而 T4 算力有限、PyTorch 后端无 TurboMind 的极致优化,2B 模型的这个延迟是中端硬件的正常表现。

c. Batch 批处理:机制生效,实现正向加速

4 个请求的 Batch 测试核心数据:

  • 总延迟:31.42s → 平均单请求延迟 7.86s(比单图的 9.63s 降低 18.4%);
  • 吞吐量提升:1.2x,验证了 LMDeploy continuous batching 的价值。

执行命令部署后台服务,

nohup lmdeploy serve api_server /workspace/LlamaFactory/saves/Qwen3-VL-2B-Instruct/qlora/merge --model-name qwen3-vl --backend pytorch --tp 1 --session-len 4096 --cache-max-entry-count 0.6 --max-batch-size 4 --eager-mode --server-port 23333 > api_server.log 2>&1 &

关键参数解析

参数作用T4 约束
--backend pytorch使用 PyTorch 后端推理必须:TurboMind(C++) 不支持 Qwen3-VL 架构,且 T4 是 SM75 架构
--tp 1张量并行数T4 只有 1 张卡,设为 1(多卡可加速但 T4 不支持 NVLink 高效通信)
--session-len 4096最大序列长度受限于 16GB 显存,4096 是安全值(过长会 OOM)
--cache-max-entry-count 0.6KV Cache 显存占比核心优化:0.6×16GB=9.6GB 给 KV Cache,剩余给模型权重 (4-5GB) 和激活值
--max-batch-size 4最大 batch sizeContinuous Batching 并发上限,T4 建议 4-8,过高会延迟增加
--eager-mode禁用 CUDA Graph 编译必须:T4 架构较旧,CUDA Graph 可能导致非法指令或内存错误
--server-port 23333API 端口默认与 OpenAI API(8080) 区分避免冲突

nohup 与重定向解析

符号含义
nohupNo Hang Up,用户退出 SSH 后进程继续运行
> api_server.log标准输出 (STDOUT) 重定向到日志文件
2>&1标准错误 (STDERR) 重定向到 STDOUT(即也进日志)
&后台运行(立即返回命令行,不阻塞)

用 curl 命令请求测试

BASE64_IMG=$(base64 -w 0 /workspace/LlamaFactory/data/open_eqa_frames/0a0c0f2b9ba65d1b/000.jpg)
curl -X POST http://localhost:23333/v1/chat/completions \
-H "Content-Type: application/json" \
-d "{ \"model\": \"qwen3-vl\", \"messages\": [{ \"role\": \"user\", \"content\": [{\"type\": \"image_url\", \"image_url\": {\"url\": \"data:image/jpeg;base64,${BASE64_IMG}\"}}, {\"type\": \"text\", \"text\": \"描述这张图片\"}] }], \"max_tokens\": 256, \"temperature\": 0.7 }"

文章配图

执行 tail -f api_server.log 查看日志。

文章配图

执行 ps aux | grep "lmdeploy serve api_server" 查看后台进程 pid。

文章配图

这说明服务正在运行,有两个进程显示是因为:

PID进程说明
12684/root/miniforge3/bin/lmdeploy serve api_server ...真正的 LMDeploy 服务(占 1.9GB 内存)
13135grep --color=auto lmdeploy serve api_server刚执行的 grep 命令本身(临时进程,已结束)

执行 kill 12684 杀死服务,注意 pid 以实际为准。

文章配图

目录

  1. 1.微调训练
  2. model
  3. method
  4. 是否使用 unsloth 加速
  5. 不启用 Unsloth 加速
  6. quantization (QLoRA)
  7. dataset
  8. output
  9. train
  10. optimization
  11. groupbylength: true
  12. evaluation
  13. save & eval 联动(可选但推荐)
  14. 2.测试评估
  15. 3.融合模型导出
  16. model
  17. export
  18. 4.推理部署 API 服务
  19. (1) Ollama
  20. ollama modelfile auto-generated by llamafactory
  21. PARAMETER temperature 0.7 #可设置温度
  22. (2) LMDeploy
  23. ⚠️ T4 必须用 PyTorch 后端(TurboMind 不支持 Qwen3-VL)
  24. T4 只有 16GB,限制并发和序列长度
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 2024 年中国 AI+ 营销趋势洞察与企业落地建议报告
  • Flutter Web 刷新后页面回退功能失效的解决方案
  • 数据结构:双向循环链表详解
  • 2026-02-24 AIGC-用vibe coding写代码
  • Qwen3-VL与ComfyUI联动实现AI绘画工作流自动标注
  • C++ 模板编程详解:从基础到元编程
  • C++11 新特性详解:Lambda、移动语义与可变参数模板
  • Ubuntu 22.04 安装 Openclaw 详细教程:配置 AI 员工与多模型接入
  • AI 时代产品经理核心技能与未来发展趋势
  • DSP 核心组件 SM 算法部署
  • Topaz Video AI 视频画质增强与修复软件安装指南
  • Flutter 组件 inappwebview_cookie_manager 适配鸿蒙 HarmonyOS 实战:Cookie 安全与跨域隔离
  • C++ STL list 容器详解:使用与模拟实现
  • C++ STL list 容器详解:使用与模拟实现
  • C++ STL 容器详解:双向链表 list 核心用法与注意事项
  • C++ 测试与调试实战:保障代码质量与稳定性
  • Llama-2-7B 昇腾 NPU 测评:性能数据、场景适配与硬件选型
  • AIGC 在现代教育技术中的应用
  • C++ STL list 容器详解:使用与模拟实现
  • 大语言模型 (LLM) 基础:原理、应用与挑战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online