[LUIS]使用Microsoft LUIS讓你的LINEBot更聰明

前面幾篇記錄了怎麼設定LINE Bot、架設Web API、申請LUIS和設定等

今天就把整個都串起來吧!

(上次LUIS好像是設定天氣..但我之前已經寫好的是匯率..只好先說聲抱歉啦!!)

Web API的部分除了之前LINE的部分之外,

我們還要把LINE收到的訊息送給LUIS分析,

分析完之後才知道User到底問了甚麼 我們要回甚麼~ 

對吧~ 那就 開始吧!!


微軟有提供SDK來給大家使用,

如果對SDK不了解怎麼使用的話(像我....) 

可以參考微軟LUIS的GitHub Sample

請進入到NuGet 下載Mircrosoft.Congnitive.LUIS 

已經下載完成的畫 到已安裝就會看的到~

下圖就是API的內容啦

其中NLPInfo 只用到了LUIS的appId和appkey

只要提供appId和appkey 產生LUIS的實體並呼叫predict Method 就可以幫你做語意分析

所以假如我們先不管GetResult到底分析了甚麼結果,

可以看到會回傳一個ReplyMessage,再將該訊息傳到原本LINEBot裡面

這樣就完成了 回應使用者了

public class LineBotWithLUISController : ApiController
    {
        BotRepository db = new BotRepository();
        public async Task<IHttpActionResult> Post()
        {
            try
            {
                //Get Message
                string postData = Request.Content.ReadAsStringAsync().Result;
                var RequestBody = isRock.LineBot.Utility.Parsing(postData);
                string Message = RequestBody.events[0].message.text;

                //取得LUIS的相關設定值
                NLPInfo LUISInfo = db.GetNLPInfo("LineBotNLP");

                //Send to Analysis
                Microsoft.Cognitive.LUIS.LuisClient lc
                    = new Microsoft.Cognitive.LUIS.LuisClient(LUISInfo.appid, LUISInfo.appKey, true);
                var AnalysisResult = await lc.Predict(Message);

                //Get Reply Message
                string replyMessage = db.GetResult(AnalysisResult);

                //Response Message
                string ChannelAccessToken = db.GetBotToken("Line");
                isRock.LineBot.Utility.ReplyMessage(RequestBody.events[0].replyToken, replyMessage, ChannelAccessToken);
                return Ok();
            }
            catch (Exception ex)
            {
                string errorMessage = string.Format("ErrorMessage:{0},ErrorStack:{1},InnerExcepton:",
                    ex.Message,
                    ex.StackTrace,
                    ex.InnerException);
                db.InsertRequestLog(errorMessage);
                return Ok(errorMessage);
            }
        }
    }

因為LUIS回傳回來的物件 大概是長這樣(來回憶一下前一篇的內容)

來看一下GetResult的內容,要怎麼判斷 

首先根據上一張圖可以看到
1.intent :是有關User要問的問題
2.entities:有兩個,分別的type是Currency和AskQuantify

所以根據intent和entities就可以抓出 User想要問甚麼~
此時我們只要根據這些內容來去資料庫抓資料就可以了

        /// 判斷User查詢內容
        /// <summary>
        /// 判斷User查詢內容
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public string GetResult(Microsoft.Cognitive.LUIS.LuisResult analysisResult)
        {
            string Default = "很抱歉,無法解析你所問的問題";
            if (analysisResult == null)
            {
                return Default;
            }

            var intent = analysisResult.TopScoringIntent;
            var enitiesDictinary = analysisResult.Entities;
            IList<Microsoft.Cognitive.LUIS.Entity> entitiesCollection;
            try
            {
                //TODO 要用設計模式比較好
                if (intent.Name == "匯率查詢")
                {
                    string CurName;
                    DateTime ExDate;
                    if (enitiesDictinary.TryGetValue("Currency", out entitiesCollection))
                    {
                        CurName = entitiesCollection.Select(o => o.Value).FirstOrDefault();
                    }
                    else
                    {
                        return Default;
                    }
                    if (enitiesDictinary.TryGetValue("ExDate", out entitiesCollection))
                    {
                        DateTime.TryParse(entitiesCollection.Select(o => o.Value).FirstOrDefault(), out ExDate);
                    }
                    else
                    {
                        ExDate = DateTime.Today;
                    }
                    return GetCurrencyExRate(CurName, ExDate);
                }
                else
                {
                    return Default;
                }
            }
            catch (Exception ex)
            {
                return Default;
            }
        }

 抓取資料庫的匯率就更簡單了,想必大家都會了吧
(別問我匯率怎麼來,可以做爬蟲可以手動建立..可以用LINEBot抓...)

        private string GetCurrencyExRate(string CurrencyName, DateTime ExDate)
        {
            string currency = DB.CurInfo.AsQueryable()
                              .Where(o => o.CurChtName == CurrencyName)
                              .Select(o=>o.CurAbName).FirstOrDefault();
            var ExRateObj = DB.ExRate.AsQueryable()
                       .Where(o=>o.Cur == currency)
                       .Select(o => new
                       {
                           BuyRate = o.ExBRate,
                           SellRate = o.ExSRate
                       }).FirstOrDefault();

            return string.Format("{0} {1}匯率 : {4}買進{2} 賣出{3}", 
                CurrencyName, 
                ExDate.ToString("yyyyMMdd"), 
                ExRateObj.BuyRate.ToString("#.####"), 
                ExRateObj.SellRate.ToString("#.####"),
                Environment.NewLine);
        }

大致上就是這樣啦!!

結果大致上是這樣 根據不同的問法,也可以解析出正確的問題回答確切的答案

Code 已經放在GitHub上囉!!!

-----------------------------------------

有時在會走之前你就得跑

你不解決問題 就等問題解決你