XamarinからLuisを使ってみる(その2)

  • 0
    Like
  • 0
    Comment

    このエントリは Xamarin(その2) Advent Calendar 2016 の13日目の投稿です。

    引き続きLUIS

    MicrosoftのBot用言語解析フレームワーク

    LUISが何をするものかというと、ざっくり言って「自然言語 → コンピュータ用コマンド」のトランスレーターです。
    人が話したり文字にしたものを定義されている文例から探し出し、スコアを付けてどのコマンドと思われるかを出力します。

    というのが Xamarin Advent Calendar 2016 の13日目 にも書いたことでした。

    今回作ったソース

    そもそもコントロールする実機を用意しているわけでもなく、LUISを使ってみたい!というところからプロジェクトに繋げているので未完成度満々ですが。

    GitHub にソースを置きました。
    (一応、uwpとiOSではLUISを呼び出して動くところまでは確認しています)

    プロジェクト拡張子 概要
    .common 共通部分(Xamarin.Forms, PCL)
    .uwp uwp用起動部分
    .ios iOS用起動部分

    基本的には.commonの中にすべて入っています。
    残りはホントに起動させるだけですね。

    LUIS呼び出し部分

    Xamarin Advent Calendar 2016 の13日目 に書いたことですが、実際には luisExecuter.cs に組み込んであります。

                var client = new HttpClient();
                var json = await client.GetStringAsync(String.Format("https://api.projectoxford.ai/luis/v2.0/apps/****?subscription-key=***&verbose=true&q={0}", Uri.EscapeDataString(query)));
    

    33行目ですね。
    ちなみに該当のLUISのアプリは削除してありますので、今このソースではどこにもつながりません。
    申し訳ない。

    その後Deserializeを行い、

                    var result = JsonConvert.DeserializeObject<LuisResult>(json);
    

    実行メソッドを呼び出します。

                            DelegateMethods[intent].Invoke(this, new object[] { result });
    

    インテントと実際のメソッドとの関連付けはどうなっているかというと、LuisIntentというAttributeを使って関連付けています。

            [LuisIntent("heatBathWater")]
            private void HeatBathWater(LuisResult result)
            {
                Debug.WriteLine("HeatBathWater,result:" + result);
                HomeItemCollection.Instance.Find("bath")?.Switch(SwitchType.On);
            }
    

    Attributeの定義はluisExecuter.cs の100行目~

        [AttributeUsage(AttributeTargets.Method)]
        public class LuisIntentAttribute : Attribute
        {
            public string IntentName { get; private set; }
    
            public LuisIntentAttribute(string intent)
            {
                IntentName = intent;
            }
        }
    

    関連付けの実行は19行目のコンストラクタ内で。

            private LuisExecuter()
            {
                foreach (var m in this.GetType().GetRuntimeMethods())
                {
                    var attr = m.GetCustomAttribute<LuisIntentAttribute>();
                    if (attr != null)
                    {
                        DelegateMethods[attr.IntentName] = m;
                    }
                }
            }
    

    このAttributeを使ってIntentとメソッドを関連付けるやり方は、Bot Frameworkでもやっていて、それと同じことを行っています。
    こうしておくことでAttribute付きのメソッドを並べていくことで対応関数を増やすことができます。

    ただまあ、手軽にやるならIntentと同じ名前のメソッドを用意してRefrectionで見つけて実行させる、という方法でも問題ないと思いますが。

    終わり

    コンセプトのわりにやっていることはC#初心者用、という感じで。
    申し訳ない。

    毎年初心者用ものを書いている気がします。

    This post is the No.15 article of Xamarin(その2) Advent Calendar 2016