在開發網頁時,我們會用網址來分辨並導向不同的功能,例如用現在最常見的 RESTful 風格來表示網址,因此基本上大部分的伺服器端框架都是使用 HTTP 的 Method、Path 來做 Routing,實現基本的功能切分。
而在機器人的架構上其實也會有類似的概念,我們需要分辨、判斷使用者送出的訊息或造成的事件並導向對應的處理方式。雖然 Conversational Interface 的辨別不會像網址那麼簡單,但不管我們是使用關鍵字、正規表達式抑或是用了機器學習的方式來辨別意圖,這依然都有 Routing 的概念在裡面。
接著,讓我們來看看要怎麼使用「Router」吧!
(注意:這篇文章需要使用最新的版本,可以用 npm update bottender
或是 yarn upgrade bottender
來做升級)
首先我們先來處理文字方面的事情,畢竟文字就是聊天機器人的精髓,是最大宗會出現的事件,所以也是最重要的。可以從 bottender/router
去取用 router
跟 text
兩個 function 來定義 Routing 規則:
// index.js
const { router, text } = require('bottender/router');
async function SayHi(context) {
await context.sendText('Hi');
}
const Router = router([
text('hi', SayHi),
]);
module.exports = function App() {
return Router;
};
當我們用字串當作第一個參數時,代表一定要輸入一模一樣的文字才會命中,並採用 Hi
回傳回去:
text('hi', SayHi)
當有多種句法時,可以傳一個字串的陣列進去:
text(['hi', 'hello'], SayHi)
或是要更細緻的規則時,也可以使用正規表達式:
text(/(hi|hello|hey)/i, SayHi)
用 *
當第一個參數,則可以處理其他前面沒命中的任何文字訊息:
const { router, text } = require('bottender/router');
async function SayHi(context) {
await context.sendText('Hi');
}
async function FallbackResponse(context) {
await context.sendText('你不是在打招呼吧');
}
const Router = router([
text(/(hi|hello|hey)/i, SayHi),
text('*', FallbackResponse),
]);
所以這邊講出不是「hi」、「hello」、「hey」的文字就會回覆「你不是在打招呼吧」。
文字以外的第二大宗,應該就是 Payload,用法跟 text
幾乎一樣,例如我們想要處理 GET_STARTED
的 Payload 可以這樣寫:
const { router, payload } = require('bottender/router');
async function SayHi(context) {
await context.sendText('Hi');
}
const Router = router([
payload('GET_STARTED', SayHi),
]);
當然除了文字跟 Payload 外,你可能還有千千萬萬種理由會想依照 Context 去做分流,那這時候可以用 route
:
const { router, route } = require('bottender/router');
async function SayHi(context) {
await context.sendText('Hi');
}
async function FallbackResponse(context) {
await context.send('你是不是做了些什麼?');
}
const Router = router([
route(
context => context.event.isText
&& context.event.text.startsWith('h'),
SayHi
),
route('*', FallbackResponse),
]);
第一個參數的 Function 或 Async Function 只要回傳 true
就算命中,false
就等同沒中。而 route('*', /* ... */)
則是會命中所有的事件,即便是文字、Payload 以外的也都會中。
Router 的使用非常彈性,可以在任意階層使用,也可以在 Router 裡面的某個 Action 裡面再放一個 Router,在設計 Router 的層級對於整個 App 的了解非常有幫助。未來我們會看到使用機器學習的東西又是如何應用 Router 的概念。