2018年5月18日 星期五

你只要堅持一天就好…

昨天去大學分享,跟同學們聊了很多,雖然大家都很開心,但時間一如往常的不夠用,有一張投影片,我沒時間講太多…

這是,我從Scrum學到的東西,Scrum告訴我們,把目標切成迭代(iteration),搞清楚這個迭代你要實現什麼(Backlogs),然後,暫且把雜事拋諸腦後,就衝刺好這個迭代就好。

昨天我說了很多,但,其實我想講的只有一句話:『你只要先堅持一天就好…』

如果我要你每天都很賣力的衝刺,那確實很難,但如果我只要你堅持一天,就只有一天,我覺得你一定能做到。

要你馬上改變,奮發圖強一學期,肯定不容易,但,請先從一天開始。

選一天,好好的衝刺,享受一下努力後的果實,然後對得起自己的安心入睡。只要一天就好,如果你能過好一天,你就有機會過好一個禮拜。你能過好一個禮拜,你就有能力過好一個月。

有一天,當你習慣性地能夠好好過每一年,你將會有一輩子豐富的人生。

一切,其實都只是從過好『一天』開始。

先為自己訂個『一天』的目標,毋須遠大,不要張狂,然後在一周裡面選一天,用盡全力實現這個目標,享受屬於你的成果與獎勵,如果你愛上那一天當中成功的感覺,你自然會為自己訂下『下一個一天』。

成功不一定有什麼大方針大架構,就只是去過好每個一天而已。

2018年3月25日 星期日

神聖不可侵犯的規格書

身為開發人員,我猜你也和我一樣曾有這種經驗…

你拿到一份規格書,依照內容進行開發,程式寫著寫著,過了一陣子之後,發現…

不對啊,這規格書本身很矛盾!? 如果依照前面說的XXX這樣做,那後面的OOO可能會做不下去,如果依照OOO的做法,那用戶顯然以後會很難用唷,反覆來回看了幾次,細細思考之後,你肯定了這份規格書確實有問題。

OK,這時候的你,會怎麼做? 一般我們會有底下三個選項:

A: 管它的,依照規格書先做完再說。
B: 找客戶或PM/SA溝通。
C: 用自己的方式直接做出更好的版本。

如果規格書真的是錯的(當然開發人員也可能自己理解錯),那走A顯然是會造成浪費,你非常有可能做出一個看起來十分符合規格但實際上沒法用的軟體,這狀況我們都碰過,而且很常見,所以這邊暫且先不討論。

選C,則在大部份公司是不受歡迎的(你誰啊?竟敢動SA/客戶的規格? 你第一天來的唷?是剛來看不懂規格書嗎? 驗收是照規格書還是照你自己發明的寫法啊? )

一般來說,你身為Developer擅自改規格是要讓SA/SD/PM怎麼拉下臉去承認自己的規格書有寫錯呢? 況且,規格書若經過了客戶的認可,那你這麼做就是一竿子打翻一條船上的所有人,要一票人去承認自己的思慮不周,而這不周還只有你一個人看的出來!?

如果你選的是B,其實是一件挺累人的事情,你可能會碰到很多挫折,過程中,發現沒甚麼人願意理你,並非所有人都跟你一樣在乎規格的正確性。你慢慢發現,似乎大家都各自幻想著一個完美的最終產出的成品,卻期待著這成品能透過一個千瘡百孔的設計圖來實現。

就算真的能夠開始溝通,你可能也會慢慢認知到,原來溝通一條規格的成本和時間比你想像的高很多很多(但又收不到錢),隨著時程越來越緊,你逐漸開始妥協,在規格書中『刻意保留模糊』,以作為日後驗收時各自表述、各自解讀的籌碼。(搞半天,原來先前規格書中的矛盾就是這麼來的…)

當然,如果規格書不出問題,那上面這些故事場景當然也都不成立,不過…我想你也做過專案,你來告訴我,碰到完美的規格書的機率有多少?

0%

不誇張,就是0%,我從來沒碰過沒寫錯的規格書。

既然規格書那麼不堪用,不如乾脆丟了吧。

所以,曾經有敏捷開發的支持者告訴你,如果想要建構出一個真的可用的軟體產品,與其讓開發人員只看規格書,不如多一些和客戶、需求單位之間的直接頻繁的溝通

這就是你會在敏捷開發價值觀中看到底下這四條的原因:

個人與互動 重於 流程與工具
可用的軟體 重於 詳盡的文件
與客戶合作 重於 合約協商 
 回應變化 重於 遵循計劃 
 

但,溝通容易嗎? 難啊。

大部分的開發人員以宅宅的身分進入0與1的數位世界,就是為了避開煩悶瑣碎的人際談判和所謂的溝通協調,把全然沒有經過溝通訓練的Developer直接拉回客戶的會議室真的是一件好事嗎? 我也不這麼認為。

所以,不可信任的規格書在這個需求變化萬千和迅速迭代的時代,有沒有被淘汰? 很抱歉,沒有,它萬壽無疆的很。

常常有對敏捷很好奇的企業或團體,請我們去介紹敏捷開發時,我偶而玩心一起,會問問學員,你覺得規格書值得信任嗎? 底下坐著SA/PM/Developer和老闆,這問題很難回答。

如果它無法被信任,你為何總是照著規格書寫程式呢? 如果它這麼值得信任,那為何照著規格書做的軟體還是常常無法順利結案呢?

Trade Off ,是你在導入敏捷時可能需要常常放在心裡的字眼,事事無絕對,Guidelines不是聖旨。

彼得杜拉克講過一句很殺的話:『管理是一種實踐,其本質不在於“知”而在於“行”;其驗證不在於邏輯,而在於成果…』

敏捷也是。

-----------------------------
本系列文章索引位於 http://studyhost.blogspot.tw/2017/02/the-devops-journey-index.html
相關教育訓練: http://www.studyhost.tw/NewCourses/ALM
若這篇文章對您有所幫助,請點選這裡加入FaceBook專頁按讚並追蹤,也歡迎您幫我們分享出去,謝謝您的支持。

2018年3月4日 星期日

使用C#開發Linebot(21) - ImageCarouselTemplate的支援

Line Messanging API在去年新增了對Template Message的支援,多了一個Image Carousel型態的訊息。

比起原本的Carousel,Image Carousel其實更簡單,使用後的畫面如下:

基本上就是可以左右切換的圖片,圖片正中下方有一個可以點選的標題,這個標題自然就是過去我們在Carousel Template Message中熟悉的Action。唯一的不同處,是Image Carousel每一個Column只有一個Action。

點選Action後,可以依照該Action的類型,呈現不同的結果,像是顯示訊息或產生postback,大致上如上圖所示。

要使用這個功能很簡單,可以直接參考下面的程式碼片段:


發送的方式一就是採用PushMessage這個Method,重點是先建立一個ImageCarouselTemplate物件,並且跟對該物件設定Columns屬性,屬性中的每一個ImageCarouselColumn item就是一張圖片和一個action。

非常簡單,完整的程式碼在github,記得請將LineBotSDK升級至0.6.8:

https://github.com/isdaviddong/Linebot-ImageCarouselTemplate

-----------
相關課程:http://www.studyhost.tw/NewCourses/LineBot
電子書:http://studyhost.blogspot.tw/2017/12/line-bot.html
LineBotSDK:https://www.nuget.org/packages/LineBotSDK
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

2018年3月1日 星期四

特權

前陣子公司附近開了一家新的拉麵店,很小,店內的座位大多是吧檯區或是僅能容納兩個人面對面擠著的小桌。

由於我的用餐時間和許多人大不相同,因此,這種『任何時間都適合一個人走進去』慢慢用餐順便在手機上看完一段影集的小店,非常適合我。大概也因為這樣,所以這半年我破天荒的光臨了不下十次。

平時我都是中午時段過去,今天不同,今天我是晚上下班後,一個人走去店裡。

好似和這家店共生的師傅看到了我,笑著喊了我一聲『大哥,剛下班?』,算是打過了招呼,我報以微笑點頭,店內已經沒多少客人,畢竟嚴格來說,現在已經不能算是晚間用餐時間了。

我一如平常的點了大致相同的拉麵和配菜,一個人自顧自地拿起手機看著新聞把麵吃完,由於不急著回去,又做在吧檯前,我吃完麵之後,不自覺的開始欣賞起吧檯後師傅正在幫剛才慌慌張張闖進來的另一組客人煮麵的流程,一邊想著今天在客戶那發生的事情。

突然間,我看到師傅停下了手上的動作,他注意到我用完餐之後似乎發呆了好一陣子,也沒說甚麼,就拿起一個小碟子,盛上了三大塊店內的招牌燒肉,往我面前的吧檯悄悄一放,笑著說:『這是今天最後的一份叉燒肉了。』

我也不客氣,報以微笑,立刻將三大塊免費的燒肉毫不留情地吞了下去。

我猜,這就是我一個人獨自來這家店那麼多次之後的一點點小小優待或特權吧。不知道為什麼,這燒肉似乎比平常點餐時端上來的,要美味更多?

當我帶著比平時滿足的肚腹走出小店時,我思考著『特權』這個問題。

大概沒有甚麼比航空公司這個行業更要把特權制度化的了,不僅你的票種可以分出差別,平時累積的里程也可以彰顯出你的與眾不同,而不同等級的客人,所享受的待遇當然是天差地遠。

以前我的老闆是海外歸來的台灣人,平時又很常出國,久而久之,他對這種『特權』很是熟稔,也習以為常。平時教導我們,對客戶也要分出『等級』,不同等級的客戶要有不同的待遇。看起來似乎老外特愛搞這套,Golden Level、Silver Level的差別待遇就看你要花多少錢來建立這個relationship。這是現代化、制度化的『特權』。

我們東方人過去比較不興這一套,印象裏家中老一輩的長輩們,口中所講究的『特權』是『親疏遠近,長幼有序』,我們被教導特權的是『敬老、尊賢』,而不是『看錢』。

現在走進便利商店,大概每個人都被一視同仁,很少人會有特權。但以前我們家巷口的那個小雜貨商店,每次我去買東西時,總是能夠多拿一顆糖果或是一把青蔥,偶而忘記帶錢也敢毫不猶豫地走進去。因為雜貨舖的老闆看著我長大,他的兒子就是我的同班同學。

在台北,現在大概已經幾乎沒有這樣的雜貨商店了,但我卻越來越是懷念那種因為熟稔和信任,而能享受到的特權。

隨著台灣接受西方文化洗禮的程度越來越高,人們似乎對因為熟悉、信任、或尊敬而帶來的特權越來越厭惡,但卻開始習慣可以用錢去買到各式各樣的權利(或權力),也開始覺得,我付了錢就是大爺,如果我可以付得起更多的錢,你就應該讓我排在前面。

有時候我們想賺更多的錢,就僅僅是為了能讓別人給我們多一點的尊重,多一點的特殊待遇,多一點的特權,座位大一點,位子好一點,視野遼闊一些,讓自己覺得更尊貴不凡一些。我們覺得,如果有夠多的錢,開更好的車,穿戴更高尚的品牌,大家理當會更尊敬自己一些。

但卻慢慢忘了,真正的尊敬是基於景仰,傳統華人社會的特權是基於禮,是為了把方便保留給需要卻又弱勢的人,而非身上帶的錢比較多的那幾位。

時代快速的變化著,我不知道哪一種社會比較好,當然也不敢說哪一種文化才對。

走回去辦公室開車下班的同時,我嘴裡,還是那三塊燒肉的甜味。我在想,甜的也許不是燒肉,而是我懷念起過去的歲月,我年輕時,那個單純、充滿著溫馨和親切感的社會。

2018年2月15日 星期四

唯有偏執狂得以倖存

Only the Paranoid Survive - Andy Grove

還記得葛洛夫嗎? Intel的創辦人之一。他說的這句話,台灣大多翻譯成『唯有偏執狂得以倖存』,乍看之下很難理解,也不太容易關連到日常工作或生活當中的情境。

為什麼我會突然想到這句話? 講個故事。

適逢農曆過年前,由於過年時候必須要往返南北長途開車,所以過年前理當去車廠保養一下,因為一直都在原廠保養,從來沒發生過什麼太大的問題,也剛好在定期保養的時間內,農曆年前又一堆課程、專案,所以預約保養的時間拖到了小年夜的最後一天。

想說換換機油什麼的,應該很快。

沒想到坐在休息室大廳,咖啡都還沒喝兩口,師傅跑出來說:『先生,我跟您解釋一下車子的狀況…』心想,不妙。師傅說:『OO這邊,和XX這邊,有這些問題,另外OOXX應該要換,但…』『最麻煩的是,車子的水箱幫浦漏水很嚴重,這個問題比較大,如果開長途,恐怕有些危險…』

『好吧,那這些換下來要多少錢?今天會好嗎?』我心裡想,錢能解決的問題都是小問題。
『恩,但是,我們這邊現在沒有料件』師傅說。
『那能不能幫我調調看,是不是其他廠有零件可以換?』我問。
師傅為難的說『恩…就是都問過其他廠了,現在剛好都缺貨,要…年後才能夠幫你調料。』頓了一下又說『但,這個問題蠻嚴重的…』

我立刻問『你是說,車這樣沒法開長途嗎?』

師傅回答:『恩…就是你要常常看水箱是不是空了,我們剛才檢查你的水箱是全空的…如果溫度…如果有亮燈,你要立刻停車。』師傅還補了這一句『這問題蠻麻煩的,如果有貨我一定會建議你立刻換…』

『所以說,我目前也沒法做什麼?』我問。
『我們可以把剛才OO和XX這幾個問題先處理,OOXX先換掉…』師傅說。
『那好吧,我在這邊等。』我回答。

回到休息區,越想越不對勁。上網一查,水箱幫浦不貴,但如果掛掉或漏水,確實風險蠻高的,對安全很有疑慮。

怎麼辦?

過年行程已經定了(訂金也付了),現在改搭高鐵(沒票)或租車都來不及。而且就算下去,沒車也挺不方便的。

剛才一邊喝咖啡一邊打開電腦螢幕上寫到一半的code已經沒法吸引我的專注力,我心想,我要怎麼解決這個問題。

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

先停在這邊,如果你有耐心讀到這裡,我想問問,如果是你,你怎麼解決這個問題?

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

每個人解決的方式不同。

壓抑下煩躁的心情。我想,反正我坐在這邊等也是等,我能做甚麼,來試著改變這個狀況呢?
就在這時候,我不知道為何想到葛洛夫這句話:『Only the Paranoid Survive…』

好吧,既然我不想改行程,我也不想沒自己的車開,那只能試著解決師傅說的『剛好都缺貨』的問題。

怎麼解決?

我上網找了台北所有的保養廠,一家一家打電話去問有沒有這個零件,師傅沒騙我,還真都缺貨,台北打完了,開始打新北,終於打到最後一家,零件部的師傅跟我說,它們沒貨,但系統上看到有一家在新莊的廠有這個料件。

中午12點了。我立即找到正在幫我換輪胎的師傅,跟他說,我問到有料件了,他一臉茫然加不可思議。我說,新莊的XX廠說有料件,你可以幫我調料嗎?

『如果不行,我自己過去拿…』我話還沒講完,師傅就說:『恩…沒關係,我們幫您處理。』他的表情很難言喻,像是有一點點不可置信,加上了一點點的無奈。

我繼續回到休息區,繼續打開NB,等師傅幫我搞定車子。

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

我回頭想…

真的是沒料件嗎? 可能真的沒有,至少,這個廠確實沒有。但師傅有幫我『盡全力』調料件嗎? 我猜也沒有。因為今天是小年夜,大家都想早點回家,萬一真的調到了料件,恐怕是會導致大家都加班這個唯一的結果。(其實我得感謝師傅願意加班)

我又想…如果今天不是我自己的車,是公司的車,我還會這樣積極嗎? 又或者,如果今天,我是請公司的小弟幫我去保養車子,他聽到了師傅這樣說,他會主動地幫我打電話去每一間保養廠問料件嗎? 他會試著想盡辦法幫我解決這個問題嗎?

我想也不會(即便他其實也得困在休息區等上兩三個小時),他依舊會回來告訴我,因為車廠說沒料,所以,我的車過年不能開下去了。而當我接到這樣的消息時,我肯定也已經無能為力,因為今天是小年夜最後一天上班日的傍晚,我當然不能怪公司小弟,也不能怪車廠,我只能接受這個結果。

好在,我是自己來保養車,好在,我是保養自己的車。也好在我想到了葛洛夫的那句話。

我想到了十多年前,我在電子製造業工作的日子。
那家CEO的口頭禪是『使命必達』,他要求同仁必須『當責(accountability)』,十多年前台灣的市場氣氛與工作環境與現在當然大不相同。沉溺在那種工作氣氛中,我們被訓練得碰到問題時,習慣性的總是先想該怎麼解決 ,即便(特別是)這個問題不是自己造成的,而是卡在別人(的配合度)的時候。

當時我幾乎不曾聽過,公司裡有任何一位同仁說,因為誰誰誰(或哪一個上下游廠商)的甚麼問題,所以這件事情沒辦法處理。大部分開會的討論只會聚焦在,那我們現在該怎麼辦?

很神奇的,當我們專注在思考解決方案(而非抱怨或歸責)時,解決方案往往真的就會出現。

十多年後的今天,我開始知道葛洛夫(Andy Grove)所謂的『Only the Paranoid Survive(唯有偏執狂得以倖存)』到底是甚麼意思…



那,葛洛夫最後如何?

毫不令人意外,死了(只要是人,終有一死),Andy Grove卒於2016年,他過世時沒像賈伯斯那樣轟動,但其實他影響程度深遠不輸賈伯斯。

這篇也算是對葛洛夫的致敬和悼念。

2018年2月13日 星期二

使用C#開發Linebot(20) - 不寫一行code完成Linebot的LUIS串接

前陣子,介紹過如何No Code完成Line bot的開發,如果你錯過了,可以看這裡

No Code當然不是一行程式碼都沒有,只是,程式碼骨架我幫你寫好了。你只需要輕鬆地填入相關的Channel Access Token等資訊即可。

而很多同學不滿足,在我們介紹了LUIS(Language Understanding Intelligent Services)之後,當然會想,能不能一行程式碼都不寫,就將Linebot的Web Hook串接到LUIS,完成一個能夠更用戶進行自然語言對談的Chat bot?

可以嗎? 沒問題,有人開口就做給你。

請打開VS2015/VS2017,然後建立一個空的Web專案:

這個畫面似曾相識? 當然,前面我們做過啊。請務必依舊選擇.net framework 4.5.2以上。然後,在下一個畫面中,直接選擇Empty(空)的範本類型,然後請務必(一定一定要)勾選WebAPI:

就這樣,VS2015會幫你建立好一個空專案,,接著,重點來了,請安裝一個nuget套件:

前面做過了,我知道,再一次加深印象,在Nuget套件安裝畫面上,選擇Studyhost.Example.Linebot套件:

按下安裝鈕,安裝完成後,你會看到這個套件已經幫你把程式碼都寫好了。只不過,跟上次不同,這次請把焦點放在TestLUISController:

你會發現,TestLUISController這支WebAPI Controller,就是一隻寫好了的支援LUIS的Line WebHook,你只需要把上面的幾個參數填進去就行,分別是:

  1. channelAccessToken: Linebot的Channel Access Token
  2. AdminUserId: 你建立Linebot的那個帳號(Admin)的UserId
  3. LuisAppId: LUIS App的App ID
  4. LuisAppKey: LUIS App的Key
  5. Luisdomain: LUIS App的domain

上面關於LUIS的幾個參數怎麼來呢?  如果你還對我們介紹過的LUIS有印象,應該會知道LUIS有一個Publish之後的會出現的Enpoint:

其中就有你需要的所有資訊了。

把相關的資訊填入程式碼之後,不用做任何事情,只需要發佈到Azure Web App站台上,並且到Line bot的後台設定一下WebHook,記得位置是 https://你的網站/api/TestLUIS 喔,類似底下這樣:

完成後,你可以試試看,你的Linebot已經可以用你訓練好的LUIS服務做基本的對談了:

由於,我們在連結的LUIS App中,設計了『客戶點餐』和『客訴』兩個intent,因此當用戶跟Line bot點餐的時候,Linebot認得用戶點餐的語句,並且可以分辨出漢堡但(即便『蛋』寫成『但』),且該bot也可以分辨出『你們服務態度很差唷』這句話是『客訴』這個Intent,而非點餐。

輕鬆愉快,透過我們的Nuget套件中的範本,你不用寫任何一行程式碼,只需要設計好LUIS App,並且把該LUIS App的ID, Key, Domain等資訊填入程式碼中,就可以完成支援LUIS的WebHook囉,至於裡面的程式碼究竟寫了什麼呢? 怎麼完成LUIS整合的功能?

請看,完整程式碼如下:

其實非常簡單,我猜不太需要解釋了,如果有甚麼地方需要說明,請留言告訴我囉。

------------------
相關課程:http://www.studyhost.tw/NewCourses/LineBot
電子書:http://studyhost.blogspot.tw/2017/12/line-bot.html
LineBotSDK:https://www.nuget.org/packages/LineBotSDK
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

2018年1月31日 星期三

使用C#開發Linebot(19) - 建立LUIS服務處裡自然語言辨識


接下來這幾篇,我們從頭開始談談NLP(自然語言處理),以及LUIS如何跟Line bot整合應用

前言

關於Linebot的開發,最終我們免不了碰到一個問題,要如何識別用戶所輸入的語句? 雖然我們有千百個不願意,Linebot也提供了Template Message之類的選單機制,可以幫助我們降低free style對談發生的機會,但終究,到最後我們還是得讓chat bot面對用戶以文字方式傳來的訊息。

怎麼說千百個不願意? 做一隻chatbot不就是希望和用戶chatting嗎?

話是這麼說沒錯,但截至今天的科技,要做一個答非所問,胡言亂語的bot來引誘用戶跟你聊天很容易(別懷疑,很多的chat bot其實目的只是要引誘用戶說話),但要做到有意義的自然語言『對談』,對電腦來說,這依舊是一個非常大的挑戰。隨著你對這個主題研究的逐漸深入,你愈會發現,人腦處理語言的神奇。

前話表過,我們終究要來看,在當前的技術下,如何讓chat bot來識別一段文字。我們在這邊推薦的技術是LUIS。

LUIS全名是Language Understanding Intelligent Services,顧名思義,是一個提供語句理解能力的雲端服務。請留意,LUIS並非去分析語句含意(這是Text Analytics的功能),而是去拆解並嘗試依照句型來判斷一個句子,分類歸納出用戶的意圖(intents)並抓取出句子當中關鍵的entities。

而這個功能,對於我們的caht bot,非常的重要。

由於bot的文字輸入介面很自由,用戶往往可以很隨興的打字輸入,你根本無法限制用戶輸入什麼,以什麼句型方式輸入。而且人很有趣,只要沒有限制,就會竭盡所能地嘗試。此外,也非常有可能因為typo之類的輸入錯誤,導致一個句子在輸入上就有錯別字或是不完整,使得chat bot無法只是抓取特定關鍵字來識別用戶的企圖與目的。

凡此種種,都讓NLP自然語言處理的難度比想像來的高。

你只要開放一個文字聊天機器人,就會有人亂打一些有的沒的,然後bot沒理解出他的意思,他就笑這個bot很笨。(這樣很有成就感?)

因此,就對談機器人來說,首要目標之一就是理解用戶輸入的內容,而LUIS是實現這個功能的重點服務。

基本概念

首先,我們需要知道一些概念,LUIS的基本功能(以後有空再說複雜的),就是分析一句話,區分出用戶的意圖(Intent)和相關的entities,我們看底下這張圖:

拿點餐這個Intent來說,如果我們要點一個早餐,用語(句型)大概會是:

  • 我要點一份燒餅油條
  • 麻煩你我需要一份蛋餅
  • 給我來個大亨堡
  • 三明治帶走

上面這四句話,基本上intent都是『客戶點餐』,而其中的entities則是『餐點』,具體的內容(Entity Value)是燒餅油條、蛋餅、大亨堡、三明治。

而LUIS的目的,是幫我們在雲端分析各種不同的句型,找出用戶的意圖,並且抓出entities。而且,由於用戶不可能只用上面這四種說法點餐,有時候可能會換成底下這樣:

今天請幫我來一個飯糰

這個句型就跟上面四種截然不同,但LUIS能夠從雲端大量的語句資料庫中,幫我們進行歸納,判斷(評估)這個句型的相似性,以判斷其意圖,和抓取其中的關鍵字。

一開始可能判斷不對,這時人工可以介入,指導LUIS,讓它理解上面這個句型就是『點餐』,這樣下次LUIS就知道了。而其中的entities也是,餐點種類繁多,第一次LUIS可能不知道有個餐點名稱叫做『飯糰』,所以它抓不出這個entity,但你可以指導它,它就知道下次在某種句型中看到飯糰,就可以將其視為entity。

而一但當我們透過LUIS服務,建立好了這個基礎架構之後,我們就可以用程式碼,把從bot接收到的語句,透過API丟給雲端的LUIS進行判斷,LUIS就會告訴我們,用戶所輸入的這個語句,其意圖intent與entities為何。

以便於我們的chat bot進一步就後續的回覆與處理。

如何使用LUIS服務

在介紹如何建立一個Luis App之前,我們先來看看如何使用一個已經建立好的Luis App。

這一個LUIS服務是我預先建立好的,並且設計了兩個Intent,分別是『客戶點餐』與『客訴』,而None則是系統預設的,為要分辨該App無法識別(或不該識別)的語句:

在設計之初,應該要餵你的每一個Intent一些語料,可以透過5-10句典型的句型,讓LUIS知道客戶點餐或客訴分別是哪些句型。

舉例來說,我們先前的那幾句:

  • 我要點一份燒餅油條
  • 麻煩你我需要一份蛋餅
  • 給我來個大亨堡
  • 三明治帶走

很明顯的就是客戶點餐,因此我們可以把這些句型作為Intent的語料,而客訴呢?則可能是:

  • 叫你老闆出來
  • 你們服務態度很差耶
  • 餐廳環境有點髒亂
  • 你們東西做的很難吃

上面標示粗體的部分,也是該句子中的entity。

我們後面討論如何建立LUIS服務的時候,會再來介紹如何訓練並讓LUIS知道intent和entity,我們先來看,如果一個model訓練好,可以怎麼使用?

我們可以透過Publish功能,將設計好的LUIS App發布到雲端:

發佈上去之後,你可以透過非常簡單的http get指令,將用戶輸入的自然語言,透過q參數傳入LUIS App,並且取得JSON格式的辨識回傳結果:

你會發現,JSON中topScoringIntent是評分最高的Intent,如果有抓取到的entities,也會透過array的方式回傳給我們,其中會包含每一個entity的分數、類型、以及在輸入語句中的開始和結束位置(4,6)。

有了這些透過LUIS幫我們剖析後的資訊,我們就可以大致了解用戶這段話的意思,並且讓chat bot做適當的回應。

除了透過http get之外,C#開發人員還有SDK可用,可以透過nuget來取得SDK套件

好,知道LUIS的功能以及基本的使用方式之後,我們來看如何建立LUIS App服務。

如何建立LUIS App

首先,請用Microsoft Account登入,登入後到底下網址註冊一個LUIS服務:
https://www.luis.ai

出現底下畫面之後,請選擇Create new App來建立新的LUIS服務:

建立LUIS App(其實我覺得叫Service比較好)時,你必須填妥底下的資訊,App名稱可以用中文,別忘了Culture這個選項請選擇Chinese(請留意,目前的Chinese指的其實是簡體中文,但我們用繁體中文測試,結果大致上是一樣的):

完成後選擇Done,接著會出現底下畫面,預設出現的是Intents畫面,我們待會要建立兩組intent,分別是客戶點餐,和客訴。但在此之前,我們先來建立一個Entities(請點選下圖B)的部分:

你會看到建立Entites的畫面,請點選Create new entity來建立一個新的entity:

接著在出現的底下畫面中,輸入entity的名稱:

這邊請注意,很多新同學搞混,在上面的Entity欄位中輸入『蛋餅』、『漢堡』之類的,不,不是這樣的。『蛋餅』、『漢堡』是『餐點』這個Entity的Value(值),而Entity name應該是餐點(或是主餐、飲料、…之類的)。

而Entity Type請先選擇Simple,然後按下Done。完成後,你可以再以同樣的方式建立出另一個Entity(飲料):

完成後,切換到建立Intents的部分,我們新增兩個Intent,分別是『客戶點餐』和『客訴』。動作是這樣的,請先點選左方的App Assets中的Intents,會跳出一個視窗讓我們輸入Intent名稱,按下Done之後,會出現下圖的畫面:

我們可以在該畫面中,輸入五六句可以描述『客戶點餐』這樣的Intent的句子,然後直接按下Enter,例如:

這邊請特別注意,上面你輸入的每一個『客戶點餐』句型,其實或多或少都有包含Entity,如果有,你可以直接透過滑鼠點選的操作,來順便標示出Entity:

如果需要操作影片可以參考:

你可以試著輸入一個包含飲料的點餐句子,例如:

好,搞定『客戶點餐』之後,我們再來建立另一個Intent『客訴』。請用同樣的方法建立一個客訴的Intent,並輸入幾句例句:

如果你願意,也可以一樣針對客訴建立一組或多組entity,然後在上面的語句中標註出entity value。

這些設計就依照你的需求來決定了,大致上都完成之後,你可以按下右上角的Train鈕:

訓練完成之後,你就可以test或publish了。

上面是點選右上角『Test』按鈕後的出現的畫面,你可以在左上角輸入一句話測試,會發現雖然LUIS App判斷出這句話是點餐,但分數也不高(0.48),且沒有抓到『漢堡蛋』。

如果此時你Publish這個App,然後用http get的URL的方式去測試,也會得到一樣的結果(publish需要Key,你必須在Auzre上,為這個LUIS App建立一組Key,具體作法我們以後再提):

這表示,該語句和entity,LUIS目前還看不太懂,但這時候,你可以進到LUIS App選單中的『Review endpoint utterances』:

你會看到這句LUIS尚未熟悉的新句子,這時候,請明確的指定該句子為『客戶點餐』,並且配置『漢堡蛋』為『餐點』:

然後點選左方的Add to aligned intent圖示:

然後重新Train這個App:

完成後,你再去Publish一次該App(注意,重新train完之後,一定要再Publish一次,才會在真正的endpoint生效):

成功publish之後,你可以透過http get方式,重新再測試一次,你會發現,這次LUIS認得這句話(Score 0.81),並且能成功抓出enity(漢堡蛋)了:

就是這樣,透過反覆的教學與訓練,你的LUIS App將會越來越聰明,知道越來越多的句型和Entities,結合Line bot之後,就能夠讓你的bot認識用戶輸入的自然語言囉。

------------------
相關課程:http://www.studyhost.tw/NewCourses/LineBot
電子書:http://studyhost.blogspot.tw/2017/12/line-bot.html
LineBotSDK:https://www.nuget.org/packages/LineBotSDK
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。