無料のDatabricks Community Editionを使って大規模言語モデルを体験してみる

こちらの続編的に。

https://qiita.com/taka_yayoi/items/5918a0e88d9b2472578c

使っているノートブックはこちらです。

https://sajpstorage.blob.core.windows.net/yayoi/ce_llm/DB-CE%E3%81%A6%E3%82%99%E5%A7%8B%E3%82%81%E3%82%8BLLM.html

# Databricksとは

[データブリックス](https://databricks.com/jp)は、学術界とオープンソースコミュニティをルーツとするデータ＋AIの企業です。Apache Spark™、Delta Lake、MLflowの開発者グループによる2013年の創業以来、最新の[レイクハウス](https://qiita.com/taka_yayoi/items/438f762126f57868aa35)アーキテクチャを基盤に、データウェアハウスとデータレイクの優れた機能を取り入れた、データとAIのためのクラウドベースのオープンな統合プラットフォームを提供しています。

このレイクハウスプラットフォームをご利用いただくことで、機械学習モデルのトレーニングはもちろん、機械学習モデルの運用管理、ETLパイプラインの開発・運用、データの蓄積、BIなど様々なワークロードを一つのプラットフォーム上で効率的に実施いただけるようになります。

:::note
**参考資料**
- [レイクハウスとは何？](https://qiita.com/taka_yayoi/items/438f762126f57868aa35)
- [Databricksの良いところ\(Jupyter notebookとの比較\)](https://qiita.com/taka_yayoi/items/d5ea3dede05a180091b2)
- [データレイクハウスに関するFAQ](https://qiita.com/taka_yayoi/items/04888e5fd08a621511e4)
- [Databricksのアーキテクチャ](https://qiita.com/taka_yayoi/items/7d209bc8d32bc5f2dba4)
:::

# Databricks Community Editionとは

Databricksではその機能を無償でお試しいただけるよう、2通りの方法を用意しております。

- 2週間の無償トライアル: Databricksのすべての機能を2週間無償でお試しいただけます。
- **Community Edition**: 利用できる機能が限定されますが、**期限なし・無償**でご利用いただけます。

本記事では、**Community Edition**でのLLMの活用を通じて、Databricksの基本的な機能を体験いただきます。

:::note
**参考資料**
- [IBJP: Community Editionで始めるDatabricks – Databricks](https://databricks.com/jp/international-blogs/get-started-with-databricks-community-edition-jp)
- [Databricksフリートライアルへのサインアップ](https://qiita.com/taka_yayoi/items/fb4f57c069e1f272e88a)
:::

# Databricks Community Editionへのサインアップ

[こちら](https://qiita.com/taka_yayoi/items/5918a0e88d9b2472578c#databricks-community-edition%E3%81%B8%E3%81%AE%E3%82%B5%E3%82%A4%E3%83%B3%E3%82%A2%E3%83%83%E3%83%97)をご覧ください。

# Databricksのウォークスルー

## Databricks Community Editionの画面構成

Databricksでは、ノートブック上にロジックを記述してそれを実行することで様々な処理を行います。この観点ではJuypter notebookと非常に近いUIを持っていると言えます。しかし、[様々な点で強化・拡張](https://qiita.com/taka_yayoi/items/d5ea3dede05a180091b2)がなされているのがDatabricksです。

画面の左側のサイドメニューにマウスカーソルを移動するとメニューが展開されます。基本的な機能にはこちらからアクセスすることになります。
![Screen Shot 2022-08-03 at 8.03.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/9c100657-915c-c120-9bd0-1236e9c6fa0e.png)

各項目については、以下の参考資料をご覧ください。ここでは、クラスターを作成するためにメニューから**クラスター**をクリックします。

:::note
**参考資料**
- [Databricksワークスペースをナビゲートする](https://qiita.com/taka_yayoi/items/dd41cd715aca272ff5ce)
:::

## クラスターの作成

[クラスター](https://qiita.com/taka_yayoi/items/c5d99cd77fe4bfcf69f0)とは、機械学習モデルのトレーニングやデータの加工を行う際に必要となる計算資源です。Databricksでは大量のデータを高速に処理できるように複数の仮想マシンをまとめて**クラスター**として構成します。Databricksクラスターを用いることで、従来であれば手間のかかる環境構築(仮想マシンの設定、ソフトウェアのインストールなど)をGUIからの操作で手軽に行えるようになります。

1. クラスターの一覧が表示されます。この時点ではクラスターは存在していないため一覧は空の状態です。左上にある**クラスターの作成**ボタンをクリックします。
![ce_create_cluster.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/209f356d-37da-1259-3f2c-1ce59f29e40a.png)

1. この画面で作成するクラスターの設定を行います。ここでは、**クラスター名**と**Databricks Runtimeのバージョン**を指定します。

    - **クラスター名**: LLM testなど人が見てわかりやすい名前を指定してください。
    - **Databricks Runtimeのバージョン**: Databricks Runtimeとはクラスターに自動でインストールされるソフトウェアのパッケージです。Pythonの実行環境やPythonライブラリなどが含まれています。ここでは、`Runtime 13.1 ML`を選択します。

    ![ce_specify_runtime.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5f930cde-9c77-98ad-6f36-ca764ce9c239.png)


1. **クラスターを作成**をクリックするとクラスターが作成されます。クラスターが作成され、起動するまでに数分要しますのでお待ちください。作成が完了するとクラスター名の右側に緑のチェックマーク入りのアイコンが表示されます。
![ce_cluster_launched.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e91f9721-05c5-8eee-3652-e5bd17578ee9.png)

## ノートブックの作成

次に、ロジックを記述する[ノートブック](https://qiita.com/taka_yayoi/items/24a897cf40bba6d9e305)を作成します。

1. サイドメニューの**ワークスペース**をクリックします。ワークスペースは名前の通り、皆様の作業場でありノートブックを格納する場所となります。
![Screen Shot 2022-08-03 at 8.13.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/bb65b30f-84d8-64e6-69f4-0343519e5e67.png)
1. ワークスペース配下には**Shared**と**Users**というフォルダが存在しています。**Shared**はワークスペース内で他のユーザーとノートブックを共有するための置き場所として使用します。**Users**はそれぞれのユーザーごとのホームフォルダが格納されています。
1. ホームフォルダにノートブックを作成するので**ホーム**ボタンをクリックして、自分のホームフォルダに移動します。
![Screen Shot 2022-08-03 at 8.13.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/4308a05e-029d-8460-5594-70e5f1d58849.png)
1. ホームフォルダは自分のメールアドレスの名称となっています。ここにフォルダを作成したり、ノートブックを格納することになります。
![Screen Shot 2022-08-03 at 8.19.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1353593d-0798-7eaa-d5a2-e614a6a32749.png)
1. ホームフォルダ名(自分のメールアドレス)の右にある下向きの矢印をクリックします。
![Screen Shot 2022-08-03 at 8.19.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7fdb70e2-953e-5790-4d9f-1f485961b26f.png)
1. メニューが表示されるので**作成 > ノートブック**を選択します。
1. ノートブックの右上からクラスターを選択します。Databricksで処理を実行するには、ノートブックをクラスターに**アタッチ**する必要があります。編集のみを行う際にはクラスターへのアタッチは不要です。
![ce_attach_cluster.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/3b3e833b-c388-f5f0-0824-7809518e83b6.png)
1. これで準備が整いました。
![ce_cluster_ready.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/425df183-dc84-0f1d-6333-48ae061bb282.png)

:::note info
**ティップス**
フルバージョンのDatabricksではフォルダやノートブックなどにアクセス権を設定できるので、ユーザー間でセキュアに資産のやり取りを行うことができます。
:::

## ノートブックの実行

すでにノートブックが表示されていますので、Juypter notebookを使うのと同様にPythonの処理を記述、実行することができます。

1. 一つ目のセルにカーソルを移動し、以下の内容を記述します。

    ```py:Python
    print("test")
    ```

1. セルを実行するにはいくつかの方法がありますが、ここではセルの右端に表示されているメニューから実行します。再生ボタンをクリックするとメニューが展開されます。
![Screen Shot 2022-08-03 at 8.35.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/b688c9b0-665e-23d1-f294-4bcb7f0b8ac5.png)
1. **▶︎セルを実行**をクリックすると当該セルが実行されます。
![Screen Shot 2022-08-03 at 8.36.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/c877e66a-816e-98c1-ddcc-772569289b86.png)
1. 以下のように結果が表示されます。
![Screen Shot 2022-08-03 at 8.37.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/b514812e-1b1c-ab24-de76-2bf843aa99bc.png)

:::note info
**ティップス**
上に表示されているように、Shift+Enterキーを押してもセルを実行することができます。
:::

新たにセルを追加するには、追加したい場所にカーソルを移動すると`+`マークが表示されるのでこれをクリックすることでセルの上下に追加することができます。

![Screen Shot 2022-08-03 at 8.39.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5b5bfc38-5cc0-bf5a-0fbe-b5a443e6cf5f.png)

![Screen Shot 2022-08-03 at 8.40.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/83345d71-1393-851d-d7d3-cf2e5ccfd3a2.png)

:::note
**参考資料**
- [Databricksノートブックを使う](https://qiita.com/taka_yayoi/items/dfb53f63aed2fbd344fc)
- [Databricksノートブックを管理する](https://qiita.com/taka_yayoi/items/c306161906d6d34e8bd5)
:::

# Databricksでの大規模言語モデルの活用

## ノートブックのインポート

上ではノートブックを作成しましたが、インターネットで公開されているノートブックなどを簡単に取り込むこともできます。

1. サイドメニューの**ワークスペース**をクリックします。
1. **ホーム**ボタンをクリックして、自分のホームフォルダに移動します。
1. ホームフォルダ名(自分のメールアドレス)の右にある下向きの矢印をクリックします。
1. メニューが表示されるので**インポート**を選択します。
![Screen Shot 2022-08-03 at 9.12.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1d65e113-a03a-518e-85b0-b36d7133a961.png)
1. ダイアログが表示されます。以下を指定して**インポート**をクリックします。

    インポート元: `URL`を選択します。
    テキストボックス: 以下のURLを貼り付けます。

    ```
    https://sajpstorage.blob.core.windows.net/yayoi/ce_llm/DB-CE%E3%81%A6%E3%82%99%E5%A7%8B%E3%82%81%E3%82%8BLLM.html
    ```

     ![Screen Shot 2022-08-03 at 9.12.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1d5c6084-814e-e930-0dbe-f97448f3b859.png)

1. 以下のようにノートブックがインポートされます。
![ce_cluster_ready.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/989943c2-31df-efc7-66f3-ef4d85145a48.png)
1. 画面右上で[上のステップ](#クラスターの作成)で作成したクラスターを選択します。

## ノートブックを実行

ここでは、13億のパラメーターを持つLLMである`rinna/japanese-gpt-1b`を用いて文書生成を行います。

**参考資料**
- [rinna 社が構築した GPT\-2 モデルを使ってみる \| Portfolio](https://guinpen98.github.io/VuePress/articles/GPT-2.html)
- [rinna/japanese\-gpt\-1b · Hugging Face](https://huggingface.co/rinna/japanese-gpt-1b)

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

使用するライブラリ`transformers`と`sentencepiece`をインストールします。

**参考資料**
- [HuggingFace Transformers が提供する学習スクリプト｜npaka](https://note.com/npaka/n/n5994274392cc)

```
%pip install transformers==4.25.1
%pip install sentencepiece
```

ライブラリのインストール後はカーネルを再起動します。
```py
dbutils.library.restartPython()
```

### モデルとトークナイザーの作成

`model`は事前学習済み大規模言語モデルです。大規模言語モデルに直接文章を入力することはできず、**トークン**に分割する必要があります。この役割を担うのが`tokenizer`です。

:::note
**注意**
以下のコマンドの実行には2分程度要します。
:::

```py
from transformers import T5Tokenizer, AutoModelForCausalLM

tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt-1b")
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-1b")
```

### モデルへの入力の準備

トークナイザーを用いて文章をトークンに分割します。

```py
text = "国境の長いトンネルを抜けると雪国であった。"
input = tokenizer.encode(text, return_tensors="pt", add_special_tokens=False)
```

トークンを確認してみます。

```py
input
```
```
Out[3]: tensor([[ 1378, 37072, 36371,  2284,  6334, 36384,  4123,    93, 37692, 36494,
           355, 36375]])
```

上で表示されているのはトークンそのものではなく、トークンに割り振られたIDです。こちらから文章に戻すことも可能です。

```py
# IDをトークンに変換
converted_tokenized_inputs = [*map(lambda x: tokenizer.convert_ids_to_tokens(x), input)] 

# テキストに戻して表示
for inputs in converted_tokenized_inputs:
    print('-'.join(inputs))
```
```
▁国-境-の-長い-トンネル-を-抜け-ると-雪-国-であった-。
```

### モデルの出力

トークン化(トークナイズ)された入力を大規模言語モデルに与えて、後続の文章を生成させます。

**参考資料**
- [Huggingface Transformers 入門 \(6\) \- テキスト生成｜npaka](https://note.com/npaka/n/n5d296d8ae26d)
- [rinna GPT\-2モデルの生成パラメータ](https://zenn.dev/tyaahan/articles/a8d99900000002)

:::note
**注意**
以下のコマンドの実行には2分程度要します。
:::

```py
output = model.generate(input, # 入力(トークン化された文章)
                        min_length=50, # 生成される文の最大長
                        max_length=100, # 生成される文の最小長
                        do_sample=True, # サンプリングを用いるかどうか。サンプリングするとダイナミックに文が変化します。
                        top_k=500, # サンプリング時に選択する確率の高い上位候補の数
                        top_p=0.95, # サンプリング時に一定確率以上の単語を選択
                        num_return_sequences=3, # 返却する文書の数
                        pad_token_id=tokenizer.pad_token_id,
                        bos_token_id=tokenizer.bos_token_id,
                        eos_token_id=tokenizer.eos_token_id
                       )
```

```py
# 生成結果をデコード
generated_sentences = tokenizer.batch_decode(output, skip_special_tokens=True)
for sentence in generated_sentences:
    print(sentence)
```
```
国境の長いトンネルを抜けると雪国であった。夜の十一時であった。時計を見ると午前一時を指していた。乗客はぼく一人、車は四十でワイパストレインばかり、乗客はぼくら二人きりだった。車掌は三十歳前後のおっさんで、ベレー帽をかぶっていた。乗客は全部日本人だった。電車は雪に飲みこまれた。プラットホームから見えるはずの家々が、雪で何も見えなかった。電車はトンネルに入ろうとした。コンフォートバスが入
国境の長いトンネルを抜けると雪国であった。バスは順調に走り続け、やがて車窓の景色は越後湯沢駅の前、旧中仙道であった。今回の旅先は新潟だ。長岡駅のホームには雪のため信号が赤く点滅し、列車は動かないようだ。しばらくして列車は新津駅に到着する。ここで列車から改札口に向かう。平日の朝は利用客も少なく、とても静かで落ち着ける。
国境の長いトンネルを抜けると雪国であった。夜の底が白くなった。白夜の北の地であった。夜行列車に乗ったから、ずっと暗い車内にいて、まどろみの中を漂っていた。見覚えのある駅で停車するたび、窓の外を流れていく雪をかぶった山が目についた。車の窓から雪を被った山肌を眺めている内に、思いのほか、親しみのある景観として、胸に入ってきて、懐かしさがこみ上げてきた。山肌にはシラカバやダケカンバ
```

### 関数化

いろいろな文章で試せるように上の処理を関数化します。

```py
def generate_text(text):
  # 文をトークナイズ
  input = tokenizer.encode(text, return_tensors="pt", add_special_tokens=False)

  # 出力の生成
  output = model.generate(input, # 入力(トークン化された文章)
                        min_length=50, # 生成される文の最大長
                        max_length=100, # 生成される文の最小長
                        do_sample=True, # サンプリングを用いるかどうか。サンプリングするとダイナミックに文が変化します。
                        top_k=500, # サンプリング時に選択する確率の高い上位候補の数
                        top_p=0.95, # サンプリング時に一定確率以上の単語を選択
                        num_return_sequences=3, # 返却する文書の数
                        pad_token_id=tokenizer.pad_token_id,
                        bos_token_id=tokenizer.bos_token_id,
                        eos_token_id=tokenizer.eos_token_id
                       )
  
  # 生成結果の表示
  generated_sentences = tokenizer.batch_decode(output, skip_special_tokens=True)

  # HTMLとして表示
  return_html = "<ul>"

  for sentence in generated_sentences:
    return_html += "<li>" + sentence

  return_html += "</ul>"
  displayHTML(return_html)
```

```py
generate_text("吾輩は猫である")
```

- 吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番悪な種族であるそうだ。この書生というのが一体何者だか知らないが、この悪な書生から色々と話を聞いた。それからか想像して見た事もあるが、今一段とハッキリした事実があるとすれば
- 吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番悪な種族である人間という獣の中で。この書生という種族は時々我々を捕へて煮て食ふという。なんでも書生というのは大抵人間の言葉を話すらしかった。この書生の話はこれ
- 吾輩は猫である。名前はまだない。どこで生れたか位な事は覚えている。吾輩はここで始めて人間という... » ようこそ『でじこの日乗』 へ【猫のメモ】『神意を感ずるべく「神罰」というものがある。元日に開帳される宝鏡をご神体とする神社で例を挙げよう。大阪四天王寺、祇園四条の二尊院、京都の鞍馬寺、長野の三千坊などを勧請寺・末

```py
generate_text("諸行無常の響きあり")
```

- 諸行無常の響きあり。二千有余年の永き歴世に諸行無常の法有り。即ち是れ我が本因妙の抄なり。仏神我が化導を行ぜり。今を以て以って言わく、仏正法に於て三大秘法の当体顕本、日本一同に南無妙法蓮華経と唱うるは本仏日蓮が直弟子之れなり。在家一同に本門戒壇の大御本尊を
- 諸行無常の響きあり りんりんりん、 りんりんりんっ。 りんりんりん、 りんりんりんっ。 ぴあの「ねこのくに」のショウコです。 ウチのハチマルは、今年生まれのオス。 うちのはやしさん、うささんなので、 来年になったら、オス。 サザナミ血統とかでは、オスの確立が、 わりと高いそうですが、ウチのはやしさんは、 ちょびちょびと誕生日が来ています。
- 諸行無常の響きあり。波の音あり。風の音あり。森のざわめきあり。森から森の間のたゆたいあり。雲間を走る霧あり。全ての物事は移り変わる。すべては、空であると......。それは、現世=日常の世界のみならず、霊界や天上界においても、同じこと。

色々試してみてください！

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)