Views
No views yet
1# llm-jp/llm-jp-3-13bを4bit量子化のqLoRA設定でロード。
2
3from unsloth import FastLanguageModel
4import torch
5max_seq_length = 512 # unslothではRoPEをサポートしているのでコンテキスト長は自由に設定可能
6dtype = None # Noneにしておけば自動で設定
7load_in_4bit = True # 今回は13Bモデルを扱うためTrue
8
9model_id = "llm-jp/llm-jp-3-13b"
10new_model_id = "llm-jp-3-13b-it" #Fine-Tuningしたモデルにつけたい名前、it: Instruction Tuning
11# FastLanguageModel インスタンスを作成
12model, tokenizer = FastLanguageModel.from_pretrained(
13 model_name=model_id,
14 dtype=dtype,
15 load_in_4bit=load_in_4bit,
16 trust_remote_code=True,
17)
18
19# SFT用のモデルを用意
20model = FastLanguageModel.get_peft_model(
21 model,
22 r = 32,
23 target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
24 "gate_proj", "up_proj", "down_proj",],
25 lora_alpha = 32,
26 lora_dropout = 0.05,
27 bias = "none",
28 use_gradient_checkpointing = "unsloth",
29 random_state = 3407,
30 use_rslora = False,
31 loftq_config = None,
32 max_seq_length = max_seq_length,
33)
34
35# 学習用のデータセットをロード
36from datasets import load_dataset
37
38dataset = load_dataset("json", data_files="./ichikara-instruction-003-001-1.json")
39
40
41# 学習時のプロンプトフォーマットの定義
42prompt = """### 指示
43{}
44### 回答
45{}"""
46
47
48"""
49formatting_prompts_func: 各データをプロンプトに合わせた形式に合わせる
50"""
51EOS_TOKEN = tokenizer.eos_token # トークナイザーのEOSトークン(文末トークン)
52def formatting_prompts_func(examples):
53 input = examples["text"] # 入力データ
54 output = examples["output"] # 出力データ
55 text = prompt.format(input, output) + EOS_TOKEN # プロンプトの作成
56 return { "formatted_text" : text, } # 新しいフィールド "formatted_text" を返す
57pass
58
59# # 各データにフォーマットを適用
60dataset = dataset.map(
61 formatting_prompts_func,
62 num_proc= 4, # 並列処理数を指定
63)
64
65dataset
66
67# 学習の諸設定
68from trl import SFTTrainer
69from transformers import TrainingArguments
70from unsloth import is_bfloat16_supported
71
72trainer = SFTTrainer(
73 model = model,
74 tokenizer = tokenizer,
75 train_dataset=dataset["train"],
76 max_seq_length = max_seq_length,
77 dataset_text_field="formatted_text",
78 packing = False,
79 args = TrainingArguments(
80 per_device_train_batch_size = 2,
81 gradient_accumulation_steps = 4,
82 num_train_epochs = 1,
83 logging_steps = 10,
84 warmup_steps = 10,
85 save_steps=100,
86 save_total_limit=2,
87 max_steps=-1,
88 learning_rate = 2e-4,
89 fp16 = not is_bfloat16_supported(),
90 bf16 = is_bfloat16_supported(),
91 group_by_length=True,
92 seed = 3407,
93 output_dir = "outputs",
94 report_to = "none",
95 ),
96)
97
98#@title 学習実行
99trainer_stats = trainer.train()
100
101
102# ELYZA-tasks-100-TVの読み込み。事前にファイルをアップロードしてください
103# データセットの読み込み。
104# omnicampusの開発環境では、左にタスクのjsonlをドラッグアンドドロップしてから実行。
105import json
106datasets = []
107with open("/content//elyza-tasks-100-TV_0.jsonl", "r") as f:
108 item = ""
109 for line in f:
110 line = line.strip()
111 item += line
112 if item.endswith("}"):
113 datasets.append(json.loads(item))
114 item = ""
115
116
117# 学習したモデルを用いてタスクを実行
118from tqdm import tqdm
119
120# 推論するためにモデルのモードを変更
121FastLanguageModel.for_inference(model)
122
123results = []
124for dt in tqdm(datasets):
125 input = dt["input"]
126
127 prompt = f"""### 指示\n{input}\n### 回答\n"""
128
129 inputs = tokenizer([prompt], return_tensors = "pt").to(model.device)
130
131 outputs = model.generate(**inputs, max_new_tokens = 512, use_cache = True, do_sample=False, repetition_penalty=1.2)
132 prediction = tokenizer.decode(outputs[0], skip_special_tokens=True).split('\n### 回答')[-1]
133
134 results.append({"task_id": dt["task_id"], "input": input, "output": prediction})
135
136# jsonlで保存
137with open(f"{new_model_id}_output.jsonl", 'w', encoding='utf-8') as f:
138 for result in results:
139 json.dump(result, f, ensure_ascii=False)
140 f.write('\n')
141
142# LoRAアダプタだけ保存
143model.push_to_hub_merged(
144 new_model_id+"_lora",
145 tokenizer=tokenizer,
146 save_method="lora",
147 token="your_token",
148 private=True
149)
150