cyberagent/calm2-7bをQLoRAで語尾をござるにする

環境

参考サイト

note.com

準備

ライブラリのインストール

QLoRAをcloneをして、ライブラリをインストールします

# パッケージのインストール
!git clone https://github.com/artidoro/qlora
%cd qlora
!pip install -U -r requirements.txt

qlora.pyの変更

学習をするために、qlora.py を変更します

573行目あたりの以下で、使用するデータセット名に書き換えます

     def load_data(dataset_name):
         if dataset_name == 'alpaca':
-            return load_dataset("tatsu-lab/alpaca")
+            return load_dataset("bbz662bbz/databricks-dolly-15k-ja-gozarinnemon")
         elif dataset_name == 'alpaca-clean':
             return load_dataset("yahma/alpaca-cleaned")
         elif dataset_name == 'chip2':

次に704行目あたりの以下で、パラメータを追加します

     model, tokenizer = get_accelerate_model(args, checkpoint_dir)
 
     model.config.use_cache = False
+    model.config.pretraining_tp = 1
     print('loaded model')
     set_seed(args.seed)

学習

以下のようなスクリプト作成して、CALM2を使って学習をします

# 学習の実行
!python qlora.py \
    --model_name cyberagent/calm2-7b \
    --output_dir "./output/calm_peft" \
    --dataset "alpaca" \
    --max_steps 1000 \
    --use_auth \
    --logging_steps 10 \
    --save_strategy steps \
    --data_seed 42 \
    --save_steps 50 \
    --save_total_limit 40 \
    --max_new_tokens 32 \
    --dataloader_num_workers 1 \
    --group_by_length \
    --logging_strategy steps \
    --remove_unused_columns False \
    --do_train \
    --lora_r 64 \
    --lora_alpha 16 \
    --lora_modules all \
    --double_quant \
    --quant_type nf4 \
    --bf16 \
    --bits 4 \
    --warmup_ratio 0.03 \
    --lr_scheduler_type constant \
    --gradient_checkpointing \
    --source_max_len 16 \
    --target_max_len 512 \
    --per_device_train_batch_size 1 \
    --gradient_accumulation_steps 16 \
    --eval_steps 187 \
    --learning_rate 0.0002 \
    --adam_beta2 0.999 \
    --max_grad_norm 0.3 \
    --lora_dropout 0.1 \
    --weight_decay 0.0 \
    --seed 0 \
    --load_in_4bit \
    --use_peft \
    --batch_size 4 \
    --gradient_accumulation_steps 2

学習したモデルで推論

以下でモデルをロードして、実際に推論してみます

import torch
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

# トークナイザーとモデルの読み込み
tokenizer = AutoTokenizer.from_pretrained(
    "cyberagent/calm2-7b-chat"
)
model = AutoModelForCausalLM.from_pretrained(
    "cyberagent/calm2-7b-chat",
    quantization_config=BitsAndBytesConfig(
        load_in_4bit=True,
        bnb_4bit_use_double_quant=True,
        bnb_4bit_quant_type="nf4",
        bnb_4bit_compute_dtype=torch.bfloat16
    ),
    device_map={"":0}
)
# LoRAの読み込み
model = PeftModel.from_pretrained(
    model,
    "./output/calm_peft/checkpoint-1000/adapter_model/",
    device_map={"":0}
)
model.eval()

# プロンプトの準備
prompt = "### Instruction: 富士山とは?\n\n### Response: "

# 推論の実行
inputs = tokenizer(prompt, return_tensors="pt").to("cuda:0")
with torch.no_grad():
    outputs = model.generate(**inputs, max_new_tokens=100)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

結果は以下のようになりました!無事に語尾が変わっていますね

### Instruction: 富士山とは?

### Response: 富士山は、日本の山の一つでござる。知らんけど。

備考

ValueError: Tokenizer class GPTNeoXTokenizer does not exist or is not currently imported.のエラー対応

以下のissueの対応を行う

github.com

346行目あたりの以下の部分を use_fast=True にする

    # Tokenizer
    tokenizer = AutoTokenizer.from_pretrained(
        args.model_name_or_path,
        cache_dir=args.cache_dir,
        padding_side="right",
        use_fast=True, # Fast tokenizer giving issues.
        tokenizer_type='llama' if 'llama' in args.model_name_or_path else None, # Needed for HF name change
        trust_remote_code=args.trust_remote_code,
        use_auth_token=args.use_auth_token,
    )