Hallucination ในโค้ด: แพ็กเกจและ API ที่ไม่มีอยู่จริง

เคยไหมที่ AI ตอบมาอย่างมั่นใจว่า "ใช้เมธอดนี้ได้เลย" แต่พอรันแล้วเจอ Call to undefined method หรือแนะนำให้ติดตั้งแพ็กเกจที่ค้นแล้วไม่เจอ อาการนี้เรียกว่า hallucination คือโมเดลสร้างคำตอบที่ดูสมเหตุสมผลแต่ไม่ตรงกับความจริง ในงานเขียนโค้ด ผลกระทบมีตั้งแต่เสียเวลา debug ไปจนถึงความเสี่ยงด้าน supply chain ที่ผู้โจมตีใช้ประโยชน์ได้ บทความนี้จะอธิบายว่าทำไมมันเกิด มีรูปแบบอะไรบ้าง slopsquatting คืออะไร และวิธีตรวจทั้งจากเอกสารจริงและจากการรันโค้ด
ทำไม AI ถึงแต่งชื่อฟังก์ชันและแพ็กเกจขึ้นมาเอง
LLM ทำงานโดยทำนายข้อความถัดไปที่น่าจะเป็นจากรูปแบบที่เรียนมา มันไม่ได้เปิดเอกสารหรือค้นใน registry ทุกครั้งที่ตอบ (เว้นแต่เครื่องมือที่ใช้จะมีความสามารถค้นหาและเราเห็นว่ามันค้นจริง) ชื่อที่ "ฟังดูใช่" จึงอาจถูกสร้างขึ้นจากรูปแบบที่พบบ่อย เช่น ถ้าไลบรารีหนึ่งมี findOne() กับ findAll() โมเดลอาจเดาว่ามี findOneOrFail() ด้วย ทั้งที่ไลบรารีนั้นไม่มี
สถานการณ์ที่ทำให้เกิด hallucination บ่อยขึ้น:
- ถามเรื่องไลบรารีที่ไม่ค่อยมีคนใช้ หรือเวอร์ชันใหม่ที่โมเดลอาจไม่รู้จัก
- ไม่ระบุเวอร์ชันของ framework ทำให้โมเดลปนความรู้จากหลายเวอร์ชัน เช่น Yii 1.1 กับ Yii2
- ปนความรู้ข้าม framework เช่น เอา API ของ framework หนึ่งมาใช้กับอีก framework เพราะชื่อแนวคิดคล้ายกัน
- ขอให้แก้ปัญหาเฉพาะทางมาก ๆ ซึ่งโมเดลมีตัวอย่างน้อย จึงเติมช่องว่างด้วยการเดา
รูปแบบ hallucination ที่เจอบ่อยในงานโค้ด
แบ่งได้คร่าว ๆ เป็นสี่แบบ แต่ละแบบมีอันตรายต่างกัน
- ฟังก์ชันหรือเมธอดที่ไม่มีอยู่ เช่น เรียกเมธอดที่ชื่อสมเหตุสมผลบน ActiveRecord หรือ Formatter ของ Yii2 แต่ไม่มีจริง แบบนี้มักพังทันทีตอนรัน จึงอันตรายน้อยที่สุด ถ้าเรารันจริง
- พารามิเตอร์หรือ option ที่ไม่มี เช่น ใส่ key ใน config array ที่ component ไม่รู้จัก บาง component จะ error แต่บางกรณีจะถูกเพิกเฉยเงียบ ๆ ทำให้เราเข้าใจผิดว่าตั้งค่าความปลอดภัยแล้ว
- พฤติกรรมที่บรรยายผิด เช่น บอกว่าฟังก์ชันหนึ่ง escape HTML ให้อัตโนมัติ ทั้งที่จริงไม่ได้ทำ แบบนี้อันตรายเพราะโค้ดรันผ่าน แต่ความเข้าใจผิดกลายเป็นช่องโหว่
- แพ็กเกจที่ไม่มีอยู่จริง AI แนะนำ
composer requireหรือnpm installชื่อที่ไม่มีใน registry ซึ่งนำไปสู่ปัญหาถัดไป
Slopsquatting: เมื่อผู้โจมตีรอรับชื่อที่ AI แต่ง
Typosquatting คือการจดชื่อแพ็กเกจที่สะกดคล้ายของจริงเพื่อรอคนพิมพ์ผิด slopsquatting เป็นแนวคิดคล้ายกัน แต่เป้าหมายคือชื่อแพ็กเกจที่ AI มักแต่งขึ้น ถ้าชื่อที่ไม่มีจริงชื่อหนึ่งถูก AI แนะนำซ้ำ ๆ ผู้ไม่หวังดีอาจจดชื่อนั้นใน registry สาธารณะแล้วใส่โค้ดอันตรายไว้ คนที่ copy คำสั่งติดตั้งจาก AI โดยไม่ตรวจก็จะได้แพ็กเกจของผู้โจมตีไป
สิ่งที่ทำให้ความเสี่ยงนี้น่ากังวลในโลก PHP และ JavaScript:
- npm รัน install scripts ได้ตอนติดตั้ง หมายความว่าโค้ดอันตรายอาจทำงานทันทีบนเครื่องนักพัฒนาหรือ CI
- Composer plugin ก็รันโค้ดตอนติดตั้งได้ Composer รุ่นใหม่จึงถามก่อนอนุญาต plugin ผ่าน
allow-pluginsซึ่งไม่ควรกดยอมรับโดยไม่อ่าน - เครื่องนักพัฒนามักมี SSH key, token ของ cloud และไฟล์
.envที่มีค่าสูงสำหรับผู้โจมตี
หลักง่าย ๆ คือ ชื่อแพ็กเกจที่มาจาก AI เป็นแค่ "ข้อเสนอ" ไม่ใช่ "ข้อเท็จจริง" ต้องตรวจก่อนติดตั้งทุกครั้ง รายละเอียดการตรวจเชิงลึกอยู่ในบทความ "ตรวจแพ็กเกจที่ AI แนะนำก่อนติดตั้ง" ในซีรีส์นี้
ตรวจกับเอกสารจริง
ขั้นแรกคือเทียบกับแหล่งข้อมูลต้นทาง ไม่ใช่ถาม AI ซ้ำว่า "แน่ใจไหม" เพราะ AI อาจยืนยันคำตอบเดิมอย่างมั่นใจ
- ฟังก์ชัน PHP ตรวจที่ php.net ดูทั้งว่ามีอยู่จริง และมีตั้งแต่ PHP เวอร์ชันไหน
- คลาสและเมธอดของ Yii2 ตรวจใน API documentation ที่ yiiframework.com โดยเลือกเวอร์ชันให้ตรงกับที่ใช้
- แพ็กเกจ ดูหน้าแพ็กเกจใน Packagist หรือ npm registry และตาม link ไปที่ repository ต้นทาง
- ดีที่สุดคือเปิดซอร์สโค้ดใน
vendor/ของเราเอง เพราะนั่นคือเวอร์ชันที่รันจริง
เทคนิคที่ช่วยได้มากคือใส่เวอร์ชันและข้อกำหนดใน prompt เช่น "ใช้ Yii2 เวอร์ชันที่ระบุใน composer.lock, ใช้เฉพาะคลาสที่มีใน vendor/yiisoft/yii2 ถ้าไม่แน่ใจว่ามีเมธอดนี้ให้บอกตรง ๆ" ถึงจะไม่กันได้ 100% แต่ช่วยลดการเดาลง และทำให้ AI บอกความไม่แน่ใจออกมามากขึ้น
ตรวจด้วยการรัน: ให้เครื่องเป็นคนจับ
วิธีที่เชื่อถือได้ที่สุดคือให้เครื่องมือตรวจ ไม่ใช่ความรู้สึก เริ่มจากคำสั่งเล็ก ๆ ที่เช็กได้ทันที
# ฟังก์ชันนี้มีใน PHP ที่เราใช้จริงไหม
php -r 'var_dump(function_exists("str_contains"));'
# คลาสและเมธอดนี้มีใน vendor ของโปรเจกต์ไหม
php -r 'require "vendor/autoload.php";
var_dump(method_exists(yii\db\ActiveRecord::class, "findOne"));'
# แพ็กเกจนี้มีอยู่ใน registry จริงไหม (ยังไม่ติดตั้ง)
composer show --available vendor-name/package-name
npm view package-name name version repository.url
ถ้าแพ็กเกจไม่มีอยู่ คำสั่งเหล่านี้จะแจ้งว่าไม่พบ ซึ่งคือสัญญาณให้หยุดทันที แต่ถ้า "พบ" ก็ยังไม่ได้แปลว่าปลอดภัย เพราะอาจเป็นแพ็กเกจที่เพิ่งถูกจดเพื่อรอเหยื่อ ต้องดูข้อมูลประกอบต่อ
สำหรับโค้ดทั้งไฟล์ ให้ใช้ static analysis อย่าง PHPStan ซึ่งจับการเรียกเมธอดหรือฟังก์ชันที่ไม่มีอยู่ได้โดยไม่ต้องรันจริง เหมาะกับโค้ดที่ AI เขียนมาก
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse common backend --level=5
สำหรับ Yii2 ซึ่งใช้ magic property หลายจุด อาจต้องตั้งค่าเพิ่มหรือใช้ extension เสริมเพื่อลด false positive ให้ศึกษาจากเอกสารของ PHPStan ก่อนตั้งระดับให้สูงขึ้น
ด่านสุดท้ายคือ test ถ้าโค้ดที่ AI เขียนมี unit test ครอบคลุมเส้นทางหลัก เมธอดที่ไม่มีอยู่จริงหรือพฤติกรรมที่ไม่ตรงกับคำบรรยายจะโผล่ออกมาเร็ว อย่าลืมว่าโค้ดในสาขาที่ไม่ค่อยถูกรัน เช่น ส่วนจัดการ error มักเป็นที่ซ่อนของเมธอดที่ไม่มีจริง เพราะไม่มีใครเคยรันถึง
เช็กลิสต์ก่อนรับโค้ดและแพ็กเกจจาก AI
- ทุก
composer requireและnpm installที่ AI เสนอ ต้องตรวจว่ามีอยู่จริงและเป็นของผู้ดูแลที่เชื่อถือได้ - ถามตัวเองว่าต้องใช้แพ็กเกจนี้จริงไหม หรือ PHP และ Yii2 ทำได้อยู่แล้ว
- เมธอดหรือ option ที่ไม่คุ้น ให้ค้นในเอกสารเวอร์ชันที่ใช้ หรือดูใน
vendor/ - รัน
php -l, PHPStan และ test ก่อนเปิด PR - สำหรับ config ด้านความปลอดภัย ตรวจว่าค่าที่ตั้งมีผลจริง เช่น ทดสอบว่า cookie มี flag ที่ต้องการจริงจาก response header
- ถ้าพบ hallucination ให้จดไว้ในบันทึกของทีม เพื่อให้คนอื่นระวังรูปแบบเดียวกัน
สรุป
- AI แต่งชื่อฟังก์ชัน option และแพ็กเกจได้ เพราะมันทำนายข้อความที่ดูสมเหตุสมผล ไม่ได้ตรวจกับความจริงทุกครั้ง
- Slopsquatting คือการที่ผู้โจมตีจดชื่อแพ็กเกจที่ AI มักแต่ง จึงห้ามติดตั้งตามคำแนะนำโดยไม่ตรวจ
- ตรวจกับเอกสารต้นทางและซอร์สใน vendor ไม่ใช่ถาม AI ซ้ำ
- ให้เครื่องเป็นคนจับด้วย php -l, PHPStan และ test
ลองทำ
นำโค้ดที่ AI เขียนให้คุณในช่วงที่ผ่านมาสักหนึ่งไฟล์ รัน PHPStan ที่ level 5 แล้วนับว่ามี error ที่เกิดจากเมธอด คลาส หรือ property ที่ไม่มีอยู่จริงกี่จุด จากนั้นลองถาม AI ให้แนะนำแพ็กเกจสำหรับงานเฉพาะทางเล็ก ๆ งานหนึ่ง แล้วตรวจทุกชื่อด้วย composer show --available หรือ npm view ก่อน บันทึกว่ามีชื่อไหนที่ไม่มีอยู่จริงบ้าง
ความคิดเห็น (0)
ยังไม่มีความคิดเห็น — เริ่มคุยเป็นคนแรก ถามสิ่งที่สงสัย หรือแชร์ประสบการณ์ของคุณ