llama-factory实战: 基于qwen2.5-7b 手把手实战 自定义数据集清洗 微调

基于qwen2.5 手把手实战 自定义数据集 微调(llama-factory)

    • 准备工作
      • 1.数据集准备(例:民法典.txt)
      • 2.服务器准备(阿里云 DSW 白嫖)
      • 3.环境配置
        • pip 升级
        • 模型下载
        • 微调助手
      • 4.数据集处理
        • 脚本文件
        • 4.1文本分割(bert-base-chinese)
        • 4.2数据集生成
        • 4.3.1数据集转换(只有一个数据集)alpaca格式
        • 4.3.2训练集验证集划分(两个数据集)alpaca格式
      • 5.开始微调
        • 5.1配置文件修改
        • 5.2进入微调ui
        • 5.3修改参数即可训练
        • 5.4训练结果
      • 6.测试评估
      • 7.模型对话
      • 8.模型合并
      • 9.模型量化

准备工作

1.数据集准备(例:民法典.txt)

《中华人民共和国民法典 》全文免费下载 - 知乎 (zhihu.com)

自行转txt格式(约11万字)

当然你可以用我清洗了的数据集
https://modelscope.cn/datasets/Zzcc10/Civil_Code

2.服务器准备(阿里云 DSW 白嫖)

创建自己的实例(选择对应环境镜像约24g多)

https://free.aliyun.com/?spm=a2c4g.11174283.0.0.46a0527f6LNsEe&productCode=learn

3.环境配置

pip 升级
!pip install --upgrade pip 
模型下载

git 下载

!git lfs install
!git clone https://www.modelscope.cn/Qwen/Qwen2.5-7B-Instruct.git
微调助手

llama-factory

!git clone https://github.com/hiyouga/LLaMA-Factory.git
%cd LLaMA-Factory
!pip install -e .

4.数据集处理

注:若缺失部分环境pip install 安装即可,此处不在强调

脚本文件
4.1文本分割(bert-base-chinese)

bert-base-chinese 下载到本地

 git clone https://www.modelscope.cn/tiansz/bert-base-chinese.git
import torch
from transformers import BertTokenizer, BertModel
import re
import os
from scipy.spatial.distance import cosinedef get_sentence_embedding(sentence, model, tokenizer):"""获取句子的嵌入表示参数:sentence (str): 输入句子model (BertModel): 预训练的BERT模型tokenizer (BertTokenizer): BERT分词器返回:numpy.ndarray: 句子的嵌入向量"""# 使用分词器处理输入句子,并转换为模型输入格式inputs = tokenizer(sentence, return_tensors="pt", padding=True, truncation=True, max_length=512)# 使用模型获取输出,不计算梯度with torch.no_grad():outputs = model(**inputs)# 返回最后一层隐藏状态的平均值作为句子嵌入return outputs.last_hidden_state.mean(dim=1).squeeze().numpy()def split_text_by_semantic(text, max_length, similarity_threshold=0.5):"""基于语义相似度对文本进行分块参数:text (str): 输入的长文本max_length (int): 每个文本块的最大长度(以BERT分词器的token为单位)similarity_threshold (float): 语义相似度阈值,默认为0.5返回:list: 分割后的文本块列表"""# 加载BERT模型和分词器tokenizer = BertTokenizer.from_pretrained('/mnt/workspace/dataset/bert-base-chinese')model = BertModel.from_pretrained('/mnt/workspace/dataset/bert-base-chinese')model.eval()  # 设置模型为评估模式# 按句子分割文本(使用常见的中文标点符号)sentences = re.split(r'(。|!|?|;)', text)# 重新组合句子和标点sentences = [s + p for s, p in zip(sentences[::2], sentences[1::2]) if s]chunks = []current_chunk = sentences[0]# 获取当前chunk的嵌入表示current_embedding = get_sentence_embedding(current_chunk, model, tokenizer)for sentence in sentences[1:]:# 获取当前句子的嵌入表示sentence_embedding = get_sentence_embedding(sentence, model, tokenizer)# 计算当前chunk和当前句子的余弦相似度similarity = 1 - cosine(current_embedding, sentence_embedding)# 如果相似度高于阈值且合并后不超过最大长度,则合并if similarity > similarity_threshold and len(tokenizer.tokenize(current_chunk + sentence)) <= max_length:current_chunk += sentence# 更新当前chunk的嵌入表示current_embedding = (current_embedding + sentence_embedding) / 2else:# 否则,保存当前chunk并开始新的chunkchunks.append(current_chunk)current_chunk = sentencecurrent_embedding = sentence_embedding# 添加最后一个chunkif current_chunk:chunks.append(current_chunk)return chunksdef read_text_file(file_path):"""读取文本文件参数:file_path (str): 文件路径返回:str: 文件内容"""with open(file_path, 'r', encoding='utf-8') as file:return file.read()def save_chunks_to_files(chunks, output_dir):"""将分割后的文本块保存到文件参数:chunks (list): 文本块列表output_dir (str): 输出目录路径"""# 如果输出目录不存在,则创建if not os.path.exists(output_dir):os.makedirs(output_dir)# 将每个文本块保存为单独的文件for i, chunk in enumerate(chunks):chunk_file_path = os.path.join(output_dir, f"chunk_{i + 1}.txt")with open(chunk_file_path, 'w', encoding='utf-8') as file:file.write(chunk)print(f"已保存第 {i + 1} 个文本块到 {chunk_file_path}")# 主程序# 设置输入和输出路径
input_file_path = './test.txt'  # 替换为你的长文本文件路径
output_dir = './saveChunk/'  # 替换为你希望保存文本块的目录路径# 读取长文本
long_text = read_text_file(input_file_path)# 设置每个文本块的最大分词数量和相似度阈值
max_length = 2048  # 可根据需要调整
similarity_threshold = 0.5  # 可根据需要调整# 分割长文本
text_chunks = split_text_by_semantic(long_text, max_length, similarity_threshold)# 保存分割后的文本块到指定目录
save_chunks_to_files(text_chunks, output_dir)
4.2数据集生成

如何获取API-KEY_大模型服务平台百炼(Model Studio)-阿里云帮助中心 (aliyun.com)

获取api 选择所需模型即可

model=“qwen-max-latest”, # 修改自己选择的 模型

import json
import os
import time
import re
from typing import List, Dict
from openai import OpenAI
import logging
import backoff
import pyarrow as pa
import pyarrow.parquet as pq
from concurrent.futures import ThreadPoolExecutor, as_completed# 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)# 从环境变量中获取 API 密钥
api_key = "???"# 初始化 OpenAI 客户端
client = OpenAI(base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key=api_key)def read_file(file_path: str) -> str:with open(file_path, 'r', encoding='utf-8') as file:return file.read()@backoff.on_exception(backoff.expo, Exception, max_tries=3)
def generate_single_entry(text: str) -> Dict:prompt = f"""基于以下文本,生成1个用于指令数据集的高质量条目。条目应该直接关联到给定的文本内容,提出相关的问题或任务。请确保生成多样化的指令类型,例如:- 分析类:"分析..."- 比较类:"比较..."- 解释类:"解释..."- 评价类:"评价..."- 问答类:"为什么..."文本内容:{text}请以下面的格式生成条目,确保所有字段都有适当的内容:{{"instruction": "使用上述多样化的指令类型之一,提出一个具体的、与文本相关的问题或任务","input": "如果需要额外的上下文信息,请在这里提供,否则留空","output": "对instruction的详细回答或任务的完成结果"}}确保所有生成的内容都与给定的文本直接相关,生成的是有效的JSON格式,并且内容高质量、准确、详细。"""try:response = client.chat.completions.create(model="qwen-plus-0919",  # 尝试使用自己选择的 模型messages=[{"role": "user", "content": prompt}],temperature=0.7,  # 增加温度以提高多样性max_tokens=4098)logger.info(f"API 响应: {response.choices[0].message.content}")json_match = re.search(r'\{.*\}', response.choices[0].message.content, re.DOTALL)if json_match:entry = json.loads(json_match.group())required_keys = ['instruction', 'input', 'output']if isinstance(entry, dict) and all(key in entry for key in required_keys):# 根据 input 是否为空来设置 text 字段if entry['input'].strip():entry['text'] = f"Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.### Instruction: {entry['instruction']}\n### Input: {entry['input']}\n### Response: {entry['output']}"else:entry['text'] = f"Below is an instruction that describes a task. Write a response that appropriately completes the request.### Instruction: {entry['instruction']}\n### Input: {entry['input']}\n### Response: {entry['output']}"logger.info("成功生成完整条目")return entryelse:logger.warning("JSON 解析成功,但缺少必要字段")return {}else:logger.error("无法从API响应中提取有效的JSON")return {}except Exception as e:logger.error(f"生成条目时发生错误: {str(e)}")return {}def process_file(file_path: str, entries_per_file: int) -> List[Dict]:dataset = []try:text = read_file(file_path)for j in range(entries_per_file):logger.info(f"  生成第 {j + 1}/{entries_per_file} 个条目")entry = generate_single_entry(text)if entry and all(key in entry for key in ['instruction', 'input', 'output', 'text']):dataset.append(entry)logger.info(f"  成功生成 1 个完整条目")else:logger.warning(f"  跳过不完整的条目")time.sleep(2)  # 在请求之间增加延迟到2秒except Exception as e:logger.error(f"处理文件 {file_path} 时发生未知异常: {str(e)}")return datasetdef generate_dataset(folder_path: str, entries_per_file: int = 2) -> List[Dict]:dataset = []files = [os.path.join(folder_path, filename) for filename in os.listdir(folder_path) if filename.endswith(".txt")]with ThreadPoolExecutor(max_workers=4) as executor:  # 调整 max_workers 数量以适应你的硬件资源futures = [executor.submit(process_file, file_path, entries_per_file) for file_path in files]for future in as_completed(futures):try:dataset.extend(future.result())except Exception as e:logger.error(f"处理未来任务时发生未知异常: {str(e)}")return datasetdef save_dataset_as_parquet(dataset: List[Dict], output_file: str):schema = pa.schema([('instruction', pa.string()),('input', pa.string()),('output', pa.string()),('text', pa.string())])arrays = [pa.array([entry['instruction'] for entry in dataset]),pa.array([entry['input'] for entry in dataset]),pa.array([entry['output'] for entry in dataset]),pa.array([entry['text'] for entry in dataset])]table = pa.Table.from_arrays(arrays, schema=schema)pq.write_table(table, output_file)if __name__ == "__main__":input_folder = "./saveChunk"  # 指定输入文件夹路径output_file = "instruction_dataset.parquet"logger.info("开始生成数据集")dataset = generate_dataset(input_folder, entries_per_file=10)save_dataset_as_parquet(dataset, output_file)logger.info(f"数据集已生成并保存到 {output_file}")logger.info(f"共生成 {len(dataset)} 个有效条目")
4.3.1数据集转换(只有一个数据集)alpaca格式
import json
import pandas as pd
from rich import print# Load local Parquet dataset
parquet_file_path = '/mnt/workspace/dataset/instruction_dataset.parquet'
dataset = pd.read_parquet(parquet_file_path)# Print the columns of the dataset to verify
print("Dataset Columns:", dataset.columns)# Convert dataset to list of dictionaries
json_data = dataset.to_dict(orient='list')# Print the first row to verify
print("First Row:", {key: json_data[key][0] for key in json_data})# Initialize list to store Alpaca format data
alpaca_data = []# Process each entry in the dataset
for i in range(len(json_data['instruction'])):instruction = json_data['instruction'][i]input_text = json_data['input'][i]original_output = json_data['output'][i]# Create Alpaca format entryalpaca_entry = {"instruction": instruction,"input": input_text,"output": original_output}alpaca_data.append(alpaca_entry)# Save in Alpaca format
with open("alpaca_dataset.json", "w") as file:json.dump(alpaca_data, file, indent=4)print("Alpaca format dataset saved as 'alpaca_dataset.json'")
4.3.2训练集验证集划分(两个数据集)alpaca格式
import json
import pandas as pd
from rich import print
from sklearn.model_selection import train_test_split# Load local Parquet dataset
parquet_file_path = '/mnt/workspace/dataset/instruction_dataset.parquet'
dataset = pd.read_parquet(parquet_file_path)# Print the columns of the dataset to verify
print("Dataset Columns:", dataset.columns)# Convert dataset to list of dictionaries
json_data = dataset.to_dict(orient='list')# Print the first row to verify
print("First Row:", {key: json_data[key][0] for key in json_data})# Initialize lists to store Alpaca format data
alpaca_data = []# Process each entry in the dataset
for i in range(len(json_data['instruction'])):instruction = json_data['instruction'][i]input_text = json_data['input'][i]original_output = json_data['output'][i]# Create Alpaca format entryalpaca_entry = {"instruction": instruction,"input": input_text,"output": original_output}alpaca_data.append(alpaca_entry)# Split the dataset into training and testing sets (80% training, 20% testing)
train_data, test_data = train_test_split(alpaca_data, test_size=0.2, random_state=42)# Save training set in Alpaca format
with open("alpaca_train_dataset.json", "w") as file:json.dump(train_data, file, indent=4)# Save testing set in Alpaca format
with open("alpaca_test_dataset.json", "w") as file:json.dump(test_data, file, indent=4)print("Alpaca format training dataset saved as 'alpaca_train_dataset.json'")
print("Alpaca format testing dataset saved as 'alpaca_test_dataset.json'")

5.开始微调

5.1配置文件修改

LLaMA-Factory/data/dataset_info.json

LLaMA-Factory/data/dataset_info.json

同时alpaca_train_dataset.json和alpaca_test_dataset.json放入LLaMA-Factory/data/路径

  "train": {"file_name": "alpaca_train_dataset.json"},"test": {"file_name": "alpaca_test_dataset.json"},
5.2进入微调ui

需要进入对应文件夹下

%cd LLaMA-Factory
!llamafactory-cli webui

注释:若出现连接失败,尝试配置环境变量

!GRADIO_ROOT_PATH=/${JUPYTER_NAME}/proxy/7860/ \
USE_MODELSCOPE_HUB=1 \
llamafactory-cli webui
5.3修改参数即可训练

模型路径使用绝对路径即可

/mnt/workspace/Qwen2.5-7B-Instruct

注:具体调整参数需自己测试

在这里插入图片描述

5.4训练结果

在这里插入图片描述

6.测试评估

注:可能需要安装(出现错误根据提示进行修改即可)

pip install rouge-chinese

在这里插入图片描述
在这里插入图片描述

7.模型对话

chat模式加载模型

若显存不够则使用huggingface推理(vllm加载速度更快)
在这里插入图片描述

8.模型合并

合并不能进行量化操作

9.模型量化

需合并了再量化选择所需量化等级即可(24g显存可能不够)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/487963.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day08 接口测试(4)知识点完结!!

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、postman读取外部数据文件&#xff08;参数化&#xff09; 1.1 数据文件简介 1.2 导入外部数据文件 1.2.1 csv文件 1.2.2 导入 json文件 1.3 读取数据文件数据 1.4 案例 1.5 生成测试报告 2、小…

基于Springboot的实验室管理系统【附源码】

基于Springboot的实验室管理系统 效果如下&#xff1a; 系统登录页面 实验室信息页面 维修记录页面 轮播图管理页面 公告信息管理页面 知识库页面 实验课程页面 实验室预约页面 研究背景 在科研、教育等领域&#xff0c;实验室是进行实验教学和科学研究的重要场所。随着实验…

selenium学习:等待方式

隐式等待 1.针对查找元素设置最大的超时时间 2.可以全局性的设置 3.不满足时&#xff0c;提示no such element driver.implicitly_wait(5) #对查找元素最大的超时时间&#xff0c;如果超过最大等待时间后&#xff0c;没有找到元素&#xff0c;则会报错&#xff1a;no such #e…

计算生成报价单小程序系统开发方案

计算生成报价单小程序报价系统&#xff0c;是根据商品品牌、类型、型号、规格、芯数、特性、颜色、分类进行选择不同的参数进行生成报价单&#xff0c;要求报价单支持生成图片、pdf、excel表格。 计算生成报价单小程序系统的主要功能模块有&#xff1a; 1、在线生成报价单&…

constexpr、const和 #define 的比较

constexpr、const 和 #define 的比较 一、定义常量 constexpr 定义&#xff1a;constexpr用于定义在编译期可求值的常量表达式。示例&#xff1a;constexpr int x 5;这里&#xff0c;x的值在编译期就确定为5。 const 定义&#xff1a;const表示变量在运行期间不能被修改&…

Spring Boot 整合 Druid 并开启监控

文章目录 1. 引言2. 添加依赖3. 配置数据源4. 开启监控功能5. 自定义 Druid 配置&#xff08;可选&#xff09;6. 访问监控页面7. 注意事项8. 总结 Druid 是一个由阿里巴巴开源的高性能数据库连接池&#xff0c;它不仅提供了高效的连接管理功能&#xff0c;还自带了强大的监控和…

Abaqus断层扫描三维重建插件CT2Model 3D V1.1版本更新

更新说明 Abaqus AbyssFish CT2Model3D V1.1版本更新新增对TIF、TIFF图像文件格式的支持。本插件用户可免费获取升级服务。 插件介绍 插件说明&#xff1a; Abaqus基于CT断层扫描的三维重建插件CT2Model 3D 应用案例&#xff1a; ABAQUS基于CT断层扫描的细观混凝土三维重建…

word poi-tl 表格功能增强,实现表格功能垂直合并

目录 问题解决问题poi-tl介绍 功能实现引入依赖模版代码效果图 附加&#xff08;插件实现&#xff09;MergeColumnData 对象MergeGroupData 类ServerMergeTableData 数据信息ServerMergeTablePolicy 合并插件 问题 由于在开发功能需求中&#xff0c;word文档需要垂直合并表格&…

【OpenCV】平滑图像

二维卷积(图像滤波) 与一维信号一样&#xff0c;图像也可以通过各种低通滤波器&#xff08;LPF&#xff09;、高通滤波器&#xff08;HPF&#xff09;等进行过滤。LPF 有助于消除噪音、模糊图像等。HPF 滤波器有助于在图像中找到边缘。 opencv 提供了函数 **cv.filter2D()**&…

Vulhub:Log4j[漏洞复现]

CVE-2017-5645(Log4j反序列化) 启动靶场环境 docker-compose up -d 靶机IPV4地址 ifconfig | grep eth0 -A 5 ┌──(root㉿kali)-[/home/kali/Desktop/temp] └─# ifconfig | grep eth0 -A 5 eth0: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 in…

Flume基础概念

目录 作用组件构成ClientFlowAgentSourceSinkEvent 和Log4j的区别与定位事务传出流程输入到sourcesource端输入Channel 接收输入到SinkSink输出 作用 Flume可以从各种来源&#xff08;如日志文件、消息队列、网络数据、文件系统、数据库等&#xff09;收集数据&#xff0c;并将…

分布式搜索引擎之elasticsearch基本使用2

分布式搜索引擎之elasticsearch基本使用2 在分布式搜索引擎之elasticsearch基本使用1中&#xff0c;我们已经导入了大量数据到elasticsearch中&#xff0c;实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。 所以j接下来&#xff0c;我们研究下…

Spring IOCAOP

Spring介绍 个人博客原地址 Spring是一个IOC&#xff08;DI&#xff09;和AOP框架 Sprng的优良特性 非侵入式&#xff1a;基于Spring开发的应用中的对象可以不依赖于Spring的API 依赖注入&#xff1a;DI是控制反转&#xff08;IOC&#xff09;最经典的实现 面向切面编程&am…

如何高效的向AI大模型提问? - 提示工程Prompt Engineering

大模型的输入&#xff0c;决定了大模型的输出&#xff0c;所以一个符合要求的提问Prompt起到关键作用。 以下是关于提示工程Prompt Engineering主要方法的详细表格&#xff0c;包括每种方法的优点、缺点、应用场景以及具体示例&#xff1a; 主要方法优点缺点应用场景示例明确性…

Linux——linux系统移植

创建VSCode工程 1、将NXP官方的linux内核拷贝到Ubuntu 2、解压缩tar -vxjf linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2 NXP官方开发板Linux内核编译 1、将.vscode文件夹复制到NXP官网linux工程中&#xff0c;屏蔽一些不需要的文件 2、编译NXP官方EVK开发板对应的Linux系统…

【C语言】16. 内存函数

文章目录 一、 memcpy使⽤和模拟实现二、memmove使⽤和模拟实现三、memset函数的使⽤四、memcmp函数的使⽤ 一、 memcpy使⽤和模拟实现 void * memcpy ( void * destination, const void * source, size_t num );• 函数memcpy从source的位置开始向后复制num个字节的数据到des…

第六届地博会世界酒中国菜助力广州龙美地标美食公司推动地标发展

第六届知交会暨地博会&#xff1a;世界酒中国菜助力广州龙美地标美食公司推动地标产品创新发展 2024年12月9日至11日&#xff0c;第六届粤港澳大湾区知识产权交易博览会暨国际地理标志产品交易博览会在中新广州知识城盛大启幕。本届盛会吸引了全球众多知识产权领域的专业人士和…

docker安装victoriametrics(单机版)

docker安装victoriametrics 1、单机版安装2、victoriametrics增删改查2.1 、插入数据2.1.1 组装数据插入victoriametrics(java代码插入)2.1.2 Prometheus数据插入victoriametrics2.1.3 官网push到victoriametrics写法 2.2 、查询2.2.1 、Instant query&#xff08;即时查询&…

【Linux】系统信息和状态命令

步骤 1&#xff1a;显示系统信息 命令&#xff1a; uname -a 1.打开终端。 2.输入命令并按回车键。 3.观察&#xff1a;输出将显示包括内核版本、主机名、硬件架构等在内的系统信息。 步骤 2&#xff1a;显示或设置系统的主机名 命令&#xff1a; hostname 1.打开终端。…

RabbitMq死信队列延迟交换机

架构图 配置 package com.example.demo.config;import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class DeadLetterConfig {public String …