LINEの日本語言語モデルを使って、とりあえずBotを作ってみよう（Power Automate）

# はじめに
先日発表された「LINEのNLP Foundation Devチームの[36億パラメータの日本語言語モデルを公開しました](https://engineering.linecorp.com/ja/blog/3.6-billion-parameter-japanese-language-model)」を参考に、APIを検証してみました。

https://qiita.com/DEmodoriGatsuO/items/274fcc7844e62d76972d



内容が浅かったので`Text Generate`について詳しく見てみましょう。

## APIのParametares
Hugging Faceの下記のページに[APIの詳細](https://huggingface.co/docs/api-inference/detailed_parameters)が記載されています。

https://huggingface.co/docs/api-inference/detailed_parameters

### Text Generation taskをテーブルに変換
英語で少しキャッチアップし辛いので、日本語に変換してみます。

|Key|必須/任意|説明
|---|---|---
|inputs|必須|テキスト生成の元となる文字列を指定します。
|parameters|任意|テキスト生成の方法を指定するための辞書です。以下のキーを含みます。
|top_k|任意|新しいテキストを作成するためのサンプル操作内で考慮されるトップトークン数を定義する整数です（デフォルト: None）。
|top_p|任意|テキスト生成のためのサンプル操作内のトークンを定義する浮動小数点数です（デフォルト: None）。確率の合計が top_p を超えるまでトークンを追加します。
|temperature|任意|サンプリング操作の温度を定義する浮動小数点数です（デフォルト: 1.0）。1.0は通常のサンプリングを、0.0は常に最高スコアを取得を意味します。
|repetition_penalty|任意|生成中にトークンが使用される回数に応じてトークンを罰するための浮動小数点数です（デフォルト: None）。
|max_new_tokens|任意|生成される新しいトークンの最大数を整数で指定します（デフォルト: None）。入力の長さは含まれず、生成されるテキストの大きさを見積もります。
|max_time|任意|クエリが最大で受けるべき時間を秒単位で指定する浮動小数点数です（デフォルト: None）。ネットワークのオーバーヘッドを考慮してソフトリミットを設定します。
|return_full_text|任意|結果に元のクエリを含めるかどうかを指定するブール値です（デフォルト: True）。Falseに設定すると、結果に元のクエリは含まれません。
|num_return_sequences|任意|返される生成提案の数を整数で指定します（デフォルト: 1）。
|do_sample|任意|サンプリングを使用するかどうかを指定するブール値です（オプション: True）。使用しない場合は貪欲なデコーディングが行われます。
|options|任意|出力オプションを指定するための辞書です。以下のキーを含みます。
|use_cache|任意|リクエストを高速化するためのキャッシュレイヤーを使用するかどうかを指定するブール値です（デフォルト: true）。
|wait_for_model|任意|モデルが準備できるまで待つかどうかを指定するブール値です（デフォルト: false）。503エラーを受け取った後にtrueに設定することを推奨します。

完全に整えると下記の様なJSONを渡すイメージになるようです。

```json
{
  "inputs": "これはテキスト生成の例です。",
  "parameters": {
    "top_k": 50,
    "top_p": 0.8,
    "temperature": 0.7,
    "repetition_penalty": 1.2,
    "max_new_tokens": 150,
    "max_time": 30.0,
    "return_full_text": false,
    "num_return_sequences": 3,
    "do_sample": true
  },
  "options": {
    "use_cache": true,
    "wait_for_model": false
  }
}
```

ただ検証をしてみているのですが、なかなか難しい。
下記の方々のnoteが本当に参考になり、Google Colabで実践してみたのですが、
`output`の精度が大幅に異なります。

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

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

:::note info
Google ColabはGoogleアカウントがあれば無料で使えますので、実践してみることをお勧めします。私もやってみました。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/cbbb5801-6a37-25a2-f937-a9b55f512e4c.png)

かなり物議が出そうな話題ですが、**正直面白いです。**

Text Generateは、やはりChat形式で実践するものなので、
`Power Automate` & `LINE`で **LINE BOTを作ってみましょう。**

## 作成に入る前に
LINE BOTの作成に関するコンテンツは、**本当に沢山あり、私が書いてもただの焼き増しになります。**
個人的に尊敬している方の記事をご紹介するので、是非LINE側の設定はこちらを参考にしてみてください🙇

https://ascii.jp/elem/000/004/081/4081158/

https://ascii.jp/elem/000/001/947/1947693/

私は **Power Automate**に焦点を当てて記事を書いていきます。

# Power Automateの作成
## 1. HTTP 要求の受信時
カテゴリは「**自動化したクラウドフロー**」になります。
トリガーは「**要求**」 > 「**HTTP 要求の受信時**」です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/8a1e0348-b292-3784-8d8d-37d765238191.png)

:::note info
Power Automateの進化のスピードは本当に速く、トリガーも加速度的に増えていきます。**検索** によって見つけるほうが、時短につながります。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/e91df341-827f-a9ca-79e8-c9a684dcd46d.png)

### HTTP POSTのURLについて
こちらにつきましては、私のJSONをコピーしていただくか、**一度、フローを保存するとURLが自動作成されます**。
LINEのWebhookを送信してみると、`サンプルのペイロードを使用してスキーマを生成する` の機能が
利用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/3f10acc6-3418-fbc9-37c9-ff82d04f0567.png)

自動作成された**Power AutomateのHTTP POSTのURL**をこちらの、**Webhook URL**に設定することで
**LINEからPower Automateにメッセージを送ったときに、Power Automateが動きます。**

実施後の画面から、受け取ったJSONを使うことで`サンプルのペイロードを使用してスキーマを生成する`が
利用できます。

ちなみに私の設定値は下記になっております。
[ 同じ値になると思いますので、下記のをコピーしても問題ないですが自前で調べる方法として共有しておきます ]

```json:要求本文のJSON スキーマ
{
    "type": "object",
    "properties": {
        "destination": {
            "type": "string"
        },
        "events": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string"
                    },
                    "message": {
                        "type": "object",
                        "properties": {
                            "type": {
                                "type": "string"
                            },
                            "id": {
                                "type": "string"
                            },
                            "text": {
                                "type": "string"
                            }
                        }
                    },
                    "webhookEventId": {
                        "type": "string"
                    },
                    "deliveryContext": {
                        "type": "object",
                        "properties": {
                            "isRedelivery": {
                                "type": "boolean"
                            }
                        }
                    },
                    "timestamp": {
                        "type": "integer"
                    },
                    "source": {
                        "type": "object",
                        "properties": {
                            "type": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            }
                        }
                    },
                    "replyToken": {
                        "type": "string"
                    },
                    "mode": {
                        "type": "string"
                    }
                },
                "required": [
                    "type",
                    "message",
                    "webhookEventId",
                    "deliveryContext",
                    "timestamp",
                    "source",
                    "replyToken",
                    "mode"
                ]
            }
        }
    }
}
``` 

## 2. アクセストークンを変数として格納する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/f912fde3-8939-e6ac-bbb6-3768ce0b20a6.png)

**LINE** と **Hugging Face**のAPI Keyを格納している変数です。

:::note warn
絶対に流出してはいけない値になります。
:::

- LINEにつきましては、紹介させていただいた記事
- Hugging Faceにつきましては前回の私の記事を参考にAPI Keyを取得してください。

## 3. Hugging Faceでテキストを作成し、LINEで返す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/eb7d1fde-6491-4290-ec71-1e1b087ce01c.png)

**LINE**から受信する値は`Array (配列)`型のデータになります。
実質的には、1回分のみの処理になると思いますが、一旦こちらで進めます。

## 3. TEXE GENERATE (japanese-large-lm)をAPIで利用する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/519653dd-ddde-4733-93c9-7180f7dd2cd2.png)

こちら前回の紹介と同様ですね。

転載しておきます。

|項目|値
|---|---
|方法|POST
|URI|https://api-inference.huggingface.co/models/line-corporation/japanese-large-lm-3.6b

ヘッダーは下記の通りです。

|Key|Value
|---|---
|Authorization|Bearer {API key}

本文
```json
{
  "inputs": "@{triggerBody()['text']}"
}
```

投稿する値は、上段で説明したパラメーターによって工夫できると思いますが、
本記事では一旦割愛してお送りします。


## 4. LINE BOTでテキストをチャンネルに投稿する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/8437afab-0351-a7ac-0826-f7623ad5b3b1.png)

|項目|値
|---|---
|方法|POST
|URI|https://api.line.me/v2/bot/message/reply

ヘッダーは下記の通りです。

|Key|Value
|---|---
|Content-Type|application/json
|Authorization|Bearer {**LINEのAPI key**}

#### 本文
```json
{
  "messages": [
    {
      "text": "@{body('HTTP_japanese-large-lm')[0]?['generated_text']}",
      "type": "text"
    }
  ],
    "replyToken": "@{items('Apply_to_each')?['replyToken']}"
}
```

#### Point 1
JSONの中に、Hugging FaceのAPIで生成したテキストを挿入しますが、こちらも`Array (配列)`型のデータです。
実質的に作成される配列の要素は1つになっていることから、Power Automateの関数で文字列に変換しています。

```plane_text
@{body('HTTP_japanese-large-lm')[0]?['generated_text']}
```

※ HTTP_japanese-large-lmの部分は、直前のアクションの名前です。

#### Point 2 replyTokenについて
replyTokenについては、`HTTP 要求の受信時`のトリガーから値が取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/eec2de63-2f2e-8685-ea66-9abc92c1234a.png)

# さあ、動かしてみよう！

https://twitter.com/DemodoriGatsuo/status/1692382399932641686

この言語モデルは、「途中まで文字列を書いて、**そのあとに推察される文字列を補完する**」という方法で活用できます。

Parametareが上手く行っていないのか、Pythonで実現するほどの面白さは作れません。
挑戦はまだまだ続きますね！

# LINE BOTのすゝめ
今回LINEを取り上げましたが、LINE BOTの作成は、本当にユーザーフレンドリーでやり易いです!
今回は**Power Automate**で紹介しましたが、**Google Apps Script**でも簡単に実装出来ます！

**BOTを始めてみようかな！の最初の選択に最適なので、是非試してみてくださいね♪**

この情報をもとに、TeamsやGoogle Chatも含めて応用の幅は広いので、
**ドンドンチャレンジしてみましょう！**

私は、Pythonで実施したくらいの面白い回答が出る方法を模索します・・・。