ทำไมการทดสอบจึงสำคัญ

ผู้ช่วยเขียนโค้ดที่ขับเคลื่อนด้วย AI มักจะปล่อยให้ทีมวางไฟล์ "rules" ไว้ใน repo และคาดหวังว่าโมเดลจะปฏิบัติตามคำสั่งในทุกๆ คำขอ ในทางปฏิบัติ โมเดลอาจจะไม่เห็นไฟล์นั้นเลย หรืออาจจะเห็นแต่เพิกเฉยต่อเนื้อหาภายใน การทดลองล่าสุดกับ Claude Code แสดงให้เห็นถึงปัญหาทั้งสองประการนี้ เครื่องมือนี้ข้ามไฟล์ AGENTS.md ขนาด 72 KB ไปโดยไม่แจ้งให้ทราบ แต่เมื่อเปลี่ยนชื่อไฟล์เดียวกันเป็น CLAUDE.md ผู้ช่วยกลับโหลดไฟล์นั้นขึ้นมาและทำให้จำนวนโทเคนในแต่ละคำขอเพิ่มสูงขึ้น งบประมาณโทเคนส่วนเกินนั้นทำให้ความหน่วง (latency) และค่าใช้จ่ายเพิ่มขึ้น และอาจทำให้คำขอเกินขีดจำกัดของโมเดลได้

นักพัฒนาที่ทึกทักเอาเองว่า "การมีไฟล์อยู่" เท่ากับ "โมเดลปฏิบัติตามกฎ" กำลังเสี่ยงต่อความไร้ประสิทธิภาพที่ซ่อนอยู่และผลลัพธ์ที่คาดเดาไม่ได้ การทดสอบสามขั้นตอนจะบังคับให้ต้องมีหลักฐานที่เป็นรูปธรรมในแต่ละขั้นตอน ได้แก่: การตั้งค่า (configuration), การโหลด (loading) และประโยชน์ที่ได้รับ (usefulness)

สามคำถามที่ต้องถาม

  1. Configured (การตั้งค่า) – ไฟล์ถูกวางไว้ในจุดที่ผู้ช่วยมองหาหรือไม่? เครื่องมือแต่ละชนิดมีการกำหนดเส้นทาง (path) หรือรูปแบบชื่อไฟล์ที่ตายตัว หากไม่ตรงกัน ไฟล์นั้นก็จะไม่ถูกส่งเข้าไปในกระบวนการสร้าง prompt
  2. Loaded (การโหลด) – ผู้ช่วยแสดงหลักฐานใดๆ หรือไม่ว่าได้รับไฟล์แล้ว? ค่าแฮช (hash) สามารถยืนยันตัวตนของไฟล์บนดิสก์ได้ แต่มีเพียงร่องรอยการส่งข้อมูล (delivery trace) เช่น บรรทัดใน log หรือจำนวนโทเคน เท่านั้นที่พิสูจน์ได้ว่าโมเดลได้อ่านไฟล์นั้นจริงๆ
  3. Useful (ประโยชน์ที่ได้รับ) – การมีไฟล์อยู่ช่วยให้ผลลัพธ์ของงานดีขึ้นหรือไม่? ไฟล์ที่ถูกโหลดขึ้นมาแต่เพิ่มจำนวนโทเคนโดยไม่ทำให้ผลลัพธ์เปลี่ยนแปลง ถือเป็นการเสียประโยชน์สุทธิ

การทดสอบ

ขั้นตอนการทดสอบถูกออกแบบมาให้เรียบง่ายที่สุดเพื่อให้สามารถทำซ้ำได้ในทุกแพลตฟอร์ม

  1. สร้างกฎที่สังเกตเห็นได้ – เขียนคำสั่งที่เรียบง่ายและสังเกตเห็นผลได้ ตัวอย่างเช่น: “แสดงรายชื่อไฟล์เพียงสองไฟล์ก่อนทำการแก้ไข” ผลลัพธ์ของกฎนี้สามารถตรวจสอบได้จากคำตอบของผู้ช่วย

  2. ตรวจสอบเวอร์ชันของเครื่องมือและโมเดล – เปิดเซสชันใหม่ จดบันทึกข้อความเวอร์ชันและตัวระบุโมเดล (model identifier) เวอร์ชันที่ต่างกันอาจมีการจดจำชื่อไฟล์ที่ต่างกันออกไป

  3. ดำเนินการทดสอบสองรอบ Run A: ใช้ชื่อไฟล์ที่เครื่องมือ ไม่ รู้จัก (เช่น AGENTS.md) Run B: ใช้ชื่อไฟล์มาตรฐานของเครื่องมือ (เช่น CLAUDE.md)

    บันทึกข้อมูลดังนี้:

    • ค่าแฮชต้นทางของไฟล์ (เพื่อพิสูจน์ว่าเนื้อหาบนดิสก์ไม่ได้เปลี่ยนแปลง)
    • เส้นทาง (path) ที่ใช้จริง
    • หลักฐานใดๆ ที่ผู้ช่วยบันทึกไว้เกี่ยวกับการโหลดไฟล์ (เช่น จำนวนโทเคนที่เพิ่มขึ้น, ข้อความ “loaded X.md” ที่ชัดเจน เป็นต้น)
    • จำนวนโทเคนในแต่ละคำขอ
    • ผลลัพธ์ของงาน (ผู้ช่วยแสดงรายชื่อไฟล์เพียงสองไฟล์ตามที่สั่งหรือไม่?)

หาก Run B แสดงให้เห็นว่ามีการปฏิบัติตามกฎและจำนวนโทเคนเพิ่มขึ้นตามที่คาดไว้ แสดงว่าไฟล์นั้นถูกโหลดและมีประโยชน์ แต่หากกฎถูกเพิกเฉยแม้จำนวนโทเคนจะเพิ่มขึ้น แสดงว่าไฟล์ถูกอ่านแล้วแต่การประมวลผล prompt ของโมเดลได้ตัดคำสั่งนั้นทิ้ง ในกรณีนี้ การเพิ่มข้อความลงในไฟล์จะไม่ช่วยอะไร ควรย้ายกฎไปไว้ที่ policy gate ที่กำหนดไว้ตายตัวหรือใช้ test harness แทน

สิ่งที่ข้อมูลเผยให้เห็น

กรณีของ Claude Code แสดงให้เห็นถึงช่องว่างที่ชัดเจนระหว่างการตั้งค่าและการโหลด ไฟล์ขนาด 72 KB มีอยู่จริง มีค่าแฮชที่ถูกต้อง และถูกซิงค์ไปยัง repository แล้ว แต่ผู้ช่วยกลับไม่เคยอ้างอิงถึงไฟล์นั้นเลย การเปลี่ยนชื่อไฟล์เป็น CLAUDE.md ซึ่งเป็นชื่อมาตรฐานทำให้เกิดการโหลดไฟล์ขึ้นมา แต่ก็เพิ่มภาระด้านโทเคน (token overhead) อย่างมาก โทเคนส่วนเกินแต่ละตัวจะใช้รอบการประมวลผล (compute cycles) และอาจทำให้คำขอเกินขีดจำกัดอัตราการใช้งาน (rate limits) ได้

การทดสอบสามขั้นตอนช่วยเผยให้เห็นต้นทุนที่ซ่อนอยู่เหล่านี้ก่อนที่จะกลายเป็นอุปสรรคในการใช้งานจริง (production blockers) การบันทึกส่วนต่างของโทเคน (token delta) จะช่วยให้ทีมตัดสินใจได้ว่าประโยชน์ของกฎนั้นคุ้มค่ากับราคาที่ต้องจ่ายหรือไม่

บทสรุป

อย่าทึกทักเอาเองว่าไฟล์กฎกำลังทำงานอยู่เพียงเพราะมันอยู่ใน repo จงใช้การทดสอบสามขั้นตอน—ตั้งค่า (configure), โหลด (load), พิสูจน์ประโยชน์ (prove usefulness)—เพื่อเปลี่ยนข้อสันนิษฐานนั้นให้เป็นหลักฐานที่วัดผลได้ เมื่อหลักฐานแสดงให้เห็นว่าไฟล์เป็นเพียงแหล่งสิ้นเปลืองโทเคน (token sink) ให้ย้ายตรรกะนั้นออกจาก prompt ไปไว้ใน deterministic gate แทน ผลลัพธ์ที่ได้คือเวิร์กโฟลว์การเขียนโค้ดด้วย AI ที่กระชับ รวดเร็ว และคาดเดาได้มากขึ้น