DeepSeek-V4-Flash LoRA 微调与 SwanLab 可视化全流程实战(self-llm 嬛嬛对话数据集)
2026/9/12 21:04:00 网站建设 项目流程

DeepSeek-V4-Flash LoRA 微调与 SwanLab 可视化全流程实战(self-llm 嬛嬛对话数据集)

【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm

导读

本文基于 self-llm 仓库中 01-DeepSeek-V4-Flash-LoRA及SwanLab可视化记录.md 一文,完整复现并深入讲解如何使用 transformers、peft 等框架,对 DeepSeek-V4-Flash 的 BF16 权重进行 LoRA 微调,构建能够模拟甄嬛对话风格的个性化大模型。读者学完后,将掌握:DeepSeek-V4-Flash 两种权重形态(BF16 与 FP4+FP8)的选择逻辑、该模型独特投影层结构下的 LoRA target_modules 配置技巧、基于SwanLabCallback的训练可视化方法,以及训练后 LoRA 权重挂载到官方 FP4 + FP8 基础模型上的推理方案。文中所有配置均可直接复制运行,训练代码与推理代码位于 01-DeepSeek-V4-Flash-LoRA.py 与 01-DeepSeek-V4-Flash-LoRA-Inference.py。

一、任务背景:用嬛嬛数据集打造个性化对话模型

大模型微调通常指指令微调(Instruction Tuning)。微调数据的形态如下:

{ "instruction": "回答以下用户问题,仅输出答案。", "input": "1+1等于几?", "output": "2" }

其中,instruction是用户指令,告知模型需要完成的任务;input是用户输入,是完成指令所必需的输入内容;output是模型应该给出的输出。核心训练目标是让模型具备理解并遵循用户指令的能力,因此在指令集构建时,应针对目标任务针对性构建任务指令集。

本文以开源 Chat-甄嬛项目为示例,目标是构建能够模拟甄嬛对话风格的个性化 LLM,指令格式如下:

{ "instruction": "你是谁?", "input": "", "output": "家父是大理寺少卿甄远道。" }

使用的示例数据集位于 dataset/huanhuan.jsonl,共 3729 条instruction/input/output数据。数据集内容全部为甄嬛传风格的宫廷对话,例如:

{"instruction":"娘娘。","input":"","output":"你放心,本宫到任何时候都不会自轻自贱委屈了这孩子。"} {"instruction":"皇上驾到!","input":"","output":"皇上万福金安。"}

实验硬件为 8 张 NVIDIA RTX PRO 6000 Blackwell Server Edition 96GB 显卡,属于较大规模的多卡训练场景。

二、环境配置

实验所依赖的基础开发环境如下:

---------------- ubuntu 22.04 Python 3.12 cuda 13.0 pytorch 2.11.0 ----------------

默认已安装上述 PyTorch 和 CUDA 环境。首先pip换源加速下载并安装依赖包:

# 升级pip python -m pip install --upgrade pip # 更换 pypi 源加速库的安装 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip install transformers==5.12.1 # Hugging Face 的模型库,用于加载和训练模型 pip install accelerate==1.14.0 # 用于分布式训练和混合精度训练 pip install datasets==5.0.0 # 用于加载和处理数据集 pip install peft==0.19.1 # 用于 LoRA 微调 pip install swanlab==0.8.4 # 用于记录和可视化训练指标 pip install huggingface_hub # 用于从 Hugging Face 下载模型 pip install kernels==0.14.1 # 用于加载 FP4 + FP8 推理算子

各依赖的角色分工如下:

  • transformers:Hugging Face 模型库,负责模型与 tokenizer 的加载及Trainer训练循环;
  • accelerate:底层支撑device_map="auto"的多卡自动分配与混合精度训练;
  • datasets:加载jsonl数据集并完成批量预处理;
  • peft:提供LoraConfigget_peft_modelload_adapter等 LoRA 微调与挂载能力;
  • swanlab:训练指标记录与可视化;
  • kernels:加载 FP4 + FP8 推理算子,用于推理阶段的低精度权重运算。

三、模型下载:BF16 权重用于训练,FP4 + FP8 权重用于推理

DeepSeek 官方发布的deepseek-ai/DeepSeek-V4-Flash为 FP4 + FP8 混合精度权重,适合推理部署,但不能直接用于本教程的 LoRA 训练。本文训练使用社区发布的RedHatAI/DeepSeek-V4-Flash-BF16权重,推理时加载 DeepSeek 官方 FP4 + FP8 权重。这一点是本节最关键的选型决策:训练需要高精度的 BF16 全精度权重以稳定计算梯度,而官方低精度权重仅适用于前向推理。

使用huggingface_hub中的snapshot_download函数下载模型。第一个参数repo_id为模型名称,第二个参数local_dir为模型的下载路径。

/root/autodl-tmp路径下新建model_download.py文件并粘贴以下代码:

from huggingface_hub import snapshot_download model_dir = snapshot_download( repo_id="RedHatAI/DeepSeek-V4-Flash-BF16", local_dir="/root/autodl-tmp/RedHatAI/DeepSeek-V4-Flash-BF16", ) print(f"模型下载完成,保存路径为:{model_dir}")

注意将local_dir修改为实际的模型下载路径。在终端运行python /root/autodl-tmp/model_download.py执行下载,模型体积较大,下载时间较久。

推理部分使用官方 FP4 + FP8 权重,可将下载代码中的repo_idlocal_dir分别修改为:

repo_id="deepseek-ai/DeepSeek-V4-Flash" local_dir="/root/autodl-tmp/deepseek-ai/DeepSeek-V4-Flash"

磁盘空间规划需要特别注意:BF16 权重约为 532GB,官方 FP4 + FP8 权重约为 149GB。如果同时保存两份权重,建议预留不少于 700GB 的磁盘空间。AutoDL 实例的数据盘空间不足时,可以将权重放到文件存储路径,例如/root/autodl-fs/models/DeepSeek-V4-Flash-BF16

四、数据格式化:按官方 chat 模式编码并构造 labels

LoRA 训练前需要对文本进行格式化和编码。input_ids保存完整对话的 token ID,labels中的用户输入部分设为-100,训练时只计算助手回答部分的损失。

DeepSeek-V4-Flash 没有提供 Jinja 格式的chat_template。本文按照模型仓库encoding目录中的官方 chat 模式定义对话格式:

def encode_chat_text(system_prompt, user_content, assistant_content=None): text = ( "<|begin▁of▁sentence|>" f"{system_prompt}" "<|User|>" f"{user_content}" "<|Assistant|></think>" ) if assistant_content is not None: text += f"{assistant_content}<|end▁of▁sentence|>" return text

这段对话格式与常见模型的<bos><user>...<assistant>...模板不同,采用了begin▁of▁sentence/User/Assistant/think/end▁of▁sentence的专属标记结构,其中<|Assistant|></think>用于触发模型的思考-回答流程。

然后定义预处理函数process_func,对每一个样本编码其输入、输出文本并返回一个编码后的字典,方便模型使用:

def process_func(example): MAX_LENGTH = 2048 # 设置最大序列长度为 2048 个 token system_prompt = "现在你要扮演皇帝身边的女人--甄嬛。" instruction = str(example.get("instruction") or "") user_input = str(example.get("input") or "") output = str(example.get("output") or "") user_content = instruction + user_input prompt_text = encode_chat_text(system_prompt, user_content) full_text = encode_chat_text(system_prompt, user_content, output) prompt_ids = tokenizer(prompt_text, add_special_tokens=False)["input_ids"] full = tokenizer(full_text, add_special_tokens=False) input_ids = full["input_ids"] attention_mask = full.get("attention_mask", [1] * len(input_ids)) labels = [-100] * len(prompt_ids) + input_ids[len(prompt_ids):] if tokenizer.eos_token_id is not None and (not input_ids or input_ids[-1] != tokenizer.eos_token_id): input_ids.append(tokenizer.eos_token_id) attention_mask.append(1) labels.append(tokenizer.eos_token_id) if len(input_ids) > MAX_LENGTH: # 超出最大序列长度截断 input_ids = input_ids[:MAX_LENGTH] attention_mask = attention_mask[:MAX_LENGTH] labels = labels[:MAX_LENGTH] return { "input_ids": input_ids, "attention_mask": attention_mask, "labels": labels, }

该函数的处理逻辑可拆解为四步:

  1. 拼接:将instructioninput拼接为user_contentoutput为期望回答;
  2. 双份编码:分别编码「提示词」(system + user,不含回答)与「完整对话」(含回答),通过两次编码的长度差切分labels
  3. 掩码:提示词部分的labels全部置为-100,使损失只由助手回答(以及追加的 eos token)贡献;
  4. 截断:超出MAX_LENGTH = 2048的序列被截断,保证 batch 内序列长度可控。

加载数据集:

from datasets import load_dataset data_path = "../../dataset/huanhuan.jsonl" dataset = load_dataset("json", data_files=data_path, split="train")

在仓库根目录下,该数据集的真实相对路径为 dataset/huanhuan.jsonl。

五、加载模型与 tokenizer

下面加载 tokenizer 和 DeepSeek-V4-Flash 的 BF16 权重。通过dtype=torch.bfloat16指定模型精度,并使用device_map="auto"将模型自动分配到可见的 GPU:

import torch from transformers import AutoModelForCausalLM, AutoTokenizer model_path = "/root/autodl-tmp/RedHatAI/DeepSeek-V4-Flash-BF16" tokenizer = AutoTokenizer.from_pretrained( model_path, use_fast=True, trust_remote_code=True, ) if tokenizer.pad_token is None: tokenizer.pad_token = tokenizer.eos_token if tokenizer.pad_token_id is None and tokenizer.eos_token_id is not None: tokenizer.pad_token_id = tokenizer.eos_token_id tokenizer.padding_side = "right" tokenized_id = dataset.map(process_func, remove_columns=dataset.column_names) model = AutoModelForCausalLM.from_pretrained( model_path, dtype=torch.bfloat16, device_map="auto", trust_remote_code=True, low_cpu_mem_usage=True, )

此处有几点关键注意事项:

  • model_path必须填写BF16 权重路径,不要使用官方 FP4 + FP8 权重路径进行训练;
  • DeepSeek-V4-Flash 模型较大,建议使用device_map="auto"加载,避免在每张显卡上完整复制一份模型;
  • low_cpu_mem_usage=True降低 CPU 侧内存峰值;
  • tokenizer 的 pad 配置:当模型没有显式定义 pad token 时,用 eos token 兜底,并将padding_side设为"right",与训练数据拼接方向保持一致。

如果想要查看模型结构,可以打印模型:

print(model)

在 DeepSeek-V4-Flash 的 attention 模块中,可以看到与常见 LLaMA/Qwen 模型不同的投影层名称,例如q_a_projq_b_projkv_projo_a_projo_b_proj。因此本文不会使用q_projk_projv_projo_proj作为 LoRA target,这是该模型与主流开源模型微调教程最大的差异点。

六、定义 LoRA 配置:避开 grouped linear 陷阱

LoraConfig用于设置 LoRA 微调参数,本文使用的主要参数如下:

  • task_type:微调任务类型,因果语言模型使用CAUSAL_LM
  • target_modules:注入 LoRA 的模型层名称;
  • r:LoRA 的秩;
  • lora_alpha:LoRA 的缩放参数;
  • lora_dropout:LoRA 层的 Dropout 比例。

本文配置的 LoRA 缩放系数为lora_alpha / r = 2

from peft import LoraConfig, TaskType, get_peft_model config = LoraConfig( task_type=TaskType.CAUSAL_LM, target_modules=["q_a_proj", "q_b_proj", "kv_proj", "o_b_proj"], inference_mode=False, # 训练模式 r=16, # LoRA 秩 lora_alpha=32, # LoRA 缩放参数 lora_dropout=0.05 # Dropout 比例 ) model = get_peft_model(model, config) model.print_trainable_parameters()

为什么没有注入o_a_projo_a_proj在 DeepSeek-V4-Flash 中是 grouped linear 结构,PEFT 会将其按普通 Linear 处理,训练时可能触发 grouped shape mismatch。因此本文只选择q_a_projq_b_projkv_projo_b_proj四个投影层。

这一取舍在训练脚本源码中也有明确注释佐证,见 01-DeepSeek-V4-Flash-LoRA.py:

# o_a_proj is a grouped linear layer. Injecting it as a regular Linear layer # can cause a grouped-shape mismatch during the forward pass. DEFAULT_LORA_TARGETS = "q_a_proj,q_b_proj,kv_proj,o_b_proj"

本教程配置下,可训练参数量约为 46,149,632(约 4600 万),相对模型总参数量而言占比极小,这正是 LoRA 高效微调的体现。训练脚本还支持通过--lora-targets以逗号分隔字符串自定义注入层,并经由parse_targets拆分为列表(01-DeepSeek-V4-Flash-LoRA.py)。

七、自定义 TrainingArguments 训练参数

TrainingArguments用于配置训练过程,本文使用的主要参数如下:

  • output_dir:模型的输出路径;
  • per_device_train_batch_size:单次迭代的样本数;
  • gradient_accumulation_steps:梯度累积步数;
  • logging_steps:训练日志记录间隔;
  • max_steps:最大训练步数;
  • gradient_checkpointing:使用计算时间换取更低的显存占用。
from transformers import TrainingArguments args = TrainingArguments( output_dir="./output/DeepSeek-V4-Flash-LoRA", per_device_train_batch_size=1, gradient_accumulation_steps=16, logging_steps=1, max_steps=200, save_steps=100, save_total_limit=2, learning_rate=5e-5, save_on_each_node=True, bf16=True, fp16=False, gradient_checkpointing=True, gradient_checkpointing_kwargs={"use_reentrant": False}, remove_unused_columns=False, report_to=[], )

参数组合要点解析:

  • per_device_train_batch_size=1配合gradient_accumulation_steps=16,等效 batch size 为 16,既保证 DeepSeek-V4-Flash 这种大模型放得进显存,又维持足够的有效批次统计量;
  • bf16=True, fp16=False使用 BF16 混合精度训练,与模型 BF16 权重精度对齐;
  • gradient_checkpointing=True用重计算换显存,use_reentrant=False是 transformers 新版本推荐的实现方式;
  • save_total_limit=2只保留最近 2 个 checkpoint,避免 500GB 级大模型的磁盘被 checkpoint 塞满;
  • report_to=[]关闭默认的第三方报告器;若启用 SwanLab,由SwanLabCallback独立接管指标上报(详见下一节);
  • remove_unused_columns=False保留原始列,避免 data collator 因列名不匹配报错。

开启梯度检查点:

model.config.use_cache = False if hasattr(model, "enable_input_require_grads"): model.enable_input_require_grads() if hasattr(model, "gradient_checkpointing_enable"): model.gradient_checkpointing_enable(gradient_checkpointing_kwargs={"use_reentrant": False})

训练时use_cache=False关闭 KV Cache(梯度检查点与 KV Cache 不兼容),并通过enable_input_require_grads()保证输入嵌入层有梯度,否则在梯度检查点场景下可能出现"输入不可导"的错误。

八、SwanLab 可视化:从实验记录到训练指标看板

SwanLab 简介

SwanLab 是一个开源的模型训练记录工具,面向 AI 研究者,提供了训练可视化、自动日志记录、超参数记录、实验对比、多人协同等功能。在 SwanLab 上,研究者能基于直观的可视化图表发现训练问题,对比多个实验找到研究灵感,并通过在线链接的分享与基于组织的多人协同训练,打破团队沟通的壁垒。

为什么要记录训练

相较于软件开发,模型训练更像一个实验科学。一个品质优秀的模型背后,往往是成千上万次实验。研究者需要不断尝试、记录、对比,积累经验,才能找到最佳的模型结构、超参数与数据配比。在这之中,如何高效进行记录与对比,对于研究效率的提升至关重要。

实例化 SwanLabCallback

建议先在 SwanLab 官网注册账号,然后在训练初始化阶段选择(2) Use an existing SwanLab account并使用 private API Key 登录。

SwanLab 与 Transformers 已经做好了集成,用法是在 Trainer 的 callbacks 参数中添加 SwanLabCallback 实例,即可自动记录超参数和训练指标,简化代码如下:

from swanlab.integration.transformers import SwanLabCallback swanlab_callback = SwanLabCallback( project="deepseek-v4-flash", experiment_name="huanhuan-r16-a32-200step", )

训练脚本中的 SwanLab 开关设计

在完整的训练脚本 01-DeepSeek-V4-Flash-LoRA.py 中,独立训练脚本默认不启用SwanLab,只有传入--swanlab-project时才会创建SwanLabCallback;不启用时保持TrainingArguments(report_to=[])

def build_swanlab_callback(args): if not args.swanlab_project: return None from swanlab.integration.transformers import SwanLabCallback return SwanLabCallback( project=args.swanlab_project, experiment_name=args.swanlab_experiment, )

这种惰性初始化设计的好处是:训练脚本可以无缝在"纯本地记录"与"云端可视化"两种模式间切换,无需修改任何训练逻辑;callbacks列表为空时,Trainer保持默认行为。

九、使用 Trainer 训练并启动 SwanLab 记录

使用Trainer类管理训练过程。TrainingArguments用于设置训练参数,Trainer负责实际的训练逻辑:

from transformers import DataCollatorForSeq2Seq, Trainer trainer = Trainer( model=model, # 要训练的模型 args=args, # 训练参数 train_dataset=tokenized_id, # 训练数据集 data_collator=DataCollatorForSeq2Seq( tokenizer=tokenizer, padding=True, label_pad_token_id=-100, ), callbacks=[swanlab_callback], ) trainer.train() # 开始训练 trainer.save_model(args.output_dir) tokenizer.save_pretrained(args.output_dir)

DataCollatorForSeq2Seq负责将 batch 内不同长度的序列 padding 到统一长度,label_pad_token_id=-100保证 padding 部分不参与损失计算。

完整训练代码见 01-DeepSeek-V4-Flash-LoRA.py。在 8 张显卡的环境中,可以使用以下命令启动训练并开启 SwanLab 记录:

python 01-DeepSeek-V4-Flash-LoRA.py \ --swanlab-project deepseek-v4-flash \ --swanlab-experiment huanhuan-r16-a32-200step

训练脚本还通过argparse暴露了丰富的命令行参数,并支持环境变量覆盖(01-DeepSeek-V4-Flash-LoRA.py),常用的包括:

命令行参数默认值说明
--model-path/root/autodl-tmp/RedHatAI/DeepSeek-V4-Flash-BF16BF16 模型路径,可用环境变量DS_V4_MODEL_PATH覆盖
--data-path仓库内dataset/huanhuan.jsonl训练数据集路径,可用DS_V4_DATA_PATH覆盖
--output-dir./output/DeepSeek-V4-Flash-LoRA输出目录,可用DS_V4_OUTPUT_DIR覆盖
--max-length2048最大序列长度
--max-steps200最大训练步数
--learning-rate5e-5学习率
--per-device-train-batch-size1单卡 batch size
--gradient-accumulation-steps16梯度累积步数
--lora-r/--lora-alpha/--lora-dropout16/32/0.05LoRA 超参数
--lora-targetsq_a_proj,q_b_proj,kv_proj,o_b_projLoRA 注入层
--system-prompt现在你要扮演皇帝身边的女人--甄嬛。系统提示词
--expected-gpus8期望的 GPU 数量(不符时打印警告)
--num-proc数据集预处理并行进程数
--swanlab-project/--swanlab-experiment空 /huanhuan-r16-a32-200stepSwanLab 项目名与实验名

其中--data-path的默认值在源码中通过Path(__file__).resolve().parents[2] / "dataset" / "huanhuan.jsonl"自动定位(01-DeepSeek-V4-Flash-LoRA.py),即无论脚本放在哪个子目录,都能正确指回仓库根目录下的 dataset/huanhuan.jsonl。脚本启动时还会校验模型与数据路径是否存在(不存在直接抛FileNotFoundError),并打印可见 GPU 数量,便于在多卡环境中提前发现问题。

十、训练结果演示

训练完成后,打开 SwanLab 即可查看训练过程中记录的参数和训练指标,包括 loss、grad_norm、learning_rate 和 epoch 的变化,如上文配图所示。

本次实验完成 200 step,训练耗时约 74 分钟,最终train_loss为 2.605。从曲线中可以观察到:

  • train/loss从约 4.5 快速下降并收敛到 2.5~3.0 区间震荡,符合指令微调的收敛特征;
  • train/grad_norm稳定在合理范围内,未出现梯度爆炸或消失;
  • train/learning_rate从 5e-5 线性衰减至 0;
  • train/epoch在 200 step 内从 0 上升至约 0.9。

训练完成后的 LoRA 权重会保存在:

./output/DeepSeek-V4-Flash-LoRA

至此,DeepSeek-V4-Flash 的 LoRA 微调训练已完成。如果需要进一步改善效果,可以增加训练步数或根据任务构建更高质量的数据集。

十一、加载 LoRA 权重推理

得到 checkpoint 之后,加载官方 FP4 + FP8 基础模型并挂载 LoRA 权重进行推理。完整推理代码见 01-DeepSeek-V4-Flash-LoRA-Inference.py:

from transformers import AutoModelForCausalLM, AutoTokenizer import torch from peft.functional import cast_adapter_dtype model_path = "/root/autodl-tmp/deepseek-ai/DeepSeek-V4-Flash" # 官方 FP4 + FP8 基础模型路径 lora_path = "./output/DeepSeek-V4-Flash-LoRA" # 训练得到的 LoRA 权重路径,按实际填写 def encode_chat_text(system_prompt, user_content, assistant_content=None): text = ( "<|begin▁of▁sentence|>" f"{system_prompt}" "<|User|>" f"{user_content}" "<|Assistant|></think>" ) if assistant_content is not None: text += f"{assistant_content}<|end▁of▁sentence|>" return text # 加载 tokenizer tokenizer = AutoTokenizer.from_pretrained(lora_path, use_fast=True, trust_remote_code=True) if tokenizer.pad_token is None: tokenizer.pad_token = tokenizer.eos_token if tokenizer.pad_token_id is None and tokenizer.eos_token_id is not None: tokenizer.pad_token_id = tokenizer.eos_token_id # 加载官方 FP4 + FP8 基础模型 model = AutoModelForCausalLM.from_pretrained( model_path, dtype=torch.bfloat16, device_map="auto", trust_remote_code=True, low_cpu_mem_usage=True, ) # 加载 LoRA 权重,并将 adapter 权重转换为可计算的浮点精度 model.load_adapter( lora_path, adapter_name="default", low_cpu_mem_usage=True, ) cast_adapter_dtype(model, adapter_name="default") model.set_adapter("default") model.eval() # 使用 DeepSeek-V4 官方 chat 模式构造对话 text = encode_chat_text( system_prompt="现在你要扮演皇帝身边的女人--甄嬛。", user_content="你是谁?", ) inputs = tokenizer(text, return_tensors="pt").to(model.device) with torch.no_grad(): generated_ids = model.generate( **inputs, max_new_tokens=128, do_sample=False, pad_token_id=tokenizer.pad_token_id, eos_token_id=tokenizer.eos_token_id, ) output_ids = generated_ids[0][inputs["input_ids"].shape[1]:] generate_text = tokenizer.decode(output_ids, skip_special_tokens=True) generate_text = generate_text.split("<|end▁of▁sentence|>", 1)[0].strip() print(generate_text)

推理链路中值得注意的实现细节:

  1. tokenizer 从 LoRA 目录加载:推理脚本会优先从 adapter 目录读取 tokenizer(训练结束时已通过tokenizer.save_pretrained保存),仅当 adapter 目录缺少tokenizer_config.json时才回退到基础模型目录(01-DeepSeek-V4-Flash-LoRA-Inference.py);
  2. cast_adapter_dtype:将 LoRA adapter 权重转换为可计算的浮点精度,确保在 FP4 + FP8 基础模型上也能正确进行浮点运算;
  3. 加载完整性校验:脚本检查load_adapter返回的 missing / unexpected / mismatched keys,任何一项非空即抛RuntimeError,防止"权重静默加载失败但推理看似正常"的隐蔽问题(01-DeepSeek-V4-Flash-LoRA-Inference.py);
  4. 输入设备对齐:将输入显式移动到模型输入嵌入层所在设备(model.get_input_embeddings().weight.device),规避device_map="auto"下设备不一致的问题;
  5. 输出后处理:用split("<|end▁of▁sentence|>")截断可能的终止标记,skip_special_tokens=True去除特殊 token。

运行推理脚本:

python 01-DeepSeek-V4-Flash-LoRA-Inference.py \ --model-path /root/autodl-tmp/deepseek-ai/DeepSeek-V4-Flash \ --adapter-path ./output/DeepSeek-V4-Flash-LoRA

输出示例:

我是甄嬛,家父是大理寺少卿甄远道。

从输出可以看出,LoRA 权重已成功加载,模型能够按照训练数据中的人物设定回答。推理脚本同样支持--prompt--system-prompt--max-new-tokens--device-map等参数以及DS_V4_MODEL_PATHDS_V4_ADAPTER_PATH环境变量覆盖,方便批量测试不同问题。

十二、总结

本文完整走通了「BF16 权重 LoRA 微调 → SwanLab 可视化 → LoRA 挂载官方 FP4 + FP8 权重推理」的 DeepSeek-V4-Flash 个性化微调闭环,核心要点可归纳为:

  • 权重选型:训练必须使用 BF16 全精度权重(约 532GB),官方 FP4 + FP8 权重(约 149GB)仅用于推理,两者需分开下载;
  • LoRA target 取舍:DeepSeek-V4-Flash 的 attention 投影层名为q_a_projq_b_projkv_projo_b_projo_a_proj,其中o_a_proj是 grouped linear 结构,注入会导致 shape mismatch,应避开;
  • 数据编码:模型无 Jinja 版 chat_template,需按begin▁of▁sentence / User / Assistant / think / end▁of▁sentence官方格式手工拼接,并将用户侧 labels 置-100
  • 训练可视化:通过SwanLabCallbackTrainer无缝集成,一个命令行参数即可开关云端指标记录;
  • 推理挂载load_adapter+cast_adapter_dtype组合可把 LoRA 权重挂到低精度基础模型上,并以校验逻辑确保加载完整。

若希望进一步改善对话质量,可增加max_steps训练步数,或根据目标场景构建更高质量、更贴近人物语言的指令数据集。训练与推理的完整可运行代码分别位于 01-DeepSeek-V4-Flash-LoRA.py 与 01-DeepSeek-V4-Flash-LoRA-Inference.py,训练数据为 dataset/huanhuan.jsonl,可供直接复现。

【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询