miyuki2026 commited on
Commit
76d081c
·
1 Parent(s): 44f10dc
examples/tutorials/dpo/ultrafeedback-dpo-unsloth/requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ transformers
2
+ peft
3
+ torch
4
+ modelscope
5
+ datasets
6
+ trl
7
+ bitsandbytes
8
+ unsloth
examples/tutorials/dpo/{ultrafeedback-dpo → ultrafeedback-dpo-unsloth}/step_2_train_dpo_model_unsloth_ddp_qlora.py RENAMED
@@ -15,7 +15,7 @@ DPO本来就是风格微调,用LoRA 训练更合理,更科学。
15
  nohup torchrun --nproc_per_node=4 step_2_train_dpo_model_unsloth_ddp_qlora.py \
16
  --num_train_epochs 5 \
17
  --learning_rate 5e-5 \
18
- --dpo_beta 0.05 \
19
  --lora_rank 32 \
20
  &
21
 
@@ -217,6 +217,9 @@ def main():
217
  num_proc=args.num_workers,
218
  remove_columns=valid_dataset.column_names,
219
  )
 
 
 
220
 
221
  def filter_long_samples(example):
222
  # 简单估计长度,实际训练时会由tokenizer处理
@@ -230,6 +233,9 @@ def main():
230
  return True
231
  train_dataset = train_dataset.filter(filter_long_samples)
232
  valid_dataset = valid_dataset.filter(filter_long_samples)
 
 
 
233
 
234
  # 配置 DPO 训练参数
235
  dpo_config = DPOConfig(
@@ -253,13 +259,16 @@ def main():
253
  bf16=is_bfloat16_supported(), # 如果支持bfloat16则使用bf16
254
  optim="adamw_8bit", # 使用8bit优化器节省显存
255
  report_to="none",
256
- max_length=args.max_seq_length, # prompt + chosen 的大长度
257
- max_prompt_length=args.max_seq_length // 2, # prompt 的最大长度
 
258
 
259
  # DPO 特定参数
260
  beta=args.dpo_beta, # DPO 的温度参数
261
  remove_unused_columns=False,
262
  dataloader_pin_memory=False,
 
 
263
 
264
  # DDP 相关参数
265
  ddp_find_unused_parameters=False, # 重要:告诉DDP忽略未使用的参数
 
15
  nohup torchrun --nproc_per_node=4 step_2_train_dpo_model_unsloth_ddp_qlora.py \
16
  --num_train_epochs 5 \
17
  --learning_rate 5e-5 \
18
+ --dpo_beta 0.1 \
19
  --lora_rank 32 \
20
  &
21
 
 
217
  num_proc=args.num_workers,
218
  remove_columns=valid_dataset.column_names,
219
  )
220
+ if is_main_process:
221
+ print(f"train_dataset mapped count: {len(train_dataset)}")
222
+ print(f"valid_dataset mapped count: {len(valid_dataset)}")
223
 
224
  def filter_long_samples(example):
225
  # 简单估计长度,实际训练时会由tokenizer处理
 
233
  return True
234
  train_dataset = train_dataset.filter(filter_long_samples)
235
  valid_dataset = valid_dataset.filter(filter_long_samples)
236
+ if is_main_process:
237
+ print(f"train_dataset filtered count: {len(train_dataset)}")
238
+ print(f"valid_dataset filtered count: {len(valid_dataset)}")
239
 
240
  # 配置 DPO 训练参数
241
  dpo_config = DPOConfig(
 
259
  bf16=is_bfloat16_supported(), # 如果支持bfloat16则使用bf16
260
  optim="adamw_8bit", # 使用8bit优化器节省显存
261
  report_to="none",
262
+ load_best_model_at_end=True, # 训练结束时加载佳模型
263
+ metric_for_best_model="eval_rewards/margins",
264
+ greater_is_better=True, # margin 越大越好
265
 
266
  # DPO 特定参数
267
  beta=args.dpo_beta, # DPO 的温度参数
268
  remove_unused_columns=False,
269
  dataloader_pin_memory=False,
270
+ max_prompt_length=args.max_seq_length // 2, # prompt 的最大长度
271
+ max_length=args.max_seq_length, # prompt + chosen 的最大长度
272
 
273
  # DDP 相关参数
274
  ddp_find_unused_parameters=False, # 重要:告诉DDP忽略未使用的参数
examples/tutorials/dpo/ultrafeedback-dpo-unsloth/step_3_infer.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ import argparse
4
+ import os
5
+ from pathlib import Path
6
+ import platform
7
+
8
+ # os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
9
+ os.environ["UNSLOTH_USE_MODELSCOPE"] = "1"
10
+
11
+ if platform.system() in ("Windows", "Darwin"):
12
+ from project_settings import project_path, temp_directory
13
+ else:
14
+ project_path = os.path.abspath("../../../")
15
+ project_path = Path(project_path)
16
+ temp_directory = Path("/root/autodl-tmp/OpenMiniMind/temp")
17
+
18
+ from unsloth import FastLanguageModel
19
+ from transformers import TextStreamer
20
+
21
+
22
+ def get_args():
23
+ parser = argparse.ArgumentParser()
24
+ parser.add_argument(
25
+ "--model_name",
26
+ default="qgyd2021/Qwen2.5-0.5B-ultrachat-sft-deepspeed",
27
+ type=str
28
+ ),
29
+ parser.add_argument(
30
+ "--model_cache_dir",
31
+ default=(temp_directory / "hub_models").as_posix(),
32
+ type=str
33
+ ),
34
+ parser.add_argument(
35
+ "--lora_adapter_path",
36
+ default=(temp_directory / "trained_models/qwen2_5-0_5B-ultrafeedback-dpo-ddp-qlora/checkpoint-800").as_posix(),
37
+ type=str
38
+ ),
39
+ parser.add_argument(
40
+ "--max_new_tokens",
41
+ default=1024, # 8192, 128
42
+ type=int, help="最大生成长度(注意:并非模型实际长文本能力)"
43
+ ),
44
+ parser.add_argument("--top_p", default=0.85, type=float, help="nucleus采样阈值(0-1)"),
45
+ parser.add_argument("--temperature", default=0.85, type=float, help="生成温度,控制随机性(0-1,越大越随机)"),
46
+
47
+ parser.add_argument(
48
+ "--num_workers",
49
+ default=None if platform.system() == "Windows" else os.cpu_count() // 2,
50
+ type=str
51
+ ),
52
+ args = parser.parse_args()
53
+ return args
54
+
55
+
56
+ def main():
57
+ args = get_args()
58
+
59
+ os.environ["MODELSCOPE_CACHE"] = args.model_cache_dir
60
+
61
+ model, tokenizer = FastLanguageModel.from_pretrained(
62
+ model_name=args.model_name,
63
+ max_seq_length=2048, # 支持32K+长上下文
64
+ device_map="auto",
65
+ dtype=None, # 自动选择最优精度
66
+ load_in_4bit=True, # 4bit量化节省70%显存
67
+ cache_dir=args.model_cache_dir,
68
+ )
69
+
70
+ # 2、注入lora适配器
71
+ model.load_adapter(args.lora_adapter_path)
72
+
73
+ # 启用unsloth推理加速
74
+ FastLanguageModel.for_inference(model)
75
+ model.eval()
76
+
77
+ messages = [
78
+ {
79
+ "role": "user",
80
+ "content": "how can i develop a habit of drawing daily"
81
+ }
82
+ ]
83
+ format_messages = tokenizer.apply_chat_template(
84
+ messages,
85
+ tokenize=False, # 训练时部分词,true返回的是张量
86
+ add_generation_prompt=True, # 训练期间要关闭,如果是推理则设为True
87
+ )
88
+
89
+ # 4、调用tokenizer得到input
90
+ inputs = tokenizer(format_messages, return_tensors="pt").to(model.device)
91
+
92
+ # 5、调用model.generate()
93
+ generated_ids = model.generate(
94
+ **inputs,
95
+ max_new_tokens=args.max_new_tokens, do_sample=True,
96
+ streamer=TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True),
97
+ pad_token_id=tokenizer.pad_token_id, eos_token_id=tokenizer.eos_token_id,
98
+ top_p=args.top_p, temperature=args.temperature, repetition_penalty=1.0,
99
+ )
100
+
101
+ response = tokenizer.decode(generated_ids[0][len(inputs["input_ids"][0]):], skip_special_tokens=True)
102
+ print(f"response: {response}")
103
+ return
104
+
105
+
106
+ if __name__ == "__main__":
107
+ main()
examples/tutorials/dpo/ultrafeedback-dpo-unsloth/step_3_merge.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ from unsloth import FastLanguageModel
4
+ import torch
5
+
6
+ # 1. 加载原始模型(必须与训练时完全一致)
7
+ model, tokenizer = FastLanguageModel.from_pretrained(
8
+ model_name="qgyd2021/Qwen2.5-0.5B-ultrachat-sft-deepspeed", # 你的基础模型
9
+ max_seq_length=2048,
10
+ dtype=None,
11
+ load_in_4bit=True, # 加载为4bit以节省内存
12
+ )
13
+
14
+ # 2. 加载训练好的 LoRA 权重
15
+ model = FastLanguageModel.get_peft_model(
16
+ model,
17
+ r=32, # 必须与训练时的 lora_rank 一致
18
+ lora_alpha=64, # lora_rank * 2
19
+ target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
20
+ lora_dropout=0,
21
+ bias="none",
22
+ use_gradient_checkpointing="unsloth",
23
+ max_seq_length=2048,
24
+ )
25
+
26
+ # 加载训练好的 adapter 权重
27
+ model.load_adapter("你的adapter目录") # 替换为你的目录路径
28
+
29
+ # 3. 合并并保存为16位精度(推荐用于上传)
30
+ model.save_pretrained_merged(
31
+ "merged_model_16bit", # 输出目录
32
+ tokenizer,
33
+ save_method="merged_16bit", # 合并为16位
34
+ )
35
+
36
+ # 或者合并为4位量化(更小,但可能影响精度)
37
+ model.save_pretrained_merged(
38
+ "merged_model_4bit",
39
+ tokenizer,
40
+ save_method="merged_4bit",
41
+ )
42
+
43
+
44
+ if __name__ == "__main__":
45
+ pass