使用 Node.js 和 Dialogflow 打造一個聰明的 LINE 電商客服機器人

以 Bottender 實作假的電商客服為例

卡米哥
15 min readApr 10, 2020

大家好,我是卡米哥,LINE 官方認證的 API 專家,LINE API Expert。目前在維護知名 Node.js 聊天機器人框架 Bottender

今天要來教大家怎麼使用 Node.js 和 Dialogflow 打造一個聰明的 LINE 電商客服機器人。我會按照以下的順序來說明:

  1. 認識 Dialogflow
  2. 使用 Bottender 實作假的電商客服 LINE Bot
  3. 導入 Dialogflow 來優化用戶體驗

認識 Dialogflow 當中會簡單說明 Dialogflow 是什麼,以及使用 Dialogflow 有什麼好處。在使用 Bottender 實作假的電商客服 LINE Bot 當中會說明如何實作以規則解析對話的 LINE Bot,接著在導入 Dialogflow 來優化用戶體驗當中會說明如何用自然語言理解來優化用戶體驗。

認識 Dialogflow

Dialogflow 是 Google 出的聊天機器人開發工具,可以串接通訊軟體、解析對話內容和生成回覆。Dialogflow 提供多種方式使用,例如以下的兩種方式:

  • 不寫任何一行程式,在 Dialogflow 後台設定與 LINE Bot 串接
  • 自己寫串接程式,只使用 Dialogflow 的自然語言處理服務

沒錯,Dialogflow 在不寫任何程式的情況下依然可以做出聊天機器人。不過這次要跟大家介紹的是自己寫串接程式的使用方法。

既然 Dialogflow 有提供串接平台服務,為什麼還要自己寫?

有些事情 Dialogflow 是很難做到的,比方說跟自己的用戶資料做深度整合,或者做複雜的查詢計算或排程工作等。只有在自己寫程式的情況下,才可以掌握最大的彈性。

使用 Dialogflow 之後可以獲得什麼好處?

自然語言理解服務提供了強大的解析功能,讓你可以解析用戶的各種相同意思但是不同用詞的句型。如果不使用自然語言理解來解析用戶輸入,就是用規則來解析用戶輸入,但是規則是很難維護以及窮舉所有可能性的。

當用戶輸入無法正確被聊天機器人理解時,通常用戶會感到不耐煩而離開,或者意識到這個機器人很廢,只能對特定的句型做出反應。不論是哪一種情況,對用戶體驗都是扣分的,而 Dialogflow 可以用來改善用戶體驗。

不過自然語言理解技術只能用來作為改善用戶體驗的手段,在我的文章:人工智慧在聊天機器人上的應用當中曾經提到過,這裡就不多做說明了。

以下將示範實作一個假的電商客服系統 LINE Bot,並且使用 Dialogflow 來改善用戶體驗。

使用 Bottender 實作假的電商客服 LINE Bot

我們從一個基本的 Bottender LINE Bot 開始,如果你不知道 Bottender 如何使用,請到「從零開始在 Windows 使用 Node.js 打造專屬於你的 LINE Bot 聊天機器人」實作出一個基本的 LINE Bot 後再接續本文閱讀。

電商客服功能設計

作為一個電商,應該要能夠回答商品是否有庫存、以及回覆常見問題。針對這兩個需求,我們設計一個假的電商客服自動回覆以下兩種問題:

  1. 「請問{商品名稱}還有貨嗎?」
  2. 「請問門市營業時間為何?」

其中 {商品名稱} 代表任意的商品名稱,比方說「請問抱枕還有貨嗎?」。

這兩個問題有完全不同的特性。第一個問題的句型當中包含了關鍵字:商品名稱,這是句子當中的重要資訊,因為我們得根據用戶詢問的商品來回答庫存量,如何擷取出用戶輸入的句子中的商品名稱是一個重點。

擷取對話中的關鍵字是自然語言處理的重點功能

而門市營業時間就不會經常改變,所以他可以是固定寫死的答案,但商品庫存就不是這樣了,商品庫存會一直改變(如果你有客人的話QQ),可能你上一秒還有庫存,下一秒就賣光了也說不一定。針對這種情況,就必須串接商品資料庫來獲得即時的庫存資訊。

面對即時資訊的需求,就需要串接程式的協助

假設我們的假電商提供的商品有抱枕貼紙,營業時間是早上 10 點到晚上 10 點,我們可以使用 Bottender 提供的 router 來寫我們的規則,修改 src/index.js 如下:

src/index.js

這樣就完成了整個假電商客服系統(畢竟我們只處理兩種需求)。

Bottender Action

Action 是在 Bottender 當中處理對話的最小單位,你可以在 Action 的第一個參數 context 當中取得所有對話資訊。

關於 Bottender action,更多資訊請參考 https://bottender.js.org/docs/zh-TW/the-basics-actions

在這段程式當中我們寫了 3 個新的 Action:

  • queryInventory
  • queryBusinessHours
  • others

分別用來處理查庫存、查營業時間和其他問題。然後我們在 App (入口 Action) 當中使用 router 建立規則來組合上述 3 個 Action,以下是 App 的程式碼:

接下來會詳細講解 App 內部的程式。

Bottender router

Bottender 的 router 是由一群規則和對應 Action 所組成,根據對話循序判斷是否滿足規則,如果對話符合第一個規則,那麼就採用第一個 Action 來處理對話,如果不符合第一個規則,那麼就看有沒有符合第二個規則,以此類推,router 的功能就是這樣將對話分成幾種情形來處理。

關於 Bottender router,更多資訊請參考 https://bottender.js.org/docs/zh-TW/the-basics-routing

以上述程式來說,我們將對話分成三種情形,並分別指定其對應處理的 Action:

  • 在 queryInventory 回答「請問{商品名稱}還有貨嗎?」
  • 在 queryBusinessHours 回答「請問門市營業時間為何?」
  • 在 others 回答所有其他對話

這樣一來就可以將問題單純化,各個擊破。

正規表示式

在 JavaScript 當中,正規表示式是由斜線開頭,斜線結尾所組成的,使用一些符號可以用來代表各式各樣的字詞,例如 \S 用來代表任意的非空白字元,而+則是代表前面一個字元重複 1 次以上,所以 \S+代表 1 個以上的任意的非空白字元。而 (?<變數名稱>規則) 是 Named Capture Groups,可以用來擷取句子當中的關鍵字。當遇到符合規則的字串時將它擷取出來並給它一個名字。

以下是本次使用的正規表示式,我們希望擷取出符合商品名稱為關鍵字,商品名稱是由任意個非空白字元所組成,擷取出來後存放至變數 name 當中。

目標句型:「請問{商品名稱}還有貨嗎?」

正規表示式:/請問(?<name>\S+)還有貨嗎?/

處理查庫存

我們在 queryInventory 處理庫存查詢,以下是 queryInventory 的程式碼:

我們先從 props 當中取得正規表示式捕捉到的 name 變數,再拿去資料庫做查詢,為了方便講解,在這裡直接使用一個物件 inventoryData 代替資料庫。

如果查詢不到庫存量,代表商品名稱輸入錯了,此時回覆「我們沒有賣{商品名稱}哦。」如果有庫存,就回覆「{商品名稱}只剩下最後 {庫存量} 個了!要買要快!」如果庫存量是 0,則回覆「很抱歉,{商品名稱}已經賣完囉,到貨時再通知您~」

試用

規則型機器人的弱點

經過測試之後你就會發現,只要你輸入的文字跟規則有落差,即使差一個字或一個標點符號,都會導致機器人無法理解對話,這就是文字比對型機器人的弱點。

甚至當用戶輸入的句型完全正確,但關鍵字沒有完全正確時,如上圖情況,由於商品名稱是「抱枕」而不是「卡米狗抱枕」的關係,所以機器人就回覆查無此商品。

當然我們的文字比對型機器人的規則可以寫得更複雜,容錯率可以再提高,但其實要解決這個問題的最佳方法就是導入自然語言理解工具。

文字比對型機器人強迫用戶學會下指令;

自然語言理解型機器人傾聽用戶對話。

導入 Dialogflow 來優化用戶體驗

在完成了基本的文字比對型機器人之後,我們可以使用自然語言理解工具 Dialogflow 來優化用戶體驗,在這個階段我們需要做的事情如下:

  1. 登入 Dialogflow
  2. 建立 Dialogflow Agent
  3. 設定 Intent 和 Entity
  4. 建立 service account 金鑰
  5. 串接至 Bottender

登入 Dialogflow

首先,先開啟網頁 https://dialogflow.cloud.google.com/ ,如果你沒有登入,你會看到下圖:

Dialogflow 登入畫面

點擊 Sign-in with Google 登入 Google 帳號後,會看見:

登入 Dialogflow 後的第一個畫面

建立 Dialogflow Agent

一個 Dialogflow Agent(以下簡稱 Agent)相當於一隻機器人的腦,通常每個專案只需要一個 Agent,所以我們要建立一個 Agent,點擊 Create Agent 後會看到以下的表單:

填寫 create agent 的表單

我填寫的資料如下:

  • Agent Name:bottender-demo
  • Default Language:Chinese (Traditional) — zh-tw
    這是預設語言,設定了就不能修改,我選擇的是繁體中文。
  • Default Time Zone:(GMT+8:00) Asia/Hong_Kong
    這是預設時區,我選擇跟台北時間相同的 GMT+8 時區
  • Google Project:Create a new Google project
    Agent 隸屬於 Google Project 下,我選擇建立一個新的 Google project

填好之後按下 Create 按鈕:

建立 Agent 後的畫面

這樣就完成了 Agent 的建立了。

設定 Intent 和 Entity

Intent 代表用戶意圖(這個用戶想幹嘛),Dialogflow 在讀取用戶對話後,會嘗試識別用戶意圖,識別出來之後我們就可以根據用戶意圖來做不同的處理,通常是執行某個功能,每個意圖都會對應到一個功能,所以其實 Agent 就相當於 Bottender router,而每個 Intent 都是其中的一組規則。我們需要設定以下兩個意圖:

  1. 「請問{商品名稱}還有貨嗎?」
  2. 「請問門市營業時間為何?」

而 Entity 則是關鍵字,設定 Entity 有助於我們擷取出對話中的關鍵字,我們需要擷取的關鍵字是商品名稱。

首先點擊左側的 Entities:

空無一物的 Entities 頁面

點擊 Create Entity:

我們要定義的是商品名稱,所以在 Entity Name 上輸入 product_name,並且在下方輸入抱枕,你可以在這裡輸入商品別名,因為抱枕可能會被用戶稱為卡米狗抱枕,所以我輸入抱枕卡米狗抱枕,而貼紙的部分以此類推,輸入完成後按下 Save。

接下來要新增 Intent,點擊左側的 Intent 分頁上的+:

填寫 create intent 的表單

在 Intent Name 輸入 queryInventory,並且點擊 Add Training phrases,然後輸入請問抱枕有貨嗎?,如下圖:

設定 Intent 的 Training phrases

輸入完成後按下 Enter 鍵:

Training phrases 設定完成

你會發現抱枕兩個字被標上黃色標記,這表示 Dialogflow 自動捕捉到抱枕是商品名稱,點擊已經設定好的 Training phrases 你會看到細節:

Training phrases 當中的 entity 自動設定成名為 product_name 的 Parameter

這樣就設定完成 Intent 了,按下 Save 鍵,並且點擊左側的 Intents:

在 Intents 列表頁,可以看到 3 個 Intent

點擊 Create Intent 建立第二個 Intent,取名為 queryBusinessHours,並且輸入 Training phrases 為請問門市營業時間為何?

你會發現請問門市被 Dialogflow 視為 location 了,我們不需要這個 Parameter,所以直接按下 x 移除 Parameter。

完成後按下 Save,然後回到 Intents 頁面:

再次回到 Intents 頁面

其實我們不需要 Default Fallback Intent 和 Default Welcome Intent,所以就把它刪除,將游標停留在 Default Welcome Intent 就會看見垃圾桶在右側出現:

準備刪除 Default Welcome Intent

點擊垃圾桶後的畫面:

確認是否要刪除 Default Welcome Intent

直接點選 Delete 即可,以此類推,把另一個也刪除。

到這裡就算是設定完成了,你可以在右側的 Try it now 測試效果。

建立 service account 金鑰

service account 是一種可以登入 Google 做事情的帳號,這是 Google 設計給不是真人用的帳號,因為我們真人的帳號密碼更珍貴,而且也會擔心帳密洩漏的問題,所以 Google 設計了 service account 讓你可以專門授權給伺服器用。

接下來我們要取得授權金鑰並且放入我們的專案資料夾下,首先點擊左側的齒輪:

Agent 設定頁

可以看到上圖的下方有個 Google Project 區塊,這裡的 Project ID 請記錄下來備用,然後 Service Account 那個超連結點進去:

服務帳戶,也就是 service account

你會看到 Google Cloud Platform,這裡已經是另外一個世界了,注意不要迷路。在畫面中可以看到已經有一個 service account,點擊右側的動作:

對 service account 做事囉

點擊建立金鑰:

建立並下載金鑰

選擇 JSON 類型金鑰下載,點擊建立:

下載完成

將剛剛獲得的 JSON 檔放入專案資料夾根目錄下,所有的材料就準備齊全了,接下來就是串接到 Bottender 上了。

串接至 Bottender

我們 Bottender 已經幫你把大部分的程式都寫完,你只要寫幾行程式就能串接好,請在小黑框(Terminal)輸入以下指令安裝 Bottender Dialogflow 套件:

關於 Bottender Dialogflow 套件,更多資訊請參考:https://bottender.js.org/docs/zh-TW/advanced-guides-nlu#%E4%BD%BF%E7%94%A8-dialogflow-%E5%BB%BA%E7%BD%AE

然後修改 .env 檔如下:

除了聊天平台的設定之外新增了兩個環境變數:

  • GOOGLE_APPLICATION_CREDENTIALS:JSON金鑰檔路徑
  • GOOGLE_APPLICATION_PROJECT_ID:剛剛叫你備用的 Project ID

設定好之後修改 src/index.js 如下:

就完成囉!以下簡單說明程式碼的變動:

Bottender chain

在 App 當中原本使用 router 改為用 chain,chain 是 bottender 所提供的責任鏈結構,你可以看到在 chain 當中有 dialogflowAction 和 others,如果 dialogflowAction 能處理這個需求,那就輪不到 others,當 dialogflowAction 不能處理的時候就會交給排在後面的 others 來處理。

關於 Bottender chain,更多資訊請參考:https://bottender.js.org/docs/zh-TW/the-basics-chain

dialogflow

在第 36 行用到了 dialogflow 函數,並且傳遞了一個 actions 變數,這個 actions 就是用來建立 Dialogflow Intents 和 Bottender actions 之間的關聯,因為我們兩邊的命名都相同的關係所以這樣寫就可以了。

另外值得注意的是,在 queryInventory 當中需要擷取出商品名稱的寫法也跟著改變了。

Dialogflow 就是強化版的 Bottender router,它也提供 Action 分流功能

試用

機器人直接智商大升級,效果超讚,直接看圖就知道了:

努力沒有白費,獲得的成果是豐碩的

這只是最基本的示範,當然還有很多微調的空間,以後再給大家講解。

覺得寫得不錯的話歡迎分享哦~

--

--