已合并
add inference and llm model #36755
bigprestigee1创建于 5月26日
add inference and llm model #36755
已合并
bigprestigee1创建于 5月26日
共 23 个文件变更+3595-0
@@ -0,0 +1,22 @@
1+--- CTR_Algorithm/pytorch/model/DCNv2.py 2026-03-31 11:09:49.207077300 +0800
2++++ dcn/CTR_Algorithm/pytorch/model/DCNv2.py 2026-03-31 11:12:56.799077300 +0800
3+@@ -120,7 +120,8 @@
4+ """
5+ super(DeepCrossNetv2, self).__init__()
6+ self.feature_fields = feature_fields
7+- self.offsets = np.array((0, *np.cumsum(feature_fields)[:-1]), dtype = np.long)
8++ self.offsets = np.array((0, *np.cumsum(feature_fields)[:-1]), dtype = np.int64)
9++ self.register_buffer("offsets_tensor", torch.as_tensor(self.offsets, dtype=torch.int64))
10+ self.model_method = model_method
11+
12+ # Embedding layer
13+@@ -157,7 +158,7 @@
14+ raise NotImplementedError
15+
16+ def forward(self, x):
17+- tmp = x + x.new_tensor(self.offsets).unsqueeze(0)
18++ tmp = x + self.offsets_tensor.unsqueeze(0)
19+
20+ # embeded dense vector
21+ embeded_x = self.embedding(tmp).view(-1, self.embedding_out_dim)
22+
@@ -0,0 +1,205 @@
1+# -*- coding: utf-8 -*-
2+import os
3+import pandas as pd
4+import numpy as np
5+import torch
6+import torch.nn as nn
7+import torch.optim as optim
8+import torch.utils.data as Data
9+import torch.nn.functional as F
10+from sklearn.preprocessing import LabelEncoder
11+from sklearn.model_selection import train_test_split
12+import sys
13+import time
14+import argparse
15+ 
16+from CTR_Algorithm.data.AmazonDataPreprocess import AmazonBookPreprocess
17+ 
18+MODEL_NAME='DCNV2'
19+ 
20+data = pd.read_csv('CTR_Algorithm/data/data.csv')
21+data_X = data.iloc[:,2:]
22+data_y = data.click.values
23+ 
24+data_X = data_X.apply(LabelEncoder().fit_transform)
25+ 
26+fields = data_X.max().values + 1
27+ 
28+# data_X = data.iloc[:,:-1]
29+# data_y = data.label.values
30+ 
31+tmp_X, test_X, tmp_y, test_y = train_test_split(data_X, data_y, test_size = 0.2, random_state=42, stratify=data_y)
32+train_X, val_X, train_y, val_y = train_test_split(tmp_X, tmp_y, test_size = 0.25, random_state=42, stratify=tmp_y)
33+ 
34+train_X = torch.from_numpy(train_X.values).long()
35+val_X = torch.from_numpy(val_X.values).long()
36+test_X = torch.from_numpy(test_X.values).long()
37+ 
38+train_y = torch.from_numpy(train_y).long()
39+val_y = torch.from_numpy(val_y).long()
40+test_y = torch.from_numpy(test_y).long()
41+ 
42+train_set = Data.TensorDataset(train_X, train_y)
43+val_set = Data.TensorDataset(val_X, val_y)
44+train_loader = Data.DataLoader(dataset=train_set,
45+ batch_size=32,
46+ shuffle=True)
47+val_loader = Data.DataLoader(dataset=val_set,
48+ batch_size=32,
49+ shuffle=False)
50+ 
51+ 
52+def detect_device_type():
53+ try:
54+ import torch
55+ if torch.cuda.is_available():
56+ return "cuda"
57+ try:
58+ import torch_npu
59+ import os
60+ os.environ['TORCHINDUCTOR_NPU_BACKEND'] = 'mlir'
61+ if torch.npu.is_available():
62+ return "npu"
63+ except ImportError:
64+ pass
65+ except ImportError:
66+ pass
67+ return "cpu"
68+ 
69+ 
70+def get_profile(profiler_start_step: int, profiler_end_step: int, profiling_save_path: str):
71+ warm_step = profiler_start_step
72+ active_step = profiler_end_step - warm_step +1
73+ print(f"[Profile INFO]: warm_step: {warm_step}, active_step: {active_step}, profiling_save_path: {profiling_save_path}")
74+ device = detect_device_type()
75+ if device == 'npu':
76+ import torch_npu
77+ g_prof_config = torch_npu.profiler._ExperimentalConfig(
78+ export_type=[
79+ torch_npu.profiler.ExportType.Text,
80+ torch_npu.profiler.ExportType.Db
81+ ],
82+ profiler_level=torch_npu.profiler.ProfilerLevel.Level2,
83+ msprof_tx=False,
84+ aic_metrics=torch_npu.profiler.AiCMetrics.AiCoreNone,
85+ l2_cache=False,
86+ op_attr=False,
87+ data_simplification=False,
88+ record_op_args=False,
89+ gc_detect_threshold=None)
90+ 
91+ return torch_npu.profiler.profile(
92+ activities=[
93+ torch_npu.profiler.ProfilerActivity.CPU,
94+ torch_npu.profiler.ProfilerActivity.NPU],
95+ schedule=torch_npu.profiler.schedule(wait=0, warmup=warm_step, active=active_step, repeat=1),
96+ on_trace_ready=torch_npu.profiler.tensorboard_trace_handler(profiling_save_path),
97+ record_shapes=False,
98+ profile_memory=False,
99+ with_stack=False,
100+ with_modules=False,
101+ with_flops=False,
102+ experimental_config=g_prof_config)
103+ elif device == 'cuda':
104+ from torch.profiler import profile, schedule, tensorboard_trace_handler, ProfilerActivity
105+ return profile(
106+ activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
107+ schedule=schedule(wait=0, warmup=warm_step, active=active_step, repeat=1),
108+ on_trace_ready=tensorboard_trace_handler(profiling_save_path),
109+ record_shapes=False,
110+ profile_memory=False,
111+ )
112+ else:
113+ print(f"[Warning]: No supported acceleration device (CUDA/NPU) detected, profiler will be disabled")
114+ return None
115+ 
116+def detect_device_type():
117+ try:
118+ import torch
119+ if torch.cuda.is_available():
120+ return "cuda"
121+ try:
122+ import torch_npu
123+ import os
124+ os.environ['TORCHINDUCTOR_NPU_BACKEND'] = 'mlir'
125+ if torch.npu.is_available():
126+ return "npu"
127+ except ImportError:
128+ pass
129+ except ImportError:
130+ pass
131+ return "cpu"
132+ 
133+def device_synchronize():
134+ if torch.cuda.is_available():
135+ torch.cuda.synchronize()
136+ elif torch.npu.is_available():
137+ torch.npu.synchronize()
138+ 
139+def eval_op_prof(model: nn.Module, device, mod, args):
140+ dl = iter(val_loader)
141+ x, _ = next(dl)
142+ x = x.to(device)
143+ pt_path= MODEL_NAME +'_'+ mod + '_result.pt'
144+ 
145+ model.eval()
146+ with torch.no_grad():
147+ res = model(x)
148+ torch.save(res, pt_path)
149+ device_synchronize()
150+ 
151+ prof = None
152+ if args.enable_profiler:
153+ profiling_save_path = args.profiler_save_path + '/' + MODEL_NAME + '/' + mod
154+ prof = get_profile(args.profiler_start_step, args.profiler_end_step, profiling_save_path)
155+ prof.start()
156+ 
157+ execution_times = []
158+ with torch.no_grad():
159+ for i in range(args.max_steps):
160+ start_time = time.time()
161+ model(x)
162+ device_synchronize()
163+ end_time = time.time()
164+ step_time_ms = (end_time - start_time) * 1000
165+ print(f"[{mod}]: Step {i}: {step_time_ms:.4f} ms")
166+ 
167+ if i >= 10:
168+ execution_times.append(step_time_ms)
169+ 
170+ if args.enable_profiler:
171+ prof.step()
172+ 
173+ if args.enable_profiler:
174+ prof.stop()
175+ if execution_times:
176+ avg_ms = sum(execution_times) / len(execution_times)
177+ print(f"[{mod}]:: Avg over {len(execution_times)} steps: {avg_ms:.4f} ms")
178+ 
179+parser = argparse.ArgumentParser(description=MODEL_NAME + " infernece")
180+parser.add_argument("--max_steps", type=int, default=200,
181+ help="Total training steps")
182+parser.add_argument("--enable_compile", action="store_true",
183+ help="Enable torch.compile and Inductor backend")
184+parser.add_argument("--enable_profiler", action="store_true",
185+ help="Enable profiler for performance analysis")
186+parser.add_argument("--profiler_start_step", type=int, default=5,
187+ help="Output directory for trained model")
188+parser.add_argument("--profiler_end_step", type=int, default=8,
189+ help="Output directory for trained model")
190+parser.add_argument("--profiler_save_path", type=str, default="./profile",
191+ help="Output directory for trained model")
192+args = parser.parse_args()
193+ 
194+from CTR_Algorithm.pytorch.model.DCNv2 import DeepCrossNetv2
195+model = DeepCrossNetv2(feature_fields = fields, embed_dim = 16, layer_num = 2, mlp_dims = (32, 16), dropout = 0.1, cross_method='Matrix')
196+ 
197+device_type = detect_device_type()
198+device = torch.device(device_type)
199+model.to(device)
200+mod = 'eager'
201+if args.enable_compile:
202+ model = torch.compile(model, dynamic=False)
203+ mod = 'compile'
204+print(f"{MODEL_NAME} inference begin, mode is {mod}")
205+eval_op_prof(model, device, mod, args)
@@ -0,0 +1,176 @@
1+# -*- coding: utf-8 -*-
2+import os
3+import time
4+import argparse
5+import sys
6+import pandas as pd
7+import numpy as np
8+import torch
9+import torch.nn as nn
10+import torch.optim as optim
11+import torch.utils.data as Data
12+import torch.nn.functional as F
13+from sklearn.model_selection import train_test_split
14+ 
15+from CTR_Algorithm.pytorch.model import DIN
16+from CTR_Algorithm.data.AmazonDataPreprocess import AmazonBookPreprocess
17+ 
18+MODEL_NAME = "DIN"
19+ 
20+data = pd.read_csv('CTR_Algorithm/data/amazon-books-100k.txt')
21+data = AmazonBookPreprocess(data)
22+fields = data.max().max()
23+ 
24+data_X = data.iloc[:,:-1]
25+data_y = data.label.values
26+ 
27+tmp_X, test_X, tmp_y, test_y = train_test_split(data_X, data_y, test_size = 0.2, random_state=42, stratify=data_y)
28+train_X, val_X, train_y, val_y = train_test_split(tmp_X, tmp_y, test_size = 0.25, random_state=42, stratify=tmp_y)
29+ 
30+train_X = torch.from_numpy(train_X.values).long()
31+val_X = torch.from_numpy(val_X.values).long()
32+test_X = torch.from_numpy(test_X.values).long()
33+ 
34+train_y = torch.from_numpy(train_y).long()
35+val_y = torch.from_numpy(val_y).long()
36+test_y = torch.from_numpy(test_y).long()
37+ 
38+train_set = Data.TensorDataset(train_X, train_y)
39+val_set = Data.TensorDataset(val_X, val_y)
40+train_loader = Data.DataLoader(dataset=train_set, batch_size=32, shuffle=True)
41+val_loader = Data.DataLoader(dataset=val_set, batch_size=32, shuffle=False)
42+ 
43+def get_profile(profiler_start_step: int, profiler_end_step: int, profiling_save_path: str):
44+ warm_step = profiler_start_step
45+ active_step = profiler_end_step - warm_step +1
46+ print(f"[Profile INFO]: warm_step: {warm_step}, active_step: {active_step}, profiling_save_path: {profiling_save_path}")
47+ device = detect_device_type()
48+ if device == 'npu':
49+ import torch_npu
50+ g_prof_config = torch_npu.profiler._ExperimentalConfig(
51+ export_type=[
52+ torch_npu.profiler.ExportType.Text,
53+ torch_npu.profiler.ExportType.Db
54+ ],
55+ profiler_level=torch_npu.profiler.ProfilerLevel.Level2,
56+ msprof_tx=False,
57+ aic_metrics=torch_npu.profiler.AiCMetrics.AiCoreNone,
58+ l2_cache=False,
59+ op_attr=False,
60+ data_simplification=False,
61+ record_op_args=False,
62+ gc_detect_threshold=None)
63+ 
64+ return torch_npu.profiler.profile(
65+ activities=[
66+ torch_npu.profiler.ProfilerActivity.CPU,
67+ torch_npu.profiler.ProfilerActivity.NPU],
68+ schedule=torch_npu.profiler.schedule(wait=0, warmup=warm_step, active=active_step, repeat=1),
69+ on_trace_ready=torch_npu.profiler.tensorboard_trace_handler(profiling_save_path),
70+ record_shapes=False,
71+ profile_memory=False,
72+ with_stack=False,
73+ with_modules=False,
74+ with_flops=False,
75+ experimental_config=g_prof_config)
76+ elif device == 'cuda':
77+ from torch.profiler import profile, schedule, tensorboard_trace_handler, ProfilerActivity
78+ return profile(
79+ activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
80+ schedule=schedule(wait=0, warmup=warm_step, active=active_step, repeat=1),
81+ on_trace_ready=tensorboard_trace_handler(profiling_save_path),
82+ record_shapes=False,
83+ profile_memory=False,
84+ )
85+ else:
86+ print(f"[Warning]: No supported acceleration device (CUDA/NPU) detected, profiler will be disabled")
87+ return None
88+ 
89+def detect_device_type():
90+ try:
91+ import torch
92+ if torch.cuda.is_available():
93+ return "cuda"
94+ try:
95+ import torch_npu
96+ import os
97+ os.environ['TORCHINDUCTOR_NPU_BACKEND'] = 'mlir'
98+ if torch.npu.is_available():
99+ return "npu"
100+ except ImportError:
101+ pass
102+ except ImportError:
103+ pass
104+ return "cpu"
105+ 
106+def device_synchronize():
107+ if torch.cuda.is_available():
108+ torch.cuda.synchronize()
109+ elif torch.npu.is_available():
110+ torch.npu.synchronize()
111+ 
112+def eval_op_prof(model: nn.Module, device, mod, args):
113+ dl = iter(val_loader)
114+ x, _ = next(dl)
115+ x = x.to(device)
116+ pt_path= MODEL_NAME +'_'+ mod + '_result.pt'
117+ 
118+ model.eval()
119+ with torch.no_grad():
120+ res = model(x)
121+ torch.save(res, pt_path)
122+ device_synchronize()
123+ 
124+ prof = None
125+ if args.enable_profiler:
126+ profiling_save_path = args.profiler_save_path + '/' + MODEL_NAME + '/' + mod
127+ prof = get_profile(args.profiler_start_step, args.profiler_end_step, profiling_save_path)
128+ prof.start()
129+ 
130+ execution_times = []
131+ with torch.no_grad():
132+ for i in range(args.max_steps):
133+ start_time = time.time()
134+ model(x)
135+ device_synchronize()
136+ end_time = time.time()
137+ step_time_ms = (end_time - start_time) * 1000
138+ print(f"[{mod}]: Step {i}: {step_time_ms:.4f} ms")
139+ 
140+ if i >= 10:
141+ execution_times.append(step_time_ms)
142+ 
143+ if args.enable_profiler:
144+ prof.step()
145+ 
146+ if args.enable_profiler:
147+ prof.stop()
148+ if execution_times:
149+ avg_ms = sum(execution_times) / len(execution_times)
150+ print(f"[{mod}]:: Avg over {len(execution_times)} steps: {avg_ms:.4f} ms")
151+ 
152+parser = argparse.ArgumentParser(description=MODEL_NAME + " infernece")
153+parser.add_argument("--max_steps", type=int, default=200,
154+ help="Total training steps")
155+parser.add_argument("--enable_compile", action="store_true",
156+ help="Enable torch.compile and Inductor backend")
157+parser.add_argument("--enable_profiler", action="store_true",
158+ help="Enable profiler for performance analysis")
159+parser.add_argument("--profiler_start_step", type=int, default=5,
160+ help="Output directory for trained model")
161+parser.add_argument("--profiler_end_step", type=int, default=8,
162+ help="Output directory for trained model")
163+parser.add_argument("--profiler_save_path", type=str, default="./profile",
164+ help="Output directory for trained model")
165+args = parser.parse_args()
166+ 
167+model = DIN.DeepInterestNet(feature_dim=fields, embed_dim=8, mlp_dims=[64,32], dropout=float(0.2))
168+device_type = detect_device_type()
169+device = torch.device(device_type)
170+model.to(device)
171+mod = 'eager'
172+if args.enable_compile:
173+ model = torch.compile(model, dynamic=False)
174+ mod = 'compile'
175+print(f"{MODEL_NAME} inference begin, mode is {mod}")
176+eval_op_prof(model, device, mod, args)
@@ -0,0 +1,510 @@
1+import argparse
2+import glob
3+import json
4+import os
5+import random
6+import stat
7+import time
8+from datetime import datetime
9+ 
10+import h5py
11+import numpy as np
12+ 
13+import torch
14+import torch.nn as nn
15+import torch.optim as optim
16+import torch.nn.functional as F
17+from torch.nn.utils.rnn import pad_sequence
18+from torch.utils.data import Dataset, DataLoader, ConcatDataset
19+from sklearn.metrics import roc_auc_score
20+ 
21+torch.manual_seed(2024)
22+random.seed(2024)
23+ 
24+MODEL_NAME = "ETA"
25+STD_DEV = (2 / 512) ** 0.5
26+EMBEDDING_FEATURE_NUM = 27
27+TARGET_FIELDS = ["206", "207", "216", "210"]
28+ 
29+def detect_device_type():
30+ try:
31+ import torch
32+ if torch.cuda.is_available():
33+ return "cuda"
34+ try:
35+ import torch_npu
36+ import os
37+ os.environ['TORCHINDUCTOR_NPU_BACKEND'] = 'mlir'
38+ if torch.npu.is_available():
39+ return "npu"
40+ except ImportError:
41+ pass
42+ except ImportError:
43+ pass
44+ return "cpu"
45+ 
46+def json_file_load(json_name: str, json_path: str) -> dict:
47+ """
48+ Load a JSON file from the specified path.
49+ """
50+ flags = os.O_RDONLY
51+ modes = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
52+ try:
53+ with os.fdopen(os.open(json_path, flags, modes), "r") as fp:
54+ json_re = json.load(fp)
55+ except FileNotFoundError as e:
56+ raise FileNotFoundError(f"{json_name} file not found: {e}") from e
57+ except Exception as e:
58+ raise RuntimeError(f"Error loading {json_name} file: {e}") from e
59+ 
60+ return json_re
61+ 
62+def collate_fn(batch):
63+ input_dicts = [item[0] for item in batch]
64+ target_dicts = [item[1] for item in batch]
65+ input_tensors = {}
66+ for key in input_dicts[0].keys():
67+ tensors = [d[key] for d in input_dicts if key in d and d[key] is not None]
68+ if not tensors:
69+ continue
70+ if tensors[0].dim() == 0:
71+ tensors = [t.unsqueeze(0) for t in tensors]
72+ input_tensors[key] = pad_sequence(tensors, batch_first=True)
73+ 
74+ target_tensors = {}
75+ for key in target_dicts[0].keys():
76+ tensors = [d[key] for d in target_dicts if key in d and d[key] is not None]
77+ if not tensors:
78+ continue
79+ target_tensors[key] = torch.stack(tensors)
80+ 
81+ return input_tensors, target_tensors
82+ 
83+def parse_arguments():
84+ parser = argparse.ArgumentParser()
85+ parser.add_argument("--embedding_size", type=int, default=16, help="Embedding size")
86+ parser.add_argument("--attention_dim", type=int, default=64, help="")
87+ parser.add_argument("--enable_compile", action="store_true", help="")
88+ parser.add_argument("--num_heads", type=int, default=4, help="")
89+ parser.add_argument("--short_output_dim", type=int, default=16, help="short attention output dimension")
90+ parser.add_argument("--max_seq_len", type=int, default=50, help="")
91+ parser.add_argument("--topk", type=int, default=16, help="")
92+ parser.add_argument("--deep_layers", type=str, default="512,256,128,64", help="deep layers")
93+ parser.add_argument("--hash_bits", type=int, default=32, help="")
94+ parser.add_argument("--reuse_hash", type=bool, default=True, help="")
95+ parser.add_argument("--batch_size", type=int, default=4096, help="Number of batch size")
96+ parser.add_argument("--learning_rate", type=float, default=0.001, help="learning rate")
97+ parser.add_argument("--optimizer", type=str, default="Adam",
98+ choices=["Adam", "Adagrad", "GD", "Momentum"], help="")
99+ parser.add_argument('--early_stop_patience', type=int, default=5, help="")
100+ parser.add_argument("--data_dir", type=str, default="./aliccp/aliccp_out/", help="data dir")
@@ -0,0 +1,577 @@
1+import os
2+import stat
3+import glob
4+import json
5+import random
6+import shutil
7+import logging
8+import time
9+from datetime import datetime
10+import argparse
11+ 
12+import pytz
13+import h5py
14+import numpy as np
15+import torch
16+import torch.nn as nn
17+import torch.optim as optim
18+from torch.nn.utils.rnn import pad_sequence
19+from torch.utils.data import DataLoader, Dataset, ConcatDataset
20+from sklearn.metrics import roc_auc_score
21+ 
22+torch.manual_seed(2024)
23+random.seed(2024)
24+ 
25+MODEL_NAME = "MMOE"
26+EMBEDDING_FEATURE_NUM = 23
27+STD_DEV = (2 / 512) ** 0.5
28+ 
29+def detect_device_type():
30+ try:
31+ import torch
32+ if torch.cuda.is_available():
33+ return "cuda"
34+ try:
35+ import torch_npu
36+ import os
37+ os.environ['TORCHINDUCTOR_NPU_BACKEND'] = 'mlir'
38+ if torch.npu.is_available():
39+ return "npu"
40+ except ImportError:
41+ pass
42+ except ImportError:
43+ pass
44+ return "cpu"
45+ 
46+def parse_arguments():
47+ parser = argparse.ArgumentParser(description='PyTorch Example with Command Line Arguments')
48+ parser.add_argument('--embedding_size', type=int, default=16, help="Embedding size")
49+ parser.add_argument('--batch_size', type=int, default=4096, help="Batch size for training")
50+ parser.add_argument('--learning_rate', type=float, default=0.001, help="Learning rate")
51+ parser.add_argument('--optimizer', type=str, default="Adam", choices=["Adam", "Adagrad", "GD", "Momentum"],
52+ help="Optimizer type")
53+ parser.add_argument('--expert_layers', type=str, default="512,256", help="Expert layers")
54+ parser.add_argument('--tower_layers', type=str, default="128,64", help="tower layers")
55+ parser.add_argument('--ctr_task_wgt', type=float, default=0.5, help="loss weight of ctr task")
56+ parser.add_argument('--data_dir', type=str, default="./aliccp/aliccp_out/", help="Data directory")
57+ parser.add_argument('--dt_dir', type=str, default="", help="Data dt partition")
58+ parser.add_argument('--model_dir', type=str, default=f"./",
59+ help="Model checkpoint directory")
60+ parser.add_argument('--servable_model_dir', type=str, default=f"./",
61+ help="Export servable model for pytorch Serving")
62+ parser.add_argument('--clear_existing_model', action="store_true", help="Clear existing model or not")
63+ parser.add_argument('--max_seq_len', type=int, default=50, help="Max length of sequence")
64+ parser.add_argument('--task_num', type=int, default=2, help="Task number")
65+ parser.add_argument('--experts_num', type=int, default=8, help="Number of experts")
66+ parser.add_argument('--log_level', type=str, default="DEBUG",
67+ choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
68+ help="Log level")
69+ parser.add_argument('--epoch_num', type=int, default=10, help="Number of epochs")
70+ parser.add_argument('--train_batch_num', type=int, default=2000, help="Number of train batchs")
71+ parser.add_argument('--eval_batch_num', type=int, default=20, help="Number of eval batchs")
72+ parser.add_argument('--test_batch_num', type=int, default=20, help="Number of test batchs")
73+ parser.add_argument("--enable_compile", action="store_true", help="")
74+ parser.add_argument("--max_steps", type=int, default=100, help="Total training steps")
75+ parser.add_argument("--enable_profiler", action="store_true",
76+ help="Enable profiler for performance analysis")
77+ parser.add_argument("--profiler_start_step", type=int, default=5,
78+ help="Output directory for trained model")
79+ parser.add_argument("--profiler_end_step", type=int, default=8,
80+ help="Output directory for trained model")
81+ parser.add_argument("--profiler_save_path", type=str, default="./profile",
82+ help="Output directory for trained model")
83+ return parser.parse_args()
84+ 
85+ 
86+def json_file_load(json_name: str, json_path: str) -> dict:
87+ """
88+ Load a JSON file from the specified path.
89+ """
90+ flags = os.O_RDONLY
91+ modes = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
92+ try:
93+ with os.fdopen(os.open(json_path, flags, modes), "r") as fp:
94+ json_re = json.load(fp)
95+ except FileNotFoundError as e:
96+ raise FileNotFoundError(f"{json_name} file not found: {e}") from e
97+ except Exception as e:
98+ raise RuntimeError(f"Error loading {json_name} file: {e}") from e
99+ 
100+ return json_re
@@ -0,0 +1,92 @@
1+# 推理说明
2+
3+本 README 说明如何使用 **DCNv2**,**DIN**,**MMOE**和**ETA**模型进行推理(含 eager / torch.compile 两种模式)。
4+在运行完成后输出
5+---
6+ 
7+## 目录
8+ 
9+- [1. 数据集处理](#1-数据集处理)
10+ - [1.1 DIN & DCNv2](#11-DIN-&-DCNv2)
11+ - [1.2 MMOE & ETA](#12-MMOE-&-ETA)
12+- [2. 模型推理](#2-模型推理)
13+ - [2.1 eager mode(默认)](#21-eager-mode默认)
14+ - [2.2 启用 torch.compile(可选)](#22-启用-torch.compile可选)
15+ - [2.3 采集 profile文件(可选)](#23-采集profile文件可选)
16+---
17+ 
18+## 1. 数据集处理
19+ 
20+### 1.1 DIN & DCNv2
21+ 
22+**DIN** 和 **DCNv2** 的推理数据集来自 CTR_Algorithm 仓库示例数据,该数据集无需手动下载
23+ 
24+https://github.com/Prayforhanluo/CTR_Algorithm/tree/main/data
25+ 
26+在DIN或DCNv2目录下执行如下命令:
27+```bash
28+git clone https://github.com/Prayforhanluo/CTR_Algorithm.git
29+```
30+- 数据集目录:`CTR_Algorithm/data/data.csv`
31+ 
32+ 
33+### 1.2 MMOE & ETA
34+ 
35+进入**MMOE**或**ETA**文件夹下,进行如下数据预处理
36+ 
37+推理数据集来自 https://tianchi.aliyun.com/dataset/408 Ali-CPP数据集,需做如下处理:
38+1. 下载数据集,存放至当前目录下alicpp文件夹中
39+2. 后续流程参考:https://gitee.com/ascend/RecSDK/blob/develop_torch_benchmark/torch_examples_benchmark/model_zoo/README.md
40+ 
41+执行完成后数据集会默认生成至aliccp_out目录下。
42+ 
43+网络依赖已整理到 `requirements.txt`,可直接安装:
44+ 
45+```bash
46+pip install -r ./requirements.txt
47+```
48+ 
49+在模型执行时,默认加载数据集路径为: `./aliccp/aliccp_out/`;模型脚本同时支持运行时使用如下命令动态指定数据集目录:
50+ 
51+```bash
52+python eta.py --data_dir path/to/your/data/
53+```
54+ 
55+ 
56+## 2. 模型推理(DCNv2网络为例)
57+ 
58+进入**DCNv2**文件夹,直接执行推理脚本`dcnv2.py`即可
59+ 
60+- 注:运行该网络前需要先将patch文件加上,具体方式如下:
61+ ```bash
62+ cd DCNv2
63+ unix2dos dcnv2.patch #如果在arm机器上需要执行
64+ git apply dcnv2.patch
65+ ```
66+ 
67+### 2.1 eager mode(默认)
68+ 
69+```bash
70+python dcnv2.py
71+```
72+ 
73+### 2.2 启用 `torch.compile`(可选)
74+ 
75+脚本已支持 `--enable_compile` 这样的开关,开启方式为:
76+ 
77+```bash
78+python dcnv2.py \
79+--enable_compile
80+```
81+ 
82+### 2.3 采集profile文件(可选)
83+ 
84+脚本已支持 `--enable_profiler` 这样的开关,开启方式为:
85+ 
86+```bash
87+python dcnv2.py \
88+ --enable_profiler \
89+ --profiler_start_step 5 \
90+ --profiler_end_step 6 \
91+```
92+可以通过 `--profiler_start_step ` 和 `--profiler_end_step` 分别设置profile开始和结束步数。
@@ -0,0 +1,5 @@
1+h5py==3.13.0
2+numpy==1.26.4
3+pandas
4+pytz
5+scikit-learn
@@ -0,0 +1,124 @@
1+# Baichuan2-7B-Chat 微调训练
2+ 
3+本 README 说明如何使用 **Baichuan2-7B-Chat** 模型权重,结合 **LlamaFactory** 提供的 `alpaca_zh_demo.json` 示例数据,完成数据下载、预处理与训练启动(含 eager / torch.compile 两种模式)。
4+ 
5+---
6+ 
7+## 目录
8+ 
9+- [1. 模型权重](#1-模型权重)
10+- [2. 数据获取](#2-数据获取)
11+- [3. 数据预处理](#3-数据预处理)
12+- [4. 模型训练](#4-模型训练)
13+ - [4.1 eager mode(默认)](#41-eager-mode默认)
14+ - [4.2 启用 torchcompile(可选)](#42-启用-torchcompile可选)
15+ 
16+---
17+ 
18+### 环境配置
19+ 
20+本项目依赖已整理到 `requirements.txt`,可直接安装:
21+ 
22+```bash
23+pip install -r ../utils/requirements.txt
24+```
25+ 
26+## 1. 模型权重
27+ 
28+- Hugging Face 模型:**baichuan-inc/Baichuan2-7B-Chat**
29+ https://huggingface.co/baichuan-inc/Baichuan2-7B-Chat
30+ 
31+- 可使用如下的自定义脚本下载
32+ 
33+```bash
34+python ../utils/download_hf.py --model baichuan-inc/Baichuan2-7B-Chat --save_path ./Baichuan2-7B-Chat
35+```
36+ 
37+## 2. 数据获取
38+ 
39+训练数据集来自 LlamaFactory 仓库示例数据:
40+ 
41+- `alpaca_zh_demo.json`
42+ https://github.com/hiyouga/LlamaFactory/blob/main/data/alpaca_zh_demo.json
43+ 
44+建议直接下载 raw 文件到本地:
45+ 
46+```bash
47+wget -O alpaca_zh_demo.json \
48+https://raw.githubusercontent.com/hiyouga/LlamaFactory/main/data/alpaca_zh_demo.json
49+```
50+ 
51+## 3. 数据预处理
52+ 
53+本项目提供 `preprocess.py`,用于把 Alpaca 格式(`instruction`/`input`/`output`)转换为 Baichuan 常用的 `conversations` 格式。
54+ 
55+### 命令
56+ 
57+```bash
58+python preprocess.py -i alpaca_zh_demo.json -o train.json
59+```
60+ 
61+## 4. 模型训练
62+ 
63+训练脚本:`run_baichuan2.sh`,脚本支持在 GPU 和 NPU 训练
64+ 
65+开始训练前,请修改脚本中的路径参数:
66+ 
67+- 模型权重路径(本地目录)
68+- 训练数据路径(预处理后的 `train.json`)
69+ 
70+### 4.1 eager mode(默认)
71+ 
72+```bash
73+bash run_baichuan2.sh
74+```
75+ 
76+### 4.2 启用 `torch.compile`(可选)
77+ 
78+可通过添加 `--enable_compile` 选项运行图模式
79+当在 GPU 上训练时,默认后端使用triton;当在 NPU 上训练时,可进一步指定后端为 mlir 或 dvm,默认使用 mlir。
80+ 
81+**默认后端(mlir,可不写 --npu-backend):**
82+ 
83+```bash
84+bash run_baichuan2.sh \
85+ --enable_compile
86+```
87+ 
88+**显式指定后端为 mlir:**
89+ 
90+```bash
91+bash run_baichuan2.sh \
92+ --enable_compile \
93+ --npu-backend mlir
94+```
95+ 
96+**切换后端为 dvm:**
97+ 
98+```bash
99+bash run_baichuan2.sh \
100+ --enable_compile \
101+ --npu-backend dvm
102+```
103+ 
104+当在 NPU 上训练时,可通过 `--mfusion` 参数开启 MFusion 图算融合优化功能, 配合不同的NPU图模式后端, 进一步提升模型的性能,使用示例如下
105+ 
106+```bash
107+bash run_baichuan2.sh \
108+ --enable_compile \
109+ --npu-backend dvm \
110+ --mfusion
111+```
112+ 
113+### 4.3 采集profile文件(可选)
114+ 
115+脚本已支持 `--enable_profiler` 这样的开关,开启方式为:
116+ 
117+```bash
118+bash run_baichuan2.sh \
119+ --enable_profiler \
120+ --profiler_start_step 5 \
121+ --profiler_end_step 6 \
122+```
123+ 
124+可以通过 `--profiler_start_step` 和 `--profiler_end_step` 分别设置profile开始和结束步数。
@@ -0,0 +1,50 @@
1+import json
2+import os
3+import argparse
4+ 
5+def convert_alpaca_to_baichuan(input_path, output_path):
6+ with open(input_path, "r", encoding="utf-8") as f:
7+ data = json.load(f)
8+ 
9+ converted_data = []
10+ 
11+ for item in data:
12+ instruction = item.get("instruction", "").strip()
13+ input_text = item.get("input", "").strip()
14+ output_text = item.get("output", "").strip()
15+ 
16+ if input_text:
17+ human_text = instruction + "\n" + input_text
18+ else:
19+ human_text = instruction
20+ 
21+ new_item = {
22+ "conversations": [
23+ {
24+ "from": "human",
25+ "value": human_text
26+ },
27+ {
28+ "from": "assistant",
29+ "value": output_text
30+ }
31+ ]
32+ }
33+ 
34+ converted_data.append(new_item)
35+ 
36+ with open(output_path, "w", encoding="utf-8") as f:
37+ json.dump(converted_data, f, ensure_ascii=False, indent=2)
38+ 
39+ print(f"Conversion completed, total {len(converted_data)} records")
40+ print(f"Output file: {output_path}")
41+ 
42+def build_argparser():
43+ p = argparse.ArgumentParser(description="Convert Alpaca JSON to Baichuan conversations JSON")
44+ p.add_argument("--input", "-i", required=True, help="Path to alpaca json file")
45+ p.add_argument("--output", "-o", required=True, help="Path to output json file")
46+ return p
47+ 
48+if __name__ == "__main__":
49+ args = build_argparser().parse_args()
50+ convert_alpaca_to_baichuan(args.input, args.output)
@@ -0,0 +1,23 @@
1+#!/bin/bash
2+export TORCHINDUCTOR_CACHE_DIR="./cache"
3+export ASCEND_RT_VISIBLE_DEVICES=0
4+export CUDA_VISIBLE_DEVICES=0
5+export TORCH_COMPILE_DEBUG=1
6+export TORCH_NPU_USE_COMPATIBLE_IMPL=1
7+ 
8+rm -rf ./cache/*
9+mkdir -p ./cache logs
10+ 
11+python train_baichuan2_7B.py \
12+ --model_path $MODEL_PATH \
13+ --data_path $DATA_PATH \
14+ --output_dir "./baichuan2-finetuned" \
15+ --num_epochs 3 \
16+ --max_steps 200 \
17+ --batch_size 1 \
18+ --learning_rate 2e-5 \
19+ --max_length 1024 \
20+ --use_lora \
21+ --use_bf16 \
22+ --gradient_checkpointing \
23+ > logs/train_baichuan.log 2>&1
@@ -0,0 +1,305 @@
1+import os
2+import json
3+import time
4+import sys
5+from pathlib import Path
6+import argparse
7+import logging
8+from typing import Dict, List, Optional
9+ 
10+import torch
11+from datasets import Dataset, load_dataset
12+ 
13+from transformers import (
14+ AutoTokenizer,
15+ AutoModelForCausalLM,
16+ TrainingArguments,
17+ Trainer,
18+ DataCollatorForSeq2Seq,
19+ TrainerCallback,
20+ set_seed,
21+)
22+from peft import LoraConfig, get_peft_model, TaskType
23+sys.path.append(str(Path(__file__).parent.parent))
24+from utils.utils import TimingCallback, get_profile, detect_device_type
25+ 
26+ 
27+logging.basicConfig(level=logging.INFO)
28+logger = logging.getLogger(__name__)
29+ 
30+MODEL_NAME = "Baichuan2-7B-Chat"
31+ 
32+class BaichuanTrainer(Trainer):
33+ def compute_loss(self, model, inputs, return_outputs=False, num_items_in_batch=None):
34+ return super().compute_loss(model, inputs, return_outputs=return_outputs)
35+ 
36+ 
37+class Baichuan2Trainer:
38+ def __init__(self, args):
39+ self.args = args
40+ self.model = None
41+ self.tokenizer = None
42+ self.setup_training()
43+ 
44+ def setup_training(self):
45+ logger.info(f"Loading model/tokenizer from {self.args.model_path}")
46+ 
47+ self.tokenizer = AutoTokenizer.from_pretrained(
48+ self.args.model_path,
49+ trust_remote_code=True,
50+ padding_side="right",
51+ model_max_length=self.args.max_length,
52+ )
53+ 
54+ if self.tokenizer.pad_token is None:
55+ self.tokenizer.pad_token = self.tokenizer.eos_token
56+ 
57+ self.model = AutoModelForCausalLM.from_pretrained(
58+ self.args.model_path,
59+ trust_remote_code=True,
60+ torch_dtype=torch.bfloat16 if self.args.use_bf16 else torch.float16,
61+ use_cache=not self.args.gradient_checkpointing,
62+ )
63+ 
64+ if self.args.gradient_checkpointing:
65+ self.model.gradient_checkpointing_enable()
66+ self.model.config.use_cache = False
67+ 
68+ def apply_lora(self):
69+ if not self.args.use_lora:
70+ return
71+ 
72+ logger.info("Applying LoRA...")
73+ 
74+ target_modules = self.args.lora_target_modules.split(",") if self.args.lora_target_modules else ["W_pack"]
75+ 
76+ lora_config = LoraConfig(
77+ task_type=TaskType.CAUSAL_LM,
78+ r=self.args.lora_r,
79+ lora_alpha=self.args.lora_alpha,
80+ lora_dropout=self.args.lora_dropout,
81+ target_modules=target_modules,
82+ bias="none",
83+ )
84+ self.model = get_peft_model(self.model, lora_config)
85+ self.model.print_trainable_parameters()
86+ 
87+ def format_conversation(self, conversations: List[Dict]) -> str:
88+ text = ""
89+ for turn in conversations:
90+ role = turn.get("from", "")
91+ content = turn.get("value", "")
92+ if role == "human":
93+ text += f"<reserved_106>{content}"
94+ elif role == "assistant":
95+ text += f"<reserved_107>{content}"
96+ elif role == "system":
97+ text += f"<reserved_106>{content}"
98+ text += self.tokenizer.eos_token
99+ return text
100+ 
101+ def load_and_preprocess_data(self) -> Dataset:
102+ logger.info(f"Loading dataset from {self.args.data_path}")
103+ 
104+ if self.args.data_path.endswith(".json") or self.args.data_path.endswith(".jsonl"):
105+ with open(self.args.data_path, "r", encoding="utf-8") as f:
106+ if self.args.data_path.endswith(".jsonl"):
107+ raw = [json.loads(line) for line in f]
108+ else:
109+ raw = json.load(f)
110+ 
111+ formatted = []
112+ for item in raw:
113+ if "conversations" in item:
114+ text = self.format_conversation(item["conversations"])
115+ else:
116+ text = item.get("text", "")
117+ formatted.append({"text": text})
118+ 
119+ dataset = Dataset.from_list(formatted)
120+ else:
121+ dataset = load_dataset(self.args.data_path, split=self.args.split)
122+ 
123+ def preprocess_function(examples):
124+ tokenized = self.tokenizer(
125+ examples["text"],
126+ truncation=True,
127+ padding="max_length",
128+ max_length=self.args.max_length,
129+ return_attention_mask=True,
130+ )
131+ tokenized["labels"] = tokenized["input_ids"].copy()
132+ return tokenized
133+ 
134+ num_proc = self.args.num_proc if self.args.num_proc > 0 else None
135+ processed = dataset.map(
136+ preprocess_function,
137+ batched=True,
138+ remove_columns=dataset.column_names,
139+ num_proc=num_proc,
140+ load_from_cache_file=not self.args.overwrite_cache,
141+ )
142+ logger.info(f"Dataset size: {len(processed)}")
143+ return processed
144+ 
145+ def create_trainer(self, train_dataset, eval_dataset=None):
146+ has_eval = eval_dataset is not None
147+ eval_strategy = "steps" if has_eval else "no"
148+ 
149+ training_args = TrainingArguments(
150+ output_dir=self.args.output_dir,
151+ overwrite_output_dir=True,
152+ num_train_epochs=self.args.num_epochs,
153+ max_steps=self.args.max_steps,
154+ per_device_train_batch_size=self.args.batch_size,
155+ per_device_eval_batch_size=self.args.batch_size,
156+ gradient_accumulation_steps=self.args.gradient_accumulation_steps,
157+ learning_rate=self.args.learning_rate,
158+ weight_decay=self.args.weight_decay,
159+ warmup_ratio=self.args.warmup_ratio,
160+ lr_scheduler_type=self.args.lr_scheduler_type,
161+ logging_dir=os.path.join(self.args.output_dir, "logs"),
162+ logging_steps=self.args.logging_steps,
163+ save_steps=self.args.save_steps,
164+ save_total_limit=self.args.save_total_limit,
165+ eval_strategy=eval_strategy,
166+ eval_steps=self.args.eval_steps if has_eval else None,
167+ bf16=self.args.use_bf16,
168+ fp16=self.args.use_fp16,
169+ gradient_checkpointing=self.args.gradient_checkpointing,
170+ remove_unused_columns=False,
171+ report_to="none",
172+ dataloader_pin_memory=False,
173+ optim="adamw_torch",
174+ )
175+ 
176+ data_collator = DataCollatorForSeq2Seq(
177+ tokenizer=self.tokenizer,
178+ model=self.model,
179+ padding="max_length",
180+ max_length=self.args.max_length,
181+ label_pad_token_id=-100,
182+ )
183+ 
184+ mode = "compile" if self.args.enable_compile else "eager"
185+ prof=None
186+ 
187+ if self.args.enable_profiler:
188+ profiling_save_path = self.args.profiler_save_path + '/' + MODEL_NAME + '/' + mode
189+ prof = get_profile(self.args.profiler_start_step, self.args.profiler_end_step, profiling_save_path)
190+ 
191+ timing_callback = TimingCallback(prof, mode)
192+ 
193+ trainer = BaichuanTrainer(
194+ model=self.model,
195+ args=training_args,
196+ train_dataset=train_dataset,
197+ eval_dataset=eval_dataset,
198+ tokenizer=self.tokenizer,
199+ data_collator=data_collator,
200+ callbacks=[timing_callback],
201+ )
202+ return trainer
203+ 
204+ def train(self):
205+ logger.info("Starting training...")
206+ 
207+ if self.args.use_lora:
208+ self.apply_lora()
209+ 
210+ if self.args.enable_compile:
211+ logger.warning("Enable torch.compile (experimental on NPU).")
212+ try:
213+ self.model = torch.compile(self.model, dynamic=False)
214+ except Exception as e:
215+ logger.error(f"torch.compile failed: {e}. Continue without compile.")
216+ 
217+ dataset = self.load_and_preprocess_data()
218+ 
219+ trainer = self.create_trainer(dataset)
220+ train_result = trainer.train()
221+ 
222+ trainer.save_state()
223+ trainer.save_model(self.args.output_dir)
224+ self.tokenizer.save_pretrained(self.args.output_dir)
225+ 
226+ metrics = train_result.metrics
227+ trainer.log_metrics("train", metrics)
228+ trainer.save_metrics("train", metrics)
229+ 
230+ logger.info(f"Training completed! Model saved to {self.args.output_dir}")
231+ return metrics
232+ 
233+ 
234+def build_argparser():
235+ parser = argparse.ArgumentParser(description="Train Baichuan2-7B-Chat (LoRA) on NPU")
236+ 
237+ parser.add_argument("--npu-backend", type=str, default="mlir")
238+ parser.add_argument("--mfusion", action="store_true",
239+ help="Enable MFusion for graph fusion optimization")
240+ parser.add_argument("--model_path", type=str, required=True)
241+ parser.add_argument("--data_path", type=str, required=True)
242+ parser.add_argument("--output_dir", type=str, default="./baichuan2-finetuned")
243+ parser.add_argument("--num_epochs", type=int, default=3)
244+ parser.add_argument("--max_steps", type=int, default=-1)
245+ parser.add_argument("--batch_size", type=int, default=1)
246+ parser.add_argument("--gradient_accumulation_steps", type=int, default=1)
247+ parser.add_argument("--learning_rate", type=float, default=2e-5)
248+ parser.add_argument("--weight_decay", type=float, default=0.1)
249+ parser.add_argument("--warmup_ratio", type=float, default=0.03)
250+ parser.add_argument("--lr_scheduler_type", type=str, default="cosine")
251+ parser.add_argument("--max_length", type=int, default=1024)
252+ parser.add_argument("--gradient_checkpointing", action="store_true")
253+ parser.add_argument("--seed", type=int, default=42)
254+ parser.add_argument("--use_bf16", action="store_true")
255+ parser.add_argument("--use_fp16", action="store_true")
256+ parser.add_argument("--use_lora", action="store_true")
257+ parser.add_argument("--lora_r", type=int, default=8)
258+ parser.add_argument("--lora_alpha", type=int, default=32)
259+ parser.add_argument("--lora_dropout", type=float, default=0.1)
260+ parser.add_argument("--lora_target_modules", type=str, default="W_pack")
261+ parser.add_argument("--validation_split", type=float, default=0.0)
262+ parser.add_argument("--split", type=str, default="train")
263+ parser.add_argument("--num_proc", type=int, default=0)
264+ parser.add_argument("--overwrite_cache", action="store_true")
265+ parser.add_argument("--logging_steps", type=int, default=1)
266+ parser.add_argument("--save_steps", type=int, default=500)
267+ parser.add_argument("--save_total_limit", type=int, default=3)
268+ parser.add_argument("--eval_steps", type=int, default=500)
269+ parser.add_argument("--enable_compile", action="store_true")
270+ parser.add_argument("--enable_profiler", action="store_true")
271+ parser.add_argument("--profiler_save_path", type=str, default="./profile")
272+ parser.add_argument("--profiler_start_step", type=int, default=5,
273+ help="Output directory for trained model")
274+ parser.add_argument("--profiler_end_step", type=int, default=7,
275+ help="Output directory for trained model")
276+ 
277+ return parser
278+ 
279+ 
280+def main():
281+ args = build_argparser().parse_args()
282+ detect_device_type()
283+ os.environ['TORCHINDUCTOR_NPU_BACKEND']=args.npu_backend
284+ if args.mfusion:
285+ os.environ['TORCHINDUCTOR_ENABLE_MFUSION']='1'
286+ os.makedirs(args.output_dir, exist_ok=True)
287+ os.makedirs(os.path.join(args.output_dir, "logs"), exist_ok=True)
288+ 
289+ set_seed(args.seed)
290+ torch.manual_seed(args.seed)
291+ 
292+ logger.info(f"npu train {MODEL_NAME}")
293+ trainer = Baichuan2Trainer(args)
294+ metrics = trainer.train()
295+ 
296+ if args.enable_compile:
297+ headers, values = torch._dynamo.utils.compile_times("csv")
298+ for header, value in zip(headers, values):
299+ if header == "PyCodeCache.load_by_key_path":
300+ numbers = [float(num.strip()) for num in value.split(',') if num.strip()]
301+ op_compile_time = sum(numbers)
302+ print(f"op_compile_time:{op_compile_time * 1e3} ms", )
303+ 
304+if __name__ == "__main__":
305+ main()
@@ -0,0 +1,119 @@
1+# gpt-oss-20B 微调训练
2+ 
3+本 README 说明如何使用 **gpt-oss-20B** 模型权重,结合 **LlamaFactory** 提供的 `c4_demo.jsonl` 示例数据,完成数据下载、预处理与训练启动(含 eager / torch.compile 两种模式)。
4+ 
5+---
6+ 
7+## 目录
8+ 
9+- [1. 模型权重](#1-模型权重)
10+- [2. 数据获取](#2-数据获取)
11+- [3. 数据预处理](#3-数据预处理)
12+- [4. 模型训练](#4-模型训练)
13+ - [4.1 eager mode(默认)](#41-eager-mode默认)
14+ - [4.2 启用 torchcompile(可选)](#42-启用-torchcompile可选)
15+ - [4.3 采集profile文件(可选)](#43-采集profile文件可选)
16+ 
17+---
18+ 
19+### 环境配置
20+ 
21+本项目依赖已整理到 `requirements.txt`,可直接安装:
22+ 
23+```bash
24+pip install -r ../utils/requirements.txt
25+```
26+ 
27+## 1. 模型权重
28+ 
29+- Hugging Face 模型地址:**gpt-oss-20B**
30+ https://huggingface.co/openai/gpt-oss-20b
31+ 
32+- 可使用如下的自定义脚本下载
33+ 
34+```bash
35+python ../utils/download_hf.py --model openai/gpt-oss-20b --save_path ./gpt-oss-20b
36+```
37+ 
38+## 2. 数据获取
39+ 
40+训练数据集来自 LlamaFactory 仓库示例数据,可直接在如下连接获取:
41+ 
42+- `c4_demo.json`
43+ https://github.com/hiyouga/LlamaFactory/blob/main/data/c4_demo.jsonl
44+ 
45+或直接下载 raw 文件到本地:
46+ 
47+```bash
48+wget -O c4_demo.json \
49+https://github.com/hiyouga/LlamaFactory/blob/main/data/c4_demo.jsonl
50+```
51+ 
52+## 3. 数据预处理
53+ 
54+在`train_gpt-oss_4B.py`中已经对数据进行了处理
55+ 
56+## 4. 模型训练
57+ 
58+训练脚本:`run_gpt-oss.sh`,脚本支持在 GPU 和 NPU 训练
59+ 
60+开始训练前,请修改脚本中的路径参数:
61+ 
62+- 模型权重路径
63+- 训练数据路径
64+ 
65+### 4.1 eager mode(默认)
66+ 
67+```bash
68+bash run_gpt-oss.sh
69+```
70+ 
71+### 4.2 启用 `torch.compile`(可选)
72+ 
73+可通过添加 `--enable_compile` 选项运行图模式
74+当在 GPU 上训练时,默认后端使用triton;当在 NPU 上训练时,可进一步指定后端为 mlir 或 dvm,默认使用 mlir。
75+ 
76+**默认后端(mlir,可不写 --npu-backend):**
77+ 
78+```bash
79+bash run_gpt-oss.sh \
80+ --enable_compile
81+```
82+ 
83+**显式指定后端为 mlir:**
84+ 
85+```bash
86+bash run_gpt-oss.sh \
87+ --enable_compile \
88+ --npu-backend mlir
89+```
90+ 
91+**切换后端为 dvm:**
92+ 
93+```bash
94+bash run_gpt-oss.sh \
95+ --enable_compile \
96+ --npu-backend dvm
97+```
98+ 
99+当在 NPU 上训练时,可通过 `--mfusion` 参数开启 MFusion 图算融合优化功能, 配合不同的NPU图模式后端, 进一步提升模型的性能,使用示例如下
100+ 
101+```bash
102+bash run_gpt-oss.sh \
103+ --enable_compile \
104+ --npu-backend dvm \
105+ --mfusion
106+```
107+ 
108+### 4.3 采集profile文件(可选)
109+ 
110+脚本已支持 `--enable_profiler` 这样的开关,开启方式为:
111+ 
112+```bash
113+bash run_gpt-oss.sh \
114+ --enable_profiler \
115+ --profiler_start_step 5 \
116+ --profiler_end_step 6 \
117+```
118+ 
119+可以通过 `--profiler_start_step` 和 `--profiler_end_step` 分别设置profile开始和结束步数。
@@ -0,0 +1,23 @@
1+#!/bin/bash
2+export TORCHINDUCTOR_CACHE_DIR="./cache"
3+export ASCEND_RT_VISIBLE_DEVICES=0
4+export CUDA_VISIBLE_DEVICES=0
5+export TORCH_COMPILE_DEBUG=1
6+export TORCH_NPU_USE_COMPATIBLE_IMPL=1
7+ 
8+rm -rf ./cache/*
9+mkdir -p ./cache logs
10+ 
11+python train_gpt_oss_20B.py \
12+ --model_path $MODEL_PATH \
13+ --data_path $DATA_PATH \
14+ --output_dir "./gpt-oss-finetuned" \
15+ --num_epochs 3 \
16+ --max_steps 200\
17+ --batch_size 1 \
18+ --learning_rate 2e-5 \
19+ --max_length 512 \
20+ --use_lora \
21+ --use_bf16 \
22+ --gradient_checkpointing \
23+ --pad_to_max_length > logs/train_gpt-oss.log 2>&1
@@ -0,0 +1,390 @@
1+import torch
2+import os
3+import sys
4+from pathlib import Path
5+import torch.nn as nn
6+from datasets import Dataset, load_dataset
7+from transformers import (
8+ AutoModelForCausalLM,
9+ AutoTokenizer,
10+ TrainingArguments,
11+ Trainer,
12+ DataCollatorForLanguageModeling,
13+)
14+from peft import (
15+ LoraConfig,
16+ get_peft_model,
17+ prepare_model_for_kbit_training,
18+ TaskType
19+)
20+import json
21+from typing import Dict, List, Optional
22+import argparse
23+import logging
24+ 
25+sys.path.append(str(Path(__file__).parent.parent))
26+from utils.utils import (
27+ TimingCallback,
28+ get_profile,
29+ detect_device_type
30+)
31+ 
32+logging.basicConfig(level=logging.INFO)
33+logger = logging.getLogger(__name__)
34+ 
35+model_name = 'GPT-OSS-20B'
36+ 
37+class GPT_OSS_20BTrainer:
38+ def __init__(self, args):
39+ self.args = args
40+ self.setup_training()
41+ 
42+ def setup_training(self):
43+ logger.info(f"Loading model from {self.args.model_path}")
44+ 
45+ self.model = AutoModelForCausalLM.from_pretrained(
46+ self.args.model_path,
47+ torch_dtype=torch.bfloat16 if self.args.use_bf16 else torch.float16,
48+ trust_remote_code=True
49+ )
50+ 
51+ logger.info(f"Moving model to {self.args.device_type}...")
52+ self.model = self.model.to(self.args.device_type)
53+ 
54+ self.tokenizer = AutoTokenizer.from_pretrained(
55+ self.args.model_path,
56+ trust_remote_code=True
57+ )
58+ 
59+ if self.tokenizer.pad_token is None:
60+ self.tokenizer.pad_token = self.tokenizer.eos_token
61+ self.model.config.pad_token_id = self.tokenizer.eos_token_id
62+ 
63+ if self.args.gradient_checkpointing:
64+ self.model.gradient_checkpointing_enable()
65+ self.model.config.use_cache = False
66+ 
67+ 
68+ def apply_lora(self):
69+ if not self.args.use_lora:
70+ return
71+ 
72+ logger.info("Applying LoRA configuration...")
73+ 
74+ if self.args.use_4bit:
75+ self.model = prepare_model_for_kbit_training(self.model)
76+ 
77+ lora_config = LoraConfig(
78+ task_type=TaskType.CAUSAL_LM,
79+ r=self.args.lora_r,
80+ lora_alpha=self.args.lora_alpha,
81+ lora_dropout=self.args.lora_dropout,
82+ target_modules=self.get_lora_target_modules(),
83+ bias="none",
84+ )
85+ 
86+ self.model = get_peft_model(self.model, lora_config)
87+ self.model.print_trainable_parameters()
88+ 
89+ if self.args.enable_compile:
90+ self.model = torch.compile(self.model, dynamic=False)
91+ 
92+ def get_lora_target_modules(self):
93+ target_modules = [
94+ "q_proj", "k_proj", "v_proj", "o_proj",
95+ "gate_proj", "up_proj", "down_proj",
96+ ]
97+ 
98+ model_modules = set([name for name, _ in self.model.named_modules()])
99+ available_modules = [m for m in target_modules if any(m in name for name in model_modules)]
100+ 
101+ if not available_modules:
102+ available_modules = ["qkv_proj", "dense", "fc1", "fc2"]
103+ 
104+ logger.info(f"Using LoRA target modules: {available_modules}")
105+ return available_modules
106+ 
107+ def load_and_preprocess_data(self) -> Dataset:
108+ logger.info(f"Loading dataset from {self.args.data_path}")
109+ 
110+ if self.args.data_path.endswith('.json') or self.args.data_path.endswith('.jsonl'):
111+ with open(self.args.data_path, 'r', encoding='utf-8') as f:
112+ if self.args.data_path.endswith('.jsonl'):
113+ data = [json.loads(line) for line in f]
114+ else:
115+ data = json.load(f)
116+ 
117+ formatted_data = []
118+ for item in data:
119+ if "conversations" in item:
120+ conversations = item["conversations"]
121+ text = self.format_conversation(conversations)
122+ elif "messages" in item:
123+ messages = item["messages"]
124+ text = self.tokenizer.apply_chat_template(
125+ messages,
126+ tokenize=False,
127+ add_generation_prompt=False
128+ )
129+ else:
130+ text = item.get("text", "")
131+ 
132+ formatted_data.append({"text": text})
133+ 
134+ dataset = Dataset.from_list(formatted_data)
135+ 
136+ else:
137+ try:
138+ dataset = load_dataset(
139+ self.args.data_path,
140+ split=self.args.split
141+ )
142+ except:
143+ dataset = load_dataset(
144+ "json",
145+ data_files=self.args.data_path,
146+ split="train"
147+ )
148+ 
149+ def preprocess_function(examples, tokenizer=self.tokenizer, max_length=self.args.max_length):
150+ tokenized = tokenizer(
151+ examples["text"],
152+ truncation=True,
153+ padding="max_length",
154+ max_length=max_length,
155+ return_tensors=None,
156+ return_attention_mask=True,
157+ )
158+ 
159+ import copy
160+ tokenized["labels"] = copy.deepcopy(tokenized["input_ids"])
161+ 
162+ return tokenized
163+ 
164+ num_proc = self.args.num_proc if self.args.num_proc > 0 else None
165+ processed_dataset = dataset.map(
166+ preprocess_function,
167+ batched=True,
168+ remove_columns=dataset.column_names,
169+ num_proc=num_proc,
170+ load_from_cache_file=not self.args.overwrite_cache
171+ )
172+ 
173+ logger.info(f"Dataset size: {len(processed_dataset)}")
174+ return processed_dataset
175+ 
176+ def format_conversation(self, conversations: List[Dict]) -> str:
177+ formatted_text = ""
178+ 
179+ for turn in conversations:
180+ role = turn.get("from", "").lower()
181+ content = turn.get("value", "")
182+ 
183+ if role == "human" or role == "user":
184+ formatted_text += f"<|im_start|>user\n{content}<|im_end|>\n"
185+ elif role == "gpt" or role == "assistant":
186+ formatted_text += f"<|im_start|>assistant\n{content}<|im_end|>\n"
187+ elif role == "system":
188+ formatted_text += f"<|im_start|>system\n{content}<|im_end|>\n"
189+ 
190+ return formatted_text
191+ 
192+ def create_trainer(self, train_dataset, eval_dataset=None):
193+ has_eval = eval_dataset is not None
194+ eval_strategy = "steps" if has_eval else "no"
195+ save_strategy = "steps" if has_eval else "steps"
196+ 
197+ training_args = TrainingArguments(
198+ output_dir=self.args.output_dir,
199+ overwrite_output_dir=True,
200+ num_train_epochs=self.args.num_epochs,
201+ max_steps=self.args.max_steps,
202+ per_device_train_batch_size=self.args.batch_size,
203+ per_device_eval_batch_size=self.args.batch_size,
204+ gradient_accumulation_steps=self.args.gradient_accumulation_steps,
205+ weight_decay=self.args.weight_decay,
206+ logging_dir=f"{self.args.output_dir}/logs",
207+ logging_steps=self.args.logging_steps,
208+ save_steps=self.args.save_steps,
209+ save_total_limit=self.args.save_total_limit,
210+ eval_strategy=eval_strategy,
211+ eval_steps=self.args.eval_steps if has_eval else None,
212+ save_strategy=save_strategy,
213+ load_best_model_at_end=has_eval,
214+ metric_for_best_model="eval_loss",
215+ greater_is_better=False,
216+ learning_rate=self.args.learning_rate,
217+ lr_scheduler_type="cosine",
218+ fp16=self.args.use_fp16,
219+ bf16=self.args.use_bf16,
220+ gradient_checkpointing=self.args.gradient_checkpointing,
221+ report_to="none",
222+ ddp_find_unused_parameters=False if torch.cuda.device_count() > 1 else None,
223+ remove_unused_columns=False,
224+ )
225+ 
226+ data_collator = DataCollatorForLanguageModeling(
227+ tokenizer=self.tokenizer,
228+ mlm=False,
229+ )
230+ 
231+ mod='compile' if self.args.enable_compile else 'eager'
232+ prof=None
233+ 
234+ if self.args.enable_profiler:
235+ profiling_save_path = self.args.profiler_save_path + '/' + model_name + '/' + mod
236+ prof = get_profile(self.args.profiler_start_step, self.args.profiler_end_step, profiling_save_path)
237+ 
238+ timing_callback = TimingCallback(prof, mod)
239+ 
240+ trainer = Trainer(
241+ model=self.model,
242+ args=training_args,
243+ train_dataset=train_dataset,
244+ eval_dataset=eval_dataset,
245+ tokenizer=self.tokenizer,
246+ data_collator=data_collator,
247+ callbacks=[timing_callback],
248+ )
249+ 
250+ return trainer
251+ 
252+ def train(self):
253+ logger.info("Starting training...")
254+ 
255+ if self.args.use_lora:
256+ self.apply_lora()
257+ 
258+ dataset = self.load_and_preprocess_data()
259+ 
260+ if self.args.validation_split > 0:
261+ split_dataset = dataset.train_test_split(
262+ test_size=self.args.validation_split,
263+ seed=self.args.seed
264+ )
265+ train_dataset = split_dataset["train"]
266+ eval_dataset = split_dataset["test"]
267+ else:
268+ train_dataset = dataset
269+ eval_dataset = None
270+ 
271+ trainer = self.create_trainer(train_dataset, eval_dataset)
272+ 
273+ train_result = trainer.train()
274+ 
275+ if self.args.enable_compile:
276+ headers, values = torch._dynamo.utils.compile_times("csv")
277+ for header, value in zip(headers, values):
278+ if header == "PyCodeCache.load_by_key_path":
279+ numbers = [float(num.strip()) for num in value.split(',') if num.strip()]
280+ op_compile_time = sum(numbers)
281+ print(f"op_compile_time:{op_compile_time * 1e3} ms", )
282+ 
283+ trainer.save_model()
284+ self.tokenizer.save_pretrained(self.args.output_dir)
285+ 
286+ metrics = train_result.metrics
287+ trainer.log_metrics("train", metrics)
288+ trainer.save_metrics("train", metrics)
289+ trainer.save_state()
290+ 
291+ logger.info(f"Training completed! Model saved to {self.args.output_dir}")
292+ 
293+ return metrics
294+ 
295+def main():
296+ parser = argparse.ArgumentParser(description="Train GPT-OSS-20B model")
297+ parser.add_argument("--model_path", type=str, required=True,
298+ help="Path to the pretrained model")
299+ parser.add_argument("--data_path", type=str, required=True,
300+ help="Path to training data (json/jsonl file or dataset name)")
301+ parser.add_argument("--output_dir", type=str, default="./GPT-OSS-finetuned",
302+ help="Output directory for trained model")
303+ parser.add_argument("--num_epochs", type=int, default=3,
304+ help="Number of training epochs")
305+ parser.add_argument("--batch_size", type=int, default=4,
306+ help="Batch size per device")
307+ parser.add_argument("--gradient_accumulation_steps", type=int, default=2,
308+ help="Gradient accumulation steps")
309+ parser.add_argument("--learning_rate", type=float, default=2e-4,
310+ help="Learning rate")
311+ parser.add_argument("--warmup_steps", type=int, default=5,
312+ help="Warmup steps")
313+ parser.add_argument("--max_steps", type=int, default=1,
314+ help="Total training steps")
315+ parser.add_argument("--weight_decay", type=float, default=0.01,
316+ help="Weight decay")
317+ parser.add_argument("--max_length", type=int, default=2048,
318+ help="Maximum sequence length")
319+ parser.add_argument("--use_lora", action="store_true",
320+ help="Use LoRA for parameter-efficient fine-tuning")
321+ parser.add_argument("--lora_r", type=int, default=8,
322+ help="LoRA rank")
323+ parser.add_argument("--lora_alpha", type=int, default=32,
324+ help="LoRA alpha")
325+ parser.add_argument("--lora_dropout", type=float, default=0.1,
326+ help="LoRA dropout")
327+ parser.add_argument("--use_4bit", action="store_true",
328+ help="Use 4-bit quantization")
329+ parser.add_argument("--use_fp16", action="store_true",
330+ help="Use FP16 precision")
331+ parser.add_argument("--use_bf16", action="store_true",
332+ help="Use BF16 precision")
333+ parser.add_argument("--gradient_checkpointing", action="store_true",
334+ help="Enable gradient checkpointing")
335+ parser.add_argument("--validation_split", type=float, default=0.1,
336+ help="Validation split ratio")
337+ parser.add_argument("--split", type=str, default="train",
338+ help="Dataset split to use")
339+ parser.add_argument("--num_proc", type=int, default=0,
340+ help="Number of processes for data preprocessing (0 = single process, avoid CUDA conflict)")
341+ parser.add_argument("--pad_to_max_length", action="store_true",
342+ help="Pad sequences to max_length")
343+ parser.add_argument("--overwrite_cache", action="store_true",
344+ help="Overwrite cached features")
345+ parser.add_argument("--seed", type=int, default=42,
346+ help="Random seed")
347+ parser.add_argument("--logging_steps", type=int, default=1,
348+ help="Log every X updates steps")
349+ parser.add_argument("--save_steps", type=int, default=500,
350+ help="Save checkpoint every X updates steps")
351+ parser.add_argument("--eval_steps", type=int, default=500,
352+ help="Evaluate every X updates steps")
353+ parser.add_argument("--save_total_limit", type=int, default=3,
354+ help="Limit the total amount of checkpoints")
355+ parser.add_argument("--report_to_tensorboard", action="store_true",
356+ help="Report metrics to TensorBoard")
357+ parser.add_argument("--enable_compile", action="store_true",
358+ help="Enable torch.compile and Inductor backend")
359+ parser.add_argument("--enable_profiler", action="store_true",
360+ help="Enable profiler for performance analysis")
361+ parser.add_argument("--profiler_start_step", type=int, default=5,
362+ help="Output directory for trained model")
363+ parser.add_argument("--profiler_end_step", type=int, default=8,
364+ help="Output directory for trained model")
365+ parser.add_argument("--profiler_save_path", type=str, default="./profile",
366+ help="Output directory for trained model")
367+ parser.add_argument("--npu-backend", type=str, default="mlir")
368+ parser.add_argument("--mfusion", action="store_true",
369+ help="Enable MFusion for graph fusion optimization")
370+ 
371+ args = parser.parse_args()
372+ torch.manual_seed(args.seed)
373+ 
374+ args.device_type = detect_device_type()
375+ os.environ['TORCHINDUCTOR_NPU_BACKEND']=args.npu_backend
376+ if args.mfusion:
377+ os.environ['TORCHINDUCTOR_ENABLE_MFUSION']='1'
378+ print(f"{args.device_type} train {model_name}")
379+ 
380+ trainer = GPT_OSS_20BTrainer(args)
381+ metrics = trainer.train()
382+ 
383+ print("\n" + "="*50)
384+ print("Training completed successfully!")
385+ print(f"Model saved to: {args.output_dir}")
386+ print(f"Final training loss: {metrics.get('train_loss', 'N/A')}")
387+ print("="*50)
388+ 
389+if __name__ == "__main__":
390+ main()
@@ -0,0 +1,118 @@
1+# Mamba-Codestral-7B 微调训练
2+ 
3+本 README 说明如何使用 **Mamba-Codestral-7B-v0.1** 模型权重,结合 **LlamaFactory** 提供的 `c4_demo.jsonl` 示例数据,完成数据下载、预处理与训练启动(含 eager / torch.compile 两种模式)。
4+ 
5+---
6+ 
7+## 目录
8+ 
9+- [1. 模型权重](#1-模型权重)
10+- [2. 数据获取](#2-数据获取)
11+- [3. 数据预处理](#3-数据预处理)
12+- [4. 模型训练](#4-模型训练)
13+ - [4.1 eager mode(默认)](#41-eager-mode默认)
14+ - [4.2 启用 torchcompile(可选)](#42-启用-torchcompile可选)
15+ 
16+---
17+ 
18+### 环境配置
19+ 
20+本项目依赖已整理到 `requirements.txt`,可直接安装:
21+ 
22+```bash
23+pip install -r ../utils/requirements.txt
24+```
25+ 
26+## 1. 模型权重
27+ 
28+- Hugging Face 模型:**mistralai/Mamba-Codestral-7B-v0.1**
29+ https://huggingface.co/mistralai/Mamba-Codestral-7B-v0.1
30+ 
31+- 可使用如下的自定义脚本下载
32+ 
33+```bash
34+python ../utils/download_hf.py --model mistralai/Mamba-Codestral-7B-v0.1 --save_path ./Mamba-Codestral-7B-v0.1
35+```
36+ 
37+## 2. 数据获取
38+ 
39+训练数据集来自 LlamaFactory 仓库示例数据,可直接在如下连接获取:
40+ 
41+- `c4_demo.json`
42+ https://github.com/hiyouga/LlamaFactory/blob/main/data/c4_demo.jsonl
43+ 
44+或直接下载 raw 文件到本地:
45+ 
46+```bash
47+wget -O c4_demo.json \
48+https://github.com/hiyouga/LlamaFactory/blob/main/data/c4_demo.jsonl
49+```
50+ 
51+## 3. 数据预处理
52+ 
53+在`train_mamba2_7B.py`中已经对数据进行了处理
54+ 
55+## 4. 模型训练
56+ 
57+训练脚本:`run_mamba2.sh`,脚本支持在 GPU 和 NPU 训练
58+ 
59+开始训练前,请修改脚本中的路径参数:
60+ 
61+- 模型权重路径
62+- 训练数据路径
63+ 
64+### 4.1 eager mode(默认)
65+ 
66+```bash
67+bash run_mamba2.sh
68+```
69+ 
70+### 4.2 启用 `torch.compile`(可选)
71+ 
72+可通过添加 `--enable_compile` 选项运行图模式
73+当在 GPU 上训练时,默认后端使用triton;当在 NPU 上训练时,可进一步指定后端为 mlir 或 dvm,默认使用 mlir。
74+ 
75+**默认后端(mlir,可不写 --npu-backend):**
76+ 
77+```bash
78+bash run_mamba2.sh \
79+ --enable_compile
80+```
81+ 
82+**显式指定后端为 mlir:**
83+ 
84+```bash
85+bash run_mamba2.sh \
86+ --enable_compile \
87+ --npu-backend mlir
88+```
89+ 
90+**切换后端为 dvm:**
91+ 
92+```bash
93+bash run_mamba2.sh \
94+ --enable_compile \
95+ --npu-backend dvm
96+```
97+ 
98+当在 NPU 上训练时,可通过 `--mfusion` 参数开启 MFusion 图算融合优化功能, 配合不同的NPU图模式后端, 进一步提升模型的性能,使用示例如下
99+ 
100+```bash
101+bash run_mamba2.sh \
102+ --enable_compile \
103+ --npu-backend dvm \
104+ --mfusion
105+```
106+ 
107+### 4.3 采集profile文件(可选)
108+ 
109+脚本已支持 `--enable_profiler` 这样的开关,开启方式为:
110+ 
111+```bash
112+bash run_mamba2.sh \
113+ --enable_profiler \
114+ --profiler_start_step 5 \
115+ --profiler_end_step 6 \
116+```
117+ 
118+可以通过 `--profiler_start_step` 和 `--profiler_end_step` 分别设置profile开始和结束步数。
@@ -0,0 +1,24 @@
1+#!/bin/bash
2+export ASCEND_RT_VISIBLE_DEVICES=0
3+export CUDA_VISIBLE_DEVICES=0
4+export TORCHINDUCTOR_CACHE_DIR="./cache"
5+export TORCH_COMPILE_DEBUG=1
6+export TORCH_NPU_USE_COMPATIBLE_IMPL=1
7+ 
8+rm -rf ./cache/*
9+mkdir -p ./cache logs
10+ 
11+python train_mamba2_7B.py \
12+ --model_path $MODEL_PATH \
13+ --data_file $DATA_PATH \
14+ --output_dir "./mamba_codestral_lora" \
15+ --epochs 3 \
16+ --batch_size 1 \
17+ --gradient_accumulation_steps 1 \
18+ --learning_rate 1e-4 \
19+ --max_seq_length 256 \
20+ --lora_r 16 \
21+ --lora_alpha 32 \
22+ --lora_dropout 0.1 \
23+ --max_steps 200 \
24+ > logs/train_mamba2.log 2>&1
@@ -0,0 +1,221 @@
1+import os
2+import sys
3+import logging
4+from pathlib import Path
5+import argparse
6+import torch
7+import time
8+from datasets import Dataset as HFDataset
9+from transformers import (
10+ AutoTokenizer,
11+ AutoModelForCausalLM,
12+ TrainingArguments,
13+ Trainer,
14+ default_data_collator,
15+ TrainerCallback,
16+)
17+from peft import (
18+ LoraConfig,
19+ get_peft_model,
20+ TaskType,
21+)
22+sys.path.append(str(Path(__file__).parent.parent))
23+from utils.utils import TimingCallback, get_profile, detect_device_type
24+ 
25+logging.basicConfig(level=logging.INFO)
26+logger = logging.getLogger(__name__)
27+ 
28+MODEL_NAME = "Mamba2"
29+TARGET_MODULES = ["x_proj", "in_proj"]
30+ 
31+def patch_remove_ops_from_generate_list(op_names=None):
32+ try:
33+ import torch
34+ from torch_npu._inductor.ascend_npu_ir.ascend_npu_ir import config as anir_config
35+ 
36+ if not op_names:
37+ print("[patch] No op names provided, nothing to do.")
38+ return
39+ 
40+ for name in op_names:
41+ parts = name.split(".")
42+ op = torch.ops
43+ for p in parts:
44+ op = getattr(op, p)
45+ 
46+ if op in anir_config.GENERATE_LIST:
47+ anir_config.GENERATE_LIST.remove(op)
48+ print(f"[patch] Successfully removed {name} from GENERATE_LIST.")
49+ else:
50+ print(f"[patch] {name} not found in GENERATE_LIST (maybe already removed).")
51+ 
52+ except Exception as e:
53+ print(f"[patch] Failed to modify GENERATE_LIST: {e}")
54+ 
55+def setup_environment():
56+ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"
57+ 
58+def parse_args():
59+ parser = argparse.ArgumentParser(description="Mamba Codestral LoRA finetune")
60+ 
61+ parser.add_argument("--model_path", type=str, default="/home/zhangyican/workspace/q4_data/Mamba-Codestral-7B-v0.1", help="Base model path")
62+ parser.add_argument("--data_file", type=str, default="./c4_demo.jsonl", help="Training data file path")
63+ parser.add_argument("--output_dir", type=str, default="./mamba_codestral_lora_no_quant", help="Output directory")
64+ parser.add_argument("--epochs", type=int, default=3, help="Number of training epochs")
65+ parser.add_argument("--batch_size", type=int, default=1, help="Batch size per device")
66+ parser.add_argument("--gradient_accumulation_steps", type=int, default=1, help="Gradient accumulation steps")
67+ parser.add_argument("--learning_rate", type=float, default=1e-4, help="Learning rate")
68+ parser.add_argument("--max_seq_length", type=int, default=256, help="Maximum sequence length")
69+ parser.add_argument("--lora_r", type=int, default=16, help="LoRA rank")
70+ parser.add_argument("--lora_alpha", type=int, default=32, help="LoRA alpha")
71+ parser.add_argument("--lora_dropout", type=float, default=0.1, help="LoRA dropout")
72+ parser.add_argument("--max_steps", type=int, default=100, help="Maximum training steps")
73+ parser.add_argument("--device", type=str, default="npu:0", help="NPU device, e.g., npu:0 / npu:6")
74+ parser.add_argument("--enable_compile", action="store_true", help="Whether to enable torch.compile")
75+ parser.add_argument("--enable_profiler", action="store_true")
76+ parser.add_argument("--profiler_save_path", type=str, default="./profile")
77+ parser.add_argument("--profiler_start_step", type=int, default=5,
78+ help="Start step for profiling")
79+ parser.add_argument("--profiler_end_step", type=int, default=6,
80+ help="End step for profiling")
81+ parser.add_argument("--npu-backend", type=str, default="mlir")
82+ parser.add_argument("--mfusion", action="store_true",
83+ help="Enable MFusion for graph fusion optimization")
84+ 
85+ return parser.parse_args()
86+ 
87+def main():
88+ args = parse_args()
89+ device = detect_device_type()
90+ os.environ['TORCHINDUCTOR_NPU_BACKEND']=args.npu_backend
91+ if args.mfusion:
92+ os.environ['TORCHINDUCTOR_ENABLE_MFUSION']='1'
93+ patch_remove_ops_from_generate_list(["aten.permute"])
94+ seed = 2
95+ torch.manual_seed(seed)
96+ 
97+ setup_environment()
98+ print("Environment setup complete")
99+ 
100+ print(f"Loading tokenizer from: {args.model_path}")
101+ tokenizer = AutoTokenizer.from_pretrained(
102+ args.model_path,
103+ trust_remote_code=True,
104+ use_fast=True
105+ )
106+ if tokenizer.pad_token is None:
107+ tokenizer.pad_token = tokenizer.eos_token
108+ 
109+ print(f"Loading base model from: {args.model_path} (no quantization)")
110+ base_model = AutoModelForCausalLM.from_pretrained(
111+ args.model_path,
112+ torch_dtype=torch.bfloat16, # Use bfloat16 precision
113+ trust_remote_code=True,
114+ use_cache=False, # Disable cache to save memory
115+ )
116+ 
117+ base_model.gradient_checkpointing_enable()
118+ 
119+ print(f"Configuring LoRA, target modules: {TARGET_MODULES}")
120+ peft_config = LoraConfig(
121+ task_type=TaskType.CAUSAL_LM,
122+ r=args.lora_r,
123+ lora_alpha=args.lora_alpha,
124+ lora_dropout=args.lora_dropout,
125+ target_modules=TARGET_MODULES,
126+ bias="none",
127+ )
128+ 
129+ print("Attaching LoRA adapters to model...")
130+ peft_model = get_peft_model(base_model, peft_config)
131+ peft_model.print_trainable_parameters() # Print number of trainable parameters
132+ 
133+ peft_model.to(device)
134+ 
135+ print("Preparing dataset...")
136+ from datasets import load_dataset
137+ dataset = load_dataset(
138+ "json",
139+ data_files=args.data_file,
140+ split="train"
141+ )
142+ 
143+ def tokenize_function(examples):
144+ return tokenizer(
145+ examples["text"],
146+ truncation=True,
147+ padding="max_length",
148+ max_length=args.max_seq_length,
149+ return_tensors=None
150+ )
151+ 
152+ train_dataset = dataset.map(tokenize_function, batched=True, remove_columns=["text"])
153+ train_dataset = train_dataset.map(lambda x: {"labels": x["input_ids"]}, batched=True)
154+ 
155+ if args.enable_compile:
156+ peft_model = torch.compile(
157+ peft_model,
158+ dynamic=False
159+ )
160+ 
161+ training_args = TrainingArguments(
162+ output_dir=args.output_dir,
163+ num_train_epochs=args.epochs,
164+ per_device_train_batch_size=args.batch_size,
165+ gradient_accumulation_steps=args.gradient_accumulation_steps,
166+ gradient_checkpointing=True,
167+ gradient_checkpointing_kwargs={"use_reentrant": False},
168+ logging_steps=1,
169+ max_steps=args.max_steps,
170+ learning_rate=args.learning_rate,
171+ warmup_ratio=0.1,
172+ lr_scheduler_type="cosine",
173+ bf16=True,
174+ fp16=False,
175+ save_strategy="steps",
176+ save_total_limit=2,
177+ remove_unused_columns=False,
178+ report_to="none",
179+ dataloader_pin_memory=False,
180+ max_grad_norm=0.3,
181+ logging_dir=f"{args.output_dir}/logs",
182+ )
183+ 
184+ mode = "compile" if args.enable_compile else "eager"
185+ prof=None
186+ 
187+ if args.enable_profiler:
188+ profiling_save_path = args.profiler_save_path + '/' + MODEL_NAME + '/' + mode
189+ prof = get_profile(args.profiler_start_step, args.profiler_end_step, profiling_save_path)
190+ 
191+ timing_callback = TimingCallback(prof, mode)
192+ 
193+ print("Initializing Trainer...")
194+ trainer = Trainer(
195+ model=peft_model,
196+ args=training_args,
197+ train_dataset=train_dataset,
198+ tokenizer=tokenizer,
199+ data_collator=default_data_collator,
200+ callbacks=[timing_callback],
201+ )
202+ 
203+ print("Starting LoRA training...")
204+ trainer.train()
205+ 
206+ if args.enable_compile:
207+ headers, values = torch._dynamo.utils.compile_times("csv")
208+ for header, value in zip(headers, values):
209+ if header == "PyCodeCache.load_by_key_path":
210+ numbers = [float(num.strip()) for num in value.split(',') if num.strip()]
211+ op_compile_time = sum(numbers)
212+ print(f"op_compile_time:{op_compile_time * 1e3} ms", )
213+ 
214+ print(f"Saving LoRA weights to {args.output_dir}")
215+ peft_model.save_pretrained(args.output_dir)
216+ tokenizer.save_pretrained(args.output_dir)
217+ 
218+ print("Training complete!")
219+ 
220+if __name__ == "__main__":
221+ main()