Qwen2.5大模型微调记录
- LLama-facroty
- Qwen2.5 模型下载。
- huggingface 下载方式
- Modelscope 下载方式
- 数据集准备
- 模型微调
- 模型训练
- 模型验证及推理
- 模型导出
- 部署推理
- vllm 推理
- Sglang 推理
LLama-facroty
- 根据git上步骤安装即可,要求的软硬件都装上。
llama-factory - 运行llama-factory:
export GRADIO_SERVER_PORT=6006 # 可以修改端口号。 export GRADIO_SERVER_NAME=*.*.*.* # 可以修改服务地址 或者可以通过修改interface.py文件的run_web_ui()函数 llamafactory-cli webui # 运行llama-factory 运行成功可以看到一个URL,点击即可跳转到页面端
Qwen2.5 模型下载。
huggingface 下载方式
qwen2.5模型地址
huggingface地址
modelscope地址
- 安装依赖
pip install -U huggingface_hub
- 模型下载
export HF_HUB_ENABLE_HF_TRANSFER=0
export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download --resume-download --local-dir-use-symlinks False Qwen/Qwen2.5-7B-Instruct --local-dir /your_model_save_path
Modelscope 下载方式
- 安装依赖
pip install modelscope
- 使用Python脚本
from modelscope import snapshot_download
cache_directory = '/your_model_save_path'
model_dir = snapshot_download('Qwen/Qwen2.5-7B-Instruct', cache_dir=cache_directory)
执行脚本即可
数据集准备
- llama-factory 支持 alpaca 格式和 sharegpt
格式的数据集,具体要求可以看llama-factory数据集格式要求 - 我这里采用的是sharegpt格式的数据集,比如我做一个信息抽取。
[
{
"conversations": [
{
"from": "human",
"value": "(这里替换成你的prompt)"
},
{
"from": "gpt",
"value": "(这里是你的标注的输出)"
}
],
"system": "你是一个信息抽取助手。你的任务是从给定的文本中提取特定的信息,并以结构化的格式呈现。提取的信息应准确、简洁且与查询相关。",
"tools": ""
},
{
...
}
]
- 在你的数据集存放位置的同级目录下,一定要有一个dataset_info.json,这个里面是你自定义数据集的描述,可以包括你的多个数据集,供llama-factory识别。如果你采用的是sharegpt格式,dataset_info.json 格式如下。file_name字段填写你的数据路径。
{
"my_dataset1": {
"file_name": "/data/llama_factory/info_extract.json",
"formatting": "sharegpt",
"columns": {
"messages": "conversations",
"system": "system",
"tools": "tools"
},
"tags": {
"role_tag": "from",
"content_tag": "value",
"user_tag": "human",
"assistant_tag": "gpt"
}
},
"my_dataset2": {
"file_name":"/data/llama_factory/info_extract2.json",
"formatting": "sharegpt",
"columns": {
"messages": "conversations",
"system": "system",
"tools": "tools"
},
"tags": {
"role_tag": "from",
"content_tag": "value",
"user_tag": "human",
"assistant_tag": "gpt"
}
}
}
模型微调
模型训练
- 我这里选择的LORA-SFT
图中模型名称选择你微调的模型类别
模型路径填写你下载的离线模型路径。
微调方法选择 lora
训练阶段 设置train 里面参数即可。
训练方式选择SFT
数据路径选择你数据集路径,选择之后,在数据集里面就可以选择你训练的数据集了。
其它参数根据自己需求和资源进行调整。
微调的时候 检查点路径不填写
点击开始训练,模型就开始训练,可以观察损失变化。
模型的输出目录在你的 llama-factory 项目下的saves文件夹中。
模型验证及推理
模型验证 - 点击evaluate&predict。
首先在 检查点路径选择你保存的某个checkpoint
然后添加你的验证集路径,选择验证集,点击开始。
到输出目录即可查看结果。
模型推理 - 点击chat。
首先在 检查点路径选择你保存的某个checkpoint。
然后选择推理引擎、数据类型,点击加载模型即可对话。
模型导出
模型导出-点击export
选择你验证过的最好的checkpoint.
设置相应的参数,
导出量化模型,需要填写一个量化数据集路径(验证集)。
导出设备如果是GPU 选择auto
导出的模型是已经merge后的模型。直接加载使用即可。
部署推理
vllm 推理
from transformers import AutoTokenizer
from vllm import LLM, SamplingParams
class VLLMInfer:
def __init__(self, model_path):
self.model_path = model_path
self.llm, self.tokenizer = self.vllm_load_model()
def vllm_load_model(self):
tokenizer = AutoTokenizer.from_pretrained(self.model_path)
llm = LLM(model=model_path,
gpu_memory_utilization=0.9,
trust_remote_code=True,
tensor_parallel_size=2 # GPU数量
)
return llm, tokenizer
# 批次
def inference(self, prompts, system):
texts = []
for prompt in prompts:
messages = [
{"role": "system", "content": system},
{"role": "user", "content": prompt}
]
text = self.tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
texts.append(text)
sampling_params = SamplingParams(temperature=0.1,
top_p=0.7,
repetition_penalty=1.0,
max_tokens=200,
)
outputs = self.llm.generate(texts, sampling_params)
result_list = []
for output in outputs:
generated_text = output.outputs[0].text
result_list.append(generated_text.replace("\n", "").replace("<|im_end|>", '').replace("json", ""))
return result_list
if __name__ == '__main__':
model_path = "your_model_path"
qwen_chat = VLLMInfer(model_path)
system = "你是一个智能的助手."
test_texts = ['', '']
result = qwen_chat.inference(test_texts, system)
print(result)
Sglang 推理
from transformers import AutoTokenizer
import sglang as sgl
import time
class SgLangInfer:
def __init__(self, model_path):
self.model_path = model_path
self.llm, self.tokenizer = self.load_model()
def load_model(self):
tokenizer = AutoTokenizer.from_pretrained(
self.model_path,
trust_remote_code=True,
clean_up_tokenization_spaces=False
)
llm = sgl.Engine(
model_path=self.model_path,
mem_fraction_static=0.85,
tp_size=2,
max_total_tokens=9000,
enable_p2p_check=True # 解决4090 p2p之间通信传输问题
)
return llm, tokenizer
def inference(self, prompts, system):
texts = []
for prompt in prompts:
messages = [
{"role": "system", "content": system},
{"role": "user", "content": prompt}
]
text = self.tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
texts.append(text)
sampling_params = {"temperature": 0,
"top_p": 1,
"repetition_penalty": 1.0,
"max_new_tokens": 200}
result_list = []
response = self.llm.generate(texts, sampling_params)
# print(f"response:{response}")
for res in response:
result_list.append(res['text'])
return result_list