Azure
LUIS
チャットボット
QnAMaker
BotService

LUISとQnaMaker、それを活用するBotServiceの概要とアクティブラーニングまで

はじめに

この記事はMicrosoft Azure Advent Calendar 2017 の6日目の記事です。

注意点(17/12/25追記)

記事を書いた直後にいろいろとGAになり、すでに遺物になっている可能性があります。。
下記などに詳しく載っています!
MS Cogbot Advent Calendar 2017

この記事は

Azureの自然言語解釈系サービスの2つと、それを利用可能とするPaaS機能について簡単な説明と使ってみた所感を記します。

17/12/6時点の情報で記載します。

正直日本語対応を謳ってますが、Preview的で、Unicode対応+分かち書きちょっとできるくらいの感触なので、今後に期待というところです。

昨日のAdvent Calendarの記事もQnaMakerとBotServiceから一歩進んだ記事ですので、ぜひ参考に。

LUIS

Language Understanding Intelligent Serviceの略ということで、イメージは公式を見るとわかります。

スクリーンショット 2017-12-07 22.34.08.png

utterance(文章)を入力とし、intent(文意)とentity(要素)をパースしてJSON形式で返すAPIとなっています。
教師あり学習なので数十の例文が必要です。下記作業はちょっと手がかかりますので、チャットボットに必須のユーザの問いかけ実データを使って再訓練なども手間がかかりそうです。

必要な作業は下記。チュートリアルレベルはドキュメントに書いてあります。

  • intent(文意)、entity(要素)を定義する
    • intentは30個まで定義できますが、多いと精度が下がります。ボットの目的を絞って、必要最小限にしましょう。
    • 事前定義済み要素(prebuilt entity)もありますが(時間など)日本語はあまり対応していないと思った方が良いでしょう
  • intentごとに例文を入力し、その正解のentityを指定する
    • 例文を入れると分かち書きされるので、entityをクリックする形です
    • 例文入力後 スクリーンショット 2017-12-07 22.59.19.png
    • entity指定後 スクリーンショット 2017-12-07 23.01.57.png
  • 学習させ、テスト用インターフェースで試す
    • LINEのようなインターフェースがあります
  • APIを公開する
    • キー取得など。指示に従っていけば特に迷わない認識です。

intentがある程度違うものであり、例文バリエーションを整えれば。。。
使用するデータをエンジンの改善に使うという規約と記憶してるので、日本語の精度を上げるためにどんどん使って欲しい、という印象を受けました。
しかし登録したentityのリストを取得する手法、entityを直接登録する手法がよくわからなくて辛い印象があリました(ご存知でしたらフォローください)

QnA Maker

公式

問いかけの文章を投げると、それに近い答えをスコアとともに返却してくれるAPIです。
こちらも教師あり学習で、QとAのペアを学習させる必要があります。
TSVで投入するのがベタですが、QAサイトのURLやWORD形式でも読めるそうです。
ただしフォーマット制約が厳しいのであまり期待しない方が良いです。
QAボットはかける手間の割に使えるものができるので、手始めにはベストです

トレーニングするインターフェースは対話的で、間違ったQAがあったら左の3択から修正しよう、なければあとで正しいAnswerをて入力する、というところが使いやすいです。
同じAnswerを期待するQuestionを右側にどんどん追加していけるのもグッドかと。

スクリーンショット 2017-12-07 23.27.17.png

Bot Service(ボットサービス)

Bot Service

App Serviceで「ボットサービス」と検索すると出てきます(Bot serviceだと当たらない?前は当たった気がするんだが)。

スクリーンショット 2017-12-07 23.49.05.png
スクリーンショット 2017-12-07 23.50.25.png

上記2つのサービスはテンプレートがあるので速攻です。
途中でQnAMakerのナレッジベース名をプルダウンで選択すれば連携終了。
デプロイされると、ブラウザ上で編集できる形でサンプルコードが出来上がります。
VisualStudioと連携してやるべきでしょうが、ちょっとの修正ならブラウザ上でも。

スクリーンショット 2017-12-07 23.54.56.png

Slack、SkypeやFacebookMessengerなども連携先のAPI情報を貼り付ければ連携OK!という仕組みです。

スクリーンショット 2017-12-07 23.42.47.png
スクリーンショット 2017-12-07 23.43.18.png

少し修正

アクティブラーニング、すなわちスコアがあまり高くないAnswerがいくつか出てきたとき、候補を提示してユーザに選んでもらう、というのをやってみました。

しかし何度ドキュメントを読んでもうまくいかず。。。
結果BotServiceが指定するライブラリのバージョンをあげたら解決しました。

修正前

project.json
{
  "frameworks": {
    "net46": {
      "dependencies": {
        "Microsoft.Bot.Builder.Azure": "3.2.1",
        "Microsoft.Bot.Builder.CognitiveServices": "1.0.3"
      }
    }
  }
}

修正後

project.json
{
  "frameworks": {
    "net46": {
      "dependencies": {
        "Microsoft.Bot.Builder.Azure": "3.2.1",
        "Microsoft.Bot.Builder.CognitiveServices": "1.1.0"
      }
    }
  }
}

これでQnaMakerDialogのクラスを一つ作り、run.csxから呼べばOKです。
TODO込みのコードで残念なのは許してください。

BasicQnAMakerDialog.csx
using System;
using System.Threading.Tasks;

using Microsoft.Bot.Builder.Azure;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.CognitiveServices.QnAMaker;

// For more information about this template visit http://aka.ms/azurebots-csharp-qnamaker
[Serializable]
public class BasicQnAMakerDialog : QnAMakerDialog
{
    // Go to https://qnamaker.ai and feed data, train & publish your QnA Knowledgebase.
    public BasicQnAMakerDialog() : base(new QnAMakerService(new QnAMakerAttribute(Utils.GetAppSetting("QnASubscriptionKey"), Utils.GetAppSetting("QnAKnowledgebaseId"), "良い回答が見つかりませんでした。別の質問に変えてもらえますか?",0.5)))
//   public BasicQnAMakerDialog() : base(new QnAMakerService(new QnAMakerAttribute(Utils.GetAppSetting("QnASubscriptionKey"), Utils.GetAppSetting("QnAKnowledgebaseId"))))
    {
    }
}

// ここから追加。TODO:APIキーとナレッジキーがべた書きになってしまったので良いやり方が知りたい。
[Serializable]
[QnAMaker("<QnAMakerのAPIキー>", "<ナレッジキー>", "わかりませんので別の質問にかえて", 0.10, 4)]
public class QnADialogWithActiveLearning : QnAMakerDialog
{
// TODO:こんな感じでかけそうなのにうまく動かなかった
//      public QnADialogWithActiveLearning() : base(new QnAMakerService(new QnAMakerAttribute(Utils.GetAppSetting("QnASubscriptionKey"), Utils.GetAppSetting("QnAKnowledgebaseId"), "良い回答が見つかりませんでした。別の質問に変えてもらえますか?",0.3,3)))
    protected override async Task QnAFeedbackStepAsync(IDialogContext context, QnAMakerResults qnaMakerResults)
    {
        // responding with the top answer when score is above some threshold
        if (qnaMakerResults.Answers.Count > 0 && qnaMakerResults.Answers.FirstOrDefault().Score > 0.75)
        {
            await context.PostAsync(qnaMakerResults.Answers.FirstOrDefault().Answer);
        }
        else
        {
            await base.QnAFeedbackStepAsync(context, qnaMakerResults);
        }
    }

}

これで自信がある回答はシングルアンサー、自信がないとマルチアンサーを返すようになります。

スクリーンショット 2017-12-08 0.09.35.png

まだ実際ユーザーが何を選択したかどうかがQnAMakerに返る訳ではなさそうなので、実際のアクティブラーニングにはもう一手間必要そうです。
どこかに吐いといて、バッチ学習でも良いと思います。

終わりに

簡単に紹介しました。今後に期待な部分も多いですし、英語のドキュメントもやや不親切ですが、
これくらいのアプリが1日あれば十分できてしまい、かつ料金もほぼ無料ということで
うまく付き合っていきたいところです。
wikiなどで情報共有しているサイトもあるかもしれませんが、意外とボット作っちゃった方がはやいかも?

以上です。