Codelab นี้คุณจะได้เรียนรู้การสร้าง LINE Chatbot ที่ทำงานร่วมกับ Dialogflow เพื่อให้ Dialogflow สามารถรองรับ Webhook Event ประเภทอื่นๆ นอกจาก Text Message ได้ด้วย เช่น รองรับการแชร์โลเคชั่น, การเลือกวันที่จาก DateTime Picker Action หรือ การกดปุ่มที่เป็น Postback Action เป็นต้น เหมาะสำหรับผู้ที่มีพื้นฐานมาบ้างแล้ว ได้ศึกษาเพิ่มเติมไปจนถึงระดับ Advance ใน Codelab เดียว
เนื้อหาของ Codelab นี้ จะเป็นลักษณะของการพัฒนาระบบขึ้นมาระบบหนึ่ง ซึ่งจะใช้เป็น Platform ในการลงทะเบียนข้อมูล โดยมีการใช้ Messaging API เป็น Chatbot ทำงานอยู่บน Cloud Functions for Firebase คอยรับ Webhook request จากนั้นจะส่งไปใช้ความสามารถด้าน NLP ของ Dialogflow ในการประมวลผลและจัดการเรื่อง Session ของบทสนทนา หลังจากได้รับข้อมูลครบถ้วนแล้ว จึงส่งไปเก็บไว้ที่ Cloud Firestore
ข้อมูลที่ต้องการเก็บ จะประกอบไปด้วย ชื่อ (Text Message Event), โลเคชั่นของผู้ใช้ (Location Message Event) และ วันที่ (DateTime Picker Action)
สิ่งที่คุณจะได้เรียนรู้
การสร้าง LINE Chatbot
การสร้างโปรเจคใน Firebase
การติดตั้ง Firebase CLI และ Cloud Functions for Firebase
สร้างฟังก์ชันสำหรับรับ LINE Webhook Request
เริ่มต้นสร้าง Chatbot ด้วย Dialogflow
การส่ง Event จาก LINE Webhook ไปที่ Dialogflow
การทำ Custom Event บน Dialogflow
การใช้งาน Dialogflow Fulfillment
การเขียนและอ่านข้อมูลกับ Cloud Firestore
สิ่งที่คุณต้องเตรียมพร้อมก่อนเริ่ม Codelab
แอปพลิเคชัน LINE(สมาร์ทโฟน) ที่ sign in พร้อมใช้งาน
บัญชี Google เช่น Gmail
Browser(Desktop หรือ Mobile)
IDE หรือ Text Editor เช่น VS Code , Sublime หรือ Atom
Terminal สำหรับการ Run คำสั่งต่างๆ
สร้าง LINE Official Account
จุดเริ่มต้นของการพัฒนา LINE Chatbot คือคุณจะต้องสร้าง LINE OA(LINE Official Account) และเปิดใช้งาน Messaging API
เข้าไปที่ https://manager.line.biz แล้วเลือก Log in with LINE account (สีเขียว) เพื่อเข้าสู่ระบบ
เข้าสู่ระบบด้วยบัญชี LINE ของคุณให้เรียบร้อย
กดสร้าง LINE OA จากปุ่ม Create LINE official account สำหรับผู้ทีสร้าง LINE OA ครั้งแรก หรือกด Create new ทางด้านซ้ายสำหรับผู้ที่เคยสร้าง LINE OA แล้ว
ให้ระบุข้อมูลต่างๆลงไปในฟอร์ม แล้วกด ตกลง
จากนั้นให้ยืนยันรายละเอียดในการสร้าง LINE OA เป็นอันเสร็จสิ้น
เปิดใช้งาน Messaging API
หลังจากที่เรามี LINE OA เรียบร้อยแล้ว ขั้นตอนนี้จะพาทุกคนไปเพิ่มความสามารถให้ LINE OA ของเรากลายเป็น LINE Chatbot ได้
เข้าไปที่ https://manager.line.biz ในกรณีที่เรามีบัญชี LINE OA ที่สร้างไว้แล้ว หน้านี้จะแสดงบัญชี LINE OA ต่างๆที่เรามี ก็ให้เรากดเลือกบัญชี LINE OA ที่เราต้องการ
ให้เราไปทีเมนู Settings > Messaging API แล้วให้กดปุ่ม Enable Messaging API
หากเป็นการ Enable Messaging API ครั้งแรกของบัญชี LINE Business ID จะเจอหน้าให้ลงทะเบียน Developer info ก็ให้กรอก ชื่อ และ อีเมล
จากนั้นให้สร้าง Provider ใหม่ หรือเลือก Provider เดิมกรณีที่เคยสร้างไปแล้ว
Note: Provider คือชื่อผู้ให้บริการ ซึ่งจะไปแสดงตามหน้า consent ต่างๆ ซึ่งถือเป็น superset ของ chatbot ทั้งหลายที่เราจะพัฒนาขึ้นรวมถึง LIFF app โดยเราสามารถระบุชื่อของ Provider เป็น ชื่อตัวเอง, ชื่อบริษัท, ชื่อทีม หรือชื่อกลุ่มก็ได้
Remember: 1 Account สามารถมี Provider สูงสุดได้ 10 Providers และไม่สามารถมีคำว่า LINE ในชื่อ Provider ได้
ระบุ URL ของ Privacy Policy และ Terms of Use (ถ้ามี) หากยังไม่มีก็สามารถกดปุ่ม ok ข้ามไปได้
ยืนยันการเปิดใช้งาน Messaging API ด้วยการกด Ok
เมื่อเจอหน้านี้ ก็แปลว่าคุณได้เปิดใช้งาน Messaging API ให้กับบัญชี LINE OA เรียบร้อยแล้ว
เพิ่ม Chatbot เป็นเพื่อนและตั้งค่า Channel
ขั้นตอนนี้เราจะเข้าไปใช้งาน LINE Developers Console ซึ่งเป็นเว็บไซต์สำหรับการบริหารจัดการ LINE Chatbot(LINE OA ที่เปิดใช้งาน Messaging API แล้ว) ในส่วนของนักพัฒนา
เข้าไปที่ https://developers.line.biz/console/
ให้กดเลือก Provider ที่ต้องการ
เราจะพบกับบัญชี LINE OA ที่เราได้เปิดใช้งาน Messaging API ไว้ ซึ่งในที่นี้เราจะเรียกมันว่า Channel(Channel จะเปรียบเสมือน Chatbot หรือ App) ก็ให้กดเลือก Channel ที่ต้องการ
ให้ไปที่ Tab ชื่อ Messaging API และทำการแสกน QR code ด้วยแอป LINE เพื่อเพิ่ม Chatbot เป็นเพื่อน
ให้ปิด Auto-reply messages เนื่องจากฟีเจอร์นี้จะเป็น default การตอบกลับของ Chatbot ซึ่งไม่จำเป็นต้องใช้ฟีเจอร์นี้
กลับมาที่ Channel ที่เราสร้างใน Tab ชื่อ Messaging API ตรงส่วนของ Channel access token ให้กดปุ่ม Issue
Important: ตัว Channel Access Token คือกุญแจสำคัญในการใช้งาน Messaging API ดังนั้นให้เก็บรักษาไว้ให้ดี
เบื้องหลังของ Chatbot ตัวนี้ เราจะใช้บริการใน Firebase อย่าง Cloud Functions for Firebase และ Cloud Firestore ดังนั้นขั้นตอนนี้เราจะมาสร้างโปรเจค Firebase เพื่อใช้งานกัน
สร้างโปรเจคใน Firebase
ให้ Sign in ใน Firebase console ด้วย Google account
ในหน้า Firebase console ให้คลิก Add project จากนั้นตั้งชื่อโปรเจคตามต้องการ
เมื่อกด Continue แล้วให้ข้ามการตั้งค่า Google Analytics ไป เพราะคุณจะไม่ได้ใช้มันในโปรเจคนี้
โปรเจคของคุณ สร้างเสร็จเรียบร้อย
เปลี่ยนแพลนจาก Spark ไปเป็น Blaze (Pay as you go)
เนื่องจาก Cloud Functions for Firebase มีเงื่อนไขว่า หากต้องการไป request ตัว APIs ที่อยู่ภายนอก Google คุณจำเป็นจะต้องใช้ Blaze plan(เราจะต้องไปเรียก Messaging API ของ LINE)
Note: เมื่อคุณเปลี่ยนมาใช้ Blaze plan นอกจากที่คุณจะสามารถ request ตัว APIs ที่อยู่ภายนอก Google ได้แล้ว คุณยังจะได้โค้วต้าในการเรียกใช้งานฟังก์ชันฟรี 2,000,000 ครั้ง/เดือน
เปิดใช้งาน Cloud Firestore
เนื่องจาก Chatbot ตัวนี้จะเก็บข้อมูลการลงทะเบียนไว้ใน Cloud Firestore ดังนั้นให้เราจะมาเปิดใช้งาน database ตัวนี้กัน
ในหน้าโปรเจคที่เราสร้างจะเลือกเมนูชื่อ Firestore ที่อยู่ทางซ้ายมือ
ในหน้า Cloud Firestore ให้คลิก Create database
ให้เลือก Start in production mode เพื่อที่จะป้องกันไม่ให้ client สามารถเขียนและอ่านข้อมูลได้
เลือก location ของ database แล้วคลิก done
Diaglogflow คืออะไร?
ตัว Dialogflow เป็นเครื่องมือในการพัฒนาให้ Chatbot สามารถเข้าใจบทสนทนาแบบมนุษย์ (Conversation Development Tool) โดยเบื้องหลังจะมี Machine learning คอยประมวลผลให้ โดยเราสามารถนำไปใช้ได้เลย ไม่ต้องพัฒนาตัว NLP เอง แถมรองรับภาษาไทยอีกด้วย
สร้าง Agent
เข้าไปที่ https://dialogflow.cloud.google.com/ และทำการ Sign-in with Google ด้วย Gmail เพื่อเข้าสู่ระบบ
กด CREATE AGENT ซึ่งคำว่า Agent ในที่นี้ก็คือตัว Chatbot นั่นเอง
ให้ระบุรายละเอียดต่างๆลงไปแล้วกด CREATE ได้เลย
ตั้งชื่ออะไรก็ได้ จากตัวอย่างใช้ชื่อว่า "handle-non-text-event-with-df "
Default Language : เลือก Thai - th
Google Project เลือกชื่อโปรเจคตอนที่สร้าง Firebase project
กด Create
มารู้จักกับคำว่า Intents
Intents คืออะไร?
Intent มาจากคำว่า Intention แปลว่า เจตนา หรือความปรารถนาของผู้ใช้ ซึ่งใน Diaglogflow เราจะต้องสร้าง Intents เป็นเรื่องๆไป เช่น เรื่องที่เกี่ยวกับทักทาย, เรื่องที่เกี่ยวกับสอบถามข้อมูล เป็นต้น ซึ่ง Chatbot ควรจะต้องเข้าใจและสามารถแยกแยะเรื่องต่างๆได้ ไม่ใช่ว่าผู้ใช้กำลังทักทายมา แต่ตัว Chatbot ดันไปพยายามตอบคำถาม
Pre-defined Intents
หลังจากที่เราสร้าง Agent จะมี Pre-defined Intents พื้นฐานมาให้ 2 ตัว ได้แก่
Default Fallback Intent
หน้าที่ของ Intent ตัวนี้คือ เมื่อไรที่ผู้ใช้ป้อนข้อความอะไรเข้ามาแล้วตัว Chatbot ไม่เข้าใจ มันจะวิ่งเข้า Intent ตัวนี้ เมื่อกดเข้าไปดูจะพบว่ามี section ที่ชื่อ Responses ซึ่งมีข้อความที่แสดงความไม่เข้าใจกรอกไว้เป็นตัวอย่างหลายบรรทัด เมื่อเราใช้งานจริงก็จะพบว่า หากเราพิมพ์อะไรที่มันไม่เข้าใจ มันจะสุ่มคำพูดใน responses ตอบกลับไปให้
Default Welcome Intent
หน้าที่ของ Intent ตัวนี้คือเกี่ยวกับเรื่องการทักทายกับผู้ใช้ กดเข้าไปดูจะพบว่าจะมีส่วนที่ชื่อ Training Phrases ที่สอนให้ Dialogflow เข้าใจว่าเมื่อผู้ใช้พิมพ์คำที่อยู่ในบริบท หรือ context เหล่านี้เข้ามา ก็ให้สุ่มคำตอบใน Responses กลับไป (ผู้ใช้ไม่ต้องพิมพ์เป๊ะๆก็ได้ มันจะพยามเข้าใจเอง)
สร้าง ‘Register' Intent
ในวันนี้เราจะทำ Chatbot ที่สามารถลงทะเบียนผู้ใช้ โดยจะเก็บข้อมูล ชื่อ ตำแหน่ง และวันที่ เรามาเริ่มสร้าง Intent แรกกันเลย
ให้กดปุ่ม CREATE INTENT และตั้งชื่อว่า Register จากนั้นเลื่อนลงมาที่ Training phrases ทำการกรอกประโยคที่ผู้ใช้น่าจะพิมพ์เข้ามาเพื่อการลงทะเบียน เช่น "ลงทะเบียน " ใส่ข้อความให้หลากหลาย ยิ่งหลากหลายยิ่งดี เพราะ Dialogflow จะเรียนรู้และทำความเข้าใจจากประโยคเหล่านี้
จากนั้นให้เลื่อนลงมาด้านล่าง ในส่วนของ Responses ให้เรากด ADD RESPONSES และทำการกรอกตรง Text Response ซึ่งก็คือประโยคที่จะตอบกลับไป เช่น "กรุณาระบุชื่อ " สามารถใส่ได้หลายประโยคและตัว Dialogflow จะสุ่มเอาประโยคเหล่านี้ไปตอบผู้ใช้ให้
กดปุ่ม Save มุมบนขวา เป็นอันว่าเราสร้าง Intent แรกสำเร็จแล้ว
ย้อนกลับไปที่หน้า Intent List
สร้าง ‘Register - name' Intent เพื่อรับค่า "ชื่อ"
เมื่อเราสร้าง Intent แรก เสร็จแล้ว ขั้นตอนต่อไป คือการสร้าง Intent อีกตัว มารับค่า ชื่อของผู้ใช้ ที่กำลังจะตอบมา โดยมีขั้นตอน ดังนี้
กดปุ่ม Add Follow Up intent ด้านหลัง Intent ที่ชื่อว่า "Register " แล้วเลือก Custom
คลิกเลือก Intent ที่เพิ่งสร้างขึ้นมาใหม่ ตรง Register - custom
ระบุรายละเอียด Intent ตามรูป
ตั้งชื่อ Intent ว่า "Register - name "
ระบุ Training Phase เป็นชื่อคน
กำหนด parameter ชื่อ name ระบุ Entity Type เป็น @sys.any กำหนด value เป็น $name
กำหนด Response เพื่อให้ผู้ใช้ตอบคำถามถัดไป คือ ให้ผู้ใช้ระบุตำแหน่ง
กด Save
{
"line": {
"type" : "text",
"text": "ขอบคุณ คุณ$name กรุณาแชร์โลเคชั่นของคุณ",
"quickReply": {
"items": [
{
"type": "action",
"action": {
"type": "location",
"label": "แชร์โลเคชั่น"
}
}
]
}
}
}
สร้าง ‘Register - location' Intent เพื่อรับค่า "ตำแหน่ง"
ขั้นตอนต่อไป คือการสร้าง Followup Intent อีกตัว มารับ ตำแหน่งของผู้ใช้
กด Add Follow Up intent ท้ายชื่อ intent "Register - name " แล้วเลือก Custom
คลิกเลือก Intent ที่เพิ่งสร้างขึ้นมาใหม่ ตรง Register - name - custom
ระบุรายละเอียด Intent ตามรูป
ตั้งชื่อ Intent ว่า "Register - location "
ระบุ Training Phase เป็นรูปแบบข้อความเพื่อระบุตำแหน่ง เช่น LAT : 13.00 , LNG : 100.00
กำหนด parameter ชื่อ latitude ระบุ Entity Type เป็น @sys.number ระบุ value เป็น $latitude
กำหนด parameter ชื่อ longitude ระบุ Entity Type เป็น @sys.number ระบุ value เป็น $longitude
กำหนด paramater ชื่อ name ระบุ Entity Type เป็น @sys.any เพื่อรับค่า "ชื่อ" มาจาก Intent ก่อนหน้านี้ โดยให้กำหนด value เป็น "#Register-name-followup.name "
Note: การระบุ value ของ parameter ที่ต้องการรับค่าจาก intent ก่อนหน้า ให้พิมพ์เครื่องหมาย # จะปรากฏรายการ context ของ intent ก่อนหน้ามาให้เลย
ให้กดเลือก แล้วตามด้วยเครื่องหมายจุด และตามด้วยชื่อ paramater ใน intent นั้น
กำหนด Custom Payload ใน Response เพื่อให้ผู้ใช้ตอบคำถามถัดไป คือ ให้ผู้ใช้ระบุวันที่
{
"line": {
"type": "text",
"quickReply": {
"items": [
{
"action": {
"label": "เลือกวันที่",
"data": "selected_date",
"mode": "date",
"type": "datetimepicker"
},
"type": "action"
}
]
},
"text": "ตำแหน่งของคุณคือ $latitude,$longitude ขั้นตอนต่อไปกรุณาเลือกวันที่"
}
}
กด Save
สร้าง ‘Register - date' Intent เพื่อรับค่า "วันที่"
ขั้นตอนต่อไป คือการสร้าง Followup Intent อีกตัว มารับ วันที่ผู้ใช้เลือก
กด Add Follow Up intent ท้ายชื่อ intent "Register - location " แล้วเลือก Custom
คลิกเลือก Intent ที่เพิ่งสร้างขึ้นมาใหม่ ตรง Register - location - custom
ระบุรายละเอียด Intent ตามรูป
ตั้งชื่อ Intent ว่า "Register - date "
ระบุ Training Phase เป็นรูปแบบข้อความเพื่อระบุวันที่ เช่น DATE : 2021-07-01
กำหนด parameter ชื่อ selected_date ระบุ Entity Type เป็น @sys.date ระบุ value เป็น $selected_date
กำหนด parameter ชื่อ latitude ระบุ Entity Type เป็น @sys.number เพื่อรับค่า "latitude" มาจาก Intent ก่อนหน้านี้ โดยให้กำหนด value เป็น "#Register-location-followup.latitude "
กำหนด parameter ชื่อ longitude ระบุ Entity Type เป็น @sys.number เพื่อรับค่า "longitude" มาจาก Intent ก่อนหน้านี้ โดยให้กำหนด value เป็น "#Register-location-followup.longitude "
กำหนด paramater ชื่อ name ระบุ Entity Type เป็น @sys.any เพื่อรับค่า "ชื่อ" มาจาก Intent ก่อนหน้านี้ โดยให้กำหนด value เป็น "#Register-location-followup.name "
ตรงส่วนของ Response ให้เว้นไว้ เพราะเดี๋ยวเราจะใช้ fulfilment ในการตอบผู้ใช้เอง
เปิดตัวเลือก Enable webhook call for this intent เพื่อใช้งาน fulfilment
กด Save
เมื่อเราสร้าง Agent จนเสร็จแล้ว ขั้นตอนต่อไป คือการทดสอบการทำงานร่วมกับ LINE Chatbot ที่เราสร้างขึ้นมาในขั้นตอนก่อนหน้านี้
โดยการไปตั้งค่าการเชื่อมต่อระหว่าง LINE กับ Dialogflow ดังนี้
ไปที่เมนู Integrations
เลื่อนลงมาตรงหัวข้อ Text Base => LINE
คลิกเลือกที่ LINE แล้วกำหนดค่าต่างๆดังนี้
Channel ID (คัดลอกจาก LINE Developers Console ) ที่ได้จากขั้นตอนที่ 2
Channel Secret (คัดลอกจาก LINE Developers Console ) ที่ได้จากขั้นตอนที่ 2
Channel Access Token (คัดลอกจาก LINE Developers Console ) ที่ได้จากขั้นตอนที่ 2
คัดลอกค่า Webhook URL จากหน้าจอนี้ ไปใส่ที่ Webhook Setting ที่ LINE Developers Console
กด START
จากนั้นเริ่มทดสอบ โดยการทัก LINE Chatbot ไปได้เลย หากทุกอย่างถูกต้อง จะได้ผลลัพธ์ ตามรูป
ขั้นตอนการเชื่อมต่อเรียบร้อยแล้ว แต่สังเกตว่าตอนที่เราส่ง Location ให้ Bot ระบบไม่ได้ทำงานต่อ เนื่องจาก Dialogflow ไม่รู้จัก Location Message Event เราจึงต้องมี Proxy server ขึ้นมาตัวนึง คั่นกลางระหว่าง LINE กับ Dialogflow เพื่อทำการรับค่า Webhook จาก LINE แล้วทำการแปลง Event ต่างๆให้อยู่ในรูปแบบที่ Dialogflow เข้าใจเสียก่อน
ไปเริ่มเตรียม Proxy Server กันเลย
การติดตั้ง Firebase CLI
Firebase CLI เป็นเครื่องมือที่จำเป็นสำหรับการ deploy ตัวฟังก์ชันที่เราพัฒนาขึ้น อีกทั้งยังสามารถจำลองการทำงานฟังก์ชัน(Emulate) ภายในเครื่องที่เราพัฒนาอยู่(Locally) ได้
Note: การติดตั้ง Firebase CLI เราจะต้องมี npm ในเครื่องซะก่อน โดยหากคุณยังไม่มี แนะนำให้ติดตั้งผ่าน Node.js
เปิด Terminal ขึ้นมาแล้ว run คำสั่ง
npm install -g firebase-tools
Caution: หากคุณพบปัญหาในการติดตั้ง Firebase CLI แบบ globally คุณจำเป็นตัองตั้งค่า npm permission ซะก่อน
ตรวจสอบว่า Firebase CLI ได้ติดตั้งเรียบร้อยแล้วโดย run คำสั่ง (หากสำเร็จจะเห็นเลขเวอร์ชัน)
firebase --version
Initialize โปรเจค
รันคำสั่งนี้ จากนั้นตัว browser จะเปิดขึ้นมาให้เราเข้าสู้ระบบด้วย Google account เดียวกันกับที่สร้างโปรดจคใน Firebase
firebase login
สร้างโฟลเดอร์เปล่า(ตัวอย่างโฟลเดอร์ชื่อ handle-non-text-event-with-df
) แล้วให้ shell เข้าไปในนั้น
mkdir handle-non-text-event-with-df
cd handle-non-text-event-with-df
เมื่อเข้ามาในโฟลเดอร์แล้ว ให้ Initial โปรเจคด้วยคำสั่ง
firebase init
เลือก Firestore และ Functions
เลือก Use an existing project จากนั้นจะเห็นเชื่อโปรเจคที่เราสร้างไว้ ก็กด enter ต่อไป
หัวข้อ Firestore Setup ให้ Enter ผ่านโดยใช้คำตอบ default ไปได้เลย
ถัดไปจะมีตัวเลือกภาษา 2 ตัวคือ JavaScript และ TypeScript โดยตัวอย่างนี้ให้เลือก JavaScript
จากนั้นมันจะถามว่าจะให้ติดตั้ง ESLint ไหม ตรงนี้แนะนำให้ตอบ N ไปก่อน(สำหรับมือใหม่)
สุดท้ายมันจะถามว่าจะให้ติดตั้ง dependencies เลยไหมก็ให้ตอบว่า Y ไป
ขั้นตอนนี้เราจะสร้างฟังก์ชันสำหรับคอยรับ webhook request จาก LINE เพื่อส่งต่อไปยัง Dialogflow อีกที
โดยในโฟลเดอร์ที่เราสร้างมา ให้เรา shell เข้าไปต่อในโฟลเดอร์ชื่อ functions
cd functions
Install @line/bot-sdk
และ express
npm i @line/bot-sdk express --save
กำหนดค่า configuration ในตัวแปร environment 2 ค่า ดังนี้ line.channel_access_token และ line.channel_secret โดยทั้งสองค่า สามารถดูได้จาก LINE Developers Console ส่วน dialogflow.agent_id ดูได้จากตัวเลขชุดสุดท้ายของ webhook url ที่ได้จากเมนู integrations
firebase functions:config:set line.channel_access_token="xxxxx" line.channel_secret="xxxxx" dialogflow.agent_id="xxxxx"
สามารถตรวจสอบความถูกต้องได้ โดยใช้คำสั่ง firebase functions:config:get
firebase functions:config:get
เปิดไฟล์ index.js แล้วเริ่มจากการ import ตัว @line/bot-sdk
และ express
เข้ามา
const functions = require('firebase-functions');
const line = require('@line/bot-sdk');
const express = require('express');
อ่านค่า configuration มาเก็บไว้
const config = {
channelAccessToken: functions.config().line.channel_access_token,
channelSecret: functions.config().line.channel_secret
}
สร้าง functions เพื่อรับค่า webhook โดยใช้ express เป็นตัว handle request
const app = express();
app.post('/webhook', line.middleware(config), (req, res) => {
console.log('req.body', JSON.stringify(req.body, null, 2));
res.status(200).end();
});
exports.api = functions
.region('asia-northeast1')
.https
.onRequest(app);
ทดสอบเบื้องต้นก่อนด้วยคำสั่ง
firebase deploy --only functions
เมื่อ deploy เสร็จแล้ว ให้ copy Function URL ที่ได้ นำไป set ที่ webhook url ใน LINE Developers Console ดังรูป (เติม /webhook ด้วยนะ)
หากกด Verify แล้วขึ้นสถานะว่า Success ก็ถือว่ามาได้ถูกทางแล้วครับ
สร้างไฟล์ dialogflow.js
ไฟล์นี้จะทำหน้าที่แปลง LINE Event ไปเป็น Text Message Event ที่ dialogflow เข้าใจได้
แต่เพื่อไม่ให้ Codelab นี้ยาวเกินไป ผมได้แนบ sourcecode ไว้ให้แล้วที่
https://gist.github.com/kamnan43/fbfd113434573adf864d3aa1ef96ed32
ให้ copy ไปบันทึกเป็นไฟล์ชื่อว่า dialogflow.js วางไว้ที่เดียวกับ index.js
จากนั้นกลับไปแก้ไขไฟล์ index.js ตามลำดับ ดังนี้
เพิ่มฟังก์ชันจาก dialogflow.js
const { postToDialogflow, createLineTextEvent, convertToDialogflow } = require('./dialogflow')
สร้างฟังก์ชั่น handleEvent เพื่อจัดการ Event Type ต่างๆ
async function handleEvent(req, event) {
switch (event.type) {
case 'message':
switch (event.message.type) {
case 'text':
return handleText(req, event);
case 'location':
return handleLocation(req, event);
}
case 'postback':
return handlePostback(req, event);
default:
throw new Error(`Unknown event: ${JSON.stringify(event)}`);
}
}
สร้างฟังก์ชั่น handleText
, handleLocation
และ handlePostback
เพื่อจัดการข้อความ Text Message, Location Message และ Postback Message ตามลำดับ
async function handleText(req) {
return await postToDialogflow(req);
}
function handleLocation(req, event) {
const message = event.message;
const newEvent = createLineTextEvent(req, event, `LAT : ${message.latitude}, LNG : ${message.longitude}`);
convertToDialogflow(req, newEvent);
}
function handlePostback(req, event) {
const data = event.postback.data;
const newEvent = createLineTextEvent(req, event, `DATE: ${data}`);
convertToDialogflow(req, newEvent);
}
เรียกใช้ handleEvent จาก request ของ /webhook
app.post('/webhook', line.middleware(config), (req, res) => {
Promise.all(req.body.events.map(event => {
return handleEvent(req, event);
}))
});
บันทึก และ deploy ใหม่ อีกครั้ง
firebase deploy --only functions
ระหว่างรอ Deploy มาดูคำอธิบายกันว่า code เราทำงานอย่างไร
handleText ทำหน้าที่ ส่งต่อ Text Message ไปที่ dialogflow โดยตรง
handleLocation จะแปลง Location Message ไปเป็น Text Message ก่อน โดยแปลงให้อยู่ในรูปแบบ
`LAT : ${message.latitude}, LNG : ${message.longitude}`
handlePostback จะแปลง Postback Message (จาก DateTime Picker) ไปเป็น Text Message ก่อน โดยแปลงให้อยู่ในรูปแบบ
`DATE: ${data}`
ทั้งนี้เพราะ Dialogflow สามารถเข้าใจข้อความที่เป็น Text Message เท่านั้น
สังเกตุว่า รูปแบบข้อความทั้งสอง จะตรงกับ Training Phase ของ Intent ที่เราออกแบบไปก่อนหน้านี้แล้ว
หลังจาก Deploy แล้ว ลองทดสอบดูอีกครั้ง จะได้แบบนี้
จะสังเกตว่า Dialogflow สามารถอ่านค่า latitude, longitude จาก LINE Location Message ได้แล้ว
แต่เมื่อกดเลือกวันที่ ระบบจะยังไม่ทำงานต่อ นั่นเพราะว่า Intent สุดท้ายที่รับค่าวันที่ ต้องทำงานร่วมกับ fulfillment เพื่อเก็บค่าลงฐานข้อมูลนั่นเอง
ขั้นตอนต่อไป เราไปสร้าง fulfillment เพื่อรับค่าจาก Dialogflow ไปเก็บลง Firestore กัน
แก้ไขไฟล์ index.js ตามลำดับ ดังนี้
เพิ่ม จาก firebase-admin และ WebhookClient
const firebase = require('firebase-admin');
const { WebhookClient } = require('dialogflow-fulfillment');
ทำการ Initial firebase
firebase.initializeApp({});
สร้างฟังก์ชั่น handleFulfillment
เพื่อจัดการข้อมูลที่ส่งมาจาก Dialogflow
async function handleFulfillment(agent) {
const userId = agent.originalRequest.payload.data.source.userId;
const { name, latitude, longitude, selected_date } = agent.parameters;
const doc = {
uid: userId,
name,
latitude,
longitude,
selected_date: Date.parse(selected_date)
};
await firebase.firestore().collection('member').doc(userId).set(doc);
agent.add('บันทึกข้อมูลสำเร็จแล้ว');
}
เรียกใช้ handleFulfillment จาก request ของ /fulfillment
app.use(express.json({ limit: '50mb' }));
app.post('/fulfillment', (request, response) => {
const agent = new WebhookClient({ request, response });
let intentMap = new Map();
intentMap.set('Register - date', handleFulfillment);
agent.handleRequest(intentMap);
});
โปรดสังเกตบรรทัด intentMap.set
และตรวจสอบว่า parameter ตัวแรก ตรงกันกับชื่อ Intent ใน Dialogflow ด้วย
บันทึก และ deploy ใหม่ อีกครั้ง
firebase deploy --only functions
หลังจาก deploy เรียบร้อยแล้ว ให้ไปตั้งค่าการเชื่อมต่อ Fulfillment ที่เมนู Fulfillment ของ Dialogflow ด้วย โดยนำ endpoint ของ Firebase Functions ต่อด้วย /fulfillment ดังรูป
กด Save แล้วทำการทดสอบดูจะได้ผลดังนี้
และจะพบข้อมูลในฐานข้อมูล Firestore ดังรูป
ยินดีด้วยครับ ถึงตรงนี้คุณก็มี LINE Chatbot ที่สามารถทำงานร่วมกับ Dialogflow ด้วย Event รูปแบบต่างๆ นอกเหนือจาก Text Message Event ได้แล้ว ลองนำไปประยุกต์ใช้กับ Event อื่นๆกันดูนะครับ
สิ่งที่คุณได้เรียนรู้ใน Codelab นี้
✅ การสร้าง LINE Chatbot
✅ การสร้างโปรเจคใน Firebase
✅ การติดตั้ง Firebase CLI และ Cloud Functions for Firebase
✅ สร้างฟังก์ชันสำหรับรับ LINE Webhook Request
✅ เริ่มต้นสร้าง Chatbot ด้วย Dialogflow
✅ การส่ง Event จาก LINE Webhook ไปที่ Dialogflow
✅ การทำ Custom Event บน Dialogflow
✅ การใช้งาน Dialogflow Fulfillment
✅ การเขียนและอ่านข้อมูลกับ Cloud Firestore
เรียนรู้เพิ่มเติม
VIDEO
Reference docs
บอกเราหน่อยว่า Codelab ชุดนี้เป็นอย่างไรบ้าง