The Making of HPChat — กว่าจะมาเป็นแชทบอทที่คว้ารางวัลที่ 1 NSC หมวด AI

National Software Contest หรือ NSC เป็นโครงการแข่งขันประกวดซอฟท์แวร์ที่จัดโดย NECTEC ครับ ผมเป็นคนหนึ่งที่แข่งงานนี้อยู่เกือบทุกปี ตั้งแต่สมัย ม.ปลาย จนกระทั่งมหาวิทยาลัยปี 4 ซึ่งกว่าจะเก็บถ้วยมาได้นี่ก็ล่อไปซะการแข่งขันครั้งสุดท้ายเลยทีเดียว 😂ซึ่งผมได้รางวัลชนะเลิศในหมวด Artificial Intelligence (AI) ด้วยแชทบอทที่ช่วยตอบคำถามแทนเจ้าหน้าที่ในโรงพยาบาล

บทความนี้จะมาเล่าเบื้องหลังเทคโนโลยีและแนวคิดของเจ้าแชทบอทนี้ให้ฟังกัน


ไอเดียของโปรเจคจบอันนี้เนี่ยเริ่มมาจากตอนปีสามที่ได้ทำ Seminar เรื่องแชทบอท พอ Seminar จบ อาจารย์ก็เลยเสนอหัวข้อนี้มาให้

แต่การตัดสินใจนี้ก็ใช้เวลาคิดอยู่นานพอสมควร เพราะจริงๆ แล้ว ก็ไม่ได้อินกับ Chatbot ขนาดนั้น แต่สนใจเรื่อง Machine Learning และ Natural Language Processing เพราะมันดูล้ำล้ำไปเลยดี ทำให้ท้ายที่สุดแล้วก็ตกลงรับหัวข้อนี้เป็นโปรเจคจบ

สโคปหลักๆ ของโปรเจคนี้คือ เราจะทำแชทบอทที่จะมาตอบคำถามแทน Receptionist ในโรงพยาบาล โดยต้องตอบคำถามภาษาไทยได้ และใช้ AI เพื่อให้แชทบอทฉลาด วู้ว ทำไงวะครับ 555 NLP ภาษาไทยไปถึงไหนละหนอ / แต่เดี๋ยวก็ทำได้แหละ เอาเป็นว่ากดๆมาก่อนละกัน

วิดีโอแนะนำ HPChat (ไม่มีเสียง)

Chatbot Framework

ขั้นแรกของโปรเจคนี้ก็เริ่มต้นจากการเลือก Framework ก่อนเลย ตัวแมสๆ ในตลาดก็เช่น DialogFlow, Chatfuel หรือ Microsoft Bot Framework

ทีมเราค่อนข้างมีความตั้งใจที่จะลงแข่ง Microsoft Imagine Cup ซึ่งจัดเป็นประจำทุกปีอยู่แล้ว เราก็เลยอยากจะใช้ Framework ที่เป็นของ Microsoft และจากการหาข้อมูลก็พบว่า ตัว Bot Framework ก็มี Dev Community ประมาณนึง มีคำถามคำตอบใน Stackoverflow (เวลาเลือกใช้อะไรอย่าลืมดูสิ่งนี้!) แล้วก็มีความสามารถในการ Deploy ลงแพลตฟอร์มที่เราต้องการได้ ทำให้ท้ายที่สุดแล้วเราก็ได้ Microsoft Bot Framework มาเป็นเครื่องมือหลักในการพัฒนา HPChat ขี้นมา 👏

AI-Powered

ชื่ออย่างเป็นทางการของโปรเจคนี้คือ ระบบสนทนาโต้ตอบอัตโนมัติสำหรับช่วยเหลือผู้ใช้บริการโรงพยาบาล (ใช้เวลานานมากในการคิดว่าจะแปลคำว่า ‘แชทบอท’ ให้มันเป็นวลีที่ทางการและสื่อความหมายได้ยังไงดี)

แล้วแชทบอทนี่มันทำอะไรได้เนี่ย

พูดถึงแชทบอทแล้ว กระบวนการของมันก็แค่ รับ Input จากผู้ใช้ แล้วดูว่ามันเป็นคำถามอันไหน แล้วก็แค่เลือกคำตอบตอบกลับผู้ใช้ เออมันก็แค่นี้เองหนิ

ซึ่งมันมี approach หลายทางมากๆ แบบ คุณจะทำเป็นชอยส์ให้ผู้ใช้จิ้มถามก็ได้ เช่น

Bot: สวัสดีค่ะ แชทบอทเองงง
User: สวัสดีครับ ถามคำถามหน่อย
Bot: อยากถามเกี่ยวกับอะไรคะ
พิมพ์ ‘การรับบริการ’เพื่อถามคำถามเกี่ยวกับการเข้ารับบริการ
พิมพ์ ‘นัดหมาย’เพื่อนัดหมายแพทย์

นี่มันระบบตอบรับอัตโนมัติตอนโทรหาคอลเซนเตอร์ชัดๆ

โปรเจคจบแห่งปี 2018 มันต้องฉลาดกว่านี้สิเว้ย เราเลยเลือกวิธีที่ใช้ Machine Learning เข้ามา ‘จำแนกประเภทคำถาม’ ของผู้ใช้ ความหมายของมันก็คือ ผู้ใช้พิมพ์อะไรเข้ามาก็ได้ เดี๋ยวโปรแกรมเรามันจะเทพ มันจะจับได้เองว่าที่พิมพ์มามันคือคำถามอะไร

ปัญหาประเภทนี้เรียกว่า Classification Problem ครับ คือการที่เราได้ข้อมูล​ Unknown มาแล้วเราต้อง Label มันให้ถูกว่ามันคือ Class ไหน ซึ่ง Class ในที่นี้ก็คือ ‘ประเภทคำถาม’ ของเรานั่นเอง (และด้วยความที่เรามีประเภทคำถามมากมาย มันจะมีชื่อเท่ๆ เจาะจงเข้าไปอีกคือ Multi-class Classification)

ฉะนั้นก่อนอื่น เราต้องกำหนด Class หรือประเภทคำถามทั้งหมดของเราก่อน โดยเราลิสท์ประเภทคำถาม ได้ออกมาทั้งหมด 8 คำถามคือ

  1. ขั้นตอนการเข้ารับบริการโรงพยาบาล
  2. นำทางไปยังสถานที่ต่างๆ ภายในโรงพยาบาล
  3. ประเมินระยะเวลาในการรอคิว
  4. แพคเกจตรวจสุขภาพ
  5. ขั้นตอนการเตรียมตัวในการตรวจสุขภาพ
  6. เวลาทำการของโรงพยาบาลและแต่ละคลินิกในโรงพยาบาล
  7. เบอร์โทรของโรงพยาบาลและแต่ละคลินิกในโรงพยาบาล
  8. ข้อมูลเกี่ยวกับสิทธิ์การรักษาพยาบาล

นอกจากคำถามทั้ง 8 เรื่องนี้แล้ว เรายังต้องเตรียมรับมือกับคำถามนอกเรื่องอีก เช่น คำทักทาย หรือคำที่ไม่ต้องการคำตอบ เช่น ขอบคุณ (ถ้าผู้ใช้พิมพ์ขอบคุณมาแล้วบอทถามกลับว่า “หมายถึงอะไรนะครับ” มันจะเบ๊อะมาก) ทำให้ท้ายที่สุดแล้วเรามี Class ของ Intent ทั้งหมด 10 Class ด้วยกัน

พอเราระบุ Class ทั้งหมดมาได้แล้วเนี่ย เราก็ต้องมาดูว่าเราจะใช้วิธีไหนในการจำแนกข้อมูล ซึ่งจริงๆ แล้วมันมีหลาย Method มาก เช่น Naive Bayes, Support Vector Machine, Decision Tree, etc. แต่จากการทำ Literature Review อย่างหนักหน่วง เค้าบอกมาว่า Multinomial Naive Bayes เนี่ยเหมาะกับการจำแนก Text Snippet หรือข้อความสั้นๆ ที่สุด (ขี้เกียจหาเปเปอร์มาแปะ แต่มันมีคนทำเปเปอร์ไว้จริงๆนะ) เราจึงตัดสินใจเลือก Method นี้มาใช้ทำ Intent Classification สำหรับแชทบอทเรา

ซึ่ง Multinomial Naive Bayes มันเป็น Supervised Classification Algorithm ความหมายคือ เราต้องสอนมันสักพักก่อนว่า คำถามแบบนี้ ต้องจัดอยู่ในหมวดนี้นะๆ ก่อนที่มันจะฉลาดจนสามารถจำแนกประเภทคำถามได้เอง

ปัญหาที่เกิดขี้นคือ แล้วเราจะเอาข้อมูลที่ไหนมาสอน 🤯

เราจึงต้องสร้างแชทบอทอีกตัวมาเก็บข้อมูลที่ใช้ในการสอนก่อน…

ตัวอย่างแชทบอทที่ใช้ในการเก็บข้อมูลเพื่อนำไปเทรนโมเดล

แชทบอทอีกตัวที่เราสร้างขี้นมาจะเป็นลักษณะที่ว่า ให้ผู้ใช้พิมพ์คำถามเข้ามา แต่บอทจะไม่ตอบ บอทจะถามกลับว่ามันคือคำถามอะไร ถ้าอันไหนที่บอทพอจะเดาได้ มันก็จะลองเดาดูแล้วถามเรากลับว่ามันใช่อันนี้ใช่มั้ย โดยทุกการถามตอบเราก็จะเก็บไว้ในรูปของ text file ที่เป็นชุดข้อมูลในลักษณะของ [ข้อความ, หมวดหมู่] ที่เราสามารถเอาไปใช้เทรนโมเดล Classifier ของเราได้

เราทำเป็นแชทบอทอีกตัวเลยเพราะเราตั้งใจจะให้มันใช้ง่าย เพื่อให้คนหลายๆ คน มาช่วยกันเทรน ทั้งเพื่อนโปรเจคกลุ่มอื่น รุ่นพี่ รุ่นน้อง อาจารย์ พ่อแม่ ซึ่งกลุ่มคนแต่ละกลุ่มก็จะมีวิธีการใช้คำที่ต่างกันไป ถ้าแชทบอทเราเรียนรู้รูปประโยคที่หลากหลายมากเท่าไหร่ มันก็จะรับมือกับความหลากหลายของ Input ในอนาคตได้ดีมากขี้นเท่านั้น

ท้ายที่สุดเราก็ได้ชุดข้อมูลที่เอามาใช้ในการเทรนและเทส Classifier ของเรา ซึ่งจริงๆ แล้วก่อนที่จะเอาเข้าไปเทรน มันจะต้องมี Process ก่อนที่จะเอาเข้าโมเดลได้ คือเราเอาข้อมูลดิบไปตัดคำ แล้วก็เอาไป Vectorize และทำ TF-IDF เพื่อให้ข้อมูลอยู่ในรูปของเมตริกซ์ (ถ้างงไปกูเกิ้ลเพิ่มนะ)โดยเราใช้ Sci-kit Learn มาเป็นเครื่องมือสำหรับใช้สร้างโมเดล ซึ่งสิ่งที่ Sci-kit Learn เตรียมไว้ให้เราคือชุดฟังก์ชันต่างๆ เราก็เอาฟังก์ชันเหล่านั้นมาร้อยๆ ต่อกัน (ด้วยความเข้าใจ) ปรับจูนพารามิเตอร์ต่างๆ นิดหน่อยก็ทำงานได้แล้ว

เราเก็บข้อมูลมาได้ทั้งหมด 700 ชุด แบ่งมาใช้เทรน ~500 ชุด (เอามาฝึกให้มันทำเป็น) แล้วอีก ~200 ชุด เอามาใช้เทส (เพื่อดูประสิทธิภาพว่า จากที่ฝึกไปเนี่ย ลองเจอโจทย์ที่ไม่เคยเห็นแล้วดูว่าจะทำได้แม่นแค่ไหน) ได้ผลลัพธ์ Accuracy มาที่ราวๆ 80% ซึ่งถือว่าน่าพอใจทีเดียว

ตอนนี้แชทบอทเราก็จะแยกประเภทคำถามได้ละ 🎉

Responses

แยกประเภทคำถามเสร็จแล้วทำไรต่อ — เราก็ต้องทำให้แชทบอทรู้ไงว่าคำถามนี้ต้องตอบอะไร

ก่อนอื่น แต่ละคำถามมันมีความยากง่าย ความซับซ้อนในการตอบแตกต่างกันไป สามารถแยกคร่าวๆ ได้ดังนี้

  1. ถามมาตอบไป
    คำถามในกลุ่มนี้เช่น เวลาเปิดปิด, เบอร์โทร อันนี้ผู้ใช้ถามเข้ามา หาข้อมูลใน Database ตอบกลับเสร็จก็ปิดจ็อบเลย
  2. ถามมา ถามกลับนิดนึงก่อนถึงจะตอบได้
    เช่น คำถามเรื่องแพคเกจตรวจสุขภาพ เราจะต้องถามกลับก่อนว่าอยากรู้รายละเอียดแพคเกจไหน หรือผู้ใช้เหมาะกับแพคเกจตรวจสุขภาพแบบใด จากนั้นค่อยหาข้อมูลใน Database แล้วโยนข้อมูลที่เหมาะสมกลับไปให้
  3. ถามมา ถามกลับนิดนึง แล้วต้องไปเรียก Service ข้างนอกอีกถึงจะตอบได้
    เช่น คำถามเรื่องการนำทางไปยังสถานที่ต่างๆ ในโรงพยาบาล ที่เราแพลนไว้ว่า แชทบอทจะสามารถนำทางแบบล้ำๆ ได้ด้วยการส่งรูปภาพบอกทาง อันนี้ต้องมียิง Request ไป Server อีกเครื่องนึงที่เราตั้งไว้เพื่อ Process รูปภาพโดยเฉพาะ (เดี๋ยวตรงนี้จะเล่าในหัวข้อถัดไป)

สำหรับคำถามกลุ่มแรก ถามมาตอบไป อันนี้เหมือนเราแค่เตรียมคำตอบไว้ แล้วเวลาถูกถามมาก็แค่ตอบคำถามตามนี้ได้เลย

แต่สำหรับคำถามกลุ่มที่สองและกลุ่มที่สามเนี่ย อันนี้ตอนที่เราจะทำ เราต้องมาวาด Flow ก่อนว่า คำถามนี้ต้องถามกลับว่าอะไร ต้องการคำตอบจากผู้ใช้แบบไหน มีช้อยส์ให้มั้ย แล้วมีอะไรให้เลือกบ้าง ตอบช้อยส์นี้ไปโผล่ที่ไหน บอทตอบกลับมาว่าอะไร ฯลฯ อันนี้ก็จะซับซ้อนขี้นมานิดนึง ซึ่งพวก Flow ทั้งหลายนี้ ตัว Bot Framework ก็จะมีฟังก์ชันช่วยจัดการเกี่ยวกับ Flow ต่างๆ ที่ค่อนข้างสะดวกเลยทีเดียว

อย่างไรก็ตาม หลายๆคำถาม จะต้องมีการวิเคราะห์ข้อมูล เพื่อหาข้อมูลเฉพาะเพิ่มเติม (Entity Extraction) จาก Input อีกนิดนึง เช่น ถ้าผู้ใช้ถามมาว่า ‘คลินิกทันตกรรมเปิดกี่โมง’ เราต้องรู้ว่า ‘ทันตกรรม’ คือชื่อคลินิก แล้วเราค่อยเอาคำว่า ‘ทันตกรรม’ ไปคุ้ยใน Database เพื่อหาว่าคลินิกทันตกรรมเปิดกี่โมง แล้วจึงเอาข้อมูลมาตอบผู้ใช้ได้

นี่ก็ยากเหมือนกัน

แต่เราใช้ Advanced AI ในการแก้ปัญหานี้ครับ

MY FAVOURITE MEME EVER

ฮา but true, เบื้องหลังของแชทบอทส่วนนี้ก็เรียกได้ว่าเป็น If-condition นั่นแหละ แต่ขอเรียกให้มันดูเท่ๆ ว่า Linguistic Rule-based หลักการทำงานของมันก็คือ เราสร้างเงื่อนไขโดยอิงตามข้อมูลทางภาษาศาสตร์นิดหน่อย ยกตัวอย่างง่ายๆ เช่น ชื่อคลินิก จะต้องอยู่หลังคำว่า ‘คลินิก’ หรือ ‘แผนก’ และต้องเป็น ‘คำนาม’ หรือ ‘คำกริยา’ เช่น ถ้า Input เป็น ‘คลินิกมะเร็ง’ จะสามารถบอกได้ว่า ‘มะเร็ง’ คือชื่อคลินิก แต่ถ้า Input เป็น ‘คลินิกไหน’ คำว่า ‘ไหน’ เนี่ย มันจะมีประเภทคำของมัน ซึ่งไม่ใช่ทั้ง ‘คำนาม’ และ ‘คำกริยา’ เราจึงไม่จำแนกคำว่า ‘ไหน’ เป็นชื่อคลินิก

มันดูโง่ แต่มันก็พอถูไถนะ 555 และนี่คือวิธีที่เราเลือกใช้จริงๆ เนื่องด้วยข้อจำกัดทางเดดไลน์ (จริงๆ มันมีวิธีที่ฉลาดกว่านี้ แต่ไม่ทันแล้ววว)

เปเปอร์ ORCHID: Thai Part-Of-Speech Tagged Corpus ที่ปริ้นท์มาดูเป็น Reference

Indoor Navigation using Images

ตัวอย่างการใช้งานฟีเจอร์นำทางภายในอาคาร

จริงๆ แล้ว ฟีเจอร์นำทางเนี่ย มันไม่ได้เป็นความตั้งใจแรกเริ่มของโปรเจคครับ

มันเพิ่งเพิ่มมาตอนที่ไปพรีเซนต์โปรเจครอบแรก แล้วอาจารย์บอก Committee ว่า กลุ่มสามคน สโคปมันน้อยไป ทำแบบนี้เพิ่มสิ ให้ผู้ใช้ถ่ายรูปเข้ามาแล้วก็ระบุตำแหน่ง แล้วก็นำทางผู้ใช้ไปแผนกนู้นแผนกนี้เลย เราก็แบบ หูว Computer Vision หวะ 🌝 555555 ลุยๆๆๆ

ซึ่งท้ายที่สุดแล้วฟีเจอร์นี้ก็เป็นหนึ่งในฟีเจอร์ที่เรียกความสนใจได้ดีมากๆ เลยทีเดียว

สำหรับฟีเจอร์นี้ อาจารย์ไกด์เรามาด้วยคีย์เวิร์ด ‘A-SIFT’ ครับ

A-SIFT หรือ Affine-SIFT เป็นวิธีที่ใช้ในการเปรียบเทียบรูปภาพ โดยเราใช้วิธีนี้ในการเปรียบเทียบรูปภาพที่ผู้ใช้ส่งเข้ามาทางแชท กับภาพใน Database ที่เราเตรียมไว้ล่วงหน้า เพื่อที่จะบอกได้ว่า รูปที่ผู้ใช้ถ่ายรูปส่งเข้ามาคือสถานที่ไหนในโรงพยาบาล

ตัวอย่างการทำงานของ A-SIFT (ซ้าย: รูปใน Database/ขวา: รูปที่ถ่ายโดยผู้ใช้)

สิ่งที่เราทำคือ เราไปสำรวจโรงพยาบาลและวาด Node graph ขี้นมาเพื่อจำลองแผนผังภายในอาคาร และเราก็ได้ถ่ายรูปตัวอย่างจากแต่ละสถานที่ไว้จำนวนหนึ่ง โดยเป็นรูปป้ายหรือวัตถุเด่นๆ ภายในโรงพยาบาล เช่น รูปภาพ หรือป้ายต่างๆ

สิ่งที่เราทำคือ เราไปสำรวจโรงพยาบาลและวาด Node graph ขี้นมาเพื่อจำลองแผนผังภายในอาคาร และเราก็ได้ถ่ายรูปตัวอย่างจากแต่ละสถานที่ไว้จำนวนหนึ่ง โดยเป็นรูปป้ายหรือวัตถุเด่นๆ ภายในโรงพยาบาล เช่น รูปภาพ หรือป้ายต่างๆ

เราเอารูปภาพเหล่านั้นมา Label ด้วยมือว่าสถานที่ในภาพนั้นอยู่ที่ Node ไหนบน Graph และก็เตรียมรูปภาพไว้จำนวนหนึ่งบนเซิร์ฟเวอร์

วิธีทำงานของมันก็คือ เมื่อผู้ใช้ส่งรูปภาพเข้ามา ตัวโปรแกรมจะพยายาม Match ว่ารูปที่ถ่ายมีจุดคล้ายกับรูปในฐานข้อมูลรูปไหนมากที่สุด (และต้องมีเปอร์เซนต์ความคล้ายถึงระดับนึงด้วย เช่นถ้า Match รูปนี้มากสุดแล้ว แต่ Match แค่ 15% เราก็จะไม่เอา) พอเรารู้ว่าภาพไหนที่ Match เราก็จะรู้ว่าผู้ใช้อยู่ที่ Node ไหนบน Graph แผนผังอาคารของเรา จากนั้นเราก็จะสามารถนำทางผู้ใช้ไปยัง Node ไหนๆ ตามที่ผู้ใช้ต้องการก็ได้ โดยใช้ Shortest Path Algorithm เช่น Dijkstra’s

ข้อเสียที่เราเจอจากการใช้ A-SIFT คือมันค่อนข้างช้า ยิ่งถ้ามีรูปเยอะอาจกินเวลาเป็นนาทีๆ ตรงนี้จะต้องใช้ Parallel Computing เข้ามาช่วยเพื่อให้โปรแกรมสามารถทำงานได้เร็วขี้นครับ

Classification Performance Improvement

จากที่เล่ามาทั้งหมดเนี่ย มันก็ยังมีปัญหาหลายๆ อย่าง โดยเฉพาะในส่วนของ Entity Extraction ที่เราใช้ Advanced AI ในการแก้ปัญหา ทำให้บางทีผู้ใช้พิมพ์มาแล้วก็เลือกคำไปคุ้ยใน Database ผิด กลายเป็นหาไม่เจอ หรือบางทีปัญหาก็เกิดจากการตัดคำผิด ก็ทำให้หาใน Database ไม่เจอเช่นกัน

Elasticsearch ช่วยเราได้!

เราใช้ Elasticsearch เป็น Database ของโปรเจคนี้เลย สิ่งที่มันช่วยเราได้มากเลยก็คือ เวลาเรา Search ข้อมูลด้วยคำที่ผิดเล็กน้อย มันจะยัง Search เจอ และคืนค่ามาพร้อมกับ Confidence Score ให้เราด้วย หรือบางทีถ้าเจอหลายๆ ผลลัพธ์ที่คล้ายกัน มันก็จะคืนผลลัพธ์มาหลายๆ อันให้เราเลย

ยกตัวอย่างการใช้งานจริงเช่น สมมติว่าใน Elasticsearch เรามีเก็บข้อมูลของสถานที่ “ร้านอาหาร” กับ “ร้านกาแฟ” ไว้ ถ้าผู้ใช้พิมพ์ถามหาข้อมูล “ร้านค้า” (ซึ่งเราไม่มีข้อมูล) ตัวโปรแกรมจะเข้าไป search ใน Elasticsearch แล้วจะได้ผลลัพธ์มา 2 อัน คือทั้ง “ร้านอาหาร” และ “ร้านกาแฟ” พร้อมกับค่า Confidence Score ที่อาจจะต่างกันเล็กน้อย ในกรณีนี้เราสามารถถามกลับไปยังผู้ใช้ได้ว่า ผู้ใช้หมายถึง “ร้านอาหาร” หรือ “ร้านกาแฟ” พร้อมให้ช้อยส์กลับไปยังผู้ใช้ เลือกจิ้มตอบได้เลย 👍

นอกจาก Elasticsearch แล้ว เรายังมีความพยายามที่จะแก้อีกปัญหานึง คือปัญหาตัดคำผิดครับ

จริงๆ ไลบรารี่ตัดคำภาษาไทยสมัยนี้ค่อนข้างฉลาดมากๆ แล้ว Accuracy 90% ปลายทั้งนั้น ปัญหาคือ บนแชทบอท คนมันไม่ได้พิมพ์กันถูกเป๊ะๆ เช่นสมมติพิมพ์คำว่า ‘โรงพยาบาล’ เป็น ‘โรงพนาบาล’ แค่นี้ก็ตัดคำผิดได้แล้ว 😩

ถ้าเราจะแก้ปัญหานี้ด้วยการแก้คำผิดให้ถูกก่อน แล้วค่อยเอาไปตัดคำล่ะ?

เรามีความพยายามที่จะใช้ Deep Learning เข้ามาแก้คำที่สะกดผิด ตั้งแต่ผู้ใช้พิมพ์ข้อความเข้ามา ก่อนที่จะเอาไปตัดคำ เพื่อที่มันจะได้ตัดคำได้อย่างถูกต้อง เราลองค้นบนอินเทอร์เน็ตดูแล้วก็พบว่า ของภาษาอังกฤษเคยมีคนทำไว้สำเร็จและเปิดซอร์สให้ดูบน Github ด้วย เราพยายามศึกษาและลองทำตามด้วย approach คล้ายๆกัน คือเราเอา Corpus ของ NECTEC มาใส่ Noise (เปลี่ยนตัวอักษรให้สะกดผิด เช่น เปลี่ยนตัวสะกดให้ใช้ตัวสะกดแม่เดียวกันแต่เป็นตัวอักษรอื่น, ดับเบิ้ลตัวอักษรบางตัวเข้าไป, ลบตัวอักษรบางตัวทิ้ง)​ แล้วก็เอาคู่ของข้อมูลที่ใส่ Noise (สะกดผิด)​ กับข้อมูลที่สะกดถูกต้อง ไปเทรนอยู่หลายวัน แต่ก็พบปัญหาว่า Accuracy ที่ได้มันไม่ดีเลย

เรามีข้อสันนิษฐานหลายๆ อย่างเกี่ยวกับปัญหาที่เกิดขี้น อย่างไรก็ตาม ด้วยเดดไลน์ที่ใกล้เข้ามา ตัวโมเดลแก้ไขการสะกดคำของเราจึงไม่สมบูรณ์อย่างที่คาดไว้ แต่ด้วยความช่วยเหลือของ Elasticsearch ทำให้ท้ายที่สุดแล้วเราก็ Handle การสะกดผิดได้ในหลายๆ เคสอย่างน่าประหลาดใจ 🙃

Put them all together!

ทำแต่ละส่วนเสร็จแล้ว เราก็ต้องเอามันมาประกอบร่างให้กลายเป็น Chatbot ให้ได้

เราเปิดเครื่องบน Azure ไว้สองเครื่อง เครื่องหนึ่งสำหรับรันตัว Bot Framework และอีกเครื่องหนึ่งเป็น Ubuntu VM เอาไว้รัน Web Service โดยเราจะเอา Web Framework มาครอบตัวโมเดล Intent Classification เพื่อที่จะทำเป็น API และเนื่องจากโค้ดส่วนที่เราทำ Intent Classification เขียนขี้นมาด้วย Python เราจึงเลือกใช้ Flask ซึ่งเป็น Python Web Framework ที่ครอบคลุมการใช้งานของเราและเป็นเฟรมเวิร์คที่มินิมอลมากๆ

ตัว Indoor Navigation เราก็ทำเป็น API เช่นกัน และในบางฟีเจอร์ที่เราต้องคุยกับ Elasticsearch เราก็ให้ Flask ยิงเข้า Elasticsearch ตรงๆ ได้เลย ดังนั้นทั้งตัว OpenCV และ Elasticsearch ก็ถูกติดตั้งไว้ในเครื่องเดียวกันนี่แหละ

มีอีกเครื่องที่เราเสียเงินไปเยอะเป็นพิเศษคือเครื่อง GPU สำหรับเทรน Deep Learning Model สำหรับแก้ไขคำผิด รันทีเป็นวันๆ ค่อนข้างสูบเงินพอสมควร

การ Deploy ทุกอย่างก็เป็นอีกเรื่องที่ใหม่สำหรับเรามาก เนื่องจากปกติใช้แต่ Host สำเร็จรูป ไม่ค่อยมีโอกาสได้ลงทุกอย่างเองตั้งแต่แรก ใช้เวลางม Tutorial อยู่สักพักเหมือนกันเนื่องจากติดปัญหาตอนที่จะ deploy Flask ทำเอาปวดหัวไปหลายวัน

แต่ท้ายที่สุดเราก็ทำให้ทุกอย่างมันเชื่อมกัน และใช้งานเป็นแชทบอทจริงๆ ที่รันอยู่บน Facebook Messenger ได้แล้ว!


อย่างนึงที่เราตั้งใจ Challenge ตัวเองด้วย Senior Project ก็คือการที่เราเลือกใช้ Tools ที่เราไม่เคยมีความรู้มาก่อนทั้งหมด นี่เป็นครั้งแรกที่เราได้แตะ Microsoft Bot Framework, Sci-kit Learn, Keras, OpenCV, Elasticsearch รวมถึงเป็นครั้งแรกที่นั่ง Set Environment ทั้งหมดด้วยตัวเองบน Azure

ส่วนตัวคิดว่า Senior Project เป็นโอกาสที่ดีมากๆ ในการได้ลองทำอะไรใหม่ๆ ออกจาก Comfort Zone และเลือกทำในสิ่งที่ไม่เคยทำมาก่อน มันอาจจะติดขัดจนเซ็ง หรืออาจจะมา Realize ทีหลังว่าที่เราทำลงไปอะมัน Bad Practice แต่อย่างน้อยเราก็ได้รู้ ได้ลอง และได้สัมผัสมันแบบเน้นๆ แล้ว

อีกอย่างนอกจากเรื่อง Tech สิ่งที่สำคัญก็คือ Presentation Skill การเตรียมสไลด์ให้ดูดี และการซ้อมพรีเซนท์ สำคัญมาก บวกกับมีอาจารย์เก่งๆ มากประสบการณ์อย่าง อ.ธีรณี และ อ.ทัศนีย์วรรณ มาช่วยไกด์ให้ (ถึงขนาดให้ไปซ้อมพรีเซนท์ให้อาจารย์ฟังถึงบ้านอาจารย์เลยอะ) การพรีเซนท์ที่ดี มันจะช่วยเสริมให้โปรเจคน่าสนใจขี้นอีกหลายเท่าตัวเลย


ขอบคุณทุกคนที่อ่านมาจนถึงตรงนี้ มีจุดไหนที่สงสัยหรือมีข้อแนะนำตรงไหน คอมเมนท์ทิ้งไว้หรือทักมาถามทางทวิตเตอร์ @winwanwon ได้ตามสะดวกเลยครับ 🙂