最新LLM「Swallow」で遊んでみた

> 本記事は[K3AdventCalendar2023](https://adventar.org/calendars/9117)19日目の記事です

この記事が投稿される予定であった12/19[^1]，Llama-2ベースの日本語能力爆上げLLM「**Swallow**」がリリースされました🎉
本記事では早速これらのモデルを動かしてみます．要は無料でダウンロードできて，ローカルで動かせるChatGPTみたいなAIで遊んでみるってことです

https://swallow-llm.github.io/swallow-llama.ja.html

https://zenn.dev/tokyotech_lm/articles/d6cb3a8fdfc907



# Swallowとは？
東京工業大学情報理工学院の岡崎研究室および横田研究室，国立研究開発法人産業技術総合研究所の共同研究チームからリリースされたLlama-2ベースの日本語モデルです．この記事を記述している12/23現在[^2]において，**オープンな日本語モデルにおいては最強無敵**です！すごい！強い！(はよOpenAIはGPTをオープンにしろ)

リリースされたモデルは以下の6つです．数字がでかくなるほど規模がデカくて戦闘力高いです
- 日本語継続事前学習済みモデル
    - [Swallow-7B](https://huggingface.co/tokyotech-llm/Swallow-7b-hf)
    - [Swallow-13B](https://huggingface.co/tokyotech-llm/Swallow-13b-hf)
    - [Swallow-70B](https://huggingface.co/tokyotech-llm/Swallow-70b-hf)
- 上記モデルに指示チューニングを施したモデル
    - [Swallow-7B-instruct](https://huggingface.co/tokyotech-llm/Swallow-7b-instruct-hf)
    - [Swallow-13B-instruct](https://huggingface.co/tokyotech-llm/Swallow-13b-instruct-hf)
    - [Swallow-70B-instruct](https://huggingface.co/tokyotech-llm/Swallow-70b-instruct-hf)


# Colabで動かしてみるよ！
本記事で用いるコードは以下で公開されています
[![Open in GitHub](https://img.shields.io/badge/Open%20in-GitHub-blue)](https://github.com/lychee1223/Swallow) [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/lychee1223/Swallow/blob/main/Swallow.ipynb)

### ライブラリの準備
まずは必要なライブラリをインポートしましょう
```python
# @title ライブラリの準備

!pip install torch transformers sentencepiece accelerate protobuf bitsandbytes

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
```

### モデルの準備
それでは早速Swallowをダウンロードしましょう！
と，その前に...．本記事を読んでいる人の多くは自然言語処理なんもわからんと思うので基本的なフローを抑えておきましょう．下図は以前僕が自然言語処理講座を行った際に用いたものです．講座資料は[こちら](https://drive.google.com/file/d/1sy6yoOffYwXcj7WdNrjYdoNOrt8JUz9k/view?usp=drive_link)

ニューラルネットワークでは入力をベクトルにする必要があります．例えば，128×128のサイズの画像を入力とする場合，画像自体が128×128次元のベクトルなのでそのまま入力できますね！しかし，入力が日本語や英語などの自然言語である場合はどうでしょう？文章をどーにかこーにかしてベクトルに直す必要があります．そこで，自然言語処理ではトークナイザで文章をトークン化(単語やサブワードへ分割すること)し，各単語に対応する分散表現へ符号化します．これで文章がベクトルになりました！やったね！下図では1つの単語に対して1つの整数が符号として割り振られていますが(例：計算⇔3181)，1つの単語をn次元のベクトルに符号化することも一般的です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619612/24ba9565-935c-5df0-aadf-930e8512e867.png)

少々説明が長くなりましたが，実際にSwallowのトークナイザとモデルをダウンロードしてみましょう！ダウンロードに少し時間がかかりますが，コーヒーでも飲みながら気長に待ちましょう．本記事では，一番軽いSwallow-7B-instructを使います．```#@param```でモデルを選択できるようになっているので，お好きなものを選んでみてください．70BとかGoogleColabの無料枠じゃ多分動かんけど...
ここでエラーが出る場合，おそらくメモリ不足なのでColabに課金するか自分のつよつよPC上で動かしてください🙇

```python
# @title モデルの準備

# モデルの選択
model_name = "tokyotech-llm/Swallow-13b-instruct-hf" # @param ['tokyotech-llm/Swallow-7b-hf','tokyotech-llm/Swallow-7b-instruct-hf','tokyotech-llm/Swallow-13b-hf','tokyotech-llm/Swallow-13b-instruct-hf','tokyotech-llm/Swallow-70b-hf','tokyotech-llm/Swallow-70b-instruct-hf']

# モデルのダウンロード
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype = "auto",
    device_map = "auto",
    trust_remote_code = True,
    low_cpu_mem_usage = True,
)

```
:::note info
Google Colab Tips!
Google Colabでは```#@param```というマークダウン機能が提供されています．変数をテキストやドロップダウン，スライダーなど様々なUIで設定できるようになるよ！

[ColabにUIをつける小技集](https://qiita.com/john-rocky/items/e5802cdd15dc2e34cb84)
:::

### プロンプトのテンプレを定義
モデルにプロンプトを入力するにあたって，おまじない部分を毎回書くのはだるいので事前にテンプレート化しておきましょう

```python
# @title プロンプトのテンプレートを定義

PROMPT_DICT = {
    "prompt_input": (
        "以下に、あるタスクを説明する指示があり、それに付随する入力が更なる文脈を提供しています。"
        "リクエストを適切に完了するための回答を記述してください。\n\n"
        "### 指示:\n{instruction}\n\n### 入力:\n{input}\n\n### 応答:"

    ),
    "prompt_no_input": (
        "以下に、あるタスクを説明する指示があります。"
        "リクエストを適切に完了するための回答を記述してください。\n\n"
        "### 指示:\n{instruction}\n\n### 応答:"
    ),
}

def create_prompt(instruction, input = None):
    if input:
        return PROMPT_DICT["prompt_input"].format(instruction = instruction, input = input)
    else:
        return PROMPT_DICT["prompt_no_input"].format(instruction = instruction)
```

### 推論
ここまで来たら，あとは入力するプロンプトを書いてモデルに食わせましょう！結構時間がかかりますが，根気よく待ちましょう．プロンプトはinstructionにモデルが実行すべきタスクの内容，inputにそのタスクにおける入力を記述してください．本記事ではUnityとUEそれぞれの特徴について聞いてみます．inputやハイパラをいろいじって遊んでみてくださいね～

```python
# @title プロンプトを作成

instruction = "以下のトピックに関する詳細な情報を提供してください。" # @param {type:"string"}
input = "UnityとUnreal Engineそれぞれの特徴について" #@param {type:"string"}

prompt = create_prompt(instruction = instruction, input = input)
```

```python
# @title 推論

temperature = 0.2 # @param {type:"slider", min:0.1, max:1, step:0.1}
top_p = 0.95 # @param {type:"slider", min:0.01, max:1, step:0.01}

with torch.no_grad():
    input_ids = tokenizer.encode(
        prompt,
        add_special_tokens=False,
        return_tensors="pt"
    )

    tokens = model.generate(
        input_ids.to(device=model.device),
        temperature = temperature,
        top_p = top_p,
        max_new_tokens=256,
        do_sample=True,
    )

output = tokenizer.decode(tokens[0], skip_special_tokens = True)
print(output)
```
UnityとUEの特徴をSwallowに聞いてみた回答はこんな感じ

>UnityとUnreal Engineは、どちらもゲーム開発に使用されるゲームエンジンです。Unityは、C#、JavaScript、Booなどのプログラミング言語で開発されたゲームを作成するために使用されます。Unreal Engineは、C++で開発されたゲームを作成するために使用されます。
>
>Unityの特徴は、以下の通りです。
>1. 無料で使用できる。
>2. マルチプラットフォームに対応している。
>3. ゲーム開発に必要な機能が揃っている。
>4. コミュニティが活発で、情報が豊富である。
>
>Unreal Engineの特徴は、以下の通りです。
>1. 有料である。
>2. シングルプラットフォームに対応している。
>3. ゲーム開発に必要な機能が揃っている。
>4. リアルなグラフィックを作成することができる。
>
>どちらのエンジンも、ゲーム開発に必要な機能を備えており、それぞれに特徴があります。

正しい情報と誤った情報が混在してますね。「UnityはC#，UEはC++」，「Unityはコミュニティが活発で情報が多い」，「UEはグラフィックが綺麗」とかは合ってそう．けどUE無料ですよ！**おまいらAIに騙されるな！**

嘘つかれたのでもう一度生成させてみました．
>UnityとUnreal Engineは、どちらもゲーム開発に使用されるゲームエンジンです。
>
>Unityは、2005年にリリースされたゲームエンジンで、C#やJavaScriptなどのスクリプト言語を使ってゲームを作成することができます。また、Unityは、モバイル、PC、コンソール、VR/ARなど、さまざまなプラットフォームに対応しています。
>
>Unreal Engineは、1998年にリリースされたゲームエンジンで、C++やBlueprintsなどのスクリプト言語を使ってゲームを作成することができます。また、Unreal Engineは、モバイル、PC、コンソール、VR/ARなど、さまざまなプラットフォームに対応しています。
>
>UnityとUnreal Engineは、どちらもゲーム開発に使用されるゲームエンジンですが、それぞれに特徴があります。Unityは、モバイル、PC、コンソール、VR/ARなど、さまざまなプラットフォームに対応しているため、幅広いプラットフォームでゲームを開発することができます。一方、Unreal Engineは、より高度なグラフィックや物理演算を必要とするゲームに適しています。

今度は完璧だ～！リリースされた年まで合ってる！？すげー！
ってな感じで，実行毎のシード値によって精度がまちまちですね．今回は一番軽いSwallow-7Bで試してますが，13Bとか70Bで試せばもう少し精度の高い結果が得られるはずです．

# 最後に
ChatGPTの出現をきっかけに，近年様々なLLMが登場していますね．今回紹介したSwallowのように日本語に対応したモデルもたくさん出始めています．GPT-4，Llama-2，LLaVA-1.5，世界を取るのはどのモデルなのか．**世はまさに大LLM時代！ﾄﾞﾝ！**
ChatGPTに研究を潰された人も多いですが，自然言語処理の研究が終焉を迎えた訳ではありません．研究者だけではなく，一般人が容易にこうした強いAIモデルを使える世の中です．今話題のモデルには何ができて何ができないのかをしっかり理解することが大切です．実際，今回もUEが有料などという戯言を吐きやがりました．血も涙もない機械それっぽく平気で噓をつきます．許せませんね
もし，本記事を読んで自然言語処理に少しでも興味を持ってくれた方がいらっしゃいましたら是非一緒に研究しましょ！今この分野めちゃくちゃ熱いですからね！おいでおいで😏

[^1]: どちゃくそ遅刻しました．ごめんなさい🙇
酒飲んで遊んでいただけなので，弁明の余地もありません…

[^2]:12/19のアドカレなのに妙だな…?