File size: 11,886 Bytes
5f4b96d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74fc7f6
 
ca1db1a
74fc7f6
 
232a6f3
74fc7f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232a6f3
74fc7f6
 
 
 
232a6f3
74fc7f6
 
232a6f3
74fc7f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232a6f3
 
 
 
 
 
 
 
 
 
 
 
 
74fc7f6
 
232a6f3
74fc7f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662dd0b
 
 
 
 
 
 
 
 
232a6f3
d6f7baa
fccd478
2be9f3c
473e620
2f526bd
fccd478
 
 
 
232a6f3
 
fccd478
232a6f3
fccd478
 
 
 
 
74fc7f6
 
fccd478
 
74fc7f6
 
fccd478
232a6f3
74fc7f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232a6f3
d53126c
74fc7f6
 
232a6f3
 
d53126c
ca1db1a
232a6f3
 
ca1db1a
 
232a6f3
ca1db1a
 
232a6f3
 
ca1db1a
 
74fc7f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fccd478
74fc7f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232a6f3
 
 
 
74fc7f6
232a6f3
74fc7f6
 
 
 
 
232a6f3
 
 
74fc7f6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
---
base_model: llm-jp/llm-jp-3-13b
tags:
- text-generation-inference
- transformers
- unsloth
- llama
- trl
license: apache-2.0
language:
- en
---

# Uploaded  model

- **Developed by:** Indy1985
- **License:** apache-2.0
- **Finetuned from model :** llm-jp/llm-jp-3-13b

This llama model was trained 2x faster with [Unsloth](https://github.com/unslothai/unsloth) and Huggingface's TRL library.

[<img src="https://raw.githubusercontent.com/unslothai/unsloth/main/images/unsloth%20made%20with%20love.png" width="200"/>](https://github.com/unslothai/unsloth)


# Sample  Use

以下は、elyza-tasks-100-TV_0.jsonlの回答のためのコードです。

```python
# Google Colab の場合は上記の環境構築手順を行なわず、単にこのセルから実行していってください。
!pip uninstall unsloth -y
!pip install --upgrade --no-cache-dir "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"


# Google Colab のデフォルトで入っているパッケージをアップグレード(Moriyasu さんありがとうございます)
!pip install --upgrade torch
!pip install --upgrade xformers


# notebookでインタラクティブな表示を可能とする(ただし、うまく動かない場合あり)
!pip install ipywidgets --upgrade

# Install Flash Attention 2 for softcapping support
import torch
if torch.cuda.get_device_capability()[0] >= 8:
    !pip install --no-deps packaging ninja einops "flash-attn>=2.6.3"


# llm-jp/llm-jp-3-13bを4bit量子化のqLoRA設定でロード。

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from unsloth import FastLanguageModel
import torch
max_seq_length = 512 # unslothではRoPEをサポートしているのでコンテキスト長は自由に設定可能
dtype = None # Noneにしておけば自動で設定
load_in_4bit = True # 今回は8Bクラスのモデルを扱うためTrue

model_id = "llm-jp/llm-jp-3-13b"
new_model_id = "llm-jp-3-13b-finetune-2" #Fine-Tuningしたモデルにつけたい名前
# FastLanguageModel インスタンスを作成
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name=model_id,
    dtype=dtype,
    load_in_4bit=load_in_4bit,
    trust_remote_code=True,
)

# SFT用のモデルを用意
model = FastLanguageModel.get_peft_model(
    model,
    r = 32,
    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
                      "gate_proj", "up_proj", "down_proj",],
    lora_alpha = 32,
    lora_dropout = 0.05,
    bias = "none",
    use_gradient_checkpointing = "unsloth",
    random_state = 3407,
    use_rslora = False,
    loftq_config = None,
    max_seq_length = max_seq_length,
)


# Hugging Face Token を指定
# 下記の URL から Hugging Face Token を取得できますので下記の HF_TOKEN に入れてください。
# https://huggingface.co/settings/tokens
HF_TOKEN = "your-token" #@param {type:"string"}

# あるいは Google Colab シークレットを使う場合、左のサイドバーより🔑マークをクリック
# HF_TOKEN という名前で Value に Hugging Face Token を入れてください。
# ノートブックからのアクセスのトグルをオンにし、下記の二行のコードのコメントアウトを外してください。

# from google.colab import userdata
# HF_TOKEN=userdata.get('HF_TOKEN')


# 学習に用いるデータセットの指定
# 今回はLLM-jp の公開している Ichikara Instruction を使います。データにアクセスするためには申請が必要ですので、使いたい方のみ申請をしてください。
# Ichikara Instruciton を Hugging Face Hub にて公開することはお控えください。

# 下記のリンクから申請を終えた先に Google Drive があり、Distribution20241221_all というフォルダごとダウンロードしてください。
# 今回は「ichikara-instruction-003-001-1.json」を使います。必要であれば展開(!unzip など)し、データセットのパスを適切に指定してください。
# omnicampusの開発環境では取得したデータを左側にドラッグアンドドロップしてお使いください。
# Google Colab の場合も左のサイドバーよりドラッグ&ドロップでアップデートしてください。

# https://liat-aip.sakura.ne.jp/wp/llmのための日本語インストラクションデータ作成/llmのための日本語インストラクションデータ-公開/
# 関根聡, 安藤まや, 後藤美知子, 鈴木久美, 河原大輔, 井之上直也, 乾健太郎. ichikara-instruction: LLMのための日本語インストラクションデータの構築. 言語処理学会第30回年次大会(2024)

from datasets import load_dataset

dataset = load_dataset("json", data_files="/content/ichikara-instruction-003-001-1.json")
# パスの指定にご注意ください。アップロードしたファイルを右クリックし、「パスをコピー」をクリック、上記の data_files と合致していることをご確認ください。Omnicampus のディレクトリ構造とは異なるかもしれません。


# 学習に用いるデータセットの指定2
# ライセンス・謝辞 
# 本コンペティションで学習に利用したクイズ問題は,「AI王 ~クイズAI日本一決定戦~」https://sites.google.com/view/project-aio/dataset において,CC BY-SA 4.0のもと提供された以下のようなデータです.記して感謝いたします.
# 第1回コンペティション 開発用データ (1,992問)「AI王 ~クイズAI日本一決定戦~」がクイズ作家に作問を依頼したクイズ問題から成るデータです.Version 1.0 で開発用データとして配布した dev1_questions.json と dev2_questions.json を連結したデータです.
# https://jaqket.s3.ap-northeast-1.amazonaws.com/data/aio_02/aio_01_dev.jsonl

# 「第1回コンペティション 開発用データ」のクイズ問題は,「AI王 ~クイズAI日本一決定戦~」が株式会社キュービック http://www.qbik.co.jp/ および クイズ法人カプリティオ http://capriccio.tokyo/ へ依頼して作成されました.
# これらのクイズ問題は,クリエイティブ・コモンズ 表示-継承 4.0 国際 ライセンス https://creativecommons.org/licenses/by-sa/4.0/deed.ja のもとに提供されています.

from datasets import load_dataset

# Load the dataset
dataset = load_dataset("json", data_files="/content/aio_01_dev.jsonl")


# Print dataset info to inspect its structure
print(dataset)  

# Check column names
print("Dataset columns:", dataset.column_names)

# Define the formatting function
def formatting_prompts_func(examples):
    # Access 'summary' instead of dynamically finding the key
    input_text = examples["original_question"]  
    return {"formatted_text": f"Processed: {input_text}"}

# Apply map function with formatting
dataset = dataset.map(
    formatting_prompts_func,
    num_proc=4,  # Parallel processing
    remove_columns=["original_question"] # remove original summary column
)

# Print the processed dataset
print(dataset)


"""
training_arguments: 学習の設定

  - output_dir:
      -トレーニング後のモデルを保存するディレクトリ

  - per_device_train_batch_size:
      - デバイスごとのトレーニングバッチサイズ

  - per_device_eval_batch_size:
      - デバイスごとの評価バッチサイズ

  - gradient_accumulation_steps:
      - 勾配を更新する前にステップを積み重ねる回数

  - optim:
      - オプティマイザの設定

  - num_train_epochs:
      - エポック数

  - eval_strategy:
      - 評価の戦略 ("no"/"steps"/"epoch")

  - eval_steps:
      - eval_strategyが"steps"のとき、評価を行うstep間隔

  - logging_strategy:
      - ログ記録の戦略

  - logging_steps:
      - ログを出力するステップ間隔

  - warmup_steps:
      - 学習率のウォームアップステップ数

  - save_steps:
      - モデルを保存するステップ間隔

  - save_total_limit:
      - 保存しておくcheckpointの数

  - max_steps:
      - トレーニングの最大ステップ数

  - learning_rate:
      - 学習率

  - fp16:
      - 16bit浮動小数点の使用設定(第8回演習を参考にすると良いです)

  - bf16:
      - BFloat16の使用設定

  - group_by_length:
      -  入力シーケンスの長さによりバッチをグループ化 (トレーニングの効率化)

  - report_to:
      - ログの送信先 ("wandb"/"tensorboard"など)
"""
from trl import SFTTrainer
from transformers import TrainingArguments
from unsloth import is_bfloat16_supported

trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset=dataset["train"],
    max_seq_length = 512,
    dataset_text_field="formatted_text",
    packing = False,
    args = TrainingArguments(
        per_device_train_batch_size = 4,
        gradient_accumulation_steps = 8,
        num_train_epochs = 1,
        logging_steps = 10,
        warmup_steps = 100,
        save_steps=500,
        save_total_limit=2,
        max_steps=-1,
        learning_rate = 3e-4,
        fp16 = not is_bfloat16_supported(),
        bf16 = is_bfloat16_supported(),
        group_by_length=False,
        seed = 42,
        output_dir = "outputs",
        report_to = "none",
    ),
)


#@title 現在のメモリ使用量を表示
gpu_stats = torch.cuda.get_device_properties(0)
start_gpu_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)
max_memory = round(gpu_stats.total_memory / 1024 / 1024 / 1024, 3)
print(f"GPU = {gpu_stats.name}. Max memory = {max_memory} GB.")
print(f"{start_gpu_memory} GB of memory reserved.")


#@title 学習実行
trainer_stats = trainer.train()


# ELYZA-tasks-100-TVの読み込み。事前にファイルをアップロードしてください
# データセットの読み込み。
# omnicampusの開発環境では、左にタスクのjsonlをドラッグアンドドロップしてから実行。
import json
datasets = []
with open("./elyza-tasks-100-TV_0.jsonl", "r") as f:
    item = ""
    for line in f:
      line = line.strip()
      item += line
      if item.endswith("}"):
        datasets.append(json.loads(item))
        item = ""


# 学習したモデルを用いてタスクを実行
from tqdm import tqdm

# 推論するためにモデルのモードを変更
FastLanguageModel.for_inference(model)

results = []
for dt in tqdm(datasets):
  input = dt["input"]

  prompt = f"""### 指示\n{input}\n### 回答\n"""

  inputs = tokenizer([prompt], return_tensors = "pt").to(model.device)

  outputs = model.generate(**inputs, max_new_tokens = 512, use_cache = True, do_sample=False, repetition_penalty=1.2)
  prediction = tokenizer.decode(outputs[0], skip_special_tokens=True).split('\n### 回答')[-1]

  results.append({"task_id": dt["task_id"], "input": input, "output": prediction})


# jsonlで保存
with open(f"{new_model_id}_output.jsonl", 'w', encoding='utf-8') as f:
    for result in results:
        json.dump(result, f, ensure_ascii=False)
        f.write('\n')


# モデルとトークナイザーをHugging Faceにアップロード。
# 一旦privateでアップロードしてください。
# 最終成果物が決まったらpublicにするようお願いします。
# 現在公開しているModel_Inference_Template.ipynbはunslothを想定していないためそのままでは動かない可能性があります。
model.push_to_hub_merged(
    new_model_id,
    tokenizer=tokenizer,
    save_method="lora",
    token=HF_TOKEN,
    private=True
)

# model.push_to_hub(new_model_id, token=HF_TOKEN, private=True) # Online saving
# tokenizer.push_to_hub(new_model_id, token=HF_TOKEN) # Online saving
```