Cách kết nối Chatwork với Rasa, và 5 phút mặc niệm latency trên trời.

Tram Ho

TL;DR: Code đây. https://github.com/ngoctnq-1957/rasa-chatwork-echo

Mở bài

Nếu bạn là người đi làm chatbot như mình, chắc hẳn bạn đã dùng Rasa. Với các ưu điểm vượt trội như là hoàn toàn local không sợ mất thông tin, một dialog handler xịn cùng các connector (cho dù bắt entity hơi ngu), Rasa là sự lựa chọn số 1 của các dự án cần tính bảo mật/hay cần mọi thứ trong 1 gói. Đồng thời, nếu bạn làm ở một công ty sử dụng Chatwork như mình, bạn sẽ cần tìm cách sao cho Chatwork liên hệ được với Rasa để nó có thể thay thế bạn trả lời tin nhắn của sếp 😄 Vậy bài này mình sẽ hướng dân bạn làm vậy nhé. Bonus thêm cách làm một con chatbot chuyên đi nhại lại đúng lời bạn nói luôn.

Chú thích: post này sử dụng Rasa<1.8.0 vì nó tương thích với TensorFlow 1.x, do kinh nghiệm là bản TF2.0 vẫn còn nát lắm.

Cách để Rasa nhại lại bạn

Đằng nào mình cũng phải xây dựng một con bot cơ bản để demo cho các bạn mà, nên tiện mình giới thiệu luôn: hành động nhại lại bạn sẽ định nghĩa trong file actions.py:

Và bạn để mặc định là sẽ chạy action đó trong config.yml:

Hết 😄

Cách để Rasa kết nối với Chatwork

Việc đầu tiên là bạn định nghĩa webhook nhận tin nhắn vào cho Rasa.

Cấu trúc của các class extend InputChannel cần có các methods sau: bắt đầu là name, sẽ quyết định webhook URL của bạn.

Ví dụ của mình để return chatwork thì URL sẽ là /webhooks/chatwork/webhook.

Tiếp theo là method để lấy các settings về token trong file credentials.yml. Phần này cũng sẽ được nói sau ở cuối mục này.

Tiếp theo là một method không bắt buộc, nhưng mình đưa vào để gỡ các loại To/Reply khỏi tin nhắn đầu vào cho nó sạch.

Quan trọng nhất trong các đoạn code là blueprint cho sanic server của Rasa. Trong đó, Rasa yêu cầu bạn cần implement 2 route đó là / với tên method health, và webhook với tên method receive.

Để tránh việc một ai đó bắn request láo vào webhook của bạn (mà không từ Chatwork), bạn cần kiểm tra tin nhắn đó có phải từ Chatwork không.

Về cơ bản, header của request được gửi đến webhook sẽ bao gồm hash của nội dung tin nhắn, ký với secret token của bạn. So sánh thấy ok là ok 👌

Và tâm điểm của bài này chính là webhook. Code có một số callback khá là cơ bản thôi.

Và cuối cùng là method không bắt buộc, dùng để tạo ra OutputChannel để bạn có thể gửi trả lại tin nhắn cho người dùng.

Sau đó, bạn định nghĩa tin nhắn gửi trả sẽ như thế nào.

Về cơ bản, class này chỉ bắn một POST request lên server Chatwork theo đúng cú pháp vào đúng phòng thôi. Nếu bạn muốn thêm một phát reply người gửi gốc cho ngầu, hãy sửa thêm như sau:

Nhớ thay code tạo ChatworkOutput object trong ChatworkInput class nhé.

Tiếp đến, bạn cần cài đặt các API cần thiết.

Cả 2 đều có thể vào được từ mục API Setting của Chatwork:

Với API key, nhập password vào mục sau và bạn sẽ lấy được flag:

Còn với webhook secret token, click vào Webhook và tạo mới một mục:

trong đó secret token là mục Token, như đã được mình highlight. Thêm nữa, bạn cần điền vào mục Webhook URL theo như cấu trúc mình đã đặt trong ảnh. Ví dụ, nếu bạn chạy Rasa và không có port proxy pass gì (như với nginx chẳng hạn) thì link đó sẽ là

Cuối cùng, bạn cần cài đặt các settings về API.

Hãy vào file credentials.yml và thêm 3 dòng này vào dưới cùng

với các giá trị token được lấy từ bước trước.

Và vấn đề của Chatwork Webhook

Chưa kể việc Chatwork đổi theme làm mù mắt tôi đi, thì Chatwork webhook nhiều lúc chạy vô cùng dở. Điển hình là việc mình đã thử gửi một tin nhắn và đến 5′ sau thì Rasa mới nhận là đến 😦 Để chứng minh đây không phải là vấn đề của Rasa hay là internet, mình đã thử bắn replay lại đúng payload của Chatwork vào cái webhook, và mọi thứ xảy ra bình thường như chưa hề có cuộc chia ly:

Trong file chatwork_connector.py như trên, trong hàm receive của Sanic blueprint, bạn hãy sửa một chút để lấy được payload của Chatwork (5′ sau khi bạn gửi):

Từ đó, bạn đã có payload để replay attack server rồi 😄 Đừng lo, bạn sẽ không thể bị hack như thế này ngoài đời thật đâu, vì Chatwork yêu cầu HTTPS nên sẽ không thể có Man-in-the-Middle (MITM) attack như mình đang làm bây giờ. Bật Postman lên và gửi vào webhook URL — nhớ bao gồm cả header để tin nhắn của bạn được validate nhé:

Mất có 1.5s thôi nhé chứ không phải 5′ đâu, biết rồi nhé. Mình cũng bắn request này từ máy mình đến server EC2 dùng để host con bot này, nên không phải latency localhost đâu.

Kết luận

Nếu bạn có thể, hãy vận động sếp đổi sang Slack. Nếu bạn không thể, hãy cố gắng cam chịu với nó, và sử dụng code này để cho cuộc đời bạn dễ thở hơn một tí tẹo 😄 Cảm ơn bạn đã đọc bài này, và chúc bạn may mắn.

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo