Azure Bot Serviceを使ってFAQBotを公開までの備忘録

#はじめに
BotFrameWorkを使ってFAQBotを作ってみました。
Azureを使ったBotを公開する方法が二通りあったので、その時の備忘録。

#環境
- Visual Studio 2017 Professional(Communityでも大丈夫らしい)
  - 言語：C#
- Azureサブスクリプション


#AzureのWeb App BotとQnAMakerを使って作成
##AzureのWeb App Botを設定

Azureのマイページから、新規 → AI+Cognitive Services → Web App Botをクリック

　　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/e6cde2ad-f3f2-02d2-b44a-216029bd11b6.png)

必須情報を入力していきます

　　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/3433894b-f6ca-998c-def7-17a03c32e0d9.png)

ボット名、価格レベル、ボットテンプレートをきちんと入力したら、
あとはいつも適当に入力してます。

ボットテンプレートの部分は、今回FAQBotをつくるため、Qusetion And Answerに変更します。

　　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/a4299624-5944-7a42-2722-58e04eda74a0.png)

入力が終了したら作成ボタンを押下し、ひとまず設定完了です。

##QnAMakerを作成
[ここ](https://qnamaker.ai/)にアクセスしてQnAを作成します。
所持しているマイクロソフトアカウントを使ってログインします。

ページ上のタブに'Create new Service'とあると思うので、クリック。

　　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/57f55124-ec44-d729-36bb-19ae478b1f5c.png)

次のような画面がでると思うので、必要情報を入力していきます。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/8f56c03f-376d-d3b9-ec1b-ab1a12fec5d0.png)

- Service name : QnAMakerの名前
- URL(s) : FAQが掲載されているサイトのUrlを貼ると自動的に判断してFAQを作ってくれます。
- FILES : Urlがない時はこちらを選択。tsv,csv形式で質問と答えを作成してアップロードすると、自動的にFAQを作ってくれます。pdfとかでもいけるみたいですが、私は上手くいきませんでした。

Createをクリックすれば終了です。
My servicesから作成したServiceを見てみます。
そこから鉛筆マークの編集をクリックすると、QAの編集ページに飛びます。

　　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/65e289f1-2589-3174-65aa-f13a03bef536.png)

今回わたしは気象庁のFAQページのUrlを拝借しました。
Urlを入力すると、自動的にこちらにFAQが入るため、入力の手間が省けて楽です。
ただ精度はまだまだのようで、編集する必要はあります。

終了したら、上部右上の'Save and retrain'をクリックします。

すべての編集が終了したら、Publishをクリックします。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/41ac95b3-131b-382d-ece3-6add733ae00e.png)

　↓
　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/be66f5e0-2592-e00b-3ff6-38c2df2c67b2.png)

上の画像に記載したQnAKnowledgebaseIdとQnASubscriptionKeyはAzureの設定で使うのでコピーしておきます。

ちなみにQnAMakerはトレーニングをすることで、回答に学習機能を持たせることが出来ます。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/eac09467-5b07-8b29-8af1-3b2057c49492.png)

回答部分には、質問の内容から考えられる他の回答を3つほど候補としてあげてくれます。
期待される回答が得られなかった場合、候補から回答を選択すると、
次からはその回答で返答してくれます。

##公開させるまでの設定
再び、設定したAzureのWeb App Botへ戻ります。
'アプリケーション設定'をクリックすると、下図のような設定ページに移行します。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/a59a396e-8431-0208-1cdf-c44dbad142c2.png)

QnAMakerでコピーしたQnAKnowledgebaseIdとQnASubscriptionKeyを入力します。
これで保存をすれば準備完了です。

試しにテストをしてみます。
テストはTest in Web Chatからできます。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/72f8ba0c-ba4c-15b1-cfdc-43a0004490a4.png)

適切な回答がみつからないとNo good match inFAQと表示されます。
みつからないときの回答や質問にどの程度の整合性があれば回答を表示させるか…
といった設定はコードをいじればできます。
QnAMakerのコードの中身については、次のBotFrameWorkで少し説明します。

このBotを自身のページに埋め込みたい場合は、チャンネルをクリックします。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/a6a79994-5468-d3de-e5e7-b7c82209f9f7.png)

編集ボタン/ボットの埋め込みコードを取得をクリックすると、作成したページの埋め込みコードが見れます。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/5b574458-f9b5-c867-4ee3-b5f67fa1c77d.png)

'シークレットを入力'とかかれた部分に、上のシークレットキーを表示させて貼り付けます。
これをHTMLで貼るだけ。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/3251c42d-cac7-9268-f438-5c892678ddc6.png)


#AzureのBot Channels RegistrationとBotFrameWorkとQnAMakerを使って作成
##BotFrameWorkを使ってローカルでBotを作成してみる
####BotFrameWorkを使うために今回インストールしたものたち
- Bot Framework Template
 
 →[Bot Frameworkダウンロードサイト](http://aka.ms/bf-bc-vstemplate)からテンプレートをダウンロード。
ダウンロードしたら下記の場所にzipファイルごと貼り付けます。

C:\Users[[ユーザ名]\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual C#

- Bot Framework Emulator

 →[ここ](https://emulator.botframework.com/)からダウンロード

さっそくプロジェクトを作ってみます。
新規プロジェクトを選択して、C#のBot Applicationを選択します。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/f826ea12-374c-713d-cdd0-040478166611.png)

このままF5でプログラムを実行し、Bot Framework Emulatorを起動させてもオウム返しのようなBotができています。

NuGetパッケージを見て更新が必要なものとかはインストールしといてください。

上のQnAMakerで作成したものと連携させてみます。

NuGetパッケージの管理を選択して、Microsoft.Bot.Builder.CognitiveServicesをインストールします。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/5bca5907-56fd-30c2-6189-1e6a75a86ac5.png)


まずRootDialogをコピーします。

コピーしたら、コードの中身はこんな感じに変更します。

```c#:WeatherQnADialog.cs
using System;
using System.Threading.Tasks;
using System.Linq;
using System.Text;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.CognitiveServices.QnAMaker;

namespace WeatherQnABot.Dialogs
{
    [Serializable]
    [QnAMaker("自分のQnASubscriptionKey", "自分のQnAKnowledgebaseId", "別の言い方で試してください。", 0.5, 3)]
    public class WeatherQnADialog : QnAMakerDialog
    {}
}
```

[QnAMaker]の中の引数ですが、3つ目に該当する回答が見つからなかったときの回答、
4つ目に質問の一致率、つまりQnAMakerに書いた質問とBotに投げた質問が同程度一致しているか、
(0.5は50%という意味になります。)
5つ目に他に考えられる回答をいくつまで候補として考えるか、
ここでは'3'としているため、候補を3つ抽出してくれます。

変更したら、Controllerの中のMessagesControllerを修正。

```c#:MessagesController.cs
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
　　　　　　　　　//RootDialogとなっている部分を上で作成したクラス名に変更
                await Conversation.SendAsync(activity, () => new Dialogs.RootDialog()); 
            }
            else
```

一度Bot Framework Emulatorを使って実行してみます。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/bd29b399-069d-85af-0066-af7f8bab20ab.png)

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/f4c2dfc6-8990-5ddf-b830-cf0a2f4e9b6e.png)


####機能の追加
今回複数回答機能を持たせたかったので、以下のコードを追加しました。

```c#:WeatherQnADialog.cs
public class WeatherQnADialog : QnAMakerDialog
    {
        //複数の解答を返したい場合
        protected override async Task RespondFromQnAMakerResultAsync(IDialogContext context, IMessageActivity message, QnAMakerResults result)
        {
            var bestAnswer = result.Answers.First();
            await context.PostAsync($"{bestAnswer.Answer}");

            if (result.Answers.Count > 1)
            {
                var sb = new StringBuilder();
                sb.Append("以下の情報も関連しているかもしれません");

                int count = 0;
                foreach (var answer in result.Answers.Skip(1))
                {
                    count += 1;
                    sb.Append($"\n\n{count}.{answer.Answer}\n\n");
                }
                await context.PostAsync(sb.ToString());
            }
        }

        //スコアが低い解答しか得られない場合
        protected override async Task QnAFeedbackStepAsync(IDialogContext context, QnAMakerResults result)
        {
            if (!IsConfidentAnswer(result))
            {
                var sb = new StringBuilder();
                sb.Append("以下の情報が関連しているかもしれません");

                int count = 0;
                foreach (var answer in result.Answers)
                {
                    count += 1;
                    sb.Append($"\n\n{count}.{answer.Answer}\n\n");
                }
                await context.PostAsync(sb.ToString());
            }
        }
    }
```


　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/6aa7712e-9388-efff-5fa0-50a73c742e64.png)


##発行
ソリューションエクスプローラーからプロジェクトを右クリックして発行を選択。
Microsoft Azure App Serviceを選択します。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/1e42ba1d-82b8-c06b-bef6-13085c709731.png)

発行ボタンを押すと下のような設定メニューが表示されるので、入力したら作成をクリックします。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/bb836fa2-dd52-c10f-9d34-65a8a2ab03b7.png)

発行されるとこんな感じに立ち上がるかと思います。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/e548fd61-03cb-4345-cfc8-e15f02abd4e5.png)


##AzureのBot Channels Registrationを設定
Azureのトップメニューに戻り、新規から"Bot Channels Registration"で検索し、作成します。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/5829efbf-42f4-14a6-18bc-b9938c57f35a.png)


ここで大事なのはメッセージング エンドポイントです。
こちらは先ほど発行したページに"api/messages"を追加したURLとなります。
私の場合、発行したURLは"https://ｗeatherqnabot.azurewebsites.net/"なので、
メッセージング エンドポイントは"https://ｗeatherqnabot.azurewebsites.net/api/messages"となります。

##公開させるまでの設定

最後の設定です。
作成したBot Channels Registrationの設定をクリックします。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/6743a0b0-e7fa-1c8b-87a1-ec275a7128aa.png)

この画像の表示名、Microsoft App IDは後ほど使うためメモしておきます。

続いてMicrosoft App ID横の(管理)ボタンをクリックします。
下のような画面が出るので、"新しいパスワードを生成"をクリックします。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/a6b9bc3e-d10a-2163-cb6a-ad2ae323b8b4.png)

ここで表示されるパスワードをメモしておきます。

　![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/4ee0459e-4f0f-0730-fe14-31e42315e2ff.png)

コードに戻って、Web.configの中身を先ほど取得したものたちに修正します。

```html:Web.config
  <appSettings>
    <!-- update these with your BotId, Microsoft App Id and your Microsoft App Password-->
    <add key="BotId" value="表示名" />
    <add key="MicrosoftAppId" value="Microsoft AppID" />
    <add key="MicrosoftAppPassword" value="上で発行したパスワード" />
  </appSettings>
```

ここで一度ローカルで動きを確認してみます。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/fce10106-2ec4-cc04-aec1-7778831ccb17.png)

Microsoft App ID と Microsof　App Passwordを自身が取得したものに変更するのを忘れずに。

確認したらもう一度発行します。
あとは、上記に記載したように、"チャンネル"から埋め込みコードを取得すれば自分のサイトに作成したBotを埋め込むことが出来ます。

  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/fbb71ad2-08c6-8901-25a5-c938c105ed78.png)


もし発行してもうまくいかなかったら、もう一度メッセージングエンド ポイントを入力し直すといいかもしれません。

#さいごに
AzureのWeb App Botを使った公開方法は、コーディングもなく、簡単でした。
こちらは本当に簡単なBotを作りたい時にお勧めだと思います。
Bot Channels Registrationを使った公開方法は、やり方が記載されているサイトが少なく、古い記事ばかりで苦労しました。
でもコードをいじる分、自由にカスタマイズが効くので作っていて楽しいと思います。

#参考
- [作業は『URLを入れる』だけ。MSの全自動FAQ bot会話生成サービス “QnAMaker” 試してみた
](https://ledge.ai/qnamaker/)
- [ヘルプ デスク ボットのハンズオン ラボ](https://github.com/satonaoki/help-desk-bot-lab-ja)
- [作ったChatbotを公開してみよう](https://thinkit.co.jp/article/12883)