more fixes and prep for llama training
Browse files- configs/llama_65B_alpaca.yml +40 -0
- configs/pythia_1_2B_alpaca.yml +4 -2
- scripts/finetune.py +75 -36
configs/llama_65B_alpaca.yml
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
base_model: decapoda-research/llama-65b-hf
|
2 |
+
model_type: LlamaForCausalLM
|
3 |
+
tokenizer_type: LlamaTokenizer
|
4 |
+
load_in_8bit: true
|
5 |
+
datasets:
|
6 |
+
- path: data/alpaca_data_gpt4.jsonl
|
7 |
+
type: alpaca
|
8 |
+
- path: data/vicuna_cleaned.jsonl
|
9 |
+
type: sharegpt
|
10 |
+
- path: data/gpt4-instruct-similarity-0.6-dataset.jsonl
|
11 |
+
type: gpteacher
|
12 |
+
- path: data/roleplay-similarity_0.6-instruct-dataset.jsonl
|
13 |
+
type: gpteacher
|
14 |
+
val_set_size: 0.04
|
15 |
+
adapter: lora
|
16 |
+
lora_model_dir:
|
17 |
+
sequence_len: 2048
|
18 |
+
lora_r: 8
|
19 |
+
lora_alpha: 16
|
20 |
+
lora_dropout: 0.05
|
21 |
+
lora_target_modules:
|
22 |
+
- q_proj
|
23 |
+
- w_proj
|
24 |
+
lora_fan_in_fan_out: true # pythia/GPTNeoX lora specific
|
25 |
+
wandb_project: llama-65b-lora
|
26 |
+
wandb_watch:
|
27 |
+
wandb_run_name:
|
28 |
+
wandb_log_model: checkpoint
|
29 |
+
output_dir: ./lora-llama-alpaca
|
30 |
+
batch_size: 128
|
31 |
+
micro_batch_size: 16
|
32 |
+
num_epochs: 5
|
33 |
+
learning_rate: 0.00003
|
34 |
+
train_on_inputs: false
|
35 |
+
group_by_length: false
|
36 |
+
bf16: True
|
37 |
+
tf32: True
|
38 |
+
resume_from_checkpoint:
|
39 |
+
local_rank:
|
40 |
+
deepspeed:
|
configs/pythia_1_2B_alpaca.yml
CHANGED
@@ -13,22 +13,24 @@ datasets:
|
|
13 |
type: gpteacher
|
14 |
val_set_size: 0.05
|
15 |
adapter: lora
|
|
|
16 |
sequence_len: 2048
|
17 |
lora_r: 8
|
18 |
lora_alpha: 32
|
19 |
lora_dropout: 0.05
|
20 |
lora_target_modules:
|
21 |
- query_key_value
|
|
|
22 |
lora_fan_in_fan_out: true # pythia/GPTNeoX lora specific
|
23 |
wandb_project: pythia-1.4b-lora
|
24 |
wandb_watch:
|
25 |
wandb_run_name:
|
26 |
wandb_log_model: checkpoint
|
27 |
output_dir: ./lora-alpaca
|
28 |
-
batch_size:
|
29 |
micro_batch_size: 4
|
30 |
num_epochs: 5
|
31 |
-
learning_rate: 0.
|
32 |
train_on_inputs: false
|
33 |
group_by_length: false
|
34 |
bf16: True
|
|
|
13 |
type: gpteacher
|
14 |
val_set_size: 0.05
|
15 |
adapter: lora
|
16 |
+
lora_model_dir:
|
17 |
sequence_len: 2048
|
18 |
lora_r: 8
|
19 |
lora_alpha: 32
|
20 |
lora_dropout: 0.05
|
21 |
lora_target_modules:
|
22 |
- query_key_value
|
23 |
+
# - xxx
|
24 |
lora_fan_in_fan_out: true # pythia/GPTNeoX lora specific
|
25 |
wandb_project: pythia-1.4b-lora
|
26 |
wandb_watch:
|
27 |
wandb_run_name:
|
28 |
wandb_log_model: checkpoint
|
29 |
output_dir: ./lora-alpaca
|
30 |
+
batch_size: 48
|
31 |
micro_batch_size: 4
|
32 |
num_epochs: 5
|
33 |
+
learning_rate: 0.00001
|
34 |
train_on_inputs: false
|
35 |
group_by_length: false
|
36 |
bf16: True
|
scripts/finetune.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import math
|
2 |
import os
|
|
|
3 |
import signal
|
4 |
import sys
|
5 |
from pathlib import Path
|
@@ -15,7 +16,7 @@ from peft import (
|
|
15 |
LoraConfig,
|
16 |
get_peft_model,
|
17 |
prepare_model_for_int8_training,
|
18 |
-
get_peft_model_state_dict,
|
19 |
)
|
20 |
from torch import nn
|
21 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
@@ -94,12 +95,16 @@ def load_model(base_model, model_type, tokenizer_type, cfg, adapter="lora"):
|
|
94 |
bias="none",
|
95 |
task_type="CAUSAL_LM",
|
96 |
)
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
98 |
if cfg.ddp:
|
99 |
model.to(f"cuda:{cfg.local_rank}")
|
100 |
|
101 |
# TODO resume_from_checkpoint handling
|
102 |
-
|
103 |
model.print_trainable_parameters()
|
104 |
return model, tokenizer, lora_config
|
105 |
|
@@ -152,6 +157,26 @@ def check_dataset_labels(dataset, tokenizer):
|
|
152 |
print("\n\n\n")
|
153 |
|
154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
def choose_config(path: Path):
|
156 |
yaml_files = [file for file in path.glob("*.yml")]
|
157 |
|
@@ -180,7 +205,7 @@ def train(
|
|
180 |
config: Path = Path("configs/"),
|
181 |
**kwargs,
|
182 |
):
|
183 |
-
if config.is_dir():
|
184 |
config = choose_config(config)
|
185 |
|
186 |
# load the config from the yaml file
|
@@ -214,41 +239,55 @@ def train(
|
|
214 |
model, tokenizer, lora_config = load_model(
|
215 |
cfg.base_model, cfg.model_type, cfg.tokenizer_type, cfg, adapter=cfg.adapter
|
216 |
)
|
|
|
|
|
|
|
|
|
|
|
217 |
datasets = []
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
AlpacaPrompter(), tokenizer, cfg.train_on_inputs, cfg.sequence_len
|
225 |
-
)
|
226 |
-
ds_wrapper = TokenizedPromptDataset(ds_strategy, ds["train"])
|
227 |
-
datasets.append(ds_wrapper)
|
228 |
-
elif d.type == "gpteacher":
|
229 |
-
ds_strategy = GPTeacherPromptTokenizingStrategy(
|
230 |
-
GPTeacherPrompter(), tokenizer, cfg.train_on_inputs, cfg.sequence_len
|
231 |
-
)
|
232 |
-
ds_wrapper = TokenizedPromptDataset(ds_strategy, ds["train"])
|
233 |
-
datasets.append(ds_wrapper)
|
234 |
-
elif d.type == "sharegpt":
|
235 |
-
ds_strategy = ShareGPTPromptTokenizingStrategy(
|
236 |
-
ShareGPTPrompter(), tokenizer, cfg.train_on_inputs, cfg.sequence_len
|
237 |
)
|
238 |
-
ds_wrapper = TokenizedPromptDataset(ds_strategy, ds["train"])
|
239 |
-
datasets.append(ds_wrapper)
|
240 |
-
constant_len_dataset = ConstantLengthDataset(
|
241 |
-
tokenizer, datasets, seq_length=cfg.sequence_len
|
242 |
-
)
|
243 |
-
constant_len_dataset = Dataset.from_list(
|
244 |
-
[_ for _ in constant_len_dataset]
|
245 |
-
).train_test_split(test_size=cfg.val_set_size, shuffle=True, seed=42)
|
246 |
-
|
247 |
-
print(constant_len_dataset)
|
248 |
-
train_dataset = constant_len_dataset["train"]
|
249 |
-
eval_dataset = constant_len_dataset["test"]
|
250 |
|
251 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
|
253 |
total_num_steps = int(
|
254 |
math.ceil(len(train_dataset) * cfg.num_epochs / cfg.batch_size)
|
|
|
1 |
import math
|
2 |
import os
|
3 |
+
import random
|
4 |
import signal
|
5 |
import sys
|
6 |
from pathlib import Path
|
|
|
16 |
LoraConfig,
|
17 |
get_peft_model,
|
18 |
prepare_model_for_int8_training,
|
19 |
+
get_peft_model_state_dict, PeftModel,
|
20 |
)
|
21 |
from torch import nn
|
22 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
|
95 |
bias="none",
|
96 |
task_type="CAUSAL_LM",
|
97 |
)
|
98 |
+
|
99 |
+
if cfg.lora_model_dir:
|
100 |
+
model = PeftModel.from_pretrained(model, cfg.lora_model_dir, device_map = cfg.device_map, torch_dtype=torch.float16)
|
101 |
+
else:
|
102 |
+
model = get_peft_model(model, lora_config)
|
103 |
+
|
104 |
if cfg.ddp:
|
105 |
model.to(f"cuda:{cfg.local_rank}")
|
106 |
|
107 |
# TODO resume_from_checkpoint handling
|
|
|
108 |
model.print_trainable_parameters()
|
109 |
return model, tokenizer, lora_config
|
110 |
|
|
|
157 |
print("\n\n\n")
|
158 |
|
159 |
|
160 |
+
def do_inference(cfg, model, tokenizer):
|
161 |
+
instruction = "Tell me a joke about dromedaries."
|
162 |
+
input = ""
|
163 |
+
prompt = "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.\n\n### Instruction:\n{instruction}\n\n### Input:\n{input}\n\n### Response:\n".format(instruction=instruction, input=input)
|
164 |
+
batch = tokenizer(prompt, return_tensors="pt", add_special_tokens=False)
|
165 |
+
with torch.no_grad():
|
166 |
+
generated = model.generate(inputs=batch["input_ids"],
|
167 |
+
do_sample=True, use_cache=True,
|
168 |
+
repetition_penalty=1.1,
|
169 |
+
max_new_tokens=50,
|
170 |
+
temperature=0.9,
|
171 |
+
top_p=0.95,
|
172 |
+
top_k=40,
|
173 |
+
return_dict_in_generate=True,
|
174 |
+
output_attentions=False,
|
175 |
+
output_hidden_states=False,
|
176 |
+
output_scores=False)
|
177 |
+
print(tokenizer.decode(generated['sequences'].cpu().tolist()[0]))
|
178 |
+
|
179 |
+
|
180 |
def choose_config(path: Path):
|
181 |
yaml_files = [file for file in path.glob("*.yml")]
|
182 |
|
|
|
205 |
config: Path = Path("configs/"),
|
206 |
**kwargs,
|
207 |
):
|
208 |
+
if Path(config).is_dir():
|
209 |
config = choose_config(config)
|
210 |
|
211 |
# load the config from the yaml file
|
|
|
239 |
model, tokenizer, lora_config = load_model(
|
240 |
cfg.base_model, cfg.model_type, cfg.tokenizer_type, cfg, adapter=cfg.adapter
|
241 |
)
|
242 |
+
|
243 |
+
if "inference" in kwargs:
|
244 |
+
do_inference(cfg, model, tokenizer)
|
245 |
+
return
|
246 |
+
|
247 |
datasets = []
|
248 |
+
if len(cfg.datasets) == 1 and cfg.datasets[0].type == "arrow":
|
249 |
+
dataset = load_dataset(cfg.datasets[0].path, split="train")
|
250 |
+
else:
|
251 |
+
for d in cfg.datasets:
|
252 |
+
ds: IterableDataset = load_dataset(
|
253 |
+
"json", data_files=d.path, streaming=True, split=None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
|
256 |
+
if d.type == "alpaca":
|
257 |
+
ds_strategy = AlpacaPromptTokenizingStrategy(
|
258 |
+
AlpacaPrompter(), tokenizer, cfg.train_on_inputs, cfg.sequence_len
|
259 |
+
)
|
260 |
+
ds_wrapper = TokenizedPromptDataset(ds_strategy, ds["train"])
|
261 |
+
datasets.append(ds_wrapper)
|
262 |
+
elif d.type == "gpteacher":
|
263 |
+
ds_strategy = GPTeacherPromptTokenizingStrategy(
|
264 |
+
GPTeacherPrompter(), tokenizer, cfg.train_on_inputs, cfg.sequence_len
|
265 |
+
)
|
266 |
+
ds_wrapper = TokenizedPromptDataset(ds_strategy, ds["train"])
|
267 |
+
datasets.append(ds_wrapper)
|
268 |
+
elif d.type == "sharegpt":
|
269 |
+
ds_strategy = ShareGPTPromptTokenizingStrategy(
|
270 |
+
ShareGPTPrompter(), tokenizer, cfg.train_on_inputs, cfg.sequence_len
|
271 |
+
)
|
272 |
+
ds_wrapper = TokenizedPromptDataset(ds_strategy, ds["train"])
|
273 |
+
datasets.append(ds_wrapper)
|
274 |
+
constant_len_dataset = ConstantLengthDataset(
|
275 |
+
tokenizer, datasets, seq_length=cfg.sequence_len
|
276 |
+
)
|
277 |
+
dataset = Dataset.from_list(
|
278 |
+
[_ for _ in constant_len_dataset]
|
279 |
+
).train_test_split(test_size=cfg.val_set_size, shuffle=True, seed=42)
|
280 |
+
dataset.save_to_disk("data/last_run")
|
281 |
+
print(dataset)
|
282 |
+
|
283 |
+
train_dataset = dataset["train"]
|
284 |
+
eval_dataset = dataset["test"]
|
285 |
+
|
286 |
+
if cfg.debug:
|
287 |
+
check_dataset_labels(
|
288 |
+
train_dataset.select([random.randrange(0, len(train_dataset) - 1)]),
|
289 |
+
tokenizer,
|
290 |
+
)
|
291 |
|
292 |
total_num_steps = int(
|
293 |
math.ceil(len(train_dataset) * cfg.num_epochs / cfg.batch_size)
|