
模型规格 | 参数量 | 推荐用途 | 显存需求(bf16 LoRA) |
|---|---|---|---|
Qwen3.5-0.8B | 8 亿 | 移动端 / 边缘设备 | 3 GB |
Qwen3.5-2B | 20 亿 | 入门微调 / 轻量应用 | 5 GB |
Qwen3.5-4B | 40 亿 | 个人开发者 / 垂直场景 | 10 GB |
Qwen3.5-9B | 90 亿 | 中小企业 / 专业应用 | 22 GB |
Qwen3.5-27B | 270 亿 | 企业级应用 | 56 GB |
Qwen3.5-35B-A3B | 350 亿(MoE) | 高性能场景 | 74 GB |
Qwen3.5-122B-A10B | 1220 亿(MoE) | 超大规模应用 | 需多卡 |
微调方式 | 显存需求 | 推荐显卡 | 精度影响 |
|---|---|---|---|
LoRA(bf16) | 10-12 GB | RTX 4070 / RTX 3090 | 精度最高 |
QLoRA(8-bit) | 6-8 GB | RTX 4060 / RTX 3070 | 轻微损失 |
QLoRA(4-bit) | 4-6 GB | RTX 3060 | 有一定损失 |
方案 | 难度 | 显存优化 | 适合人群 | 特点 |
|---|---|---|---|---|
Unsloth Studio(无代码) | ⭐ | 70% 显存节省 | 零基础用户 | Web UI 操作,全程鼠标点击 |
Unsloth + Python 代码 | ⭐⭐ | 70% 显存节省 | 有 Python 基础 | 2x 训练加速,灵活度高 |
MS-SWIFT 框架 | ⭐⭐⭐ | 支持多卡分布式 | 专业开发者 | 企业级框架,支持多卡训练 |
LLaMA-Factory | ⭐⭐ | 中等 | 有经验用户 | Web UI + 命令行,支持多种模型 |
irm https://unsloth.ai/install.ps1 | iexunsloth studio -H 0.0.0.0 -p 8888http://localhost:8888,首次登录设置密码后就能开始了。Qwen3.5conda create -n qwen35-finetune python=3.10 -yconda activate qwen35-finetunepip install unsloth unsloth_zoo torch accelerate transformers datasets peft bitsandbytes sentencepiece modelscopepip install modelscopefrom modelscope import snapshot_downloadmodel_dir = snapshot_download('Qwen/Qwen3.5-4B')print(f"模型已下载到: {model_dir}")modelscope download --model Qwen/Qwen3.5-4B --local_dir ./models/Qwen3.5-4B[ { "messages": [ {"role": "system", "content": "你是一个专业的智能财务助理。"}, {"role": "user", "content": "公司差旅费报销的上限是多少?"}, {"role": "assistant", "content": "根据公司最新财务制度,普通员工国内差旅住宿费上限为 400 元/晚..."} ] }, { "messages": [ {"role": "system", "content": "你是一个专业的智能财务助理。"}, {"role": "user", "content": "发票抬头写错了怎么办?"}, {"role": "assistant", "content": "发票抬头错误需要联系开票方重新开具,流程如下..."} ] }]import torchfrom transformers import ( AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig)from unsloth import FastLanguageModel# 方式一:使用 Unsloth 加载(推荐,更快更省显存)model, tokenizer = FastLanguageModel.from_pretrained( model_name="Qwen/Qwen3.5-4B", max_seq_length=2048, dtype=None, # 自动检测 load_in_4bit=False, # 不推荐 4-bit 训练)# 方式二:使用 transformers 加载(传统方式)bnb_config = BitsAndBytesConfig( load_in_8bit=True, llm_int8_threshold=6.0,)model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen3.5-4B", quantization_config=bnb_config, device_map="auto", trust_remote_code=True)tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3.5-4B", trust_remote_code=True)tokenizer.pad_token = tokenizer.eos_tokenfrom peft import LoraConfig, get_peft_model# LoRA 配置lora_config = LoraConfig( r=16, # 秩(rank),常用 8/16/32/64 lora_alpha=32, # alpha 参数,通常为 rank 的 2 倍 target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], # 目标模块 lora_dropout=0.05, # dropout 比例 bias="none", task_type="CAUSAL_LM")# 应用 LoRAmodel = get_peft_model(model, lora_config)model.print_trainable_parameters()参数 | 推荐值 | 说明 |
|---|---|---|
r(rank) | 16 / 32 | 秩越大,可训练参数越多,效果可能更好但显存占用更高 |
lora_alpha | rank × 2 | 缩放因子,通常设为 rank 的 2 倍 |
lora_dropout | 0.05 | 防止过拟合 |
target_modules | q_proj, k_proj, v_proj, o_proj | 注意力层的投影矩阵 |
from datasets import load_dataset# 加载本地 JSONL 数据集dataset = load_dataset("json", data_files="train.jsonl")# 数据预处理函数def format_prompts(examples): convos = examples["messages"] texts = [ tokenizer.apply_chat_template(convo, tokenize=False, add_generation_prompt=False) for convo in convos ] return {"text": texts}dataset = dataset.map(format_prompts, batched=True)from transformers import TrainingArguments, Trainerfrom unsloth import is_bfloat16_supported# 训练参数training_args = TrainingArguments( output_dir="./output", per_device_train_batch_size=2, gradient_accumulation_steps=4, warmup_steps=100, num_train_epochs=3, learning_rate=2e-4, fp16=not is_bfloat16_supported(), bf16=is_bfloat16_supported(), logging_steps=10, save_steps=500, save_total_limit=2, optim="adamw_8bit", weight_decay=0.01, lr_scheduler_type="linear", seed=3407,)# 创建 Trainertrainer = Trainer( model=model, args=training_args, train_dataset=dataset["train"], tokenizer=tokenizer,)# 开始训练trainer.train()参数 | 推荐值 | 说明 |
|---|---|---|
per_device_train_batch_size | 1-4 | 单卡批次大小,显存不足时调小 |
gradient_accumulation_steps | 4-8 | 梯度累积,等效批次 = batch_size × accumulation |
num_train_epochs | 2-5 | 训练轮数,过多易过拟合 |
learning_rate | 1e-4 ~ 5e-4 | 学习率,LoRA 微调推荐较小值 |
warmup_steps | 50-200 | 预热步数,稳定训练 |
# 保存 LoRA 适配器model.save_pretrained("./lora_adapter")tokenizer.save_pretrained("./lora_adapter")print("LoRA 适配器已保存到 ./lora_adapter")from peft import PeftModelfrom transformers import AutoModelForCausalLM, AutoTokenizer# 加载基座模型base_model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen3.5-4B", torch_dtype=torch.bfloat16, device_map="auto", trust_remote_code=True)# 加载 LoRA 适配器model = PeftModel.from_pretrained(base_model, "./lora_adapter")# 合并权重merged_model = model.merge_and_unload()# 保存合并后的模型merged_model.save_pretrained("./merged_model")tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3.5-4B")tokenizer.save_pretrained("./merged_model")# 使用 Unsloth 导出 GGUFmodel.save_pretrained_gguf( "./gguf_model", tokenizer, quantization_method="q4_k_m" # 4-bit 量化)print("GGUF 模型已保存到 ./gguf_model")from transformers import AutoModelForCausalLM, AutoTokenizerimport torch# 加载合并后的模型model = AutoModelForCausalLM.from_pretrained( "./merged_model", torch_dtype=torch.bfloat16, device_map="auto", trust_remote_code=True)tokenizer = AutoTokenizer.from_pretrained("./merged_model", trust_remote_code=True)# 构建对话messages = [ {"role": "system", "content": "你是一个专业的智能财务助理。"}, {"role": "user", "content": "公司差旅费报销的上限是多少?"}]# 应用 ChatML 模板text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)inputs = tokenizer(text, return_tensors="pt").to(model.device)# 生成回复outputs = model.generate( **inputs, max_new_tokens=512, temperature=0.7, do_sample=True, top_p=0.8)response = tokenizer.decode(outputs[0], skip_special_tokens=True)print(response)from peft import PeftModelfrom transformers import AutoModelForCausalLM, AutoTokenizer# 加载基座模型base_model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen3.5-4B", torch_dtype=torch.bfloat16, device_map="auto", trust_remote_code=True)# 加载 LoRA 适配器model = PeftModel.from_pretrained(base_model, "./lora_adapter")# 推理同上...环境准备 → 模型下载 → 数据集准备 → LoRA 配置 → 训练 → 保存适配器 → 合并模型 → 推理测试 → 部署↓ 详细步骤 ↓1. 创建 Conda 环境,安装 unsloth/transformers/peft 等依赖2. 从 ModelScope 下载 Qwen3.5-4B 模型3. 准备 JSONL 格式数据集(ChatML 对话格式)4. 配置 LoRA 参数(rank=16, alpha=32, dropout=0.05)5. 设置训练参数并启动训练6. 保存 LoRA 适配器7. 合并 LoRA 适配器与基座模型8. 测试微调效果9. 导出 GGUF 格式,用 Ollama 部署问题 | 原因 | 解决方案 |
|---|---|---|
CUDA out of memory | 显存不足 | 减小 batch_size;增加 gradient_accumulation_steps;使用 8-bit 量化 |
transformers 版本报错 | 版本不兼容 | 升级到 transformers==5.2.0 |
数据集格式错误 | JSON/JSONL 格式不正确 | 检查是否为 ChatML 格式,确保 messages 字段存在 |
训练不收敛 | 学习率过大或数据质量差 | 降低学习率(1e-4 ~ 2e-4);检查数据质量 |
模型效果差 | 数据量不足或数据质量差 | 增加数据量(至少 500-1000 条);清洗数据 |
LoRA 合并失败 | 路径错误或模型不匹配 | 确认基座模型路径正确;检查 LoRA 适配器是否完整 |
GGUF 导出失败 | unsloth 版本过低 | 升级 unsloth 到最新版本 |
4-bit 训练效果差 | Qwen3.5 不推荐 QLoRA 4-bit | 改用 bf16 LoRA 或 8-bit QLoRA |