บทที่ 32
บทที่ 32 — การมาสก์ข้อมูลส่วนบุคคลภาษาไทย
เปลี่ยนข้อมูลส่วนบุคคลภาษาไทยให้เป็น placeholder ก่อนที่ข้อความจะออกจาก
เครื่องคุณ แล้วใส่ค่าจริงกลับคืนก่อนที่คุณจะเห็นคำตอบ โมเดลทำงานกับ
[PHONE_1] และ [ID_2] ส่วน log ของ provider ไม่เคยเห็นตัวเลขจริง
ปิดไว้เป็นค่าเริ่มต้น เปิดใน .thclaws/settings.json
{ "sensitive": { "enabled": true } }
ไม่มีปุ่มใน GUI และไม่มี slash command — นี่เป็นการตัดสินใจระดับไฟล์ตั้งค่า ทำครั้งเดียวต่อโปรเจกต์
หน้าตาเป็นอย่างไร
คุณพิมพ์ข้อความที่มีเบอร์โทรอยู่ในนั้น โมเดลได้รับ
ผู้ติดต่อคือ [PHONE_1] โปรดร่างอีเมลถึงเขา
โมเดลตอบโดยใช้ placeholder นั้น ก่อนคำตอบจะถึงมือคุณ ค่าจริงจะถูกใส่กลับ พร้อมเครื่องหมายให้คุณเห็นว่าเกิดอะไรขึ้น
ผมจะร่างอีเมลถึง 🔓« 081-234-5678 » ให้ครับ
เครื่องหมาย 🔓« » เป็นแค่การแสดงผล สิ่งที่เครื่องเอาไปใช้ต่อ — ไฟล์ที่เขียน tool ที่เรียก และประวัติ session — ได้ค่าจริงที่ไม่มีเครื่องหมายติดไปด้วย
กฎที่ทำให้มันปลอดภัย
ประวัติเก็บเป็น plaintext ส่วนการมาสก์อยู่ที่สายส่ง
นี่คือหลักการที่ควรเข้าใจ เพราะมันตรงข้ามกับที่หลายคนคาด ไฟล์ session บน ดิสก์ของคุณเก็บค่าจริง การมาสก์เกิดขึ้นตอนประกอบ request ทุก turn ใหม่ทุกครั้ง
การทำอีกแบบ — มาสก์ลงไปในประวัติเลย — ฟังดูเรียบร้อยกว่าแต่พัง เพราะ
placeholder ที่ถูกเขียนลงประวัติใน turn ที่ 3 ต้องยังหมายถึงสิ่งเดิมใน turn
ที่ 30 ข้าม compaction ข้าม /load และข้ามการสลับโมเดล พลาดการ re-map
ครั้งเดียว โมเดลก็ไปให้เหตุผลเกี่ยวกับคนผิดคนแล้ว การมาสก์ที่สายส่งแปลว่า
ทุก turn มาสก์ใหม่จากข้อความจริง และ coreference map ทำให้ [PHONE_1] ชี้ไป
เบอร์เดิมตลอดอายุ session
อะไรถูกมาสก์บ้าง
มีตัวตรวจจับในตัวสี่แบบ แต่ละแบบมี validator ไม่ใช่แค่ pattern เปล่า ๆ
| ประเภท | Placeholder | ตรวจจับอย่างไร |
|---|---|---|
| เลขบัตรประชาชน | [ID_1] |
หาเลข 13 หลักก่อน แล้วให้ checksum ตามมาตรฐาน เป็นตัวตัดสิน เลข 13 หลักที่ไม่ใช่บัตรจริงจะถูกปล่อยผ่าน |
| เบอร์โทร | [PHONE_1] |
รูปแบบเบอร์ไทย และถูกปฏิเสธเมื่อมีตัวเลขติดอยู่ข้าง ๆ จึงไม่ไปแคะเบอร์โทรออกจากเลขบัญชีธนาคาร |
| ทะเบียนรถ | [PLATE_1] |
ต้องมีบริบท คือมี ทะเบียน… นำหน้า หรือมีชื่อจังหวัดตามหลัง |
| ชื่อที่มีคำนำหน้า | [NAME_1] |
นาย / นาง / นางสาว / น.ส. / ด.ช. / ด.ญ. ตามด้วยชื่อ |
เลขไทยถูกแปลงก่อน ๐๘๑… คือเบอร์โทรจริง และเวอร์ชันแรกเคยปล่อยให้มัน
หลุดไปโดยไม่ถูกมาสก์ นั่นคือ failure mode เดียวที่ฟีเจอร์นี้ต้องไม่มีเด็ดขาด
คือรั่วเพราะ pattern ไม่รู้จักตัวเลข ระบบจึงแปลง ๐-๙ เป็น ASCII ก่อน match
ทุกส่วนของ request ที่มีข้อความถูกครอบคลุมหมด ทั้งข้อความของคุณ system prompt อาร์กิวเมนต์ของ tool และผลลัพธ์ของ tool
ความแม่นยำคือข้อจำกัด ไม่ใช่ความครอบคลุม
นี่คือการตัดสินใจเชิงออกแบบที่อธิบายทุกอย่างที่เหลือในบทนี้
ภาษาไทยเขียนติดกันไม่เว้นวรรค pattern ที่หลวมจึงไม่ได้แค่มาสก์เกินไปหนึ่งคำ แต่กลืนทั้งประโยครอบ ๆ ไปด้วย และโมเดลก็ได้รับ prompt ที่เละ ตัวตรวจจับจึง ถูกทำให้แคบโดยเจตนา และแต่ละตัวมีเงื่อนไขขอบเขตหรือบริบทกำกับ
กฎเวอร์ชันแรกให้ผล 119 จุดบนบทความภาษาไทยห้าบทที่ไม่มีข้อมูลส่วนบุคคลอยู่ เลย นั่นคือที่มาของการจูน
ตัวอย่างที่ชัดที่สุด: คุณ ไม่ใช่ตัวกระตุ้นชื่อ เพราะมันคือสรรพนามบุรุษ
ที่สองในชีวิตประจำวัน และปรากฏ 80 ครั้งในคลังข้อความปลอด PII ชุดเดียวกันนั้น
การนับ คุณสมชาย เป็นชื่อจะเท่ากับนับบทสนทนาไทยทั่วไปครึ่งหนึ่งเป็นข้อมูล
ส่วนบุคคล ชื่อที่นำหน้าด้วย คุณ จึงถูกปล่อยไว้โดยตั้งใจ
ในทำนองเดียวกัน พยัญชนะสองสามตัวตามด้วยตัวเลขก็ดูเหมือนทะเบียนรถ แต่ก็เป็น
ภาษาไทยธรรมดาด้วย (ครบ 3 ปี) ทะเบียนจึงต้องมีบริบทประกอบ
อะไรที่มันจับไม่ได้
ควรเข้าใจให้ชัดก่อนจะพึ่งพามัน
- ชื่อที่ไม่มีคำนำหน้าทางการ เช่น
คุณสมชายหรือสมชายเฉย ๆ นี่คือ ช่องว่างที่ใหญ่ที่สุด และเป็นความตั้งใจตามเหตุผลข้างบน การตรวจจับชื่อและ ที่อยู่แบบอิสระต้องใช้โมเดลภาษา ไม่ใช่ regex ซึ่งชั้นนั้นอยู่ในแผน ยังไม่ ได้ ship - ที่อยู่ ด้วยเหตุผลเดียวกัน
- อีเมลและเลขบัญชีธนาคาร ยังไม่มีตัวตรวจจับ
- ใบหน้าและเอกสารในรูปภาพ รูปถ่ายบัตรประชาชนคือข้อมูลส่วนบุคคลจริงที่กฎ ระดับข้อความแตะไม่ได้ รูปภาพผ่านไปโดยไม่ถูกแตะต้อง
- อะไรก็ตามที่อยู่นอกรูปแบบภาษาไทย นี่เป็นฟีเจอร์เฉพาะภาษาไทย
ให้ใช้กลไก placeholder นี้ในฐานะการลดการเปิดเผยอย่างมีนัยสำคัญ ไม่ใช่ในฐานะ การรับประกันการปฏิบัติตามกฎหมาย ถ้ามีเอกสารที่ต้องไม่ถึงมือ provider เด็ดขาด ก็อย่าวางมันลงในแชทที่วิ่งไปหา provider
ที่ไหนที่มันไม่ทำงาน
มีสองกรณีที่ปิดการมาสก์ทั้งหมด และเป็นความตั้งใจทั้งคู่
- โมเดลในเครื่อง Ollama, LM Studio, vLLM และ llama.cpp รันบนเครื่องคุณ ไม่มีอะไรออกจากเครื่อง การมาสก์จึงมีแต่จะกิน context ที่โมเดลควรได้ใช้ ระบบข้ามให้เป็นราย request โดยดูจากโมเดลที่ใช้จริงใน turn นั้น
- Multiuser pod การมาสก์ปฏิเสธที่จะติดอาวุธเมื่อ engine รันแบบหลาย tenant
เพราะ worker ตัวเดียวให้บริการหลายคน และ coreference map เป็นของราย process
failure mode ที่จะเกิดคือ
[PHONE_1]ของ tenant หนึ่งไปแปลงกลับเป็นเบอร์ของ อีก tenant การปฏิเสธจึงเป็นคำตอบเดียวที่ปลอดภัย
thinking block ก็ถูกปล่อยไว้เช่นกัน เพราะการให้เหตุผลของโมเดลมีแต่ placeholder อยู่แล้วโดยธรรมชาติ (มันเห็นแต่ placeholder มาตลอด) และ Anthropic เซ็นบล็อกพวกนั้นไว้ การเขียนทับจึงจะทำให้ลายเซ็นเสีย
โมเดลถูกบอกอะไรบ้าง
ขณะที่การมาสก์ทำงานอยู่ system prompt จะมีหัวข้อ Redacted values เพิ่มเข้ามา
มันมีอยู่เพราะความผิดพลาดที่เห็นได้ชัดเป็นเรื่องการสนทนา ไม่ใช่เรื่องเทคนิค
โมเดลที่เห็น [PHONE_1] แล้วตีความว่า ข้อมูลหายไป จะถามคุณกลับมาอย่างสุภาพ
ว่าขอเบอร์จริงหน่อย — แล้วตัว un-masker ก็จะเขียนประโยคนั้นใหม่ให้กลายเป็นการ
อ้างว่าเบอร์จริงคือ placeholder
โมเดลจึงถูกบอกสั้น ๆ ว่า placeholder แทนข้อมูลจริงที่ผู้ใช้ให้มาแล้ว มันไม่ได้ หายไป ไม่ใช่ template และไม่ใช่ error ให้ใช้ซ้ำตรง ๆ แล้วค่าจริงจะถูกแทนกลับ ก่อน tool ทำงาน และอย่าพยายาม validate หรือจัดรูปแบบใหม่ เพราะมันมองไม่เห็น ตัวเลขที่อยู่ข้างใต้
คำเฉพาะของคุณเอง
ตัวตรวจจับรองรับ dictionary ที่กำหนดเองได้ คือคำเฉพาะของโปรเจกต์ที่จะถูกมาสก์
เป็น [CUST_1] แต่ยังไม่มี key ใน settings ให้ตั้ง วันนี้จึงเข้าถึงได้จาก
โค้ดเท่านั้น ถ้าคุณต้องการมาสก์ข้อความเฉพาะบางอย่าง นั่นคือช่องว่าง ไม่ใช่การ
ตั้งค่าที่คุณหาไม่เจอ
การเปิดใช้งาน
{
"sensitive": { "enabled": true }
}
ตั้งรายโปรเจกต์ใน .thclaws/settings.json การเปลี่ยนค่ามีผลกับ request ใหม่
ส่วน session ที่ติดอาวุธอยู่แล้วจะรักษา coreference map ไว้ การเปลี่ยน
settings เรื่องอื่นกลางบทสนทนาจึงไม่ทำให้เลข placeholder ของคุณเปลี่ยน
อย่าลืมว่า settings.json ที่รูปแบบผิดจะถูกอ่านผ่านไปเงียบ ๆ
ทุก flag แบบ opt-in จะกลายเป็นปิดโดยไม่มีคำเตือน ถ้าตั้งค่านี้แล้วไม่เห็น
placeholder เลย ให้ตรวจก่อนว่าไฟล์เป็น JSON ที่ถูกต้อง
การแก้ปัญหา
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| ไม่มีอะไรถูกมาสก์เลย | ยังไม่ได้เปิด หรือ settings.json parse ไม่ผ่าน |
ตรวจ JSON ให้ถูก และ sensitive.enabled ต้องเป็น true |
| ตั้งค่าถูกแล้วแต่ยังไม่มาสก์ | คุณใช้โมเดลในเครื่อง หรืออยู่บน multiuser pod | ปกติ — ดูข้างบน |
| มีชื่อหลุดไป | ชื่อนั้นไม่มีคำนำหน้าทางการ หรือใช้ คุณ |
ปกติในตอนนี้ การตรวจชื่ออิสระยังไม่ได้ ship |
| เลข 13 หลักไม่ถูกมาสก์ | มันไม่ผ่าน checksum บัตรประชาชน แปลว่าไม่ใช่เลขบัตร | ทำงานตามที่ตั้งใจไว้ |
| โมเดลขอ “เบอร์จริง” กลับมา | มันอ่าน placeholder ว่าข้อมูลหายไป | คำอธิบายใน system prompt มีไว้กันเรื่องนี้ ถ้ายังเกิดซ้ำให้แจ้ง |
| เห็น 🔓« » ในไฟล์ที่ agent เขียน | เป็นบั๊ก — เครื่องหมายควรอยู่แค่ตอนแสดงผล | แจ้งได้เลย |