สำหรับ Ep.2 เราจะมาเริ่มพัฒนา Chatbot ของเราให้เจ๋งขึ้นไปอีกขั้น ด้วยการเชื่อมต่อ Webhook กับ LINE Bot SDK สำหรับ Python โดยการทำงานคร่าว ๆ ของ webhook นั้นเราจะทำการเชื่อม webhook ของ LINE Messaging API ไปให้กับ Dialogflow แล้วจากนั้น ก็เชื่อม webhook ของ Dialogflow ไปยัง Back-end ที่เราสร้างขึ้นมาเองโดยใช้ Flask web framework ของ Python เป็นตัวรับ request จาก Dialogflow แล้วนำ data ต่าง ๆ ที่ได้มาใช้ไปงานกับ LINE Bot SDK เท่านี้เราก็สามารถเขียน code เชื่อมต่อฐานข้อมูล API และ service อื่น ๆ ได้อย่างอิสระมากขึ้น
บทความแนะนำ
Step 1>>
มาเริ่มต้นกันเลยจาก Ep.1 เราได้ทำการเชื่อมต่อ Dialogflow กับ LINE Messaging API เรียบร้อย โดยเราได้ให้ตัว Dialogflow เป็นตัว Responses หรือตอบกลับเท่านั้น หากเราต้องการทำตัว Responses หรือตอบกลับเอง เราต้องทำการเปิด webhook ให้ Dialogflow ก่อน ขั้นแรกให้เราเตรียมสร้างโปรเจคท์โดยใช้ Flask web framework ของ python เป็นตัวรับ request จาก dialogflow ก่อนศึกษา Flask เพิ่มเติมได้ที่นี่ได้เลยครับ
ให้เราสร้างโปรเจคท์ Python และติดตั้ง library Flask กับ Line Bot SDK ของ Python ให้เรียบร้อยและเตรียม Channel secret / Channel access token ไว้ด้วย (จาก Ep.1) ดู document เพิ่มเติมของ Line Bot SDK ได้ที่
https://github.com/line/line-bot-sdk-python
เริ่มต้นสร้างโปรเจคท์และวางโครงสร้างก่อนโดยการเขียน
code ตามนี้ได้เลย
from flask import Flask, request
from linebot import *
app = Flask(__name__)
line_bot_api = LineBotApi('xxxxxx')
handler = WebhookHandler('xxxxxx')
@app.route("/callback", methods=['POST'])
def callback():
body = request.get_data(as_text=True)
print(body)
return 'OK'
if __name__ == "__main__":
app.run()
ถ้า RUN ได้ตามนี้ก็ถือว่าผ่าน
Step 2>>
จากนั้นการที่เราจะทำให้
localhost ของเราสามารถออนไลน์ได้ เราจำเป็นต้องใช้โปรแกรมช่วยในที่นี้เราจะใช้ NGROK สามารถดาวน์โหลดได้ที่นี่เลย https://ngrok.com/download
ดาวน์โหลดเสร็จแล้วกดเปิดขึ้นมาให้พิมพ์
ngrok
http 5000
จะได้หน้าตาประมาณนี้ก็ถือว่าสำเร็จแล้ว
Step 3>>
ให้เราทำการ copy บรรทัด Forwarding เอาไว้
Step 4>>
จากนั้นให้เราไปที่
Dialogflow
ของเรา https://dialogflow.cloud.google.com
กดไปที่ Fulfillment และกดเปิด webhook ได้เลย
Step 5>>
ให้เรานำ URL ทีได้จาก Forwarding ใน Ngrok มาใส่ในนี้ได้เลย แล้วให้ใส่ /callback ปิดท้าย แล้วกด SAVE ก็เป็นอันเสร็จ
Step 6>>
ต่อไปเราจะมาทดสอบกันให้เราสร้าง intent ขึ้นมา 1 intent โดยในตัวอย่างผมจะตั้งชื่อว่า intent 5 และมีการ Training ไว้ว่า “ทดสอบ”
ให้เลื่อนลงมาในส่วนของ Responses นั้นปกติเราจะใส่คำให้ Dialogflow ตอบกลับไปครั้งนี้เราจะไม่ทำแบบนั้นให้กดไปที่ Fulfillment แล้วกด เปิด Enable webhook call for this intent ตามภาพได้เลย เพื่อเป็นการทำให้ intent นี้เชื่อมต่อกับ webhook ที่เราผูกไว้
เสร็จแล้วกด SAVE จากนั้นไปทดสอบกัน
จะเห็นว่า Chatbot ของเราจะไม่มีการตอบกลับมา ไม่ต้องตกใจเพราะว่าเราได้ทำการผูก webhook ไปยัง Flask หรือโปรเจคท์ของเรานั่นเอง โดยให้ไปกลับไปดูที่โปรเจคท์ของเรา
จะเห็นว่ามีการส่ง request เข้ามาใน route /callback ของเรา ซึ่งหากขึ้นตามนี้ก็ถือว่าโอเครครับ
Step 8>>
ต่อไปเราจะมาทำการแปลงข้อมูลที่ได้มาให้อยู่ในรูปแบบของ JSON และทำการแกะโค้ดเพื่อนำสิ่งที่เราต้องใช้ออกมากันโดยโครงสร้าง code ตามนี้เลย
@app.route("/callback", methods=['POST']) def callback(): body = request.get_data(as_text=True) # print(body) req = request.get_json(silent=True, force=True) intent = req["queryResult"]["intent"]["displayName"] text = req['originalDetectIntentRequest']['payload']['data']['message']['text'] reply_token = req['originalDetectIntentRequest']['payload']['data']['replyToken'] id = req['originalDetectIntentRequest']['payload']['data']['source']['userId'] disname = line_bot_api.get_profile(id).display_name print('id = ' + id) print('name = ' + disname) print('text = ' + text) print('intent = ' + intent) print('reply_token = ' + reply_token) return 'OK'
reply token คือตัวที่จะให้เราสามารถตอบกลับไปยังผู้ใช้งานได้แบบ 1 NO 1 ซึ่งจะเป็นการตอบกลับเมื่อผู้ใช้งานมีการส่งข้อความมายัง Chatbot ของเราเท่านั้นเมื่อเราต้องการตอบกลับไป เราต้องผูก reply token กลับไปด้วยเพื่อให้ Chatbot ของเราสามารถตอบกลับได้อย่างถูกต้องโดย LINE Mressaging API นั้นสามารถส่งข้อความได้ 4 แบบคือ
1. 1 NO 1
คือการส่งข้อความแบบ ถามมา-ตอบกลับ จำเป็นต้องมี reply token ทุกครั้งในการตอบกลับ ซึ่งเป็นการส่งข้อความแบบฟรี
2. Push
คือการส่งข้อความหาผู้ใช้งาน โดยที่ผู้ใช้งานไม่จำเป็นต้องพิมพ์ข้อความมา เราก็สามารถส่งข้อความไปยังผู้ใช้งานได้เลยซึ่ง ทาง LINE ได้จำกัดการส่งอยู่ที่ 1000 ครั้งต่อเดือน หากเกินนี้จะต้องเสียค่าบริการเพิ่มเติม
3. Multicast
จะเหมือนกับ Push ทุกอย่างแต่สามารถส่งได้พร้อมกันหลาย
id
4. Broadcast
จะเป็นการส่งข้อความให้ผู้ใช้งานทุกคนที่เป็นเพื่อนกับ Chatbot ของเราจำกัดการส่งอยู่ที่
1000 ครั้งต่อเดือน หากเกินนี้จะต้องเสียค่าบริการเพิ่มเติมเช่นกัน
Step 9>>
ต่อไปเราจะมาทำให้ Line Bot SDK ของเราสามารถตอบกลับไปยังผู้ใช้งานได้กัน
เริ่มต้นให้เราสร้างฟังก์ชันขึ้นมาก่อนโดยผมจะสร้างฟังก์ชันชื่อว่า reply และการมีการส่งค่าของ
intent/text/reply_token/id/disname
เข้าไปเพื่อใช้งาน และให้ทำการเพิ่ม
from linebot.models import *
เข้ามาด้วย จากนั้นในฟังก์ชัน reply ผมก็ทำการเช็คค่า intent ที่ส่งมาว่าชื่อ 'intent 5' หรือไม่ ถ้าใช่ก็จะใช้ Line Bot SDK ส่งคำตอบพร้อม reply_token กลับไปว่า ‘ทดสอบสำเร็จ’
from flask import Flask, request
from linebot.models import *
from linebot import *
app = Flask(__name__)
line_bot_api = LineBotApi('xxxxxxxx')
handler = WebhookHandler('xxxxxxxx')
@app.route("/callback", methods=['POST'])
def callback():
body = request.get_data(as_text=True)
# print(body)
req = request.get_json(silent=True, force=True)
intent = req["queryResult"]["intent"]["displayName"]
text = req['originalDetectIntentRequest']['payload']['data']['message']['text']
reply_token = req['originalDetectIntentRequest']['payload']['data']['replyToken']
id = req['originalDetectIntentRequest']['payload']['data']['source']['userId']
disname = line_bot_api.get_profile(id).display_name
print('id = ' + id)
print('name = ' + disname)
print('text = ' + text)
print('intent = ' + intent)
print('reply_token = ' + reply_token)
reply(intent,text,reply_token,id,disname)
return 'OK'
def reply(intent,text,reply_token,id,disname):
if intent == 'intent 5':
text_message = TextSendMessage(text='ทดสอบสำเร็จ')
line_bot_api.reply_message(reply_token,text_message)
if __name__ == "__main__":
app.run()
มาทดสอบกันเลย
Job Done !!
ทีนี้เราจะลองมาทำ
workshop
เล็กๆน้อยๆกันเป็น workshop ในการเช็คยอดผู้ติดเชื้อ
Covid19
เริ่มต้นเช่นเคยไปที่ https://dialogflow.cloud.google.com/
สร้าง intent ชื่อ covid 19 และ Training ให้เรียบร้อยพร้อมเปิด Fulfillment กด SAVE ให้เรียบร้อย
กลับมาที่ โปรเจคของเราทำการเขียน code เพื่อดึง API จากกรมควบคุมโรค กระทรวงสาธารณสุขได้เลย
จากนั้นทำการ import json และ import requests เข้ามาด้วยเพื่อทำการดึงข้อมูลจาก API กรมควบคุมโรค
และแปลงเป็น JSON
import json import requests
จากนั้นมาเขียนฟังก์ชันกันเลย
from flask import Flask, request
from linebot.models import *
from linebot import *
import json
import requests
app = Flask(__name__)
line_bot_api = LineBotApi('xxxxxxxx')
handler = WebhookHandler('xxxxxxxx')
@app.route("/callback", methods=['POST'])
def callback():
body = request.get_data(as_text=True)
# print(body)
req = request.get_json(silent=True, force=True)
intent = req["queryResult"]["intent"]["displayName"]
text = req['originalDetectIntentRequest']['payload']['data']['message']['text']
reply_token = req['originalDetectIntentRequest']['payload']['data']['replyToken']
id = req['originalDetectIntentRequest']['payload']['data']['source']['userId']
disname = line_bot_api.get_profile(id).display_name
print('id = ' + id)
print('name = ' + disname)
print('text = ' + text)
print('intent = ' + intent)
print('reply_token = ' + reply_token)
reply(intent,text,reply_token,id,disname)
return 'OK'
def reply(intent,text,reply_token,id,disname):
if intent == 'covid 19':
data = requests.get('https://covid19.th-stat.com/api/open/today')
json_data = json.loads(data.text)
Confirmed = json_data['Confirmed'] # ติดเชื้อสะสม
Recovered = json_data['Recovered'] # หายแล้ว
Hospitalized = json_data['Hospitalized'] # รักษาอยู่ใน รพ.
Deaths = json_data['Deaths'] # เสียชีวิต
NewConfirmed = json_data['NewConfirmed'] # บวกเพิ่ม
text_message = TextSendMessage(
text='ติดเชื้อสะสม = {} คน(+เพิ่ม{})\nหายแล้ว = {} คน\nรักษาอยู่ใน รพ. = {} คน\nเสียชีวิต = {} คน'.format(
Confirmed, NewConfirmed, Recovered, Hospitalized, Deaths))
line_bot_api.reply_message(reply_token, text_message)
if __name__ == "__main__":
app.run()
มาทำการทดสอบกัน
เรียบร้อย!! เท่านี้เราก็ได้ Chatbot ไว้เช็คยอดผู้ติดเชื้อ Covid 19 แบบง่ายๆ แล้ว และนี้คือตัวอย่างข้อดีของการใช้ Line Bot SDK ทำ Webhook เอง ซึ่งทำให้เรา เพิ่มความสามารถให้กับ Chatbot ได้อย่างมาก ซึ่งแน่นอนว่านอกจาก TEXT Message แล้วยังสามารถตอบกลับผู้ใช้งานในรูปแบบอื่นได้อีกด้วยโดย Line Bot SDK ได้ทำ Objects มาให้เราใช้งานไว้เรียบร้อยเรียบแล้วไม่ว่าจะเป็น
Image
image_message = ImageSendMessage(
original_content_url='https://example.com/original.jpg',
preview_image_url='https://example.com/preview.jpg'
)
Video
video_message = VideoSendMessage( original_content_url='https://example.com/original.mp4', preview_image_url='https://example.com/preview.jpg' )
Audio
audio_message = AudioSendMessage( original_content_url='https://example.com/original.m4a', duration=240000 )
Location
location_message = LocationSendMessage( title='my location', address='Tokyo', latitude=35.65910807942215, longitude=139.70372892916203 )
และยังมี Template Send Message อีกหลายตัวที่เราจะได้เรียนรู้กันใน EP ถัดๆไป หรือสามารถดู document เพิ่มเติมของ Line Bot SDK ได้ที่ https://github.com/line/line-bot-sdk-python
สำหรับ EP.2 เราก็ขอจบลงเพียงเท่านี้ก่อนไว้พบกัน EP.3 กันต่อซึ่งจะเป็น Ep สุดท้ายกันแล้วสำหรับซีรีย์ Python Line Chatbot โดยจะทำการ Deploy Chatbot App ของเราไปที่ Heroku กันครับ
ถ้าชื่นชอบบทความนี้ ซัพพอร์ตเราได้โดยการกด Response หรือคอมเมนต์ด้านล่างบทความนี้ได้เลยนะครับ ขอบคุณครับ
กิจกรรมที่กำลังจะมาถึง
ไม่พลาดกิจกรรมเด็ด ๆ ที่น่าสนใจ
Event นี้จะเริ่มขึ้นใน April 25, 2023
รายละเอียดเพิ่มเติม/สมัครเข้าร่วมคอร์สเรียนไพธอนออนไลน์ที่เราได้รวบรวมและได้ย่อยจากประสบการณ์จริงและเพื่อย่นระยะเวลาในการเรียนรู้ ลองผิด ลองถูกด้วยตัวเองมาให้แล้ว เพราะเวลามีค่าเป็นอย่างยิ่ง พร้อมด้วยการซัพพอร์ตอย่างดี