项目背景
研究大语言模型时,让模型呈现出特定的对话风格很有意思。比如,借鉴热门剧集《甄嬛传》,若模型能效仿甄嬛的谈吐,那将是一种全新的体验。我们运用Lora技术对deepseek - r1 - distil - 7b模型进行了微调,目的是使其能够再现甄嬛的说话方式。随后,我们将对模型进行修改并导出为gguf格式。接着,在Ollama本地框架内执行该模型。此外,我们还将提供API接口,以便满足不同用户的个性化定制需求。
from unsloth import FastLanguageModel
# 加载预训练模型
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/llama-2-7b", # 模型名称
max_seq_length = 2048, # 最大序列长度
dtype = "float16", # 数据类型
load_in_4bit = True, # 4 位量化加载
)
# 准备数据集
train_dataset = [
{"input": "什么是机器学习?", "output": "机器学习是人工智能的一个分支,专注于通过数据训练模型。"},
{"input": "Python 的优点是什么?", "output": "Python 语法简洁、易学,拥有丰富的库和框架。"},
]
# 微调模型
model.finetune(
train_dataset = train_dataset,
learning_rate = 2e-5,
batch_size = 2,
num_epochs = 3,
)
# 保存微调后的模型
model.save_pretrained("./my_finetuned_model")
modelscope
transformers
accelerate
peft
datasets
unsloth
bitsandbytes
unsloth_zoo
requests==2.27.1
urllib3==1.25.11
bitsandbytes
unsloth_zoo
pandas
该项目支持用户在本地执行自定模型,不依赖云端,极大增强了数据保护,即便无网络也能正常操作,极具开发优势。
from unsloth import FastLanguageModel
import torch
max_seq_length = 2048 # 选择最大序列长度!unsloth自动支持 RoPE 缩放!
dtype = None # None 自动检测数据类型。对于 Tesla T4,V100 使用 Float16,对于 Ampere+ 使用 Bfloat16。
load_in_4bit = True # 使用 4bit 量化来减少内存占用。可以设置为 False。
# unsloth支持的 4bit 预量化模型,下载速度快 4x,且一般不会出现 OOM(内存不足)问题。
# 更多模型见 https://huggingface.co/unsloth
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/llama-3-8b-bnb-4bit",
max_seq_length = max_seq_length,
dtype = dtype,
load_in_4bit = load_in_4bit,
# token = "hf_...", # 如果使用像 meta-llama/Llama-2-7b-hf 这样的 gated 模型,需要提供 token
)
import os
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
环境与模型下载
配置了HF_ENDPOINT环境变量后,仍有不少用户遇到了网络难题,导致模型下载未能顺利完成。在这种情况下,您可以访问国内的魔搭社区ModelScope,查找deepseek - r1 - distil - 7b模型文件,并利用git进行本地克隆。不过,要留意的是,这些模型文件体积较大,普通的git克隆命令可能无法实现。需确认git - lfs是否已安装。如需安装其他系统,请参考Git Large File Storage的官方页面。下载完毕后,记得将model_name的值修改为模型文件夹的实际路径。若采用相对路径,开头不要使用点号。
git lfs install
sudo apt update
sudo apt install git-lfs
数据格式转换
下载的数据集或许是自己构建的,里面含有众多数据列。这些数据列必须转换成特定的格式。转换成这种格式,是为了让像GPT这样的语言模型能进行交流。合适的数据格式能让模型更精确地解读输入,从而提高训练的效率和输出的品质,为后续的精细调整工作做好铺垫。只有数据格式准确无误,模型才能准确接收训练资料,进而生成符合预期的输出效果。
model = FastLanguageModel.get_peft_model(
model,
r = 16, # 选择任何大于 0 的数字!推荐值为 8、16、32、64、128
target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",], # 指定要应用 LoRA 的模块
lora_alpha = 16, # LoRA 的 alpha 超参数,控制适应的强度
lora_dropout = 0, # 支持任何值,但设置为 0 时已优化
bias = "none", # 支持任何设置,但设置为 "none" 时已优化
# [新] "unsloth" 使用更少30%的显存,可以适应更大的批处理大小!
use_gradient_checkpointing = "unsloth", # 如果上下文非常长,设置为 True 或 "unsloth" 可以启用梯度检查点,以节省显存
random_state = 3407, # 设置随机种子
use_rslora = False, # 支持稳定化秩的 LoRA
loftq_config = None, # 以及 LoftQ
)
模型微调
[
...
{
"instruction": "小姐,别的秀女都在求中选,唯有咱们小姐想被撂牌子,菩萨一定记得真真儿的——",
"input": "",
"output": "嘘——都说许愿说破是不灵的。"
},
{
"instruction": "这个温太医啊,也是古怪,谁不知太医不得皇命不能为皇族以外的人请脉诊病,他倒好,十天半月便往咱们府里跑。",
"input": "",
"output": "你们俩话太多了,我该和温太医要一剂药,好好治治你们。"
},
{
"instruction": "嬛妹妹,刚刚我去府上请脉,听甄伯母说你来这里进香了。",
"input": "",
"output": "出来走走,也是散心。"
},
...
]
SFTTrainer是Hugging Face TRL库里的一个工具,用于监督微调训练。它能用微调数据集来训练大型语言模型。借助这个训练器,我们可以根据《甄嬛传》中甄嬛的说话特点,用Chat - 嬛嬛数据集,对deepseek - r1 - distil - 7b模型做个性化调整。通过这种方式,模型能够掌握甄嬛的说话风格,从而产出类似的语言表达。经过调整,该模型将展现出甄嬛特有的语言特点。
merged_prompt = "{instruction}[[\nYour input is:\n{input}]]"
模型格式转换
import pandas as pd
from unsloth import to_sharegpt
from unsloth import standardize_sharegpt
df = pd.read_json(data_file)
dataset = Dataset.from_pandas(df)
dataset = to_sharegpt(
dataset,
merged_prompt = "",
output_column_name = "output",
conversation_extension = 3, # Select more to handle longer conversations
)
dataset = standardize_sharegpt(dataset)
Unsloth可以将微调后的模型直接导出为GGUF格式,也就是llama.cpp格式。这样一来,使用Ollama运行模型就更加便捷了。即便训练好的模型保存成了其他格式,也不是问题,可以加载后利用llama.cpp中的转换工具进行转换。但要注意,转换过程中可能会出现错误,这通常是因为训练和模型加载没有在同一环节完成所致。训练结束后,要把Lora的权重等数据保存在文件里。然后,其他程序可以读取这个模型和权重,或者用FastLanguageModel.from_pretrained方法重新加载模型。得留心的是,如果tokenizer没使用uncloth的apply_chat_template方法,得把这个步骤再做一遍。具体操作细节,可参考GitHub上的issue。
{
"instruction": "小姐,别的秀女都在求中选,唯有咱们小姐想被撂牌子,菩萨一定记得真真儿的——",
"input": "",
"output": "嘘——都说许愿说破是不灵的。"
}
项目成果与展望
chat_template = """{SYSTEM}
USER: {INPUT}
ASSISTANT: {OUTPUT}"""
借助Unsloth工具包的高效微调功能,结合Chat - 嬛嬛数据集,我们完成了模型的定制化训练。训练完毕后,模型顺利转换为gguf格式,并在Ollama平台上流畅运行。同时,我们开发了可调用的API,简化了模型在实际应用中的微调过程。展望未来,我们计划进一步优化训练数据集,增强模型的真实度。同时,我们打算对其他模型进行细致调整。我们旨在拓宽它们的应用领域。此外,我们还将致力于打造更多具有创新性的对话风格模型。
chat_template = """<|begin_of_text|><|start_header_id|>system<|end_header_id|>
{SYSTEM}<|eot_id|><|start_header_id|>user<|end_header_id|>
{INPUT}<|eot_id|><|start_header_id|>assistant<|end_header_id|>
{OUTPUT}<|eot_id|>"""
大家觉得这个项目让模型学习甄嬛的说话方式和动作,有什么想法或者建议吗?欢迎在评论区发表意见。另外,别忘了点赞和分享这篇文章!
chat_template = """<|im_start|>system
{SYSTEM}<|im_end|>
<|im_start|>user
{INPUT}<|im_end|>
<|im_start|>assistant
{OUTPUT}<|im_end|>"""