Azure Bot Service(SDK v4)を使って雑談対話させてみるまで

# はじめに
Tech Summit2018に行ってきました。
そこでAzure Bot ServiceがSDK v4になっていたので、ハンズオンにて体験。
v3と変更箇所がけっこうありました。
加えて、これまでSlackを使っていたのですが、Teamsへ移行が決定。。
そこで、docomoAPIの自然対話を盛り込んだBotをTeamsにあげるまでを備忘録的に残します。

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

# Azure Bot Service (SDK v4)
[こちら](https://qiita.com/usomaru/items/40731858a561cad4b7b9)ではSDK v3を使って作っているのですが、
まず作成方法・作成後の画面が大きく変わっていました。
１から作り方を備忘録。

1. Azureポータル画面のリソースの追加にて「Web App Bot」で検索
Web App ということで、今回は、Web Apps上にBotを乗せるイメージです。そのため常時稼働しているという感じになります。
一方、Bot作成方法としてもうひとつファンクションを使って作成する方法があると思います。
こちらは、アクションがあってから動くので、返答までに少々時間がかかってしまいます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/51786968-1b00-bd89-36bd-79ee236424ff.png)

2. 作成をクリックし、基本情報を入力していきます。大きな変更点としてはボットテンプレートが下記のように変更されました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/9546abb8-24e9-1445-7d95-048f75cc9409.png)
Echo Botは簡単なオウム返しBotであり、コードも追いやすいということで今回はこちらを選択します。

3. 作成が完了しましたら、Web アプリ ボットを確認してみます。
Web アプリ ボットの"Webチャットでテスト"から、チャットの確認ができます。
ここで表示される概要画面も大きく変更されている点だと思います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/47f08192-8251-0df6-c43c-5390f2aacf44.png)


# docomoAPIを使った自然対話処理をコードに追加

docomoAPIの取得方法は私の過去記事を参照してみてください。
[Slackbot備忘録(2)　～docomoAPIを使ったbot～](https://qiita.com/usomaru/items/c31ec525eacb5e10c3a1)

## ソースコードのダウンロード
1. Web アプリ ボットのビルドを選択します。
2. すると、次のような画面がでると思うので、zipファイルをダウンロードをクリックします。
こちらもv3にはなかった機能で、ここからファイルをダウンロードすれば、
自動的にBot作成に必要なファイルを用意してくれます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/ebe58d9d-19f4-e263-bdcb-89078f177c8f.png)


3. ダウンロードされたファイルの中身はこんな感じ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/56392284-6f9b-09c8-c56f-8bcce933287b.png)
EchoBotWithCounter.slnをダブルクリックすればすぐにプロジェクトを始められます。

## 対話処理の追加
C#は普段かかないため、他サイトを参考にしながら作成しています。
文法的におかしい部分があるかもしれませんが、ご了承ください。。

今回追加したusingは以下の通りです。

```C#:EchoWithCounteBot.cs
using System.Net.Http;
using System.Text;
using Newtonsoft.Json;
```

まずはAPIで送るjson部分のモデルクラスを作成します。


```C#:EchoWithCounteBot.cs

 [JsonObject]
        public class DocomoAPI
        {
            [JsonProperty("language")]
            public string Language { get; private set; }

            [JsonProperty("botId")]
            public string BotId { get; private set; }

            [JsonProperty("appId")]
            public string AppId { get; private set; }

            [JsonProperty("voiceText")]
            public string VoiceText { get; private set; }

            public DocomoAPI(string language, string botId, string appId, string voiceText)
            {
                this.Language = language;
                this.BotId = botId;
                this.AppId = appId;
                this.VoiceText = voiceText;
            }
        }
```

続いてAPI処理部分をかいていきます。

```C#:EchoWithCounteBot.cs

 public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                // メッセージ取得
                var receivedMessage = turnContext.Activity.Text;

                // 本当は関数に切り出した方がいいんだろうけど、とりあえずここにdocomoAPIの処理
                string baseUrl = "https://api.apigw.smt.docomo.ne.jp/naturalChatting/v1/dialogue";
                // key
                string registerKey = "docomoAPIから取得したKey";
                string url = $"{baseUrl}?APIKEY={registerKey}";

                var client = new HttpClient();
                string appid = "docomoAPIから取得したappid";
                var jsonpost = new DocomoAPI("ja-JP", "Chatting", appid, receivedMessage);
                var json = JsonConvert.SerializeObject(jsonpost);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                var response = await client.PostAsync(url, content);
                var data = await response.Content.ReadAsStringAsync();
                dynamic obj = JsonConvert.DeserializeObject(data);

                string mes = obj.systemText.utterance;

                await turnContext.SendActivityAsync(mes);
            }
            else
            {
                await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected");
            }
        }
```

APIの処理部分は関数に切り出した方がスマートですが、
今回はひとまずOnTurnAsyncの中に書いています。
後日ちゃんと書き直したものをUPしたいと思います。
すみません。

コードをデバックしながら見ると流れを追いやすいと思いますが、
メッセージを受け取って、返答を処理をしているのは基本的にこの部分です。
なので、自分なりの処理を追加したい場合は、EchoWithCounteBot.csにかくのがいいのかなと思います。

## 発行
作成したBotを発行してTeamsで動かす準備をします。

1. リソースグループから、App Serviceを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/9a38922f-0729-962a-88ab-ddf3e39f0476.png)
1. 発行プロファイルの取得をクリックして、発行プロファイルをダウンロードします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/fa0085c6-ad84-16a0-82c8-df6a19785416.png)

2. ダウンロードしたプロファイルをメモ帳なりサクラエディタなりで開きます。
開くと"userPWD"という部分があるので、そこをコピーしておきます。
3. Visual Studioに戻り、ソリューションを右クリックして発行を選びます。![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/26c1e366-a6c0-f0b9-d593-f4a0942111bd.png)
4. 構成をクリックすると、パスワードを入力する部分が表示されるので、そちらに先ほど取得した"userPWD"を入力します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/37a01b18-3e9d-815f-2dc1-bee6ad9b6c37.png)

5. 接続の検証をしてみて、正常に検証出来たら保存。そして発行ボタンをクリックします。
以上で発行は終了です。

# Teamsにあげてみる
1. 再びWeb アプリ ボットからチャンネルをクリックします。
2. 私はすでに登録しているため、上にMicrosoft Teams実行中となっていますが、
実際は接続したいチャンネルをクリックして、保存ボタンを押せば追加できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/4e5567ca-b9b4-654b-7f5b-1d8619c4c91a.png)

1. 設定をクリックします。Microsoft App IDという画面があるので、このIDをコピーします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/a114dee1-0a2b-a95a-6c8d-69e11b50d12a.png)




1. Teamsを立ち上げて、チャットから新しいチャットをクリックします。
2. メンバーの入力欄に先ほどのMicrosoft App IDを入力すると、ボットの表示名が現れると思います。
3. 会話してみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201826/535c3658-9162-53a3-8058-e9996b139051.png)
相変わらずなんともいえない会話ができました。


# さいごに
普段C#書かないので、コード調べるのに苦労しました…
pythonも早く導入されるといいなぁ…
オウム返しBotを作成するまではほんと一瞬です。
チームで会話させたかったのですが、なかなかうまくいっていないので、
出来次第投稿予定。
ぜんぜん関係ないですが、Tech Summitで聞いたちょまどさんの、
スマートスピーカのセッションが面白かったです。

# 参考
- [C#でJSONを扱う方法まとめ](https://dev.classmethod.jp/etc/c-sharp-json/)
- [Tech Summit 2018 チャットボットハンズオン](https://github.com/NoOps-jp/mstsjp18-chatbot-handson)