Large Language Models ได้เปลี่ยนแปลงการพัฒนาซอฟต์แวร์ไปอย่างมาก แต่พวกมันยังคงมีปัญหากับความท้าทายพื้นฐานที่โปรแกรมเมอร์มนุษย์สามารถจัดการได้อย่างเป็นธรรมชาติ: การเขียนโค้ดที่ต้องสร้างจากขวาไปซ้ายหรือไม่เป็นลำดับ ข้อจำกัดนี้เห็นได้ชัดเจนเป็นพิเศษกับภาษาโปรแกรมเฉพาะทางอย่าง q/kdb+ และ APL ซึ่งใช้การประเมินผลจากขวาไปซ้าย แต่ปัญหานี้ขยายไปไกลกว่าภาษาเฉพาะกลุ่มเหล่านี้
ปัญหาหลักเกิดจากวิธีที่ LLMs ปัจจุบันสร้างข้อความ พวกมันผลิต tokens ตามลำดับจากซ้ายไปขวา ทำให้เป็นเรื่องยากที่จะเขียน expressions ที่ผลลัพธ์สุดท้ายขึ้นอยู่กับการดำเนินการที่ควรเขียนที่ท้ายก่อน สิ่งนี้สร้างปัญหาไม่เพียงแค่กับภาษาที่ทำงานจากขวาไปซ้าย แต่ยังรวมถึงเมื่อทำการ refactoring nested function calls หรือทำงานกับโครงสร้างโค้ดใดๆ ที่ได้ประโยชน์จากการจัดองค์ประกอบแบบไม่เป็นเส้นตรง
ภาษาโปรแกรมมิ่งแบบขวาไปซ้าย:
- q/kdb+: ภาษาสำหรับประมวลผลข้อมูลทางการเงินที่มีการประเมินผลแบบขวาไปซ้าย
- APL: ภาษาโปรแกรมมิ่งแบบ Array ที่สร้างโดย Ken Iverson ผู้ได้รับรางวัล Turing Award
- K: ภาษาที่สืบทอดมาจาก APL โดยมีหลักการประเมินผลที่คล้ายคลึงกัน
- รูปแบบการประเมินผล: ขวาไปซ้ายโดยไม่มีลำดับความสำคัญของตัวดำเนินการ (RL/NOP)
ปัญหาการสร้างแบบลำดับ
โมเดลที่ใช้ transformer ปัจจุบันเก่งในการทำนาย token ถัดไปจาก context ก่อนหน้า แต่วิธีการนี้จะล้มเหลวเมื่อการไหลเชิงตรรกะของการสร้างโค้ดไม่ตรงกับรูปแบบการเขียนจากซ้ายไปขวา นักพัฒนามนุษย์มักจะเริ่มต้นด้วยผลลัพธ์ที่ต้องการและทำงานย้อนกลับ หรือกระโดดไปมาระหว่างส่วนต่างๆ ของ expression ขณะที่พวกเขาสร้างมันขึ้น LLMs ไม่สามารถจำลองพฤติกรรมการเขียนโค้ดตามธรรมชาตินี้ได้
ชุมชนได้ระบุสิ่งนี้เป็นข้อจำกัดทางสถาปัตยกรรมที่กว้างขึ้น เมื่อนักพัฒนาเขียน expressions ที่ซับซ้อน พวกเขามักจะต้องพิจารณาผลลัพธ์สุดท้ายก่อน จากนั้นจึงเติมขั้นตอนกลาง วิธีการสร้างโค้ดแบบ top-down นี้เป็นสิ่งที่โมเดลปัจจุบันไม่สามารถทำได้อย่างมีประสิทธิภาพ
ข้อจำกัดปัจจุบันของ LLM ในการสร้างโค้ด:
- การสร้าง token แบบต่อเนื่องทำให้ไม่สามารถสร้างโค้ดจากขวาไปซ้ายได้
- ประสบปัญหากับภาษาที่ใช้การประเมินผลจากขวาไปซ้าย ( q/kdb+ , APL , K )
- ความยากลำบากในการเขียนโค้ดแบบไม่เป็นเส้นตรงและการปรับปรุงโครงสร้างโค้ด
- ปัญหาเกี่ยวกับการจัดการสถานะแบบซ่อนเร้นที่ซับซ้อน ( Ruby on Rails )
- แนวโน้มในการเพิ่ม import ที่ไม่จำเป็นเป็นพฤติกรรมการป้องกันความเสี่ยง
ทำไมข้อมูลการฝึกอบรมจึงไม่ใช่คำตอบเดียว
แม้ว่าบางคนจะแนะนำว่าข้อมูลการฝึกอบรมเพิ่มเติมสำหรับภาษาเฉพาะทางอาจแก้ปัญหาได้ แต่ปัญหานี้ลึกกว่าการได้รับข้อมูลเพียงอย่างเดียว ลักษณะการทำงานแบบลำดับของสถาปัตยกรรมโมเดลปัจจุบันหมายความว่าพวกมันมีปัญหากับ programming paradigm ใดๆ ที่ต้องการการคิดแบบไม่เป็นเส้นตรง ไม่ว่าจะมีข้อมูลการฝึกอบรมมากแค่ไหนก็ตาม
แม้แต่ภาษายอดนิยมก็แสดงจุดอ่อนนี้ แอปพลิเคชัน Ruby on Rails ที่มีการจัดการ state แบบ implicit ที่ซับซ้อน มักจะทำให้ LLMs สับสนแม้จะมีข้อมูลการฝึกอบรมมากมาย โมเดลเหล่านี้ยังมีแนวโน้มที่จะเพิ่ม imports ที่ไม่จำเป็นใน Python โดยป้องกันความเสี่ยงด้วยการรวม modules ที่พวกมันอาจต้องการในภายหลังในกระบวนการสร้าง
Diffusion Models เป็นทางออกที่มีศักยภาพ
ทางออกที่มีแนวโน้มดีที่สุดที่กำลังถูกหารือคือ diffusion-based language models ต่างจาก sequential generators แบบดั้งเดิม diffusion models เริ่มต้นด้วยข้อความสุ่มและค่อยๆ ปรับแต่งให้เป็นผลลัพธ์ที่สอดคล้องกัน วิธีการนี้สามารถให้โมเดลทำงานกับส่วนต่างๆ ของโค้ดพร้อมกันได้ในทางทฤษฎี โดยแก้ไข dependencies ในลำดับใดก็ตามที่สมเหตุสมผลที่สุด
diffusion-based coding models หลายตัวกำลังเกิดขึ้นแล้ว แม้ว่าพวกมันยังไม่ได้รับการฝึกอบรมเฉพาะเจาะจงเพื่อจัดการกับการประเมินผลจากขวาไปซ้ายหรือการสร้างโค้ดแบบไม่เป็นเส้นตรง สถาปัตยกรรมในทางทฤษฎีรองรับการโฟกัสในพื้นที่ต่างๆ ของโค้ดในเวลาต่างๆ ซึ่งอาจแก้ปัญหาการเขียนแบบย้อนกลับได้
วิธีการทางเลือกและการแก้ไขชั่วคราว
นักพัฒนาบางคนกำลังสำรวจทางออกกลาง เช่น การสร้าง syntax คล้าย Python ที่ compile เป็นภาษาเฉพาะทาง วิธีการนี้ใช้ประโยชน์จากจุดแข็งของ LLMs กับ syntax ที่คุ้นเคย ในขณะที่จัดการลำดับการประเมินผลที่ซับซ้อนผ่านการแปลอัตโนมัติ
บางครั้งฉันเริ่มต้นด้วยข้อมูลและทำงานย้อนกลับผ่าน outer functions โดย unnesting ไปเรื่อยๆ บางครั้งฉันเริ่มต้นด้วย final return และทำงานย้อนกลับไปยัง inputs ฉันสังเกตเห็นว่าบางครั้ง LLMs ควรทำงานแบบนี้ แต่ทำไม่ได้
ทางออกอื่นๆ ที่เสนอรวมถึงการฝึกโมเดลให้สร้าง Abstract Syntax Trees โดยตรง หรือใช้วิธีการฝึกอบรมแบบสองทิศทาง อย่างไรก็ตาม วิธีการเหล่านี้เผชิญกับความท้าทายในทางปฏิบัติเนื่องจากลักษณะที่ใช้ข้อความเป็นหลักของข้อมูลการฝึกอบรมการเขียนโปรแกรมส่วนใหญ่
แนวทางแก้ไขที่เสนอ:
- โมเดลการแพร่กระจาย (Diffusion Models): เริ่มต้นด้วยข้อความแบบสุ่มและปรับปรุงทีละน้อย ทำให้สามารถสร้างโค้ดแบบไม่ต่อเนื่องได้
- แนวทาง Transpilation: ใช้ไวยากรณ์คล้าย Python ที่คอมไพล์เป็นภาษาเฉพาะทาง
- การสร้าง AST: สร้าง Abstract Syntax Trees โดยตรงแทนการสร้างข้อความ
- การฝึกแบบสองทิศทาง: ฝึกโมเดลทั้งไปข้างหน้าและย้อนกลับบนโค้ด
- การปรับปรุง Prompting: ใช้ขั้นตอนการใช้เหตุผลที่ชัดเจนและการใส่คอมเมนต์อย่างละเอียด
มองไปข้างหน้า
ข้อจำกัดนี้เน้นช่องว่างพื้นฐานระหว่างวิธีที่มนุษย์คิดเกี่ยวกับการสร้างโค้ดและวิธีที่โมเดล AI ปัจจุบันทำงาน แม้ว่าจะมีการแก้ไขชั่วคราวสำหรับกรณีการใช้งานเฉพาะ แต่การแก้ไขปัญหาหลักอาจต้องใช้สถาปัตยกรรมโมเดลใหม่ที่สามารถจัดการการสร้างแบบไม่เป็นลำดับได้อย่างเป็นธรรมชาติมากขึ้น
เมื่อ diffusion models ยังคงพัฒนาและอาจรวมการรองรับ structured output อย่างโค้ดได้ดีขึ้น เราอาจเห็นการปรับปรุงที่สำคัญในความสามารถของ LLMs ในการจัดการงานการเขียนโปรแกรมที่ซับซ้อนที่ต้องการการคิดแบบไม่เป็นเส้นตรง จนกว่าจะถึงเวลานั้น นักพัฒนาที่ทำงานกับภาษาเฉพาะทางหรืองาน refactoring ที่ซับซ้อนจะต้องพึ่งพากลยุทธ์การ prompting ที่ระมัดระวังและเครื่องมือแปลกลาง
อ้างอิง: Why LLMs Can't Write q/kdb+: Writing code Right-to-Left