การเขียนตัวแยกวิเคราะห์ Recursive Descent ใหม่ให้ pycparser ด้วยเอเจนต์เขียนโค้ด LLM
(eli.thegreenplace.net)สรุป:
- กล่าวถึงกระบวนการแทนที่ตัวแยกวิเคราะห์ภาษา C ของ
pycparserซึ่งทำงานบนพื้นฐานของ PLY (Python Lex-Yacc) มาเกือบ 20 ปี ด้วยตัวแยกวิเคราะห์แบบ Recursive Descent ที่เขียนด้วยมือทั้งหมด โดยอาศัยเอเจนต์เขียนโค้ด LLM (Codex) - ผลลัพธ์ที่ได้คือการตัดการพึ่งพาภายนอก (PLY) ลดความยากในการบำรุงรักษา และเพิ่มประสิทธิภาพขึ้น 30% พร้อมพิสูจน์ความเป็นประโยชน์เชิงปฏิบัติของ LLM ในการรีแฟกเตอร์โค้ดเลกาซีขนาดใหญ่
- เน้นความสำคัญของการทบทวนซ้ำโดยนักพัฒนามนุษย์และการทำ prompt engineering เพื่อแก้ปัญหาคุณภาพของโค้ดที่ LLM สร้างขึ้น (เช่น ความอ่านง่าย ความซับซ้อน เป็นต้น)
สรุปแบบละเอียด:
- ภูมิหลังและแรงจูงใจ
pycparserเป็นโครงการโอเพนซอร์สสำคัญที่มียอดดาวน์โหลดราว 20 ล้านครั้งต่อวัน เดิมใช้ไลบรารี PLY เพื่อจัดการไวยากรณ์ C99 แต่เมื่อเวลาผ่านไปก็มีปัญหาสะสมดังนี้:
- ปัญหาการพึ่งพา: ไลบรารี PLY ถูกยุติการดูแลแล้ว (Archived) ทำให้เกิดความเสี่ยงด้านความปลอดภัยและการบำรุงรักษา
- ความซับซ้อนของไวยากรณ์: เมื่อรองรับมาตรฐานใหม่อย่าง C11, C23 และไวยากรณ์ส่วนขยายต่าง ๆ ความขัดแย้งแบบ reduce-reduce อันเป็นลักษณะเฉพาะของ YACC ก็เกิดบ่อยขึ้น ทำให้การขยายความสามารถทำได้ยาก
- การเปลี่ยนแปลงทางแนวคิด: เมื่อเวลาผ่านไป ผู้เขียนยิ่งมั่นใจว่าตัวแยกวิเคราะห์แบบ Recursive Descent ที่เขียนเองมีข้อได้เปรียบกว่าตัวสร้าง parser ทั้งในด้านความเข้าใจและการบำรุงรักษา
- กระบวนการทำงานร่วมกับ LLM (Codex)
ผู้เขียนตัดสินใจมอบงานนี้ให้ LLM แทนการทำเอง ซึ่งคาดว่าจะใช้เวลามากกว่าหนึ่งสัปดาห์ ชุดทดสอบที่แข็งแรงของpycparserซึ่งมีมากกว่า 2,500 บรรทัด ทำหน้าที่เป็น "ราวกันตก" สำหรับตรวจสอบผลลัพธ์ของ LLM
- การย้ายระบบช่วงแรก: เมื่อได้รับพรอมป์ต์ว่า "คง lexer ไว้ แล้วเปลี่ยนเฉพาะ parser เป็น Recursive Descent" Codex ใช้เวลาทำงานกว่าหนึ่งชั่วโมงและสร้างต้นแบบที่ผ่านการทดสอบได้
- การปรับปรุงแบบวนซ้ำ: โค้ดเริ่มต้นแม้จะสมบูรณ์ในเชิงการทำงาน แต่ยังอ่านยาก และมีการใช้ exception เกินความจำเป็นเพื่อควบคุมการไหลของโปรแกรม ทำให้คุณภาพโดยรวมยังไม่น่าพอใจ ผู้เขียนใช้
Gitbranch อย่างเต็มที่และค่อย ๆ ขัดเกลาโค้ดผ่านการคอมมิตหลายสิบครั้ง
- ผลลัพธ์และบทเรียน
- ประสิทธิภาพดีขึ้น: parser ที่เขียนด้วยมือตัวใหม่นั้นทำงานเร็วกว่าแบบเดิมที่อิง YACC ราว 30%
- คุณภาพโค้ดและการบำรุงรักษา: LLM มีแนวโน้มจะเขียนโค้ดแบบขี้เกียจหรือซับซ้อนเกินจำเป็น แต่เมื่อผู้พัฒนาให้คำสั่งที่ชัดเจน (เช่น "เปลี่ยน X เป็น Y", "เพิ่มคอมเมนต์") ก็สามารถตอบสนองได้อย่างมีประสิทธิภาพ
- ความสำคัญของ static typing: ในงานต่อมา เมื่อเพิ่ม Type Annotation ของ Python เข้าไป ความแม่นยำของข้อเสนอจาก LLM ก็สูงขึ้น ผู้เขียนคาดการณ์ว่าเอเจนต์เขียนโค้ดในอนาคตจะยิ่งทำผลงานได้โดดเด่นในภาษาที่มีชนิดข้อมูลเข้มงวดอย่าง Rust หรือ TypeScript
- บทสรุป
ผู้เขียนยืนยันผ่านโครงการนี้ว่า LLM ไม่ใช่ของเล่นธรรมดา แต่เป็นเครื่องมือที่ช่วยเพิ่มผลิตภาพได้มากกว่า 10 เท่า งานที่เดิมอาจต้องใช้เวลาประมาณ 30–40 ชั่วโมง กลับเสร็จได้ในเพียง 4–5 ชั่วโมง และยังประเมินว่า LLM มีคุณค่าอย่างมากในฐานะตัวเร่งให้ผู้พัฒนาเข้าสู่ภาวะการทำงานแบบลื่นไหล (Flow) ได้
1 ความคิดเห็น
แค่คิดตั้งแต่แรกว่าจะทำงานนั้นให้เสร็จภายใน 30~40 ชั่วโมงก็ระดับเซียนจัดแล้ว...