前言
今年的 Chatbot 很火紅,不知大家都用什麼來開發 Chatbot 呢?
筆者使用的是 Microsoft Botframework 來開發,它提供了很多語言的 SDK,讓我們可以快速的開發出 Chatbot。
最近開發 Vitals ESP (KM) Chatbot,一開始規劃好畫面及流程後,很快就開發完成了。
接下來就跟大家分享開發的過程 :)
需求
Vitals ESP 是 KM 系統,希望 KM Chatbot 可以方便讓人查詢,在手機上畫面不大,所以需要分頁。如果有人 Mention 到你的話,也可以發通知到 Chatbot 上,讓你可以快速地回覆。
所以需求主要有 2 個,
1.使用者在輸入框輸入文字,立即依關鍵字查詢,並顯示出查詢結果(分頁),使用者可以按上一頁、下一頁去瀏覽,並可按文章串到系統去。
下圖為使用者在輸入框輸入「關鍵字」去查詢,並顯示出查詢結果
下圖為使用者按「下一頁」,系統切到第 2 頁
2.當其他人在文章中有 Mention 到使用者時,使用者可以立馬收到別人在 Cue 你的內容。
下圖為當 KM 系統收到有人在 Cue 使用者時,除了 Mail 通知外,現在會再通知 IM ,讓使用者可以立馬可以知道
下圖為使用者收到被 Cue 的內容後,可以針對該內容進行回覆
實作
1.定義 Actions
從需求來看,可以將目前行為規劃為 2 個 Action ,一個是 Keyword Search ,另一個是 Mention 回覆。
當使用者從輸入框輸入文字的查詢,它的查詢頁為第 1 頁,卡片中的上、下頁,則依 Acton 中的頁碼來決定。
Mention 回覆則需要記錄要要回覆的文章相關資訊及回覆的內容。
所以以下就建立這 2 個 Action 的類別,如下,
1 | public enum KMActionType |
從上面可以發現我們定義了 2 個 Action ,分別為 KMSearchAction 及 KMReplyMentionAction ,它們都繼承自 KMAction 。
而設定 KMActionConverter 可以讓我們依 KMActionType 來分別 Deserialize 到對應的物件 ,如下的程式,
1 | //會依 KMActionType 來分別轉成對應的物件 (KMSearchAction or KMReplyMentionAction ) |
當使用者按 上、下頁時,透過 JsonConvert.DeserializeObject
當使用者在回覆卡片上按下送出時,透過 JsonConvert.DeserializeObject
2.建立查詢結果及 Mention 回覆的 Adaptive Cards
使用 Adaptive Cards 時,需要從 Nuget 中安裝 AdaptiveCards 套件,如下,
AdaptiveSubmitAction 物件有一個 DataJson 的屬性,是可以讓我們放入物件的 JSON 字串 。
所以在建立畫面這些 Button 時,就可以建立 Action 物件後,將它們的 JSON 放到 DataJson 屬性中 。
當使用者按下 Button 時,它的值就會在 MessageActivity 的 Value 屬性之中 。
所以在 RootDialog 中,我們就可以用這個屬性值來區分是按下 Button 進來的,還是使用者從輸入框輸入字串進來的,如下,
1 | public class RootDialog : IDialog<object> |
筆者建立執行 Action 的 IActionStrategy interface,然後將 Keywrod Search 與 回覆 Mention 分別放到不同的類別之中,並實作 IActionStrategy 。
然後再透過 KMActionType 來決定要生成那個類別,最後執行 DoAction 就可以了 。
1 | /// <summary> |
在 SearchKeywordActionStrategy Class 中,依 KMSearchAction 的內容,來建立查詢結果的 Adaptive Card
1 | /// <summary> |
上面建立 Adaptive Cards ,我是透過 Card Elements 一個一個來加入 。
您也可以到 Adaptive Cards Designer 設計好之後,將 json 存檔後,透過 AdaptiveCard.FromJson將它們匯進來哦!
建立 Mention 回覆的 Adaptive Cards ,是在另一個 Controller 在收到通知後,就建立它。
主要部份是建立 KMReplyMentionAction Class 一樣給 AdaptiveSubmitAction 的 DataJson 屬性,而 AdaptiveTextInput 的 Id 值要跟 KMReplyMentionAction Class 中的屬性值相同,只是 KMReplyMentionAction 是 PascalCase ,AdaptiveTextInput 的 Id 值是 CamelCase ,如下,
1 | public static async Task<Attachment> BuildMentionCard() |
處理使用者回覆的 ReplyMentionActionStrategy Class ,只要呼叫 KM API 檢查狀態 OK ,就可以了,如下,
1 | public class ReplyMentionActionStrategy : IActionStrategy |
而在上面有些檢查筆者是 throw BotException,然後透過 Bot Framework Custom Error Messages and Exception Handling 來將訊息顯示給使用者,如下,
1 | public class BotException : Exception |
下圖是系統收到 Exception 後,透過客製的錯誤處理將訊息傳送給使用者,
- 註:在 Application_Start 那記得要跟 Autofac 註冊 PostUnhandledExceptionToUserOverrideTask 哦!
結論
從上面的分享中,可以透過自定的 JsonConverter (KMActionConverter),在 JsonConvert.DeserializeObject 時,取回正確的物件,再交給對應的 Strategy 類別來處理。
所以只要規劃好流程腳本,再透過 Microsoft Bot Framework,就可以讓我們快速開發出 Chatbot, 而 Adaptive Cards 則讓我們可以在 Chatbot 中建構出完整的 UI ,透過 Action.Submit 將 UI 轉化成需要的 Model 大大簡化開發的複雜度。
未來如果再加一個 Action 的話,只要擴充 KMActionType 及對應的 Action 及 ActionStrategy 就可以了哦。
註 1: 目前 Adaptive Cards 的 Action 只能放在最下面,未來版本應該可以放在 Card 的中間,可以到 Adaptive Cards Designer 設計看看哦~
註 2: 上述範例中,因為有使用 Makedown 的 link ,所以如果用 webchat 測試的話,請加入以下的 script 哦!
1 | <script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/8.4.2/markdown-it.js" /> |
- 註 3:有時想要讓使用者知道 Chatbot 有收到它的輸入,可以在 MessagesController 的 Post Method 中一收到訊息時,就先回個 Typing 的訊息給使用者,如下,
1 | //先發送 typing 的 message |
參考資料
Schema Explorer
Adaptive Cards Designer
Deserializing different types based on properties, with Newtonsoft.Json
Bot Framework Custom Error Messages and Exception Handling
BotFramework-WebChat Customization
Bot Framework Typing Activity – Let users know your bot is responding (and know when they are too)
Customize Web Chat for your websites - 亂馬客