N番煎じでLLM-jp 13BをDatabricksで動かす

N番煎じシリーズです。

下記リンク先で紹介されているLLM-jpのLLMをDatabricks上で試してみます。

https://note.com/npaka/n/n60b0abf54ed5

https://note.com/shi3zblog/n/n6e9a45dfbec6

CTranslate2での変換がうまくできなかったので、今回はTransformersでそのまま動かします。

# LLM-jpとは

国立情報学研究所が構築したLLMです。
モデルだけでなくコーパスデータも公開されており、ライセンスもApache 2.0です。

https://www.nii.ac.jp/news/release/2023/1020.html

今回は公開されているモデルのうち、Instructモデルである```llm-jp/llm-jp-13b-instruct-full-jaster-dolly-oasst-v1.0```を試します。

# 検証環境

Databricks on AWSを使って検証しています。
DBRは14.0ML、g5.2xlargeのクラスタを利用しました。

# Step1. モデルの取得と保管

[こちら](https://qiita.com/isanakamishiro2/items/4258143eb9de158cda69)とほぼ同じです。
最終的にUnity CatalogのVolumesに保管します。

```python
%pip install -U -qq transformers accelerate

dbutils.library.restartPython()
```

```python
import os
from huggingface_hub import snapshot_download

UC_VOLUME = "/Volumes/モデルの保管場所"

model = "llm-jp/llm-jp-13b-instruct-full-jaster-dolly-oasst-v1.0"
local_dir = f"/tmp/{model}"
uc_dir = "/models--llm-jp--llm-jp-13b-instruct-full-jaster-dolly-oasst-v1.0"

snapshot_location = snapshot_download(
    repo_id=model,
    local_dir=local_dir,
    local_dir_use_symlinks=False,
)

dbutils.fs.cp(f"file:{local_dir}", f"{UC_VOLUME}{uc_dir}", recurse=True)
```

# Step2. 推論準備

必要なモジュールをインストールして、モデルをロードします。

```python
%pip install -U -qq transformers accelerate bitsandbytes sentencepiece 
dbutils.library.restartPython()
```

```python
import torch
import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer

UC_VOLUME = "/Volumes/モデルの保管場所"

tokenizer_path = (
    f"{UC_VOLUME}/models--llm-jp--llm-jp-13b-instruct-full-jaster-dolly-oasst-v1.0"
)
model_path = (
    f"{UC_VOLUME}/models--llm-jp--llm-jp-13b-instruct-full-jaster-dolly-oasst-v1.0"
)

tokenizer = AutoTokenizer.from_pretrained(tokenizer_path)
# 8bit量子化で読込
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    load_in_8bit=True,
    device_map="auto",
)

# 推論用の関数
def generate_batch(instruction: str):

    prompt = f"{instruction}### 回答："

    with torch.no_grad():
        token_ids = tokenizer.encode(
            prompt, add_special_tokens=False, return_tensors="pt"
        ).to(model.device)

        output_ids = model.generate(
            token_ids.to(model.device),
            max_new_tokens=512,
            do_sample=True,
            top_p=0.95,
            temperature=0.1,
            pad_token_id=tokenizer.pad_token_id,
            eos_token_id=tokenizer.eos_token_id,
        )
    output = tokenizer.decode(output_ids.tolist()[0][token_ids.size(1) :], skip_special_tokens=True)

    return output

```
# Step3. 推論

いくつかやってみます。

## 質問

```python
generate_batch("宮﨑駿の主な作品は?")
```

```:出力
'風の谷のナウシカ』、『となりのトトロ』、『魔女の宅急便』、『千と千尋の神隠し』、『もののけ姫』、『崖の上のポニョ』、『風立ちぬ』、『かぐや姫の物語』、『未来のミライ』、『レッドタートル』、『未来少年コナン』、『ルパン三世カリオストロの城』、『天空の城ラピュタ』、『となりのトトロ』、『火垂るの墓』、『おもひでぽろぽろ』、『紅の豚』、『千と千尋の神隠し』、『ハウルの動く城』、『もののけ姫』、『風立ちぬ』、『かぐや姫の物語』、『未来のミライ』、『レッドタートル』、『未来少年コナン』、『ルパン三世カリオストロの城』、『天空の城ラピュタ』、『となりのトトロ』、『火垂るの墓』、『おもひでぽろぽろ』、『紅の豚』、『千と千尋の神隠し』、『ハウルの動く城』、『もののけ姫』、『風立ちぬ』、『かぐや姫の物語』、『未来のミライ』、『レッドタートル』、『未来少年コナン』、『ルパン三世カリオストロの城』、『天空の城ラピュタ』、『となりのトトロ』、『火垂るの墓』、『おもひでぽろぽろ』、『紅の豚』、『千と千尋の神隠し』、『ハウルの動く城』、『もののけ姫』、『風立ちぬ』、『かぐや姫の物語』、『未来のミライ』、『レッドタートル』、『未来少年コナン』、『ルパン三世カリオストロの城』、『天空の城ラピュタ』、『となりのトトロ』、『火垂るの墓』、『おもひでぽろぽろ』、『紅の豚』、『千と千尋の神隠し』、『ハウルの動く城』、『もののけ姫』、『風立ちぬ』、『かぐや姫の物語』、『未来のミライ』、『レッドタートル』、『未来少年コナン』、'
```

## 架空の説明

```python
generate_batch("架空の生き物をデザインし、その特徴や能力について説明してください。")
```

```:出力
'こんにちは'
```

## コード生成

```python
generate_batch("ランダムな10個の要素からなるリストを作成してソートするコードをPythonで書いてください。")
```

```:出力
'以下は、Pythonでランダムな10個の要素からなるリストを作成し、ソートするコードです：  ``python import random def random_sort(arr): """ランダムな10個の要素からなるリストを作成し、ソートする。""" arr = [random.randint(0, 10) for _ in range(10)] arr.sort() return arr ``` このコードは、10個のランダムな要素からなるリストを作成し、ソートします。'
```

## 表作成指示

```python
generate_batch("日本国内で観光に行きたいと思っています。東京、名古屋、大阪、京都、福岡の特徴を表にまとめてください。列名は「都道府県」「おすすめスポット」「おすすめグルメ」にしてください。")
```

```:出力
'東京：東京は日本の首都であり、日本の経済、文化、政治の中心地である。東京は、日本の伝統文化と現代文化が融合したユニークな都市である。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物や文化を体験できる場所がたくさんある。東京には、日本の伝統的な建築物'
```


# まとめ

repetition_penaltyをきちんと設定していないせいか、それとも量子化したせいか、いくつかの例では文章の繰り返し出力をしてしまってました。おそらくこれは解消可能だと思います。

いくつか実行してみた感じ、日本語知識は豊富に持っている印象で、そのあたりの質問は的確に答えてくれそうです。
ただ、Instruction Tuningの問題なのか、何か指示して実行させる部分はそこまで得意ではない印象。このあたりはLlama2ベースのElyza社のモデルとかの方が良さそうな気がします。

しかし、13B水準の日本語LLMがどんどん出てきているのはいいですね。
パラメータサイズ7B～13Bはバランスが良くて使い勝手がとてもいいと思っています。

どこか、Mistralベースの日本語LLMを作って公開しないかなー（人任せ）。