学習させることで、どんどん賢くなっていくLUISをbotサービスで活用するには認識系API活用入門(終)(2/3 ページ)

» 2017年08月22日 05時00分 公開
[岩本禎史株式会社クロスキャット]

LUISに接続する処理の作成

 実際にプログラムからLUISを呼び出すところを作成します。プログラムの流れとしては非常にシンプルで、下記のようになります。

  1. ユーザーの入力内容を受け取る
  2. LUISのAPIにユーザーの入力内容を渡す
  3. LUISが解析した結果を受け取る

 LUISも連載第5回で紹介したComputer Vision APIと同様に、Tokenを使用しない方式です。LUISでは、Tokenを取得せずに直接Endpoint URLにSubscription-Keyを渡すようになっています(ただし、現在LUISはプレビュー扱いであるため、今後どうなるかは分かりません)。

 まず、LUISに処理をお願いしてJSON形式で返ってくるデータを受け取るためのクラスを作成します。

 メニューバーの「プロジェクト」から「クラスの追加」をクリックします。

クラスの追加(1)

 追加するのは通常のクラスです。名前を「LUIS.cs」として「追加」ボタンをクリックします。

クラスの追加(2)

 クラスが追加されたら、下記コードをコピーしてそのクラスにペーストしてください。また、ソースコード73行目のurlは、前回の連載で取得したエンドポイントURLに適宜置き換えてください

 ちなみに「LUIS」という名前のフォルダを作成しその下にクラスを置いたので、名前空間が「LUIS_WeatherBotApp.LUIS」となっています。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Runtime.Serialization.Json;
 
namespace LUIS_WeatherBotApp.LUIS
{
    public class LUIS
    {
        //========================================================
        // LUISのデータを受け取るためのクラスたち
        //========================================================
        public class RootObject
        {
            public string query { get; set; }
            public List<Intents> intents { get; set; }
            public List<Entities> entities { get; set; }
        }
        public class Entities
        {
            public string entity { get; set; }
            public string type { get; set; }
            public string startIndex { get; set; }
            public string endIndex { get; set; }
            public string score { get; set; }
        }
 
        public class Intents
        {
            public string intent { get; set; }
            public string score { get; set; }
            public List<Actions> actions { get; set; }
        }
 
        public class Actions
        {
            public string triggered { get; set; }
            public string name { get; set; }
            public List<Parameters> parameters { get; set; }
        }
 
        public class Parameters
        {
            public string name { get; set; }
            public string required { get; set; }
            public List<Value> value { get; set; }
        }
 
        public class Value
        {
            public string entity { get; set; }
            public string type { get; set; }
            public string score { get; set; }
        }
 
 
        //========================================================
        // LUISの結果が入る
        //========================================================
        public RootObject LUISResult;
 
        //========================================================
        // コンストラクタ
        //========================================================
        public LUIS(string pMessage)
        {
            try
            {
                // LUISにbotで受信したメッセージを投げる 
                // string url にEndpoint URL を記載
                string url = "https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?subscription-key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&staging=true&verbose=true&timezoneOffset=0.0&q=";
                url += System.Web.HttpUtility.UrlEncode(pMessage);
 
                var request = (HttpWebRequest)WebRequest.Create(url);
 
                var response = request.GetResponse();
                var responseStream = response.GetResponseStream();
                if (responseStream == null)
                {
                    throw new Exception();
                }
 
                //受け取ったJsonをデシリアライズ
                DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(RootObject));
 
                LUISResult = (RootObject)dcjs.ReadObject(responseStream);
 
 
            }
            catch
            {
 
            }
        }
    }
}

天気予報Webサービスに接続する処理の作成

 続いて、天気予報を取得する処理です。今回は無料で使用できるLivedoor天気予報のお天気Webサービスを使用します。

 APIでは、「city」がパラメーターとして必須になっています。これは都道府県名や県庁所在地が対応しているのですが、名前ではなくIDで渡す必要があります。そのため名前からIDを求める処理が入っています。

 LUISと同様に通常のクラスを追加し、名前を「WeatherForecast.cs」とします。

 プログラムとしては、こちらのようになります。ちなみに「WeatherForecast」という名前のフォルダを作成しその下にクラスを置いたので、名前空間が「LUIS_WeatherBotApp.WeatherForecast」となっています。

LUISと天気予報を呼び出して応答を返す

 続いて、RootDialog.csに、LUISと天気予報を呼び出して応答を返すように変更を加えます。RootDialog.csは以下のようになります。

using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
 
namespace LUIS_WeatherBotApp.Dialogs
{
    [Serializable]
    public class RootDialog : IDialog<object>
    {
        public Task StartAsync(IDialogContext context)
        {
            context.Wait(MessageReceivedAsync);
 
            return Task.CompletedTask;
        }
 
        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
        {
            try
            { 
                var activity = await result as Activity;
 
                // -----------------------
                // LUIS
                // -----------------------
                string date = "";
                string prefecture = "";
 
                LUIS.LUIS luis = new LUIS.LUIS(activity.Text);
                if (luis.LUISResult == null)
                {
                    throw new Exception("もう一度お願いしします。");
                }
 
                foreach(LUIS.LUIS.Entities entities in luis.LUISResult.entities)
                {
                    switch (entities.type)
                    {
                        case "date":
                            date = entities.entity;
                            break;
 
                        case "prefecture":
                            prefecture = entities.entity;
                            break;
                    }
                }
 
                if (date == "" || prefecture == "")
                {
                    throw new Exception("もう一度お願いしします。");
                }
 
                // -----------------------
                // 天気予報の取得
                // -----------------------
                WeatherForecast.WeatherForecast weatherForecast = new WeatherForecast.WeatherForecast(prefecture);
 
                if (weatherForecast.weatherResult == null)
                {
                    throw new Exception("その場所の天気予報が取得できませんでした。");
                }
 
                WeatherForecast.WeatherForecast.Forecast forecast = null;
                switch (date)
                {
                    case "今日":
                    case "きょう":
                        forecast = weatherForecast.weatherResult.forecasts[0];
                        break;
                    case "明日":
                    case "あす":
                    case "あした":
                        forecast = weatherForecast.weatherResult.forecasts[1];
                        break;
                    case "明後日":
                    case "あさって":
                        forecast = weatherForecast.weatherResult.forecasts[2];
                        break;
                }
 
                if (forecast == null)
                {
                    throw new Exception("もう一度お願いしします。");
                }
 
                string replyMessage = "";
                replyMessage += forecast.dateLabel + "は\r\n";
                replyMessage += forecast.telop;
                if (forecast.temperature.min != null) replyMessage += "\r\n最低気温:" + forecast.temperature.min.celsius + "℃";
                if (forecast.temperature.max != null) replyMessage += "\r\n最高気温:" + forecast.temperature.max.celsius + "℃";
            
                await context.PostAsync(replyMessage);
                context.Wait(MessageReceivedAsync);
            }
            
            catch(Exception exception)
            {
                await context.PostAsync(exception.Message);
                context.Wait(MessageReceivedAsync);
            }
        }
    }
}

 最終的なプロジェクトの構成は、下記のようになります。

プロジェクトの構成

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。