11/08/2018, 20:40

Tạo Skype Chatbot với Microsoft Bot Framework sử dụng REST API

Tại hội nghị Build 2016 diễn ra từ ngày 30/3 đến hết ngày 1/4 ở San Francisco, Microsoft đã đưa ra 7 thông báo lớn, quan trọng và mang tầm chiến lược. 2 trong 7 thông báo đó có liên quan đến Chatbot: Công bố dự án Bot Framework Skype thế hệ mới sẽ có khả năng giao tiếp với Bot Qua đó, ...

Credit: Thinkstock

Tại hội nghị Build 2016 diễn ra từ ngày 30/3 đến hết ngày 1/4 ở San Francisco, Microsoft đã đưa ra 7 thông báo lớn, quan trọng và mang tầm chiến lược. 2 trong 7 thông báo đó có liên quan đến Chatbot:

  • Công bố dự án Bot Framework
  • Skype thế hệ mới sẽ có khả năng giao tiếp với Bot

Qua đó, chúng ta cũng có thể thấy được phần nào tầm quan trọng của chatbot đối với tương lai của ngành công nghệ. Không chỉ Microsoft mà các ông lớn khác trong ngành như Apple (Siri), Amazon (Alexa), Google (Google Now), Facebook (Messenger Bots) đều đang tham gia vào cuộc đua tranh nhau vị trí số 1 vể Chatbot.

Vậy còn chờ gì nữa, chúng ta sẽ bắt tay luôn vào việc tìm hiểu Chatbot cũng như những dịch vụ của Microsoft sẽ giúp chúng ta phát triển Chatbot một cách dễ dàng như thế nào.

1. Chatbot

1.1. Chatbot là gì?

Theo đúng như tên gọi, chatbot là một con bot có thể…chat. Nếu bạn đã từng chơi CS 1.1 với các đối thủ máy mà chúng ta thường gọi là "bot" thì chắc bạn đã hiểu khá rõ khái niệm "bot": một phần mềm có khả năng hoạt động độc lập và trong phần lớn các trường hợp là tương tác với con người. Chatbot thực chất là web service tương tác với user qua các cuộc hội thoại thông qua các channel được thiết lập sẵn (Skype, Slack, Facebook Messenger,…)

1.2. Cơ chế hoạt động của bot

alt text

2. Microsoft Bot Framework

Microsoft Bot Framework là một nền tảng gồm các công cụ và tài nguyên nhằm giúp cho các nhà phát triển có thể tự xây dựng Chatbot của riêng mình. Microsoft Bot Framework bao gồm các phần chính:

  • Bot Builder SDK: Bộ công cụ được chia sẻ trên GitHub dưới dạng mã nguồn mở theo giấy phép MIT này sẽ cung cấp tất cả mọi thứ bạn cần để xây dựng Chatbot bằng Node.js, .NET hay REST API.
  • Bot Framework Developer Portal: Cho phép bạn kết nối Chatbot của mình tới Skype, Slack, Facebook Messenger,... những kênh giao tiếp thông dụng khác. Đơn giản chỉ việc đăng ký bot, chọn kênh giao tiếp và publish bot lên Bot Directory.
  • Bot Emulator: dùng để test và debug bot trong quá trình dev
  • Bot Connector Service: service giúp cho bạn kết nối được với bot của bạn thông qua việc thiết lập các channel
  • Bot Directory: Đây là một thư mục cộng đồng chứa tất cả những bot đã được kiểm duyệt đăng ký thông qua Developer Portal. Người dùng có thể trải nghiệm, khám phá những bot có sẵn hoặc thêm bot mà mình phát triển vào Bot Directory.

3. Tạo Skype Chatbot với Microsoft Bot Framework sử dụng REST API

Microsoft cung cấp SDK cho .NET và NodeJS, với các ngôn ngữ khác thì sử dụng REST API để tương tác với Bot Connector

  • SDK cho bot là open source, bạn có thể xem tại BotBuilder
  • Các ví dụ có thể xem tại BotBuilder-Samples

Việc tạo chatbot bằng SDK cho .NET và NodeJS các bạn có thể xem hướng dẫn cụ thể tại Bot Framework Document. Trong khuôn khổ bài viết này, mình sẽ trình bày cách tạo một Skype chatbot đơn giản sử dụng REST API với ngôn ngữ PHP.

3.1. Đăng ký bot với Bot Framework

Để đăng ký con bot của bạn, trước tiên cần đăng nhập vào Bot Framework Portal, sau đó click Register, tiếp đó nhập Bot profile (Icon, Display Name, Description) và các thông tin cấu hình bot, trong đó cần chú ý:

  • Endpoint: là nơi mà con bot của bạn sẽ nhận một HTTP POST request từ Bot Connector. Một điều cần chú ý là endpoint phải có giao thức https
  • Click Manage Microsoft App ID and password để lấy App ID, tiếp đó click Generate an app password to continue để lấy App password, nhớ lưu lại ID và password này để cấu hình cho bot ở các bước sau

Cuối cùng, click Register để hoàn thành việc đăng ký bot

3.2. Cấu hình bot để kết nối với Skype

  • Đăng nhập vào Bot Framework Portal
  • Click My bots
  • Chọn con bot mà bạn muốn config
  • Click Channels
  • Ở phần Add channel, chọn Skype

3.3. Kết nối bot với Skype

Channels page, ấn vào Skype, sau đó click Add to contact, đăng nhập vào Skype bằng chính tài khoản MS mà bạn vừa tạo con bot, vì khi bot chưa Publish thì chỉ có tài khoản đó mới có thể kết nối được với con bot.

3.4. Xây dựng endpoint với Bot Connector Service

Như vậy là với các bước ở trên, chúng ta đã có được một con bot, tuy nhiên nó chưa hề "thông minh" chút nào. Việc cần làm bây giờ là lập trình cho con bot để nó có thể tự động trả lời khi nhận được tin nhắn. Bot Connector Service cho phép con bot của bạn có thể trao đổi tin nhắn với các kênh giao tiếp (mà ở đây cụ thể là Skype) được cấu hình trong Bot Framework Portal. Nó sử dụng tiêu chuẩn REST và JSON trên giao thức HTTPS và cho phép xác thực bằng JWT Bearer tokens.

3.4.1. Nhận tin nhắn

Khi một user gửi một tin nhắn, một POST request sẽ được Bot Connector gửi đến endpoint mà bạn đã khai báo khi đăng ký bot. Body của request này là một đối tượng Activity. Dưới đây là một ví dụ về body request mà bot của bạn nhận được khi một user gửi tin nhắn tới bot:

{
    "type": "message",
    "id": "bf3cc9a2f5de...",
    "timestamp": "2017-05-20T20:17:52.2891902Z",
    "serviceUrl": "channel's service URL",
    "channelId": "channel's id",
    "from": {
        "id": "1234abcd",
        "name": "user's name"
    },
    "conversation": {
        "id": "abcd1234",
        "name": "conversation's name"
   },
   "recipient": {
        "id": "12345678",
        "name": "bot's name"
    },
    "text": "Haircut on Saturday"
}

3.4.2. Tạo tin nhắn trả lời

Để tạo một tin nhắn trả lời, ta sẽ tạo một đối tượng Activity với các thuộc tính sau:

  • conversation là nội dung của thuộc tính conversation trong phần body request phía trên mà bot nhận được khi được user gửi tin nhắn tới bot
  • from là nội dung của thuộc tính recipient trong phần body request phía trên
  • recipient là nội dung của thuộc tính from trong phần body request phía trên
  • replyToId là nội dung của thuộc tính id trong phần body request phía trên
  • type là message

3.4.3. Lấy access token

  • Request


POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
Body: grant_type=client_credentials&client_id=MICROSOFT-APP-ID&client_secret=MICROSOFT-APP-PASSWORD&scope=https://api.botframework.com/.default

Code mẫu (PHP Slim Framework):

<?php
namespace AppControllers;

use MonologLogger;

use SlimContainer;
use SlimHttpRequest;
use SlimHttpResponse;
use GuzzleHttpClient;
class ChatBotController {
    public function getAccessToken(Request $request)
    {
        $client_request_token = new Client();
        return $access_token = json_decode($client_request_token->request(
            'POST', 
            'https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token', 
            [
            'form_params' => 
                [
                    'grant_type'    => 'client_credentials',
                    'client_id'     => 'MS_APP_ID',
                    'client_secret' => 'MS_APP_PASSWORD',
                    'scope'         => 'https://api.botframework.com/.default',
                ],
            'headers' => 
                [
                    'Content-Type' => 'application/x-www-form-urlencoded',
                ]
            ]
        )->getBody()->getContents())->access_token;
    }
}
  • Response
{
    "token_type":"Bearer",
    "expires_in":3600,
    "ext_expires_in":3600,
    "access_token":"eyJhbGciOiJIUzI1Ni..."
}

3.4.4. Gửi tin nhắn trả lời


POST {serviceUrl}/v3/conversations/{conversationId}/activities/{activityId}
Authorization: Bearer {access_token}
Content-Type: application/json

Body (JSON):

{
    "type": "message",
    "from": {
        "id": "botId",
        "name": "botName"
    },
    "conversation": {
        "id": "conversationId",
        "name": "conversationName"
   },
   "recipient": {
        "id": "userId",
        "name": "userName"
    },
    "text": "My bot's reply",
    "replyToId": "activityId"
}

Code mẫu (PHP Slim Framewok):

<?php
namespace AppControllers;

use MonologLogger;

use SlimContainer;
use SlimHttpRequest;
use SlimHttpResponse;
use GuzzleHttpClient;
use GuzzleHttpPsr7;
use GuzzleHttpExceptionTransferException;

class ChatBotController {

    private $logger;

    private $settings;

    function __construct(Container $container) {
        $this->logger = $container->get('logger');
        $this->settings = $container->get('settings');

    }

    public function chatBot(Request $request, Response $response)
    {
        $params       = $request->getParsedBody();
        $text         = $params['text'];
        $conversation = $params['conversation'];
        $bot          = $params['recipient'];
        $user         = $params['from'];
        $activity_id  = $params['id'];
        $service_url  = $params['serviceUrl'];

        $client_request_token = new Client();
        $access_token = json_decode($client_request_token->request(
            'POST', 
            'https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token', 
            [
            'form_params' => 
                [
                    'grant_type'    => 'client_credentials',
                    'client_id'     => $this->settings['MICROSOFT_APP']['ID'],
                    'client_secret' => $this->settings['MICROSOFT_APP']['PASSWORD'],
                    'scope'         => 'https://api.botframework.com/.default',
                ],
            'headers' => 
                [
                    'Content-Type' => 'application/x-www-form-urlencoded',
                ]
            ]
        )->getBody()->getContents())->access_token;

        if ($text == "Hello" || $text == "hello") {
            $client_reply_message = new Client();
            $url = $service_url.'/v3/conversations/'.$conversation['id'].'/activities/'.$activity_id;
            try {
                $client_reply_message->request(
                    'POST', 
                    $url, 
                    [
                    'json' => 
                        [
                            'type' => 'message',
                            'from' => [
                                'id'   => $bot['id'],
                                'name' => $bot['name'],
                            ],
                            'conversation' => [
                                'id'   => $conversation['id'],
                            ],
                            'recipient' => [
                                'id'   => $user['id'],
                                'name' => $user['name'],
                            ],
                            'text' => "Bye",
                            'replyToId' => $activity_id,
                        ],
                    'headers' => 
                        [
                            'Content-Type' => 'application/json',
                            'Authorization' => 'Bearer '.$access_token
                        ]
                    ]
                );
            } catch (TransferException $e) {
                $this->logger->info(Psr7str($e->getRequest()));
                if ($e->hasResponse()) {
                    $this->logger->info(Psr7str($e->getResponse()));
                }
            }
        }
    }
}

3.5. Deploy bot

Có thể deploy bot lên Azure Cloud từ local git repository, từ GitHub hoặc từ Visual Studio. Ngoài ra cũng có thể deploy bot lên server của riêng mình, ví dụ nếu deploy lên server hoangnh.com thì endpoint URL sẽ là https://hoangnh.com/chatbot.
Như code ví dụ phía trên thì mình đã code cho con bot của mình vô cùng thông minh, mỗi khi nhận được tin nhắn Hello hoặc hello thì nó sẽ tự động trả lời là Bye :sweat_smile:
Sau khi deploy bot và cấu hình lại endpoint cho bot trong Bot Framework Portal thì ta có thể test xem con bot đã hoạt động ngon lành hay chưa. Có thể test thông qua Bot emulator hoặc test trực tiếp trên Skype

3.5.1. Test với Bot emulator

  • Download Emulator
  • Cài đặt ngrok để kết nối tới bot hosted-remotely: download ngrok, mở App Settings trong Emulator, nhập đường dẫn tới file ngrok, chọn bypass ngrok for local addresses và click Save
  • Mở Emulator, nhập endpoint URL, MS_APP_ID và MS_APP_PASSWORD rồi click Connect alt text

3.5.2. Test trực tiếp trên Skype

  • Kết nối bot với Skype (tham khảo 3.2, 3.3)
  • Đăng nhập vào Skype bằng chính tài khoản MS tạo con bot đó
  • Tìm kiếm bot bằng Display Name trong Skype Directory
  • Add bot và nhắn thử hello/Hello alt text

Chúc các bạn thành công!

Nguồn tham khảo

  • https://docs.microsoft.com/en-us/bot-framework/rest-api/bot-framework-rest-connector-quickstart
  • https://dev.skype.com/bots
  • http://docs.guzzlephp.org/en/latest/
0