BloomをLoRaを使い日本語alpaca datasetでfine tuneを動かす

llamaをAlpacaデータセットを使いLoRaでfine tuneしたものが良い感じだったので、Bloomを日本語でfine tuneしてみようと思う

以下をそのまま参考にする

https://github.com/tloen/alpaca-lora

**とりあえず、fine funeを動かしただけで、ちゃんと学習させてないので注意**

HugginfaceのBloomとpeftも参考にする

https://github.com/huggingface/transformers/blob/main/src/transformers/models/bloom/modeling_bloom.py#L622

https://github.com/huggingface/peft

## fine tune

fine tune対象をBloomに変更

```python:finetune.py
model = LlamaForCausalLM.from_pretrained(
    "decapoda-research/llama-7b-hf",
    load_in_8bit=True,
    device_map=device_map,
)
tokenizer = LlamaTokenizer.from_pretrained(
    "decapoda-research/llama-7b-hf", add_eos_token=True
)
```
[https://github.com/tloen/alpaca-lora/blob/main/finetune.py#L47-L54](https://github.com/tloen/alpaca-lora/blob/main/finetune.py#L47-L54)

こんな感じで良さそう。一旦動かしたいので小さいモデルを使う

```python
model_name = "bigscience/bloom-560m"
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    load_in_8bit=True,
    device_map=device_map,
)
tokenizer = AutoTokenizer.from_pretrained(
    model_name,add_eos_token=True
)
```


LoraConfigの`target_modules`をBloom用に変更

```python:finetune.py
config = LoraConfig(
    r=LORA_R,
    lora_alpha=LORA_ALPHA,
    target_modules=TARGET_MODULES,
    lora_dropout=LORA_DROPOUT,
    bias="none",
    task_type="CAUSAL_LM",
)
```

[https://github.com/tloen/alpaca-lora/blob/main/finetune.py#L58-L65](https://github.com/tloen/alpaca-lora/blob/main/finetune.py#L58-L65)


huggingfaceのpeftを見ると、以下を指定すれば良さそう。

```python:mapping.py
  "bloom": ["query_key_value"],
```

[https://github.com/huggingface/peft/blob/main/src/peft/mapping.py#L46](https://github.com/huggingface/peft/blob/main/src/peft/mapping.py#L46)

llamaやOPTだと、queryとvalue layerのみを指定しているが、Bloomの場合query_key_valueすべて指定している。Bloomのlayerがそもそもquery, key, valueが１つのLayerになっているので、こういう指定なのかもしれないが、key layerはできるだけ低ランクにしないほうが良いとかあるんでしょうか？？
詳しい方コメント下さい。


このあたりも日本語にしとく

```python:finetune.py
user_prompt = (
        (
            f"""Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
```

[https://github.com/tloen/alpaca-lora/blob/main/finetune.py#L112](https://github.com/tloen/alpaca-lora/blob/main/finetune.py#L112)

データセットは、DeepLを使って翻訳した。
とりあえず動かしたかったので、一部のみ

```
{
    "instruction": "波ではなく、神の手を見る」の意味を説明する。", 
    "input": "", 
    "output": "私は波を見ず、神の手を見る」という言葉は、しばしば信仰の力を表現するために使われます。これは、どんな逆境に立たされても、最終的には神が支配し、激動の時代を導いてくれることを意味しています。困難に目を向けるのではなく、信仰を強く持ち、神の計画を信じるべきだということを示唆しています。"
    }, 
{
    "instruction": "平均年齢を算出する。", 
    "input": "ジェームズ - 22\nマルティナ - 18\nジョニー - 26", 
    "output": "22.3"
}, 
{
    "instruction": "xが4、yが7のとき、x÷yを計算する。", 
    "input": "", 
    "output": "0.5714285714285714"
}
```

あとは、`python finetune.py`で動かすだけ

## genarate

以下を参考に、Bloomとfinetuneしたweightをロードする

```python:finetune.py
  model = LlamaForCausalLM.from_pretrained(
        BASE_MODEL,
        load_in_8bit=True,
        torch_dtype=torch.float16,
        device_map="auto",
    )
    model = PeftModel.from_pretrained(model, LORA_WEIGHTS, torch_dtype=torch.float16)
```

[https://github.com/tloen/alpaca-lora/blob/main/generate.py#L28-L34](https://github.com/tloen/alpaca-lora/blob/main/generate.py#L28-L34)

デフォルトで`./lora-alpaca`以下に`adapter_config.json`と`adapter_model.bin`が生成されるので、`PeftModel`のロードには、`./lora-alpaca`を指定する。

modelとweightのロードは以下のような感じ

```python
BASE_MODEL = "bigscience/bloom-560m"
model = AutoModelForCausalLM.from_pretrained(
    BASE_MODEL,
    load_in_8bit=True,
    torch_dtype=torch.float16,
    device_map="auto",
)
LORA_WEIGHTS = './lora-alpaca'
model = PeftModel.from_pretrained(
    model,
    LORA_WEIGHTS,
    torch_dtype=torch.float16,   
)
```

あとは、`python generate.py`で動かす

動作確認は、以下のコメントアウトされてる部分を復活させて動かした

```python:generate.py
if __name__ == "__main__":
    # testing code for readme
    for instruction in [
```

[https://github.com/tloen/alpaca-lora/blob/main/generate.py#L144](https://github.com/tloen/alpaca-lora/blob/main/generate.py#L144)

## まとめ
alpaca data setを使ってLoRaでBloomをfine tuneしてみた。
ここまでで、とりあえずfine tuneのコードが動くことは確認できた。
ざっくり動かしただけなので間違っているところがあればコメント下さい

ライセンス的にllamaよりBloomのほうが使いやすそうなのと、試せてないがcppもあるみたいなのでinferenceもローカルの環境で動かせそうなので期待

https://github.com/NouamaneTazi/bloomz.cpp

次は、Bloom用のparameterの調整やモデルサイズ、alpaca data setを全体を使って試そうと思う。