DeepSeek R1微调训练

环境信息

操作系统:Ubuntu 24.04.1 LTS
模型:DeepSeek-R1-Distill-Llama-8B
训练框架:unsloth、pytorch
显卡:4090

一、准备训练数据

将自己的数据处理成prompt(输入)、completion(输出)两个字段,每条数据一行,保存成jsonl格式,如training_data.jsonl。
数据格式示例:

{"prompt": "医药和消费有什么基金推荐的","completion": "医药可以看看工银前沿的xx,她挺均衡的,对于这个行业我了解不多,你还可以看看xx指数"}
{"prompt": "请简述一下人工智能在医疗诊断中的应用及其优势。","completion": "人工智能在医疗诊断中发挥着越来越重要的作用。通过深度学习和机器学习等技术,人工智能能够辅助医生进行疾病诊断,提高诊断的准确性和效率。"}
...

二、安装环境

1、用conda创建python虚拟环境(非必要)

① conda安装:

官网地址:https://www.anaconda.com/download/success

② 执行命令:conda create unsloth python=3.11
③ 切换环境:conda activate unsloth

2、安装jupyter(非必要)

在命令行中执行:
pip install jupyterlab
jupyter lab
执行后会自动弹出浏览器,或手动打开浏览器访问:http://localhost:8888。显示页面如下:
在这里插入图片描述
点击Python 3 创建一个Notebook,后续的代码都可以在此执行。

3、安装训练环境

① 查看cuda版本,命令行输入nvidia-smi
如果提示命令不存在说明没装驱动,先装驱动去。
在这里插入图片描述

② 安装pytorch:

!pip install torch==2.5.0 torchvision==0.20.0 torchaudio==2.5.0 --index-url https://download.pytorch.org/whl/cu124

根据自己的显卡驱动选择对应cuda版本的torch包,将上面命令中的index-url地址换成适配自己的CUDA版本,比如换成11.8版CUDA换成
index-url https://download.pytorch.org/whl/cu118
③ 安装unsloth:

!pip install "unsloth[cu124-torch250] @ git+https://github.com/unslothai/unsloth.git"

三、开始训练

1、加载模型

提前下载好模型,model_name改成模型目录。可以到魔塔社区搜索模型名称,根据指示下载模型到本地。
https://modelscope.cn/models/deepseek-ai/DeepSeek-R1-Distill-Llama-8B/files
在这里插入图片描述

如果目录文件不存在,框架会尝试从huggingface下载模型,没有梯子下载不了。

from unsloth import FastLanguageModel

max_seq_length = 2048
dtype = None
load_in_4bit = True

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "../DeepSeek-R1-Distill-Llama-8B",
    max_seq_length = max_seq_length,
    dtype = dtype,
    load_in_4bit = load_in_4bit,
)

2、 加载训练数据集

其中train_prompt_style根据你的场景进行自定义,本示例中用于工单生成;
data_files='training_data.jsonl' 改成自己的数据集路径.

train_prompt_style = """以下是一条描述任务的指令,附带用于生成工单的输入参数。
撰写响应时,请严格遵守业务规范和安全协议。
在生成之前,请分析输入参数并构建一个结构化的推理过程。

### Instruction:
您是一位拥有10年以上xx行业工单管理经验的高级维护计划员。
请根据以下参数和行业标准生成工作步骤。
### Question:
{}

### Response:
{}"""
EOS_TOKEN = tokenizer.eos_token
def formatting_prompts_func(examples):
    inputs = examples["prompt"]
    outputs = examples["completion"]
    texts = []
    for input, output in zip(inputs, outputs):
        text = train_prompt_style.format(input, output) + EOS_TOKEN
        texts.append(text)
    return {
        "text": texts,
    }

from datasets import load_dataset
dataset = load_dataset('json', data_files='training_data.jsonl')
dataset = dataset['train'].map(formatting_prompts_func, batched = True,)
dataset['text'][0]

3、 构建训练参数并开始训练

model = FastLanguageModel.get_peft_model(
    model,
    r=16,
    target_modules=[
        "q_proj",
        "k_proj",
        "v_proj",
        "o_proj",
        "gate_proj",
        "up_proj",
        "down_proj",
    ],
    lora_alpha=16,
    lora_dropout=0,
    bias="none",
    use_gradient_checkpointing="unsloth",  # True or "unsloth" for very long context
    random_state=3407,
    use_rslora=False,
    loftq_config=None,
)
from trl import SFTTrainer
from transformers import TrainingArguments
from unsloth import is_bfloat16_supported

trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    dataset_text_field="text",
    max_seq_length=max_seq_length,
    dataset_num_proc=2,
    args=TrainingArguments(
        per_device_train_batch_size=2,
        gradient_accumulation_steps=4,
        # Use num_train_epochs = 1
        warmup_steps=300,
        # max_steps=60,
        learning_rate=2e-4,
        fp16=not is_bfloat16_supported(),
        bf16=is_bfloat16_supported(),
        logging_steps=10,
        optim="adamw_8bit",
        weight_decay=0.01,
        lr_scheduler_type="linear",
        seed=3407,
        output_dir="outputs",
        num_train_epochs=1,
    ),
)
trainer_stats = trainer.train()

4、 训练完成后测试效果

question = "此处改成你的提问"

FastLanguageModel.for_inference(model)
inputs = tokenizer([prompt_style.format(question, "")], return_tensors="pt").to("cuda")

outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=1200,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs)
print(response[0].split("### Response:")[1])

5、 保存训练后的模型

new_model_local = "DeepSeek-R1-xxx"
model.save_pretrained_merged(new_model_local, tokenizer, save_method = "merged_16bit",)

四、在Ollama中运行模型

① 首先安装Ollama(https://ollama.com/),步骤略。
② 接着上面的代码,如果要用Ollama运行模型,需将模型合并成gguf格式:

model.save_pretrained_gguf("DeepSeek-R1-xxx", tokenizer, quantization_method = "f16")

此时,会自动下载llama.cpp目录,如果执行报错,就打开终端手动执行命令看看什么问题,没问题后再运行上面的代码转成gguf。

cmake llama.cpp -B llama.cpp/build -DBUILD_SHARED_LIBS=OFF -DGGML_CUDA=OFF -DLLAMA_CURL=ON

转换成功后可以在DeepSeek-R1-xxx目录下看到一个unsloth.F16.gguf文件。
③ 在unsloth.F16.gguf同目录下创建ollama.modelfile文件,内容如下:

FROM unsloth.F16.gguf

TEMPLATE """{{- if .System }}{{ .System }}{{ end }}

{{- range $i, $_ := .Messages }}

{{- $last := eq (len (slice $.Messages $i)) 1}}

{{- if eq .Role "user" }}<|User|>{{ .Content }}

{{- else if eq .Role "assistant" }}<|Assistant|>{{ .Content }}{{- if not $last }}<|end▁of▁sentence|>{{- end }}

{{- end }}

{{- if and $last (ne .Role "assistant") }}<|Assistant|>{{- end }}

{{- end }}"""

PARAMETER stop <|begin▁of▁sentence|>

PARAMETER stop <|end▁of▁sentence|>

PARAMETER stop <|User|>

PARAMETER stop <|Assistant|>

④ 打开命令行,用ollama创建模型:

ollama create r1:xxx -f ollama.modelfile

成功后通过 ollama ls命令可以看到r1:xxx这个模型。
执行ollama run r1:xxx可以进行对话。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔希达

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值