Help us understand the problem. What is going on with this article?

Azure BOT Service とCognitive Service QnA MakerでFAQのBOTを作る

More than 3 years have passed since last update.

概要

こんにちは!吉田です。今回は、マイクロソフトが12月13日にリリースした、質問に対して回答を返してくれる新しいCognitive Service「QnA Maker」と11月にリリースされたAzure BOT Serviceを組み合わせて、とある企業のFAQに対応するチャットボットを作ってみたいと思います。

事前に準備するもの

  • 時間:30分ほど
  • Azure サブスクリプション
  • 質問・回答が同じページに掲載されているFAQのサイト(例:https://www.microsoft.com/ja-jp/software-download/faq 等)
  • Skype アカウント(Microsoft Account) ※もしSkypeで試したい場合のみ必要

設定手順

Azure Bot Serviceの作成

  1. Azureポータルへアクセスし、新規(+)から、「Intelligence + analytics」をクリックし、「Bot Service」をクリックします。
    image

  2. 画面下から新規作成画面が表示されます。サイト名を記入し、場所を選択し、「作成」をクリックします。
    image

  3. デプロイが開始されます。1分ほどで完了します。デプロイが完了すると、以下のように表示されます。
    image

  4. 新しく作成したBot Serviceをすべてのリソース(または設定したリソースグループ)から選択します。
    image

  5. 開くと、Microsoft App IDの作成が求められます。「Create Microsoft App ID and Password」をクリックします。
    image

  6. アプリ名は(1)で設定したアプリ名、アプリIDは自動で生成されます。「アプリパスワードを生成して続行」をクリックします。
    image

  7. パスワードが表示されます。表示されたパスワードをメモ帳等のテキストエディタへ貼り付けて、「OK」をクリックします。パスワードは後程利用します。
    image

  8. 「終了してボットのフレームワークに戻る」をクリックします。
    image

  9. 先ほど表示されていた、App IDとメモ帳へ貼り付けていたパスワードを入力します。
    image

  10. 次に言語を選びます。今回はC#で作りますので、「C#」をクリックします。
    image

  11. 前回の投稿にはなかった、「Question and Answer」が選択できるようになっています!これを選択し、「Create bot」をクリックします。
    image

  12. ウィザードが立ち上がります。QnA MakerはBot Serviceとは別のサービスなのですが、ここから作成すると、ウィザードが自動的にアカウントを作成してくれます。「Sign In」をクリックします。
    image

  13. サインインが求められます。Microsoft Accountのものを選択しましょう。別のにすることも可能です。
    image

  14. 利用許可の確認画面が出ます。「はい」をクリックしましょう。
    image

  15. 「I agree...」のところにチェックを入れて、「OK」をクリックします。OKをクリックしてから次の画面に移るまで10秒ぐらいあり、「あれ?反応しない?」っと最初は焦りましたが、待っていれば大丈夫(のはず)です。
    image

  16. BOTの作成がはじまります。2分ぐらいこの画面が表示されるので、待ちましょう。
    image

  17. 次に「run.csx」のプログラムを以下のコードで上書きしてしまいます。ナレッジベースIDとキーの取得は、事前にQnA Makerで「Publish」をした後に表示されたものを利用します。
    ※本来はコードを書き換えなくてもそのまま利用できるはずなのですが、試したところ、日本語だと返ってくるメッセージが文字化けしてしまったので、暫定的にこの方法にしています。(修正されたら、この記事にも反映します)

run.csx
#r "Newtonsoft.Json"
#load "BasicQnAMakerDialog.csx"

using System;
using System.Net;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using Microsoft.Bot.Builder.Azure;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;

public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"Webhook was triggered!");

    // Initialize the azure bot
    using (BotService.Initialize())
    {
        // Deserialize the incoming activity
        string jsonContent = await req.Content.ReadAsStringAsync();
        var activity = JsonConvert.DeserializeObject<Activity>(jsonContent);

        // authenticate incoming request and add activity.ServiceUrl to MicrosoftAppCredentials.TrustedHostNames
        // if request is authenticated
        if (!await BotService.Authenticator.TryAuthenticateAsync(req, new[] { activity }, CancellationToken.None))
        {
            return BotAuthenticator.GenerateUnauthorizedResponse(req);
        }

        if (activity != null)
        {
            // one of these will have an interface and process it
            switch (activity.GetActivityType())
            {
                case ActivityTypes.Message:
                    //await Conversation.SendAsync(activity, () => new BasicQnAMakerDialog());

                    //ナレッジベースIDとキーの取得は、事前にQnA Makerで「Publish」をした後に表示されたものを利用します。
                    var knowledgebaseId = "ここにナレッジベースIDを入力してください"; //Utils.GetAppSetting("QnASubscriptionKey"); // Use knowledge base id created.
                    var qnamakerSubscriptionKey = "ここにサブスクリプションキーを入力してください"; //Utils.GetAppSetting("QnAKnowledgebaseId"); //Use subscription key assigned to you.

                    //Build the URI
                    Uri qnamakerUriBase = new Uri("https://westus.api.cognitive.microsoft.com/qnamaker/v1.0");
                    var builder = new UriBuilder($"{qnamakerUriBase}/knowledgebases/{knowledgebaseId}/generateAnswer");

                    //Add the question as part of the body
                    var postBody = $"{{\"question\": \"{activity.Text}\"}}";
                    //QnAMakerResult qnaresponse = new QnAMakerResult();
                    String qnaresponse = null;
                    //Send the POST request
                    using (WebClient webclient = new WebClient())

                    {
                        //Set the encoding to UTF8
                        webclient.Encoding = System.Text.Encoding.UTF8;

                        //Add the subscription key header
                        webclient.Headers.Add("Ocp-Apim-Subscription-Key", qnamakerSubscriptionKey);
                        webclient.Headers.Add("Content-Type", "application/json");
                        log.Info($"Requesting QnA...");
                        var qnaresponseString = webclient.UploadString(builder.Uri, postBody);
                        //qnaresponse = JsonConvert.DeserializeObject< QnAMakerResult >(qnaresponseString);
                        qnaresponse = JObject.Parse(qnaresponseString)["answer"].ToString();
                    }

                    var qnaclient = new ConnectorClient(new Uri(activity.ServiceUrl));
                    var qnareply = activity.CreateReply();
                    //qnareply.Text = qnaresponse.Answer.ToString();
                    qnareply.Text = qnaresponse;
                    await qnaclient.Conversations.ReplyToActivityAsync(qnareply);
                    break;

                case ActivityTypes.ConversationUpdate:
                    var client = new ConnectorClient(new Uri(activity.ServiceUrl));
                    IConversationUpdateActivity update = activity;
                    if (update.MembersAdded.Any())
                    {
                        var reply = activity.CreateReply();
                        var newMembers = update.MembersAdded?.Where(t => t.Id != activity.Recipient.Id);
                        foreach (var newMember in newMembers)
                        {
                            reply.Text = "Welcome";
                            if (!string.IsNullOrEmpty(newMember.Name))
                            {
                                reply.Text += $" {newMember.Name}";
                            }
                            reply.Text += "!";
                            await client.Conversations.ReplyToActivityAsync(reply);
                        }
                    }
                    break;
                case ActivityTypes.ContactRelationUpdate:
                case ActivityTypes.Typing:
                case ActivityTypes.DeleteUserData:
                case ActivityTypes.Ping:
                default:
                    log.Error($"Unknown activity type ignored: {activity.GetActivityType()}");
                    break;
            }
        }
        return req.CreateResponse(HttpStatusCode.Accepted);
    }
}
  1. この画面が表示されたら、Bot Serviceの作成は完了です。次に質問集を登録していきます。 image

質問と回答を登録する

Bot Serviceは出来上がりましたが、このままでは質問と回答が登録されていません。このステップでは、事前に用意しておいた質問と回答を登録し、Botが答えられるようにします。

  1. QnA Makerのサイト(https://qnamaker.ai) へアクセスし、「My services」を選択します。ログインされていない場合は、先ほどの13の手順で利用していたMicrosoft Accountでログインしてください。
    image

  2. 「I agree...」のところにチェックを入れて、「OK」をクリックします。(2回目作成時からは表示されません)
    image

  3. 先ほどAzure Bot Serviceで登録したQnA Makerが表示されています。鉛筆マークをクリックします。
    image

  4. 質問・回答集が表示されます。既定では「hi」という質問に対し、「hello」と返答することだけが登録されているので、これから編集します。「Settings」をクリックします。
    image

  5. 手動で登録する方法もありますが、QnA Makerには、URLを指定するだけで自動で質問回答集を作成してくれる、非常に便利な機能が用意されています。今回はStarbucks Coffee JapanさんのFAQ(http://www.starbucks.co.jp/faq/products/) を試してみたいと思います。(スタバさん、勝手に使ってすみません…)
    このように、質問と回答が同じページでないと、QnA Makerは自動で認識できないので、要注意です。
    image

  6. URLを入力したら、「Save and retrain」をクリックし、「Knowledge Base」へ戻ります。
    image

  7. FAQの内容が登録されたことが確認できました。「Test」をクリックして、試してみましょう。
    image

  8. 試しに質問を送信してみます。回答がでましたね。次に「Publish」をクリックし、この内容を発行します。
    image

  9. 確認画面が表示されるので、「Publish」をクリックします。
    image

  10. この画面が表示されたらQnA Makerの設定は完了です。Azure Portalから作成したAzure Bot Serviceへ戻ります。
    image

Skype BOTを作成する

FAQの登録が完了したので、Skypeで試してみます。Skypeでのテストは、Azure Bot Serviceの画面からBOTの連絡先が追加できるようになっています。

  1. 「Channels」タブから「Add to Skype」をクリックします。
    image

  2. 「Add to Contacts」をクリックします。
    image

  3. Skypeが立ち上がりますので、試してみましょう!
    image

taiki_yoshida
吉田の備忘録をやっています、吉田です。 Microsoft製品やソリューションをより身近に、より分かりやすく、より早く共有することが日々の目標です。Dynamics 365、Office365、Azure関連の記事を投稿してます。 ※発言は個人の見解であり、所属する組織の公式見解ではありません。
http://memo.tyoshida.me
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした