Azure OpenAI ✖️ LINE MessagingAPI を使って自分だけのAIチャットボットを作ろう！

# 目次

1. はじめに
2. 今回作成するシステムの概要
3. リソースグループの作成
4. Azure OpenAI セットアップ
5. Azure Bot Service のセットアップ
6. App Service のセットアップ
7. App ServiceへDeploy
8. LINE MessagingAPIの設定
9. 動作確認
10. お片付け

## はじめに

![azureopenai_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/461f17c5-47ad-97cd-0d5a-412aadfa6904.png)


昨今ちまたで話題の OpenAI。AIと普段使ってるサービスを連携させて面白いものを作りたいなぁと考えるエンジニアの同志達に向けたハンズオン 🖐️ となります。
この記事の目標としては、LINE botにメッセージを送信すると、AIが返信をくれるサービスをリリースすることです。
セットアップで詰まるところはどんどんコメント欄に質問していただいたら、がんがん返していきますので、ご遠慮なく質問してください！

### では、Let's ハンズオン！

## 今回作成するシステムの概要

今回作成するシステムは Azure 上で作成します。
下の図をご覧ください。

![zentai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/8d62e831-e42c-2fde-7674-20e4d2d0dff7.png)

以下の様な技術を使います。

- Azure OpenAI
- Azure App Service
- Azure Bot Service
- Managed ID
- LINE MessagingAPI
- javascript

工夫次第でめちゃくちゃ面白いものが作れる予感...！！
みなさん頑張っていきましょう！

## 前提条件
以下のインストールおよびサブスクリプションの契約が必要となります。
- Node.js
    - https://nodejs.org/en/blog/release/v16.20.2 
    - Node.js v16.20.2
    - npm v8.19.4

- Bot Framework Emulator
    - https://github.com/Microsoft/BotFramework-Emulator/releases/tag/v4.14.1 

- Azure
    - https://azure.microsoft.com/ja-jp/pricing/purchase-options/pay-as-you-go

## リソースグループの作成
まずは何がともあれリソースグループの作成です。
全体図で言うとここの部分です。
![rg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/9e920a7f-7a62-82ee-f725-093ba5425c08.png)

まずは、Azure 上で動作させるので、何がともあれ Azure の無料アカウントを作成してみましょう！
[Azure の無料アカウントを使ってクラウドで構築](https://azure.microsoft.com/ja-jp/free)

Microsoft アカウントを作成して Azure へログインすれば OK です。

こんな感じの画面が出てきたでしょうか。

![azure_main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/d8124685-8a1b-df8c-ccc5-c85f86bce3ef.png)

何がともあれ、リソースグループを作成しましょう！
上の検索窓に`リソースグループ`と入力して検索してください。

![resouce_gr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/0bb625e5-f479-88ea-af3c-35d5c0aa8a2f.png)

リソースグループの画面に進んだら、左上らへんにある作成をクリックして、リソースグループを作成しましょう！
次へを進んで、タグは別になくて大丈夫です。
![make_ai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/a83feca4-e809-8b4f-63e0-b57b55380e55.png)

作成できましたか？

![rg_fin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/c82ff89f-4c9a-4cd4-b2b5-c5c12b61d368.png)

## Azure OpenAI セットアップ

次に Azure OpenAI のセットアップです。全体図で言うとここの部分です。
![ai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/f5d8d4c6-3c79-4db8-bd90-167700100218.png)

ここまで作成できたら、また検索窓に`OpenAI`と入力して Azure OpenAI の画面を開いてください。

また、左上らへんにある作成ボタンをクリックです。
リソースグループは先ほど作成したものを指定し、あとは下の画像のように設定してください。

![make_ai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/2d295f2b-0cfb-acd0-eb78-cdcd1bfe92c8.png)

ネットワークは`インターネットを含むすべてのネットワークがこのリソースにアクセスできます。`を選択してください。
タグは特に何もつけなくて OK です。

作成ボタンをクリックしてください。デプロイが進行するはずです。(5 分ぐらいでしょうか。)
デプロイが完了すれば、リソースへ移動です。

次はモデルを Deploy する必要があります。

画面左上らへんにある`Azure OpenAI Studioへ移動`をクリックしてください。

![azureopenaistudio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/80cf5e19-8fba-a238-363a-6a805a58ade8.png)

新しいデプロイの作成をクリック → 新しいデプロイの作成をクリックしてください。

以下の様な画面が出てくると思うので、いい感じに入力して作成をクリック

![modeldeploy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/eea65584-5bbc-62be-e7a3-c8bd807a3d22.png)


このデプロイはすぐ完了します。
下の画面のようになりましたか？
![deploysuccess.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/07649ed4-cdef-4c94-9a0e-2dc7a2d5b35f.png)

ここまで来れば、AzureOpenAI のセットアップは完了です！
次に進みましょう！

:::message
初回はこのような表示が出ている可能性があります。
![aoai_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/a1f910cb-2e20-a421-bf7a-07b8e53e0928.png)

その場合は表示されているリンクをクリックすると、Microsoft へリクエストを送ることができます。
![request_access.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/3431a9ab-e9aa-2308-b64b-c65348a2d0f4.png)

ゆうじろうは数時間ぐらいで許可されたので、気長に待ちましょう。

:::

## Azure Bot Service のセットアップ

次は Azure Bot Service をセットアップしていきます。
全体図で言うとここです。

![bot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/3efef970-317f-72f6-999c-b6a31136525d.png)


まずは ローカルでJavaScriptで少しだけコーディングしてみます。
お好きなディレクトリに移動して、以下のコマンドを実行してください。

> 私は```tmp```フォルダで作業することにします。
![tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/04b56371-a5d2-e69e-aa59-e9c18ad8f31d.png)

```bash
npm init -y
```

package.json が作成されたら、以下のコマンドを実行してください。

```bash
npm install --save-dev yo generator-botbuilder
```

次にスケルトンの作成をしていきます。

```bash
npx yo botbuilder
```

上記コマンドを実行すると、ウィザードが上がってきます。

```powershell
PS C:\Users\yusuke\dev\03.azure\tmp> npx yo botbuilder

Welcome to the Microsoft Bot Builder generator v4.17.0.

Detailed documentation can be found at https://aka.ms/botbuilder-generator

? What's the name of your bot? chatbot
? What will your bot do? Demonstrate the core capabilities of the Microsoft Bot Framework
? What programming language do you want to use? JavaScript
? Which template would you like to start with? Echo Bot - https://aka.ms/bot-template-echo
? Looking good.  Shall I go ahead and create your new bot? Yes

...

Run `npm audit` for details.
------------------------
 Your new bot is ready!
------------------------
Open the README.md to learn how to run your bot.
Thank you for using the Microsoft Bot Framework.

```

上記のような表示がされればOKです！

そして今回使用するのはchatbotだけなので、残りのフォルダは削除してください。

![chatbot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/94e7b823-a491-e05a-ca95-2174aab848b0.png)

一旦ターミナルやpowershellでchatbotへ入り、以下のコマンドを実行です。

```bash
npm install
```
問題なく終了すれば、以下のコマンドでVSCodeを開きます。

```bash
code .
```

デバッグ実行したいので、VSCodeの左側のデバッグをクリックしてください。
そこでlaunch.jsonを作成します。をクリック。
![Azure](/images/azure_openai_chatbot_handson/vscode.png)

デバッガーの選択では```Node.js```を選択してください。

launch.jsonは以下のように記載してください。

```json
{
  // IntelliSense を使用して利用可能な属性を学べます。
  // 既存の属性の説明をホバーして表示します。
  // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "プログラムの起動",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "program": "${workspaceFolder}/index.js",
      "envFile": "${workspaceFolder}/.env"
    }
  ]
}
```
ここまで出来たらセーブして、F5を押してください。
デバッグ実行が開始されます。
デバッグコンソールへ以下の表示がされればOKです。(これからlocalhost:3978へアクセスしに行きます。)
![debugconsole.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/7a9cbf9e-c2a9-f476-4095-cfa903fb9439.png)

次にBot Framework Emulatorを使って動作確認していきます。

Bot Framework Emulatorのインストールは[こちら](https://github.com/Microsoft/BotFramework-Emulator/releases/tag/v4.14.1)

- MACの方はこちら
  - BotFramework-Emulator-4.14.1-mac.dmg

- Windowsの方はこちら
  - BotFramework-Emulator-4.14.1-windows-setup.exe

以下のようなエミュレータが起動出来ればOKです。

![botemulator.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/5f39a91d-7d9c-0b30-3f21-8fab1a383aef.png)

Open Botを開き、以下のように入力してください。

![openbot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/765e7d53-538d-2320-6fb8-1088479f0275.png)

Connectをクリックして、以下のような表示になったでしょうか。
Hello and Welcome!と表示されればOKです。

![botemu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/ae48328c-9c06-2309-645c-0efd25b7c55e.png)

今のところはオウム返ししてくるBotになります。

![oumu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/522dc8a0-9aa3-9a10-3f4c-8afb74885162.png)

これをOpenAIに接続し、AIと会話出来るチャットボットにするためにbot.jsを以下のコードに差し替えてください。

```javascript:bot.js
/* eslint-disable */
const { ActivityHandler, MessageFactory } = require('botbuilder');
const axios = require('axios');

const OPENAI_RESOURCE = process.env.OPENAI_RESOURCE;
const OPENAI_DEPLOYMENT = process.env.OPENAI_DEPLOYMENT;
const OPENAI_API_VERSION = process.env.OPENAI_API_VERSION;
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
const OPENAI_COMPLETION_URL = `https://${OPENAI_RESOURCE}.openai.azure.com/openai/deployments/${OPENAI_DEPLOYMENT}/chat/completions?api-version=${OPENAI_API_VERSION}`;

var getCompletion = async function (text) {
  var data = {
    messages: [
      {
        role: 'user',
        content: text,
      },
    ],
  };
  var res = await axios({
    method: 'post',
    url: OPENAI_COMPLETION_URL,
    headers: {
      'Content-Type': 'application/json',
      'api-key': OPENAI_API_KEY,
    },
    data,
  });
  return (res.data.choices[0] || []).message?.content;
};

class EchoBot extends ActivityHandler {
  constructor() {
    super();
    this.onMessage(async (context, next) => {
      try {
        const replyText = await getCompletion(context.activity.text);
        await context.sendActivity(replyText);
      } catch (error) {
        console.log(
          '🚀 ~ file: bot.js:43 ~ EchoBot ~ this.onMessage ~ error:',
          error.message
        );
      }
      await next();
    });

    this.onMembersAdded(async (context, next) => {
      const membersAdded = context.activity.membersAdded;
      const welcomeText = 'Hello and welcome!';
      for (let cnt = 0; cnt < membersAdded.length; ++cnt) {
        if (membersAdded[cnt].id !== context.activity.recipient.id) {
          await context.sendActivity(
            MessageFactory.text(welcomeText, welcomeText)
          );
        }
      }
      // By calling next() you ensure that the next BotHandler is run.
      await next();
    });
  }
}

module.exports.EchoBot = EchoBot;

```

次に.envファイルを修正します。

```env:.env
MicrosoftAppType=
MicrosoftAppId=
MicrosoftAppPassword=
MicrosoftAppTenantId=
OPENAI_RESOURCE=xxxxxxxxxxxxxxxxx
OPENAI_DEPLOYMENT=xxxxxxxxxxxxxxxxx
OPENAI_API_VERSION=2023-03-15-preview
OPENAI_API_KEY=xxxxxxxxxxxxxxxxx
```

それぞれの値の確認方法は以下です。
- OPENAI_RESOURCE
  - Azureポータルより、Azure OpenAIのリソース名を参照
- OPENAI_DEPLOYMENT
  - Azure OpenAI Studioのデプロイの箇所より、デプロイ名を参照
- OPENAI_API_VERSION
  - 2023-03-15-preview と入力
- OPENAI_API_KEY
  - AzureポータルのAzure OpenAIのキーとエンドポイントの箇所より、キー 1 を参照

これで再度実行してみましょう！
以下のようにAIが返信してくれるはずです。

![aireturn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/a23fa9e1-fe9f-9ee1-314a-8c8a9a604579.png)

ここまで出来たら、次にAzureにてAzure Bot Serviceを作成します。

![botservice.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/0f0a786a-4064-7bbc-5cc9-666c33350e64.png)

Bot Service → 作成をクリックしてください。

```Azure Bot```というサービスが表示されるので、選択し作成をクリック。(かなり下の方です。)
![azurebot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/68db0219-d79f-a5fe-a243-4c621a702582.png)

作成画面ではボットハンドルとリソースグループを指定してください。
![makebot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/44f686de-4478-c3f5-9e86-d68204fa1b42.png)

もう少し下のほうにMicrosoft App ID (Managed ID)の作成項目があります。

アプリの種類を```ユーザ割り当て済みマネージドID```へ変更してください。

こちらの設定は以上です。
確認と作成をクリックして、BotServiceを作成してください。

今のところはリソースグループを確認すると３つ出来ていれば順調です。

![tochu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/e68b23ef-62a3-ff2a-c01a-8dd05f6475cb.png)

## App Service のセットアップ

ここからはBot Serviceの裏側で動作するApp Serviceを作成していきます。
全体図で言うとここです。

![appservice.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/4caf0c82-3392-36f3-5cc1-a82d79c50b2d.png)

まずは、Azureポータルへログインし、App Serviceを検索してください。
![appservice1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/5ebbfb2a-4364-5a2e-d141-5e34353d266a.png)

App Serviceの画面へ進んだら、Webアプリ作成をクリックしてください。
![appservice2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/26407c11-51bc-8a89-f7be-708378c7d8ad.png)

nodeのバージョンはご自身の環境に併せて設定してください。
以下のコマンドで調べることが出来ます。
```bash
node -v
```

価格プランはBasicを選択してください。

![appservice3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/a20854cb-a01c-4bea-fc76-eedda9aa3e7b.png)

デプロイ・ネットワーク・監視は初期設定のままでOK
そこまで出来たら、確認及び作成をクリックしてください。

WebAppが作成されたらOKです！

## App ServiceへDeploy

ここまでできたら後はデプロイとなります。
VSCodeを開けて、画面左側の拡張機能のAzureのアイコンをクリックし、App Serviceを選択してください。

右クリックメニューよりDeploy to Web Appを選択し、デプロイを開始してください。

![deploy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/378e70cb-7b56-31e1-6e16-bbbde4eaa3ce.png)

問題なくデプロイが完了したら、Application Settingの箇所を選択し、右クリックから ```Upload local Settings```を選択。
.envファイルの内容が自動でUploadされます。

これにてローカルでの作業は完了です。
次にAzureポータルへ再度アクセスしてください。
先ほどBotService作成時に生成したマネージドIDをAppServiceへ適用していきます。

Azureポータル→App Service→IDを選択

ユーザ割り当て済みのタブを選択し、ユーザ割り当て済みマネージドIDを追加をクリック。

![managedid2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/5aecfe4b-d9a9-710c-2b38-99a626315614.png)

先ほど作成したマネージドIDを選択し、追加をクリック

![managedid3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/bad40105-23ce-843f-1b0a-dfe5fc7abd5c.png)

続いて最後に環境変数の設定です。
そのままAppServiceの構成より以下のように環境変数を設定していきます。

```
MicrosoftAppId→マネージドIDのプロパティよりクライアントIDをコピーして設定
MicrosoftAppType→UserAssignedMSI と入力
MicrosoftAppPassword→こちらは設定しなくてOK
MicrosoftAppTenantId→マネージドIDのプロパティよりテナントIDをコピーして設定
```

上記、入力出来たら、保存をクリックしてください。

## LINE MessagingAPIの設定

ここからはBot ServiceとLINEの連携を行っていきます。
全体図で言うとここです。

![botandline1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/836cda03-d894-1d06-b4eb-4a7db146a8aa.png)

まずはApp ServiceとBot Serviceを連携させます。
Azureポータル→Bot Service→構成→メッセージングエンドポイントへAppServiceの概要の規定のドメインに記載されているURLに/api/messagesと追記して設定してください。

![url.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/d0b06ff9-be3d-ceea-649e-f85a21241b9a.png)

次はBot ServiceにLINEを設定していきます。

AzureポータルよりBot Serviceを開き、チャンネルからLINEを選択
LINEのチャネルシークレットとチャネルアクセストークンを入力します。

以下サイトより、コンソールへログインし、プロバイダーを作成してください。
Messaging APIを使用します。
[LINE Developers](https://developers.line.biz/ja/)

以下のようなプロバイダーを作成してください。

![messagingapi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/471340f2-2033-c45a-13c7-45155d1af27c.png)

作成したら、チャネルの基本設定より、チャネルシークレットを、
MessagingAPIの箇所でチャネルアクセストークンを発行してください。

発行したら、Azureポータルに戻り、チャネルシークレットとチャネルアクセストークンを入力後、
Webhook の URLを生成してください。

上記で生成したURLをWebhook URLに貼り付ければOKです。

![lc1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/7be2ba9e-a833-eb18-15a4-56591bdfe829.png)

これで設定は全て完了です。
お疲れさまでした。

## 動作確認
では、LINE botへメッセージを送信してみましょう！

![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326114/7e2555e4-173a-062d-d1d7-554cee155563.png)

AIが返信してくれましたか？
ここまで出来たら完了です！
本当にお疲れさまでした。

## お片付け

最後にずっと残してて課金されないようにお片付けです。

以下、2つの操作を実行すれば OK です。

- Azure OpenAI Studio からデプロイの削除
- Azure よりリソースグループの削除

しっかりお片付けして本日は終わりです。

お疲れ様でした。

## 最後に
なかなか盛りだくさんの内容なので、詰まっちゃった方はぜひコメント欄にてどしどし質問してくださいね！