大約從 2016 年 4 月開始,我們逐漸意識到,將通訊軟體(例如 Facebook Messenger 和 LINE)化身為服務入口,免開網頁、免下載 App,而聊天對象也由真人改為自動應答機器人,也許是個不錯的主意。當時 Facebook 在 F8 開發者大會上宣布將旗下的 Messenger 平台化,也就是允許聊天對象不是真人,而是一個用程式寫的、具備應答能力的服務,統稱為聊天機器人 (Chatbot)。無獨有偶的是,在台灣滲透率超高的 LINE,也在半年後 2017 年 1 月的開發者大會上,推出了更好用、更友善的第二版 Messaging API。
既然是一項服務,我們自然非常期待獲得與真人不同的回覆體驗,比方說更豐富、更聰明。以更豐富為例,除了文字、影音、貼圖之外,聊天機器人的回覆確實還包括了可以左右滑動的按鈕選單,這個在 LINE 裡面叫做旋轉木馬 (Carousel);至於更聰明嘛,聊天機器人也許在數據的查詢速度和精確度方面是沒有問題的,但是在對話理解和上下文溝通方面則有待加強,也就是說碰到答非所問是常有的事(好吧,我們在使用 Siri 或 Google Assistant 的時候好像也曾遇過)。
時至今日,經過兩年半的發展,聊天機器人的應用可謂遍地開花,例如在 LINE Taiwan TechPulse 2018 開發者大會中上台展示的潔客幫 (@jackercleaning) 和跑跑腿 (@85run)。儘管開發者對於主機和程式語言都有各自的喜好,不過在本文中,我們將以 ngrok 在本機打造可以接受外部網路連線的測試環境,並且使用 Mac 電腦內建的 PHP 程式語言,來開發具有人工智慧(假裝的?!)的應聲蟲聊天機器人。現在就讓我們開始吧!
建立 Messaging API 頻道
首先必須知道的第一件事,就是 LINE 聊天機器人也是一組帳號,但是有別於我們平常與朋友閒聊的那種 LINE 帳號,它可以從 LINE@ 帳號轉換而來(但是就目前的規範而言,一旦切換成機器人之後,便無法再由真人介入回覆了),也可以建立全新的 Messaging API 頻道。在本文中,我們採用的是第二種作法,因此第一步是建立頻道,我們可以來到 LINE 開發者網站,選擇「使用 LINE 帳號登入」。
這個帳號是你的個人 LINE 帳號,輸入綁定的電子郵件帳號和密碼來完成登入。如果你忘記了電子郵件帳號,可以開啟 LINE App,在「設定」的「我的帳號」中找到相關資訊。
登入成功之後,可以選擇現有的供應商,或是建立新的供應商:
接著進入「下一頁」(Next page),開始填寫頻道的詳細資訊,包括:
- App 圖示:在 LINE 的聊天清單中出現的那個大頭照。
- App 名稱:在 LINE 的聊天清單中顯示的粗體名稱。請留意,一旦設定好,要 7 天過後才能夠再次修改。
- App 描述
- 計畫:可以選擇「開發者試用版」(Developer Trial),雖然好友人數上限是 50 人,但是可以使用包括 Push 推播在內的所有功能(許多功能原先是要收費的),不過日後無法升級成正式版,也無法註冊專屬 ID。所以如果已有營運規劃,請選擇一般的「免費版」(Free)。
- 主分類
- 次分類
- 電子郵件信箱:用來接收重要信件
所有欄位都是必填,填寫完畢之後,點擊「確認」(Confirm) 進入下一頁,勾選相關的同意條款之後,點擊「建立」(Create) 即完成資料的填寫,隨後會進入 LINE 開發者網站的頻道清單頁面:
因為我們的 LINE@ 帳號是從 LINE 開發者網站這邊以 Messaging API 頻道方式建立的,所以開啟瀏覽器來到 LINE@ 管理畫面,從「帳號一覽」進入剛才建立的帳號,查看「帳號設定 → Messaging API 設定」的時候,會發現狀態已經是「開啟」:
接著回到LINE開發者網站的頻道清單頁面,點擊剛才建立的頻道,完成後續的相關設定。在「頻道設定」(Channel settings) 分頁中,有幾個小節和欄位值得特別探討一下。
首先,不妨掃描一下「你的機器人的 QR Code」(QR code of your bot) 小節的 QR Code:
嘗試將剛才建立的這支機器人加為好友,成功加入之後,立刻就會收到一則自動送出的罐頭歡迎訊息:
仔細一看,會發現反行銷的意味濃厚,好似在跟使用者說,如果覺得我這個機器人帳號太囉唆的話,可以將我封鎖喔。
事實上,歡迎訊息應該要格外重視,因為那是使用者成功加為好友之後,所感受到的第一印象,所以我們可以在「使用 LINE@ 功能」(Using LINE@ features) 小節中,將「歡迎訊息」(Greeting messages) 從「啟用」(Enabled) 改成「停用」(Disabled),之後在設計聊天機器人邏輯的時候,再利用程式碼重寫這段歡迎訊息。或者也可以不必停用,直接從 LINE@ 管理畫面的「訊息→加入好友的歡迎訊息」去編輯內容。
最後在「訊息設定」(Messaging settings) 小節中,將「使用 Webhooks」(Use webhooks) 欄位改為「啟用」,代表將由我們的程式邏輯接手處理並回覆來自使用者的所有訊息,充當接收 HTTP POST 回呼的端點。
執行 EchoBot 應聲蟲範例程式
到目前為止,我們已經大致完成 LINE 聊天機器人帳號的建立與設定,接著要討論的是程式邏輯的部分。首先,開啟終端機,切換到你的工作目錄底下,並且透過下列指令取得 Composer 程式(PHP 的套件相依性管理工具):
curl -sS https://getcomposer.org/installer | php # Install composer.phar
接著透過下列指令從 GitHub 上取得 LINE 官方的 PHP SDK 及範例程式:
./composer.phar require linecorp/line-bot-sdk
完成之後,可以在 vendor/linecorp/line-bot-sdk/examples/EchoBot 資料夾底下,找到應聲蟲範例程式。切換到 EchoBot 目錄,再次取得 Composer 程式:
curl -sS https://getcomposer.org/installer | php # Install composer.phar
接著執行下列指令,把必要的套件(包括 LINE PHP SDK 和 Slim 框架)都下載回來:
./composer.phar install
我們只需要修改 src/LINEBot/EchoBot/Setting.php 當中,與 channelToken
和 channelSecret
有關的兩行程式碼。回到 LINE 開發者網站的「頻道設定」分頁的「訊息設定」小節,點擊「頻道存取權杖」(Channel access token) 這個欄位右側的「核發」(Issue) 按鈕,用這串編碼取代 Setting.php 中的 <your channel token>
。而 <your channel secret>
則是用「基本資訊」(Basic information) 小節的「頻道密鑰」(Channel secret)欄位的數值來取代。
到這裡為止,程式碼和所需套件都已經就緒了,現在執行下列指令,讓 PHP 內建的網頁伺服器在 public 資料夾中(目錄內有 index.php)將應聲蟲程式跑起來(如下圖所示):
php -S 0.0.0.0:8080 -t public
接著從 ngrok 官網取得程式(ngrok 是一種反向代理器服務,主機在美國,可以將本機通訊埠對應到一個公開網址) ,需要註冊或登入,並且使用 authtoken
參數來連結帳號。
執行下列指令,讓 ngrok 以 http/https 通訊協定跑在跟剛才 PHP 程式相同的通訊埠(如下圖所示):
./ngrok http 8080
最後把 ngrok 終端機畫面中的網址複製起來(請留意,每次執行 ngrok 指令,網址就會改變),貼到 LINE 開發者網站的「頻道設定」分頁的「訊息設定」小節的「Webhook 網址」(Webhook URL) 欄位當中,並且點擊「驗證」(Verify) 按鈕,看看會發生什麼事。
結果在終端機視窗的輸出和 LINE 開發者頁面看到的都不是預期的 200 OK,而是 404 Not Found,原來是巧遇開發 LINE 聊天機器人的過程當中,偶然會碰見的地雷之一:路由 (Route) 設定錯誤。檢視 src/LINEBot/EchoBot/Route.php 程式碼可以得知,Webhook 其實是掛在 /callback
,所以回到 LINE 開發者網站的「Webhook 網址」欄位,在「ngrok.io」網址的後面加上「/callback」就可以了。
一旦點擊「驗證」按鈕確認已經接通,你就可以嘗試使用 LINE App 開啟聊天視窗來傳送訊息看看,隨後你將會發現,的確你輸入什麼,它就回覆什麼,而且是秒讀秒回,活脫脫就是一支應聲蟲:
本文接下來的篇幅,我們將會為它添加更多的樂趣,加入偽裝的人工智慧語意辨識功能。
打造人工智慧EchoBot應聲蟲
EchoBot 應聲蟲範例是基於 Slim 框架實作,Slim 是小型的 PHP 框架,非常適合當作 Webhook 回呼端點,用來接收 HTTP POST 資料。檢視線上的 Messaging API 參考文件,你會發現各種訊息型態都被封裝起來,定義在 LINEBot/Event/MessageEvent 資料夾底下,包括常見的文字 (TextMessage)、圖片 (ImageMessage)、貼圖(StickerMessage) 等。
EchoBot 應聲蟲範例的主要邏輯都實作在 Route.php 裡面,這段不到百行的程式碼非常具有參考價值與擴充性,很容易可以看出訊息如何被處理(透過 $event
變數)與回覆(透過 $bot
變數)。檢視程式碼,你會發現在 foreach ($events as $event)
區塊中,有三個主要動作:一、如果 $event
不是 MessageEvent
類型的話,例如可能是加為好友的 FollowEvent
事件,則不回應,直接用 continue
跳掉;二、僅針對文字的部分做出回應,相反地,如果是圖片或貼圖等,也是直接用 continue
跳掉,已讀不回;三、使用 $event->getText()
當作 $bot->replyText
的回應文字,實現你說什麼、我就說什麼的應聲蟲。
foreach ($events as $event) {
if (!($event instanceof MessageEvent)) {
$logger->info('Non message event has come');
continue;
}
if (!($event instanceof TextMessage)) {
$logger->info('Non text message has come');
continue;
}
$replyText = $event->getText();
$logger->info('Reply text: ' . $replyText);
$resp = $bot->replyText($event->getReplyToken(), $replyText);
$logger->info($resp->getHTTPStatus() . ': ' . $resp->getRawBody());
}
每次提到聊天機器人,大家總是興致勃勃地想要跟它閒聊,於是筆者想起了一個網路冷笑話,原來實現人工智慧應答機器人的演算法只需要兩條規則:一、忽略疑問詞「嗎」;二、把問號「?」都換成驚嘆號「!」。在理解了 EchoBot 應聲蟲的程式邏輯之後,會發現只要在 $replyText = $event->getText();
的下面加入三行程式碼(因為問號有全形和半形兩種)就可以瞬間提升十倍功力,變身偽人工智慧的聊天機器人。不信的話,請你依序輸入這幾句話試試看(如下圖所示):「有人在嗎」、「你好嗎」、「今晚天氣好嗎」、「一起吃宵夜?」
$replyText = str_replace('嗎', '', $replyText);
$replyText = str_replace('?', '!', $replyText);
$replyText = str_replace('?', '!', $replyText);
透過程式碼自訂歡迎訊息
在前文中,我們曾經提到歡迎訊息的重要性,因為歡迎訊息是使用者加為好友之後,所獲得的第一印象。現在就讓我們嘗試透過程式碼來改寫歡迎訊息的內容吧!同樣來到 EchoBot 範例的 Route.php,在 foreach ($events as $event)
區塊最開始的地方,加入一個 if
判斷式,如果 $event
的事件類型是 FollowEvent
,代表使用者剛加為好友或是剛解除封鎖,那麼就回覆一段歡迎訊息。
根據 Messaging API 文件,在一次回覆裡面,最多可以有 5 個訊息物件,也就是可以圖文影音混搭。在本例中,我們使用 MultiMessageBuilder
多重訊息建構器,再搭配 TextMessageBuilder
和 StickerMessageBuilder
,依序在歡迎訊息中加入一段文字和一張貼圖,總共兩則訊息。
在文字的部分,若要斷行,可以使用「\n」跳脫字元,若要使用顏文字 (Emoji),可以參考 LINE 官方的顏文字清單,舉例而言,雙眼愛心笑臉的 Unicode 是 0x100078,搭配「\u」跳脫字元就是「\u{100078}」。此外請特別留意,在使用跳脫字元的時候,PHP 字串必須使用雙引號而不能夠是單引號。
而在貼圖的部分,則可以參考 LINE 官方的貼圖清單,內建有兩組 LINE 好友成員的貼圖,舉例而言,雙手合十充滿期待的饅頭人是第 1 組的第 4 號貼圖。
程式碼示範如下:
foreach ($events as $event) {
if ($event instanceof FollowEvent) {
$multipleMessageBuilder = new MultiMessageBuilder();
$multipleMessageBuilder->add(new TextMessageBuilder("感謝加我為好友,祝您闔家~~~\n諸事大吉\u{10005D} 萬事如意\u{100078}"))
->add(new StickerMessageBuilder(1, 4));
$resp = $bot->replyMessage($event->getReplyToken(), $multipleMessageBuilder);
$logger->info($resp->getHTTPStatus() . ': ' . $resp->getRawBody());
continue;
}
......
改寫完程式碼之後,回到聊天視窗,因為先前已經加過好友了,所以請先封鎖再解除封鎖,即可重新體驗歡迎訊息的效果。
結語
在本機使用 ngrok 的好處是開發和測試都很方便,程式碼修改完並存檔之後,功能立即就生效了,而且免部署,也就沒有衍生的主機花費。若要將同樣的應聲蟲程式放置到 Heroku 或 Linode 等熱門的主機上,只需要把整個 EchoBot 資料夾上傳,並且在 LINE 開發者網站中,將「Webhook 網址」改成「https://你的主機/EchoBot/public/callback」 即可。
為了方便說明,筆者將本文採用的 Route.php 程式碼放在 GitHub 供下載參考,此外你也可以掃描下列的 QR Code(可以從 LINE@ 管理畫面的「帳號設定→基本設定→加入好友的按鍵」找到產生 QR Code 的網址):
或是搜尋「@aiverygood」這組專屬 ID(可以從「帳號資訊→註冊資訊」購買專屬 ID),直接體驗與偽人工智慧應聲蟲進行問答互動的樂趣。