Views
No views yet
llm-jp/llm-jp-3-13b)を用いて入力データ(elyza-tasks-100-TV_0.jsonl)を推論し、その結果をllm-jp/llm-jp-3-13b-outputs.jsonlというファイルに出力できます。1!pip install -U bitsandbytes
2!pip install -U transformers
3!pip install -U accelerate
4!pip install -U datasets
5!pip install -U pef
6!pip install ipywidgets --upgrade1from google.colab import userdata
2HF_TOKEN = userdata.get('HF_TOKEN')1import torch
2from transformers import (
3 AutoModelForCausalLM,
4 AutoTokenizer,
5 BitsAndBytesConfig,
6)
7from peft import PeftModel
8import json
9from tqdm import tqdm
10import re
11
12base_model_id = "models/models--llm-jp--llm-jp-3-13b/snapshots/cd3823f4c1fcbb0ad2e2af46036ab1b0ca13192a"
13new_model_id = "llm-jp-3-13b-finetune"
14
15# QLoRA用の設定
16bnb_config = BitsAndBytesConfig(
17 load_in_4bit=True,
18 bnb_4bit_quant_type="nf4",
19 bnb_4bit_compute_dtype=torch.bfloat16,
20)
21
22# モデル読み込み
23model = AutoModelForCausalLM.from_pretrained(
24 model_id,
25 quantization_config=bnb_config,
26 device_map="auto"
27)
28
29tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
30
31def find_all_linear_names(model):# モデル内の4bit量子化線形層を探します。
32 cls = bnb.nn.Linear4bit # 4bit量子化線形層クラスを指定
33 lora_module_names = set() # ここに取得した線形層を保持します。
34
35 # モデル内の全てのモジュールを探索します
36 for name, module in model.named_modules():
37 if isinstance(module, cls): # モジュールが4bit量子化線形層の場合
38 names = name.split('.') # モジュールの名前を分割 (ネストされてる際などに対処)
39 lora_module_names.add(names[0] if len(names) == 1 else names[-1]) # 最下層の名前をlora_module_namesに追加
40
41 # 'lm_head' は16ビット演算の際に除外する必要があるため、lora_module_namesから削除
42 if 'lm_head' in lora_module_names:
43 lora_module_names.remove('lm_head')
44
45 return list(lora_module_names) # lora_module_namesをリストに変換して返します。
46
47modules = find_all_linear_names(model)
48
49# Peftモデルを適用
50peft_config = LoraConfig(
51 r=16,
52 lora_alpha=32,
53 lora_dropout=0.05,
54 bias="none",
55 task_type="CAUSAL_LM",
56 target_modules=modules,
57)
58
59model = get_peft_model(model, peft_config)ichikara-instruction-003-001-1.jsonというファイルからデータセットをロードします。1
2dataset = load_dataset("json", data_files="./ichikara-instruction-003-001-1.json")
3dataset
4
5# 学習時のプロンプトフォーマットの定義
6prompt = """### 指示
7{}
8### 回答
9{}"""
10
11
12"""
13formatting_prompts_func: 各データをプロンプトに合わせた形式に合わせる
14"""
15EOS_TOKEN = tokenizer.eos_token # トークナイザーのEOSトークン(文末トークン)
16def formatting_prompts_func(examples):
17 input = examples["text"] # 入力データ
18 output = examples["output"] # 出力データ
19 text = prompt.format(input, output) + EOS_TOKEN # プロンプトの作成
20 return { "formatted_text" : text, } # 新しいフィールド "formatted_text" を返す
21pass
22
23# # 各データにフォーマットを適用
24dataset = dataset.map(
25 formatting_prompts_func,
26 num_proc= 4, # 並列処理数を指定
27)
28
29dataset
30
31print(dataset["train"]["formatted_text"][3])1training_arguments = TrainingArguments(
2 output_dir=new_model_id,
3 per_device_train_batch_size=1,
4 gradient_accumulation_steps=2,
5 optim="paged_adamw_32bit",
6 num_train_epochs=1,
7 logging_strategy="steps",
8 logging_steps=10,
9 warmup_steps=10,
10 save_steps=100,
11 save_total_limit = 2,
12 max_steps = -1,
13 learning_rate=5e-5,
14 fp16=False,
15 bf16=False,
16 seed = 3407,
17 group_by_length=True,
18 report_to="none"
19)
20
21trainer = SFTTrainer(
22 model=model,
23 train_dataset=dataset["train"],
24 peft_config=peft_config,
25 max_seq_length= 512,
26 dataset_text_field="formatted_text",
27 tokenizer=tokenizer,
28 args=training_arguments,
29 packing= False,
30)
31
32model.config.use_cache = False # キャッシュ機能を無効化
33trainer.train() # トレーニングを実行1import json
2datasets = []
3with open("./elyza-tasks-100-TV_0.jsonl", "r") as f:
4 item = ""
5 for line in f:
6 line = line.strip()
7 item += line
8 if item.endswith("}"):
9 datasets.append(json.loads(item))
10 item = ""
11
12from tqdm import tqdm
13
14results = []
15for data in tqdm(datasets):
16
17 input = data["input"]
18
19 prompt = f"""### 指示
20 {input}
21 ### 回答
22 """
23
24 tokenized_input = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt").to(model.device)
25 attention_mask = torch.ones_like(tokenized_input)
26
27 with torch.no_grad():
28 outputs = model.generate(
29 tokenized_input,
30 attention_mask=attention_mask,
31 max_new_tokens=100,
32 do_sample=False,
33 repetition_penalty=1.2,
34 pad_token_id=tokenizer.eos_token_id
35 )[0]
36 output = tokenizer.decode(outputs[tokenized_input.size(1):], skip_special_tokens=True)
37
38 results.append({"task_id": data["task_id"], "input": input, "output": output})1import re
2jsonl_id = re.sub(".*/", "", new_model_id)
3with open(f"./{jsonl_id}-outputs.jsonl", 'w', encoding='utf-8') as f:
4 for result in results:
5 json.dump(result, f, ensure_ascii=False) # ensure_ascii=False for handling non-ASCII characters
6 f.write('\n')
7
8# モデルとトークナイザーをHugging Faceにアップロード
9model.push_to_hub(new_model_id, token=HF_TOKEN, private=True) # Online saving
10tokenizer.push_to_hub(new_model_id, token=HF_TOKEN, private=True) # Online saving