さくらのクラウドのGPUサーバ(Tesla V100)で商用利用可能なLLM Dollyを動かす

商用利用可能なOSSのLLM、Dollyが登場しました。
さくらのクラウドのGPUサーバで動くか確認してみます。

https://huggingface.co/databricks/dolly-v2-3b

# 1.GPUサーバの作成
さくらのクラウドのコントロールパネルから、石狩第1ゾーンを選択し、サーバ追加画面を開きます。
サーバプランは `GPUプラン` を選択、ディスクのアーカイブは `Ubuntu 22.04.1 LTS` を選択します。
ディスクサイズは `100GB` を選択します。

![スクリーンショット 2023-03-17 10.26.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58803/25cfba44-9a3e-d1e1-804f-f1a94bf8b68e.png)

# 2.GPUドライバのインストール
GPUサーバが完成したら、SSHでログインします。

NVIDIAのドキュメント通りにインストールを行う。
https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html

```shell-session
$ sudo apt-get install linux-headers-$(uname -r)
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID | sed -e 's/\.//g')
$ wget https://developer.download.nvidia.com/compute/cuda/repos/$distribution/x86_64/cuda-keyring_1.0-1_all.deb
$ sudo dpkg -i cuda-keyring_1.0-1_all.deb
$ sudo apt-get update
$ sudo apt-get -y install cuda-drivers
```

インストールが終わったら再起動を行う。

# 3.pythonライブラリのインストール
```shell
$ pip3 install accelerate>=0.12.0 transformers[torch]==4.25.1
```


# 4.サンプルコードを動かしてみる(dolly-v2-3b)
dolly-v2-3bをまずは動かしてみます。

```python
>>> import torch
>>> from transformers import pipeline
>>> generate_text = pipeline(model="databricks/dolly-v2-3b", torch_dtype=torch.bfloat16, trust_remote_code=True, device_map="auto")
Downloading (…)lve/main/config.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 820/820 [00:00<00:00, 403kB/s]
Downloading (…)instruct_pipeline.py: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 9.10k/9.10k [00:00<00:00, 4.57MB/s]
Downloading pytorch_model.bin: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5.68G/5.68G [01:05<00:00, 86.3MB/s]
Downloading (…)okenizer_config.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 450/450 [00:00<00:00, 201kB/s]
Downloading (…)/main/tokenizer.json: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2.11M/2.11M [00:00<00:00, 4.80MB/s]
Downloading (…)cial_tokens_map.json: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 228/228 [00:00<00:00, 94.3kB/s]
>>>
>>> generate_text("Explain to me the difference between nuclear fission and fusion.")
[{'generated_text': 'Nuclear fission occurs when a subatomic particle known as a neutron hits a uranium atom, ejecting two particles: a proton and an electron. The nucleus of the atom splits in half, and two free neutrons are formed. These fission further the nucleus, creating several atoms that have lost a neutron, each of which is a smaller atomic nucleus with a single proton and electron. Atoms of this type are called fission products and include carbon, nitrogen, and oxygen. \n\nIn contrast, when two atoms touch and collide head on, and they contain nuclei with a high atomic number, their nuclei fuse to form a more massive nucleus. This is called fusion. For example, hydrogen fusion to create deuterium, or two deuterium nuclei to form tritium. In addition, fusion occurs in stars to create heavy elements.'}]
```

問いが自分の専門分野外なので正しいかは分かりませんが、大体合っていそうな返答が得られました。

## 日本語で問いかけてみる
20秒ほどくらいかかって以下の返答が得られました。

```python
>>> generate_text("おはようございます")
[{'generated_text': 'こんにちわっしょいです。めっteriorみませんか。こんにちわっしょいです。めっteriorみませんか。めっteriorみです。'}]
```

実行時のGPUメモリに余裕があるため、 `torch_dtype=torch.bfloat16` という引数は外しても動くようです。
```python
>>> import torch
>>> from transformers import pipeline
>>> generate_text = pipeline(model="databricks/dolly-v2-3b", trust_remote_code=True, device_map="auto")
>>> generate_text("おはようございます")
[{'generated_text': '今日はうれしいことだったのではないでしょうか！？（うれしいことには大体どれかということです）？！？'}]
```

# 5.サンプルコードを動かしてみる(dolly-v2-7b)
```python
>>> import torch
>>> from transformers import pipeline
>>> generate_text = pipeline(model="databricks/dolly-v2-7b", torch_dtype=torch.bfloat16, trust_remote_code=True, device_map="auto")
Downloading (…)lve/main/config.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 820/820 [00:00<00:00, 452kB/s]
Downloading (…)instruct_pipeline.py: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 9.10k/9.10k [00:00<00:00, 4.12MB/s]
Downloading pytorch_model.bin: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 13.8G/13.8G [04:50<00:00, 47.7MB/s]
Downloading (…)okenizer_config.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 450/450 [00:00<00:00, 178kB/s]
Downloading (…)/main/tokenizer.json: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2.11M/2.11M [00:00<00:00, 3.61MB/s]
Downloading (…)cial_tokens_map.json: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 228/228 [00:00<00:00, 91.1kB/s]
>>> res = generate_text("Explain to me the difference between nuclear fission and fusion.")
>>> print(res[0]["generated_text"])
Nuclear fission and fusion are both processes where two very heavy nuclei combine to create a single lighter nucleus. This process releases huge amounts of energy. Nuclear fission, also known as atomic splitting, occurs when a heavy nucleus is split in two. This releases a tremendous amount of energy compared to fusion, where two nuclei slam together and create a single even bigger nucleus.
```

## 日本語で問いかけてみる
まともな返答が得られました。

```python
>>> res = generate_text("おはようございます")
>>> print(res[0]["generated_text"])
おはようですね。
今日も朝となってきました。皆さんも朝起きましたか。
そう、朝起きましたね。普段と変わりません。
```

# 6.サンプルコードを動かしてみる(dolly-v2-12b)
```python
>>> import torch
>>> from transformers import pipeline
>>>
>>> generate_text = pipeline(model="databricks/dolly-v2-12b", torch_dtype=torch.bfloat16, trust_remote_code=True, device_map="auto")
Downloading (…)lve/main/config.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 819/819 [00:00<00:00, 396kB/s]
Downloading (…)instruct_pipeline.py: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 9.10k/9.10k [00:00<00:00, 5.14MB/s]
Downloading pytorch_model.bin: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 23.8G/23.8G [07:23<00:00, 53.8MB/s]
Downloading (…)okenizer_config.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 449/449 [00:00<00:00, 124kB/s]
Downloading (…)/main/tokenizer.json: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2.11M/2.11M [00:00<00:00, 6.77MB/s]
Downloading (…)cial_tokens_map.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 228/228 [00:00<00:00, 121kB/s]
>>> res = generate_text("Explain to me the difference between nuclear fission and fusion.")
>>> print(res[0]["generated_text"])
Nuclear fusion occurs when two lighter nuclei join to become one larger nucleus. This process releases energy. Nuclear fusion helps to provide the light output needed for Earth to maintain life.

Nuclear fission is a process in which one heavy nucleus breaks up into two or more lighter nuclei. In this process, energy is not released. However, the heavy nucleus becomes a less stable configuration. This is why nuclear fission is an important energy source for some nuclear power plants.
```

## 日本語で問いかけてみる
なかなか日本語で返してくれないようです。
```python
>>> res = generate_text("おはようございます")
>>> print(res[0]["generated_text"])
Good morning.
>>> res = generate_text("おはようございます")
>>> print(res[0]["generated_text"])
Good morning.
>>> res = generate_text("おはようございます")
>>> print(res[0]["generated_text"])
Good morning.
>>> res = generate_text("おはようございます")
>>> print(res[0]["generated_text"])
おはようございます。まだお値ご利bridleも上がっていません。明るいですね。明るくしてください。

現在日本でおすすめされている英語の勉強法は？
```

# 感想
環境構築がシンプルですぐに動かす環境ができました。
Tesla V100でパラメータが12 billionのモデルでも動きました。
今後LangChainを使って何か作ってみたいと思います。