เขียน Python API เรียกใช้ผ่าน LINE สำหรับแนะนำภาพยนต์ (Recommendation System) + ใช้ Docker ขึ้น Heroku
บทความนี้จะมาแนะนำการพัฒนา API ให้บริการแบบจำลอง Machine Learning สำหรับการแนะนำภาพยนต์ และใช้ line bot sdk เพื่อให้บริการผ่าน LINE ได้ด้วยนะครับ โดย source code ทั้งหมดสามารถดาวน์โหลดได้จาก Github ของผมได้เลยครับ
โดยผลลัพธ์ที่ต้องการคือ LINE Chat Bot ที่สามารถแนะนำภาพยนต์ได้ โดยแนะนำจากชื่อภาพยนต์ที่เราเลือกจากรายการและการพิมพ์เข้าไปเองตามด้านล่างครับ 😁
เริ่มใช้งาน Line Developer
สมัครได้ที่ https://developers.line.biz/console ด้วย LINE Account
สร้าง Provider
สร้าง Channel
สำหรับเนื้อหาโดยละเอียดเกี่ยวกับการใช้งาน Line Developer สามารถดูได้จากบทความของคุณ Thannob ได้นะครับ
ติดตั้งสภาพแวดล้อมของ API
ติดตั้งซอฟต์แวร์ดังต่อไปนี้ครับ
- ติดตั้ง Python + PIP แนะนำเป็น version 3.8.7 ดาวน์โหลดได้จาก https://www.python.org/downloads/release/python-387/
- git ใช้ clone Source Code สามารถดาวน์โหลดได้จาก https://git-scm.com/downloads
- ngrok เพื่อทดสอบ API จากเครื่องของตนเองแบบเป็นสาธารณะ https://ngrok.com/download
ติดตั้ง virtualenv ผ่าน pip
$ pip install virtualenv
ใช้ git clone source code ที่ผมเตรียมไว้แล้วมาได้เลยนะครับ
$ git clone https://github.com/KarnYong/line-movie-recommendation-api.git
cd เข้าไปในโฟล์เดอร์ของ code ก่อนนะครับ ต่อไปทุกขั้นตอนจะต้องทำที่โฟลเดอร์นี้นะครับ
$ cd line-movie-recommendation-api
สร้าง virtual environment ชื่อ venv
$ virtualenv venv
เปิดใช้ virtual environment
- Windows:
$ venv\Scripts\activate.bat
- Mac และ Linux:
$ source venv/bin/activate
ติดตั้ง packages ของ Python ที่จำเป็น
$ pip install -r requirements.txt
กำหนด Channel secret และ Channel access token จาก LINE
สร้างไฟล์ .env (ไม่ต้องมีนามสกุล) ที่โฟลเดอร์นี้เลยนะครับ และใส่เข้าไป 2 บรรทัดตามด้านล่าง โดยให้คัดลอก Channel secret และ Channel access token (จากใน LINE Channel ที่เราสร้างไว้ตอนต้น) มาแทนที่ตรงที่ทำตัวหนานะครับ
LINE_CHANNEL_SECRET='<<Line Channel Secret>>'
LINE_CHANNEL_ACCESS_TOKEN='<<Line Channel Access Token>>'
บันทึก Cosine Similarity ข้อมูลภาพยนต์
ที่ไฟล์ movie-model.py ใช้สำหรับอ่านข้อมูลจากไฟล์ movies_metadata.csv โดยตอนนี้อ่านเฉพาะข้อมูล 5,000 แถวแรกนะครับ (บรรทัดที่ 8) เพื่อให้ไม่ใช้ memory เยอะจนเกินไป จากนั้นจึงคำนวณหาความเหมือนของภาพยนต์จากคำอธิบาย (overview) ของภาพยนต์นะครับ โดยตัดคำด้วย TfidVectorizer และคำนวณความเหมือนแบบ Cosine Similarity ด้วย linear_kernel (ขอไม่ลง detail เยอะนะครับ เดี๋ยวจะยาวเกิน 555)
จากนั้นนำค่าของรายชื่อของภาพยนต์ (movies) และผลการคำนวณ Cosine Similarity (cosine_overview) บันทึกลงไฟล์ movies.p ด้วย pickle ในบรรทัดสุดท้าย
เรียกคำสั่งด้านล่าง เพื่อสร้างไฟล์ movies.p
$ python movie-model.py
ทดสอบการแนะนำภาพยนต์จากไฟล์ข้อมูล ที่ไฟล์ movie-recommend.py ใช้ทดสอบการแนะนำภาพยนต์ โดยบรรทัดที่ 4 จะเป็นการใช้ pickle โหลดค่าของรายชื่อของภาพยนต์ (movies) และผลการคำนวณ Cosine Similarity (cosine_overview) จากไฟล์ movies.p สำหรับการใช้แนะนำภาพยนต์ในบรรทัดที่ 18 ที่สามารถเปลี่ยนชื่อภาพยนต์ได้ (อาจจะลองเปลี่ยนเป็น Toy Story หรือ The Godfather เพื่อทดสอบได้ครับ โดยชื่อที่ใช้ต้องมีอยู่ในข้อมูลรายชื่อภาพยนต์นะครับ)
เรียกคำสั่งด้านล่าง เพื่อได้รับการแนะนำภาพยนต์
$ python movie-recommend.pyYour Recommendations for the Movie Die Hard are:
Die Hard: With a Vengeance
Die Hard 2
Hot Shots! Part Deux
Death Before Dishonor
You Can Count on Me
--------------
เริ่มการทำงานของ API
สั่ง start API ด้วยคำสั่ง
$ python line-movie-api.py
ทดสอบจากการ deploy จากเครื่องของตนเองก่อนด้วย ngrok เปิด Command Prompt หรือ Terminal และให้เปลี่ยนตำแหน่งไปที่ Nrgok.exe จากนั้นสั่งคำสั่งต่อไปนี้
$ ngrok http 8000
นำ Forwarding url ของ ngrok ด้านบนไปใส่ไว้ที่ webhook ของ Line Channel ตามด้านล่าง และต่อท้ายด้วย /callback
ทดสอบ Webhook URL ด้วยการกดปุ่ม Verify ถ้าขึ้นว่าเป็น Success แปลว่าสำเร็จ
ทดสอบผ่าน LINE จะได้ผลลัพธ์ของการแนะนำภาพยนต์ตามด้านล่าง โดยให้พิมพ์ข้อความส่งไปว่า movies แล้วจะมี Carousel โผล่ขึ้นมาเพื่อให้เลือกภาพยนต์ครับ เมื่อเลือกเสร็จก็จะมีรายการภาพยนต์ที่แนะนำแสดงขึ้นมาครับ หรือจะพิมพ์ชื่อภาพยนต์ไปก็ได้ ถ้ามีอยู่ในข้อมูลจะส่งรายชื่อภาพยนต์ที่แนะนำมาครับ
อธิบาย Source Code ของ API
API ไฟล์ line-movie-api.py เป็นการนำตัวอย่าง flask-kitchensink จาก line-bot-sdk-python (link ด้านล่าง) มาปรับแก้และเพิ่มเติมนะครับ
เพิ่มเติมในส่วนของการใช้ pickle ค่ารายชื่อของภาพยนต์ (movies) และผลการคำนวณ Cosine Similarity (cosine_overview) จากไฟล์ movies.p
handle_text_message คือส่วนของการรองรับข้อความที่ส่งมายัง Bot ของ LINE นะครับ
ถ้าส่งมาเป็นข้อความว่า movies จะตอบกลับเป็น Carousel ที่มีรูปของภาพยนต์ที่สามารถเลือกได้อยู่นะครับ โดยจะฝัง PostbackAction ไว้เพื่อให้ handle_postback เป็นตัวจัดการ event ให้นำชื่อของภาพยนต์มาใช้เพื่อทำการแนะนำภาพยนต์ที่มีเนื้อหาใกล้เคียงกันครับ หรือถ้าส่งข้อความอื่นมา จะนำข้อความนั้นมาเป็นชื่อภาพยนต์เพื่อแนะนำครับ
handle_postback เป็นตัวจัดการ event จากการนำชื่อของภาพยนต์ที่ส่งมาจาก code ด้านบน มาใช้เพื่อทำการแนะนำภาพยนต์ที่มีเนื้อหาใกล้เคียงกันด้วยฟังค์ชัน get_recommendations ครับ
เตรียมนำ API ขึ้น Heroku Cloud
ติดตั้ง software ที่จำเป็นดังนี้ครับ ติดตั้งเสร็จแล้ว restart ซักครั้งด้วยนะครับ
- Docker Desktop ใช้สำหรับ build Docker Image จากโปรแกรมที่เราเขียนด้วย Python + Flask เพื่อนำขึ้น Heroku Cloud Application Platform สามารถดาวน์โหลดและติดตั้ง Docker Desktop ได้จาก https://www.docker.com/products/docker-desktop
- สำหรับ Windows ให้ลง wsl2-kernel ด้วยครับ https://docs.microsoft.com/en-us/windows/wsl/wsl2-kernel
- set BIOS ให้รองรับการทำ Virtualization วิธีเปิดใช้งาน Virtualization
- Heroku CLI ดาวน์โหลดและติดตั้งได้จาก https://devcenter.heroku.com/articles/heroku-cli#download-and-install
- สร้าง Account ของ Heroku ด้วยครับ โดยสามารถ Deploy ได้สูงสุดถึง 5 Application ในแบบฟรี สมัครได้ที่ https://signup.heroku.com/login
ใช้ Docker นำ API ขึ้น Heroku Cloud
build Image ตามคำสั่งด้านล่าง โดยระบุชื่อของ Docker Image ว่าเป็น line-movie-api
$ docker build --tag line-movie-api:latest .
run Container จาก Image เพื่อเป็นการทดลอง deploy ภายในเครื่องคอมเราเองก่อน โดยให้ forward port 8000 จากเครื่องของเราไปยัง port เดียวกันภายใน Container
$ docker run -p 8000:8000 -d --name line-movie-api line-movie-api
ใช้ Heroku CLI เพื่อ login
$ heroku login
$ heroku container:login
สร้าง Application บน Heroku โดยตั้งชื่อว่า line-movie-api (ให้ตั้งชื่อใหม่ด้วยนะครับ)
$ heroku create line-movie-api
deploy API ขึ้นไปที่ Application line-movie-api (ใช้ชื่อเดียวกับที่ตั้งไว้ด้านบน) บน Heroku Cloud ด้วยการ push และ release ตามคำสั่งด้านล่าง
$ heroku container:push web -a line-movie-api
$ heroku container:release web -a line-movie-api
นำ URL https://line-movie-api.herokuapp.com/callback โดยเปลี่ยน line-movie-api เป็นชื่อ Application ที่ตั้งไว้ด้านบน ใส่ไว้ที่ webhook ของ Line Channel ตามด้านล่าง
สามารถดู log ได้จากคำสั่งนี้นะครับ (เปลี่ยนชื่อ line-movie-api ด้วยนะครับ)
$ heroku logs --tail -a line-movie-api
ทดสอบผ่าน LINE อีกครั้งนะครับ ถึงตรงนี้ถ้าติดตรงใหนหลังไมค์มาถามได้นะครับ แล้วพบกันในบทความหน้าครับ 😄
สำหรับเนื้อหาเกี่ยวกับการใช้งาน Docker และ Heroku สามารถดูเพิ่มเติมได้จากบทความของผมเองนะครับ
- แนะนำวิธีใช้ Docker deploy API ที่เขียนด้วย Python + FastAPI ขึ้น Cloud (Heroku) สำหรับทำ Face Recognition ทดสอบด้วยภาพสาว ๆ Blackpink
- สร้าง API ตรวจจับวัตถุด้วย YOLOv5 ผ่าน LINE (ตอนที่ 2 deploy ด้วย Docker ขึ้น Heroku Cloud)
บทความโดย อ.ดร.กานต์ ยงศิริวิทย์
วิทยาลัยนวัตกรรมดิจิทัลเทคโนโลยี มหาวิทยาลัยรังสิต