ความปลอดภัยของ AI · AI สนทนาด้วยเสียง · วิศวกรรมซอฟต์แวร์
AI รับสายของคลินิก ห้ามพูดอะไรบ้าง
ผู้ช่วย AI ของคลินิกช่วยนัดหมาย ตอบคำถามทั่วไป และส่งเรื่องให้เจ้าหน้าที่ได้ ส่วนการวินิจฉัย การแนะนำเรื่องยา และการรับประกันผลการรักษาเป็นเรื่องที่เราห้ามไว้ชัดเจน พร้อมวางระบบตรวจในโค้ดให้ทำงานร่วมกับกฎใน prompt
พนักงานต้อนรับคลินิกรับโทรศัพท์ เช็กตารางหมอ ลงนัด และตามเจ้าหน้าที่เมื่อมีเรื่องที่ต้องให้ทีมรักษาดูแล หน้าที่นี้รวมถึงการรู้ด้วยว่าคำถามไหนไม่ควรตอบเอง ถ้าคนไข้เล่าอาการ พนักงานต้อนรับไม่ควรตอบว่า “อาการแบบนี้น่าจะติดเชื้อนะคะ ลองทานยา…” แม้จะอยากช่วยก็ตาม
เราสร้างผู้ช่วยต้อนรับ AI ให้คลินิก รับสายเป็นภาษาไทยและตอบแชตใน LINE งานของมันคือให้ข้อมูลเวลาเปิดปิด บริการ การเตรียมตัวก่อนมาคลินิก และรับคำขอนัดหมาย ส่วนคำถามที่ต้องใช้ความเห็นด้านการรักษา เราให้ทีมของคลินิกรับช่วงต่อ
ระหว่างทำ เราพบว่าการเขียนข้อห้ามไว้ใน prompt อย่างเดียวไม่พอ บทความนี้จึงเล่าถึงข้อห้ามสามข้อ และวิธีที่เราเพิ่มการตรวจเข้าไปในระบบ
สามเรื่องที่ห้ามตอบ
- ห้ามวินิจฉัย รวมถึงการคาดเดาว่า “อาจจะเป็น X” เพราะคนไข้ยังอาจเข้าใจว่าเป็นความเห็นทางการแพทย์ แม้จะใช้คำที่ฟังไม่ฟันธงก็ตาม
- ห้ามแนะนำเรื่องยา ทั้งปริมาณที่ควรทาน ความถี่ หรือวิธีจัดการเมื่อลืมทานยา
- ห้ามรับประกันผลการรักษา เช่น “ทำแล้วหายแน่นอน” หรือ “เห็นผลชัวร์”
พอเขียนเป็นรายการก็ดูตรงไปตรงมา แต่บทสนทนาจริงมักไม่แยกเป็นข้อแบบนี้ คนไข้เล่าอาการปวดแล้วถามต่อ โมเดลก็อาจพยายามช่วยจนตอบเกินหน้าที่ เราจึงต้องดูทั้งเนื้อหาของคำตอบและจังหวะที่ควรส่งเรื่องให้คนรับต่อ
ทำไม prompt อย่างเดียวไม่พอ
เวอร์ชันแรกของเราก็ใส่กฎเหล่านี้ไว้ใน system prompt และส่วนใหญ่โมเดลทำตามได้ ปัญหาคือยังมีบางครั้งที่หลุด ซึ่งเป็นเรื่องที่ปล่อยผ่านไม่ได้สำหรับงานนี้
ตอนแก้ เราเริ่มจากเพิ่มคำสั่งและย้ำกฎเดิม แต่ยิ่ง prompt ยาว การแก้พฤติกรรมหนึ่งก็ยิ่งกระทบอีกพฤติกรรมหนึ่ง กฎที่ย้ำไปหลายรอบยังหลุดได้เป็นครั้งคราว เราจึงเริ่มย้ายการตรวจบางส่วนออกมาไว้ในโค้ด เพื่อให้ระบุได้ชัดว่าจะตรวจอะไร ที่จุดไหน และเขียนเทสต์ครอบคลุมได้
เราแบ่งหน้าที่ให้โมเดลดูแลภาษา น้ำเสียง และวิธีอธิบาย ส่วนข้อห้ามที่ต้องตรวจทุกครั้งให้มีโค้ดรองรับด้วย คำตอบต้องผ่านขั้นตอนตรวจนี้ก่อนส่งออก การทำแบบนี้ช่วยให้เราไม่ต้องพึ่งการทำตาม prompt เพียงอย่างเดียว แต่ตัวตรวจเองก็ยังต้องทดสอบและแก้ไขเมื่อพบกรณีที่พลาด
โค้ดตรวจอะไรบ้าง
ทุกคำตอบผ่านชุดตรวจหลังโมเดลร่างเสร็จ และก่อนระบบส่งข้อความหรือเสียงออกไป
- ข้อความจากคนไข้ ตรวจหาอาการเฉียบพลันที่ระบบกำหนดไว้ หากพบให้เข้าสู่ขั้นตอนส่งต่อ โดยไม่ต้องรอให้โมเดลเป็นผู้ตัดสินเพียงตัวเดียว
- โมเดลร่างคำตอบ เรียบเรียงภาษาไทยและเลือกน้ำเสียงให้เหมาะกับบทสนทนา
- ตรวจความปลอดภัย ตรวจหาการวินิจฉัย คำแนะนำเรื่องยา และการรับประกันผล ก่อนตัดเนื้อหาหรือระงับคำตอบที่ไม่ควรส่ง
- คำตอบที่ส่งออก ข้อความหรือเสียงหลังผ่านการตรวจแล้ว
ตัวตรวจขาออกจะหาการวินิจฉัย คำแนะนำทางการแพทย์ และการอ้างผลการรักษาในคำตอบดิบ มันทำงานแยกจากโมเดลและจาก logic การส่งต่อ เพื่อให้เราตรวจสอบความผิดพลาดของแต่ละส่วนได้ชัดขึ้น
ตัวกรองเรื่องยาจะตัดประโยคที่บอกวิธีใช้ยาออกทั้งประโยค แล้วปรับคำตอบให้คนไข้สอบถามคุณหมอหรือเภสัชกรแทน เรากำหนดขอบเขตของตัวกรองให้แคบพอที่จะยังส่งคำแนะนำดูแลตัวเองพื้นฐานที่คลินิกอนุมัติไว้แล้วได้ ถ้าบล็อกกว้างเกินไป ผู้ช่วยก็จะตอบข้อมูลที่ควรตอบได้ไม่เหลือมากนัก
ฝั่งขาเข้าก็มีการตรวจเช่นกัน เราตั้งให้ระบบส่งต่อทันทีเมื่อพบอาการเฉียบพลันตามเงื่อนไขที่กำหนด เช่น บวมลามเร็ว ไข้สูง หรือเลือดออกไม่หยุด แม้โมเดลจะไม่ได้ติดธงไว้ ในส่วนนี้เราเลือกให้ระบบส่งต่อไว้ก่อนเมื่อพบสัญญาณเสี่ยง เพราะการพลาดเรื่องที่ควรส่งต่อมีผลเสียมากกว่า ถ้าคลินิกปิดอยู่ ระบบจะบอกให้ไปห้องฉุกเฉินของโรงพยาบาล แทนการรอคลินิกเปิดตอนเช้า
อีกส่วนที่ต้องจัดการคือข้อความที่คนอ่านเข้าใจได้ แต่ตัวตรวจจับรูปแบบอาจมองข้าม เช่น อักขระที่มองไม่เห็นแบบ zero-width ตัวเลขที่หน้าตาคล้ายกัน หรือคำที่ผสมอักขระจากหลายภาษาไว้ด้วยกัน เราต้องจัดการรูปแบบเหล่านี้ก่อนตรวจเนื้อหาด้วย
ส่งเรื่องให้เจ้าหน้าที่รับต่อ
ถ้าผู้ช่วยตอบไม่ได้ บทสนทนาก็ยังต้องไปต่อได้ คนไข้ควรรู้ว่าเรื่องจะส่งให้ใคร และจะได้รับการติดต่อกลับประมาณเมื่อไร
เมื่อเข้าสู่ขั้นตอนส่งต่อ ระบบจะเปิดเคสและส่งการ์ดเข้ากลุ่ม LINE ของเจ้าหน้าที่คลินิก พร้อมคำถามของคนไข้ เจ้าหน้าที่กดพัก AI แล้วเข้ามาคุยใน LINE เองได้ การเปิดเคสกับการที่เจ้าหน้าที่รับเรื่องแล้วเป็นคนละขั้นตอนกัน จึงต้องระวังไม่ให้คำตอบบอกว่ามีคนรับเรื่องแล้ว หากระบบยังยืนยันได้เพียงว่าเริ่มส่งต่อ
ตอนเจ้าหน้าที่ส่งบทสนทนาคืนให้ AI เราให้โค้ดจัดการปุ่มกลับมาตอบก่อนเรียกโมเดล เพราะเคยเจอว่า AI ย้อนอ่านบทสนทนาแล้วส่งต่อเรื่องเดิมซ้ำ คนเพิ่งคืนงานให้ แต่ AI ก็ส่งงานกลับมาอีก เราแก้ลูปนี้ที่การจัดการสถานะในโค้ด ซึ่งตรงกับต้นเหตุของปัญหามากกว่าการเพิ่มคำสั่งอีกข้อใน prompt
คำตอบตอนส่งต่อจึงควรบอกขั้นตอนถัดไปให้ชัด พร้อมกรอบเวลาที่ระบบมีข้อมูลรองรับ แทนที่จะจบเพียงว่า “ช่วยไม่ได้ค่ะ”
ข้อมูลเดียวกัน เขียนได้หลายแบบ
เรื่องที่ทำให้เราเสียเวลาแก้มากเรื่องหนึ่ง คือข้อมูลถูกต้องในรูปแบบหนึ่ง แต่อาจหลุดเมื่อโมเดลเขียนอีกแบบ
เบอร์โทรเขียนเป็นตัวเลขติดกัน แบ่งกลุ่ม ใช้เลขไทย หรืออ่านทีละตัวก็ได้ ช่วงราคาอาจใช้ขีดหรือคำว่า “ถึง” ส่วนเวลามีทั้งตัวเลขและคำอย่าง “บ่ายสามโมง” หรือ “หนึ่งทุ่ม”
081-234-5678
081 234 5678
๐๘๑-๒๓๔-๕๖๗๘
ศูนย์ แปด หนึ่ง สอง สาม สี่ ห้า หก เจ็ด แปด เราเคยมีตัวตรวจเบอร์โทรที่ผู้ช่วยทวนให้คนโทรเข้าฟัง มันตรวจคำอ่านทีละตัวได้ เพราะเป็นรูปแบบที่ผู้ช่วยใช้ตอนทวนครั้งแรก แต่ในการโทรทดสอบครั้งหนึ่ง พอจะจบสาย โมเดลทวนเบอร์อีกครั้งเป็นเลขแบ่งกลุ่มและทำตัวเลขหล่นไปหนึ่งตัว ตัวตรวจของเราไม่ครอบคลุมรูปแบบนั้น จึงปล่อยเบอร์ผิดผ่านออกไป ถ้าเกิดขึ้นในการใช้งานจริง คลินิกก็อาจโทรกลับผิดคน
หลังจากนั้น เราไม่ได้แก้แค่รูปแบบที่เพิ่งเจอ แต่กลับมาไล่ว่าข้อมูลแต่ละชนิดปรากฏในคำตอบได้กี่แบบ แล้วเพิ่มเทสต์ให้ครอบคลุมรูปแบบที่คาดว่าจะเจอ รวมถึงข้อความจริงที่เคยทำให้ระบบพลาด
หลักนี้สำคัญกับข้อมูลที่คนจะนำไปใช้ต่อ เช่น เบอร์โทร ราคา วันและเวลา รวมถึงข้อมูลอย่างขนาดยาในระบบที่มีหน้าที่แสดงข้อมูลนั้น ส่วนผู้ช่วยรับสายตัวนี้ยังคงไม่ให้คำแนะนำวิธีใช้ยา
ตัวอย่างย่อสำหรับเบอร์โทรคือแปลงรูปแบบที่ต่างกันให้เป็นค่ามาตรฐานก่อน แล้วเทียบกับข้อมูลที่บันทึกไว้ หากไม่ตรงกัน ให้ใช้เบอร์จากข้อมูลต้นทางแทนข้อความที่โมเดลร่างมา
// Collapse every surface form to one canonical value, then compare it
// with the record. The record wins; the model's version never ships.
const canonical = (s: string) =>
thaiWordsToDigits(thaiNumeralsToAscii(stripInvisible(s)))
.replace(/\D/g, '');
if (canonical(readBack) !== canonical(record.phone)) {
reply = withPhone(reply, record.phone);
} ถ้ารูปแบบข้อมูลมีขอบเขตชัดเจน เราก็ลดงานที่ต้องให้โมเดลสร้างเองได้อีก อย่างการอ่านเวลาภาษาไทย เราเก็บเวลาเป็นตัวเลข แล้วให้ฟังก์ชันในโค้ดแปลงเป็นคำอ่าน พร้อมทดสอบไล่ครบทั้งวัน วิธีนี้ช่วยจัดการความผิดพลาดกลุ่มเดียวกันได้คราวเดียว แทนการรอแก้ทีละกรณีจากสายทดสอบ
ตรวจคำตอบหลังผ่านตัวกรองด้วย
อีกเรื่องที่ทำให้เราเข้าใจผลทดสอบผิดได้คือ log ถ้าบันทึกไว้เฉพาะคำตอบดิบของโมเดล เราจะไม่เห็นว่าตัวกรองแก้หรือตัดอะไรออกไปก่อนส่ง
เราเจอมากกว่าหนึ่งครั้งที่ log ดูเหมือนผู้ช่วยตอบบางอย่าง ทั้งที่ข้อความนั้นถูกตัดออกก่อนส่งไปแล้ว เวลาตรวจระบบจึงต้องดูคำตอบหลังผ่านตัวกรองด้วย และแยกให้ชัดว่ากำลังดูสิ่งที่โมเดลร่างหรือสิ่งที่ระบบส่งออก ทั้งนี้ การมีบันทึกว่าส่งข้อความหรือเสียงออกไป ยังไม่ได้ยืนยันว่าคนไข้ได้รับ อ่าน หรือได้ยินครบถ้วน
การประเมินคุณภาพก็ต้องระวังในลักษณะเดียวกัน การใช้ AI ให้คะแนนตัวอย่างที่ผู้ช่วยมีส่วนเขียนเองเสี่ยงจะได้ผลที่เข้าข้างผู้ช่วยมากเกินไป เราจึงให้การตรวจแบบ deterministic ซึ่งตรวจตามกฎและให้ผลเดิมเมื่อข้อมูลเหมือนเดิม เป็นด่านแรก ส่วนคะแนนจาก AI ที่ทำหน้าที่กรรมการจะนำมาใช้ก็ต่อเมื่อเทียบกับบทสนทนาที่คนให้คะแนนไว้แล้ว
ขอบเขตงานต้องชัดในข้อตกลงด้วย
นอกจากโค้ด ข้อตกลงกับคลินิกต้องระบุให้ชัดว่าผู้ช่วยทำหน้าที่อะไรบ้าง งานของตัวนี้คือช่วยเรื่องนัดหมายและข้อมูลทั่วไป ส่วนคำปรึกษาและการตัดสินใจด้านการรักษาให้ทีมของคลินิกเป็นผู้ดูแล ขอบเขตที่เขียนไว้กับพฤติกรรมของระบบควรสอดคล้องกัน
สำหรับเรา การทำให้ผู้ช่วยตอบได้อย่างเป็นธรรมชาติเป็นเพียงส่วนหนึ่งของงาน อีกส่วนคือทำให้มันหยุดตอบในเรื่องที่เกินหน้าที่ ส่งต่อได้ถูกจังหวะ และให้ทีมตรวจสอบได้ว่าเกิดอะไรขึ้นในแต่ละขั้น เรื่องเหล่านี้ต้องทดสอบกับบทสนทนาจริง และคอยแก้เมื่อพบกรณีที่ระบบยังรับมือได้ไม่ดีครับ