THAIPO.ai
กลับไปหน้าบล็อก

Glossary ที่สอนตัวเองจนเพี้ยน

10 พฤศจิกายน 2569 · ThaiPo

มีอยู่ช่วงหนึ่ง แชทหนึ่งของเราสั่งตัวแปลอย่างมั่นอกมั่นใจว่า คำไทยที่แปลว่า "Thailand" หมายถึงธนาคาร ไม่ใช่พลาดครั้งเดียวแล้วจบ แต่เป็นกฎที่เขียนลงไปในความจำของแชทนั้น และถูกใช้กับทุกข้อความที่มันแปล

ThaiPo เรียนรู้ไปเรื่อยๆ ตามที่แชทเดินไป มี background job คอยอ่านประวัติของแต่ละแชท แล้วขุด glossary ออกมา: ชื่อเล่น สถานที่ คำที่กลุ่มนี้ใช้ในแบบของตัวเอง glossary ถูกปิดผนึกแยกรายแชท (ไม่มีอะไรที่เรียนจากแชทหนึ่งไปโผล่ในอีกแชทได้) และถูก inject เข้า prompt ของแชทนั้น เพื่อให้คำแปลเข้ากับคนในแชทมากขึ้นเรื่อยๆ นั่นคือฟีเจอร์ ส่วนโพสต์นี้คือเรื่องของฤดูร้อนที่มันใช้ไปกับการสอนเรื่องเหลวไหลให้ตัวเอง และเรื่องที่ตารางลดจาก 111,798 row เหลือ 10,844

หุ่นยนต์บรรณารักษ์ท่าทางใจดีนั่งอยู่ที่โต๊ะ กำลังประทับตราไม่ผ่านลงบนบัตรรายการกองสูงเกือบทั้งกอง และเก็บเพียงไม่กี่ใบลงลิ้นชักเล็กๆ ที่เป็นระเบียบ

อาการ: คำตอบที่ไม่เกี่ยวกับอะไรเลย

ที่มีคนรายงานเข้ามาคือ บางแชทได้คำแปลที่ไม่เกี่ยวกับสิ่งที่พิมพ์ไป ประโยคภาษาไทยมาถึงพร้อมภาษาอังกฤษดิบๆ แปะอยู่กลางประโยค ที่แย่กว่านั้นคือมันเป็นๆ หายๆ เราเอา prompt ที่โดนวางยาตัวเดียวกันเป๊ะมารันสองรอบเป็น A/B: รอบแรก output เพี้ยนสามในสี่ รอบสองเพี้ยนหนึ่งในสี่ มองจากข้างในแชท ไม่มีอะไรดูเป็นปัญหาเชิงระบบเลย มันถึงซ่อนตัวอยู่ได้เป็นเดือนๆ

ต้นเหตุคือตัวขุด มันได้รับลิสต์ข้อความแบนๆ ไม่มีชื่อคนพูด ไม่มี tag ภาษา และไม่มีการจับคู่ เพราะข้อความที่อยู่ติดกันในแชทคือการตอบกัน ไม่ใช่คำแปลของกันและกัน ในแชทที่เกือบทั้งหมดเป็นภาษาเดียว จึงไม่มีคู่ข้ามภาษาให้หา แต่ model ที่ถูกขอให้หาคู่จะไม่ยักไหล่แล้วคืนลิสต์ว่างกลับมา มันผลิตสิ่งเดียวที่ input เอื้อให้ทำได้: พจนานุกรมอธิบายศัพท์แบบอังกฤษเป็นอังกฤษ

จากนั้น row พวกนั้นก็ถูก inject ไว้ใต้หัวข้อที่บอกว่าให้ใช้คำแปลตามนี้เป๊ะๆ เสมอ ในกลุ่มหนึ่ง 148 จาก 149 คำที่ inject เข้าไปเป็นคู่ประเภทนี้ และเมื่อดูทั้งระบบ 35% ของ 159,718 คำที่เก็บไว้ไม่ใช่คำแปลเลย

gate แรกง่ายจนเกือบน่าอาย ทุกแชทแปลระหว่างภาษาไทยกับอีกหนึ่งภาษาเท่านั้น ดังนั้น คำศัพท์ของจริงต้องข้ามเส้นแบ่งภาษาไทย การเช็กแบบ deterministic ครั้งเดียวฆ่าได้ทั้งพจนานุกรมอธิบายศัพท์ คู่ที่ซ้ำกันเอง และคู่คำพิมพ์ผิด (ซึ่งที่ผ่านมาสอนคำพิมพ์ผิดให้ model อย่างซื่อสัตย์) มันรันตอน write ตารางจึงหยุดโต และรันตอน read ด้วย row เสียที่เก็บไว้แล้วทุกตัวจึงหมดฤทธิ์ทันทีที่ deploy โค้ด จากนั้นเราลบไป 55,853 row prompt ของตัวขุดบอกเป็นนัยมาตลอดว่าต้องเป็นคู่ข้ามภาษา model เมินมันอยู่หลายเดือน prompt คือคำขอ ส่วน filter คือหลักประกัน

ถูกรูปแบบ แต่ยังผิดอยู่ดี

สองสัปดาห์ต่อมาเรากลับไปดูของที่รอดมา กลุ่มหนึ่งที่ใช้แพลนฟรีมีคำที่ขุดไว้ 4,905 คำ แพลนฟรี inject 25 คำล่าสุด ความจำใช้งานทั้งหมดของแชทนั้นจึงเท่ากับผลผลิตของวันเดียว จากการขุดมาเจ็ดสิบวัน ทุกอย่างที่มันเรียนรู้มาจริงๆ ถูกฝังอยู่ใต้ row ใหม่อีกหลายพัน

ใน 25 ช่องที่ใช้งานอยู่นั้น เก้าช่องเป็นศัพท์ที่ตัวแปลไหนก็รู้ขึ้นใจ (คำไทยของ Spain คำไทยของ electricity) สามช่องเป็นเศษเพี้ยนๆ จากการถอดเสียง และอีกสามช่องผิดไปเลย เมืองไทย หรือ "Thailand" ถูกจับคู่กับธนาคารที่ชื่อคล้ายกัน กราบ หรือ "to bow in respect" ถูกจับคู่กับ Grab แอปเรียกรถ เป็นคู่ไทย-อังกฤษที่รูปแบบถูกต้องทุกประการ และเหลวไหลโดยสมบูรณ์

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

gate จึงเป็น classifier สามทาง ทุก candidate ถูกจัดเข้า ซ้ำซ้อน ผิด หรือ มีประโยชน์ และเก็บเฉพาะที่มีประโยชน์ prompt เวอร์ชันแรกอธิบายคำตัดสินทั้งสามแบบแล้วขอมาหนึ่งอย่าง ทดสอบกับคำที่ขุดมาจริง 60 คำ มันตัดสินซ้ำซ้อน 44 คำและผิด 9 คำได้ถูกต้อง แล้วก็บอกว่าทั้งสามคำที่มีพิษนั้นมีประโยชน์ พอเห็นการจับคู่ที่ดูเป็นไปได้ระหว่างของจริงสองอย่าง model อ่านมันเป็นความรู้ท้องถิ่น ซึ่งก็คือสิ่งที่ glossary มีไว้เก็บนั่นเอง เติมคำว่า "be strict" ลงไปก็ไม่ได้เปลี่ยนอะไร

สิ่งที่ได้ผลคือลำดับ model ต้องเขียนออกมาก่อนว่าคำต้นทางหมายถึงอะไร ด้วยคำของมันเอง ก่อนจะได้รับอนุญาตให้ตัดสินคู่ที่ถูกเสนอมา พอผูกมัดตัวเองไว้แล้วว่า "ประเทศไทย" มันก็หาทางทำให้เข้ากับธนาคารไม่ได้

มีรายละเอียดหนึ่งที่เราชอบ: gate กับการกวาดล้าง fail ไปคนละทิศ gate ตัดสินว่าจะเพิ่มหรือไม่ คำที่ไม่มีคำตัดสินจึงไม่ถูกเก็บ การกวาดล้างตัดสินว่าจะลบหรือไม่ row ที่ไม่มีคำตัดสินจึงถูกเก็บไว้ หลักการเดียวกัน การกระทำตรงข้าม การกวาดล้างรันผ่าน batch API: 441 request ไม่ถึงสามนาที ไม่มี failure เลย $6.78 และ 111,798 row กลายเป็น 10,844

ผู้ต้องสงสัยที่มีพยานยืนยันที่อยู่

แล้วก็มีเคสที่ดูเหมือนเรื่องเดิมอีกรอบ ชื่อเฉพาะของกลุ่มหนึ่งกลับมาแบบเละเทะ: ชื่อธุรกิจถูกแปลเป็นไทยตรงตัวทีละส่วน (นึกภาพร้านชื่อ Brightside ที่กลับมาเป็น "ฝั่งสว่างของถนน") ตัวย่อถูกสะกดตามเสียงด้วยตัวอักษรไทย glossary อีกแล้วแน่ๆ

แชทนั้นมี glossary ศูนย์ row

ตัวการคือ rolling context window ลิสต์สั้นๆ ของบทสนทนาล่าสุดที่ model อ่านเพื่อรักษาความคงเส้นคงวา มันเก็บแต่ละคู่เป็นต้นทางกับคำแปล แล้วส่งกลับไปให้ดูเป็นตัวอย่างที่ทำเสร็จแล้ว ในแชทที่ข้อความส่วนใหญ่เป็น label สั้นๆ ทุกบรรทัดของ window นั้นก็คือ row แทนคำ window กลายเป็น glossary ที่ไม่มีใครตรวจไปอย่างเงียบๆ และคำแปลผิดครั้งเดียวก็กลายเป็นวิธีที่แชทนั้นสะกดชื่อนั้น จนกว่า window จะหมุนพ้นไป (อาการวนซ้ำเป็นเกลียวใน โพสต์เรื่องตัวแปลต้องไม่ตอบเอง ก็เป็นญาติตระกูลเดียวกัน)

วิธีแก้คือการปฏิเสธสองแบบตอน write: คู่ที่ชื่อถูกแปลจนเละ หรือคู่ที่ label สั้นๆ แค่ถูกสะกดใหม่ตามเสียง จะไม่ได้เข้า window เด็ดขาด ซึ่งปฏิเสธไป 0.8% ของคู่ทั้งหมดในระบบ เวอร์ชันแรกของเราปฏิเสธทุก label ที่ภาษาอังกฤษหายกลายเป็นไทย แก้แชทนั้นได้จริง แต่เสียคู่ไป 16.3% และสอน window ว่าภาษาอังกฤษควรอยู่เป็นภาษาอังกฤษ เมื่อวัดบน window จริงผ่าน model ตัวที่ใช้งานจริง คำแปลเสียลดจาก 34 ใน 66 เหลือ 14 ใน 66

glossary ก็ได้ gate คู่กัน: คู่ที่ขุดมาแล้วเป็นเสียงเดียวกันในสองชุดตัวอักษรจะถูกปฏิเสธ โดยเทียบโครงพยัญชนะ เพราะพยัญชนะคือสิ่งที่รอดมาได้เวลาคนเดาตัวสะกด threshold ถูก sweep บน row จริง จาก 739 คู่ที่ไม่ซ้ำกันที่ถูกทิ้ง มีสามคู่ที่เป็นการเสียของดีไปจริงๆ

คำเตือนที่ไม่ได้ทำอะไรเลย

ระหว่างทางเราได้วัดทางแก้ราคาถูกด้วย สองครั้ง คือเขียนหัวข้อของ block ที่ inject ใหม่: นี่เป็นแค่คำใบ้ ไม่ใช่กฎ คำแปลในอดีตอาจผิดได้ อย่าลอกบรรทัดไหนไปตรงๆ บน block ของ glossary แบบนั้นได้ 8 จาก 24 เทียบกับ baseline ที่ได้ 9 ส่วน gate ที่เอา row ออกได้ 12 และใช้ทั้งคู่ได้ 14 บน context window หัวข้อใหม่ได้ผลเสีย 33 กับ 25 เทียบกับ control ที่ได้ 32 กับ 40 จาก A/B สองรอบ เป็นแค่ noise

ป้ายที่แปะบน block เดินทางไปไม่ถึง สิ่งที่อยู่ใน block ต่างหากที่ไปถึง model อ่านเนื้อหาเป็นตัวอย่าง และแทบจะเมินข้อความที่อธิบายว่าควรอ่านมันยังไง

สิ่งที่เราเก็บกลับมา

  • ระบบที่เรียนรู้ได้ต้องมีระบบภูมิคุ้มกัน อะไรก็ตามที่เขียนลง prompt ในอนาคตของตัวเองได้ สักวันจะเขียนอะไรผิดลงไป แล้วก็ทำตามสิ่งนั้น
  • validate ตอน write ไม่ใช่ตอน read คำเตือนตอน read วัดแล้วไม่มีผล สองครั้ง การปฏิเสธ row ได้ผลทั้งสองครั้ง
  • loop ที่ train ตัวเองจะขยายความผิดพลาดของตัวเองผิดครั้งเดียวคือพิมพ์ผิด ผิดแล้วเก็บไว้คือนโยบาย
  • วัดจากตาราง อย่าวัดจากความรู้สึกการแก้ทั้งหมดในเรื่องนี้เริ่มจากการนับ row และคำอธิบายเชิงเหตุผลที่ยืนอยู่ได้คือข้อที่เรา A/B test กับข้อมูลจริง "regression" สองตัวที่เราอ่านจากตัวอย่างชุดเดียวหายไปในรอบที่สอง

ThaiPo ออกแบบ สร้าง และดูแลโดยนักพัฒนาคนเดียว Steven Acreman

ลองใช้ในแชทของคุณเอง

ThaiPo อยู่ใน LINE และแปลทุกข้อความให้สองทาง ฟรีตลอดไป เริ่มใช้ฟรี หรือ เพิ่มเพื่อน @thaipo.ai ใน LINE แล้วบอทจะส่งลิงก์สมัครให้ในแชทเลย

ThaiPo is operated by Marine Entertainment Co., Ltd. · Docs · Blog · Privacy · Terms · Contact