使用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專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

留言

Alan寫道…
David 老師~ 您的 SDK 那時會支援 .NET Core 2 呀?
isDavid寫道…
@Alan,

哈,其實目前沒啥動力。 XD
目前自己的案子找不太到上Windows平台以外的機會,問的人也不多...

或許2018Q1看看.net Core後面發展的狀況吧。
Alan寫道…
謝謝~ 期待中!! ^^
小煉表示…
請問老師
有辦法在LINE聊天室中對BOT進行LUIS的TRAINING
意旨說我想要對BOT進行我說A 他回B的動作
藉由直接在聊天室打個指令命令BOT這樣
又或者可能要利用到什麼方式才能做到我想要的動作
謝謝老師
isDavid寫道…
LUIS做這種事情太迂迴了,建議你用QnA Services,具體怎麼做可能無法三言兩語講完耶。
小煉表示…
謝謝老師回應
關於QnA Services 我再去做相關的了解^^
carlshen寫道…
老師 您好
我有購買您的電子書,請問候選章節什麼時候會推出,或是要報名什麼課程,才有可能取得,謝謝。
Unknown寫道…
老師 您好
該如何在Auzre上,建立一個 LUIS Key 呢。

這個網誌中的熱門文章

使用 Airtable 在小型需求上取代傳統資料庫

精彩(且驚人)的Semantic Kernel入門範例

使用Semantic Kernel 建立自然語言請假系統

在 LINE Bot 開發中使用Semantic Kernel建立自然語言請假系統

專業的價值...