- การใช้งาน LLM อย่างมีประสิทธิภาพในโค้ดเบสขนาดใหญ่ จำเป็นต้องลงทุนกับ ‘การชี้นำ(guide)’ และ ‘การกำกับดูแล(oversight)’ เป็นหลัก
- การชี้นำให้บริบทและสภาพแวดล้อม เพื่อช่วยให้ LLM ตัดสินใจได้ดีขึ้น ขณะที่ การกำกับดูแลมีหน้าที่ตรวจสอบผลลัพธ์และชี้ทิศทาง
- การสร้าง ไลบรารีพรอมป์ต์ เพื่อให้ LLM เข้าใจกฎ เอกสาร และแนวปฏิบัติที่ดีของโค้ดเบสเป็นสิ่งสำคัญ
- การจัดการ technical debt และการทำให้โครงสร้างโค้ดเรียบง่าย เป็นโมดูล และสม่ำเสมอ เชื่อมโยงโดยตรงกับการเพิ่มความเข้าใจโค้ดและประสิทธิภาพการทำงานของ LLM
- ระบบกำกับดูแลและตรวจสอบแบบอัตโนมัติ คือหัวใจของการขยายระบบในระยะยาว เพื่อช่วยให้ LLM สร้างโค้ดที่ปลอดภัยและสอดคล้องกัน
แนวคิดหลักสำหรับการขยาย LLM
- แม้วิธีนำ LLM ไปใช้กับโค้ดเบสขนาดใหญ่จะยังไม่ถูกกำหนดตายตัว แต่มีการเสนอว่า การลงทุนกับการชี้นำและการกำกับดูแล คือแนวทางที่ได้ผลที่สุด
- การชี้นำ(Guidance) หมายถึงบริบทและสภาพแวดล้อมที่ช่วยให้ LLM เลือกได้อย่างถูกต้อง ส่วน การกำกับดูแล(Oversight) มีหน้าที่ตรวจสอบผลลัพธ์ที่สร้างขึ้นและปรับทิศทาง
การลงทุนด้านการชี้นำ
- หากต้องการให้ LLM สร้างโค้ดคุณภาพสูงได้ในครั้งเดียว หรือ ‘one-shotting’ จำเป็นต้องมีการชี้นำที่ชัดเจน
- ในทางกลับกัน หากผลลัพธ์ไม่เหมาะสมจนต้องแก้ไขด้วยมือ จะกลายเป็น rework ที่ไม่มีประสิทธิภาพ
- เพราะ LLM เป็นผู้สร้างทุกทางเลือกในโค้ดขึ้นมาเองทั้งหมด ไม่ว่าจะเป็นชื่อตัวแปร โครงสร้างฟังก์ชัน หรือเทคโนโลยีสแต็ก ดังนั้นจึงเหมาะที่สุดหาก พรอมป์ต์มีเพียงความต้องการทางธุรกิจ ส่วนที่เหลือสามารถอนุมานได้หรือถูกเข้ารหัสไว้แล้ว
การสร้างไลบรารีพรอมป์ต์
- ไลบรารีพรอมป์ต์ คือชุดบริบทสำหรับ LLM ที่รวมเอกสารของโค้ดเบส แนวปฏิบัติที่ดี และแผนผังเชิงโครงสร้าง
- ทุกครั้งที่ผลลัพธ์ของ LLM ออกนอกทาง ควรทบทวนว่า “มีอะไรที่ควรทำให้ชัดเจนกว่านี้” แล้วเพิ่มสิ่งนั้นเข้าไปในไลบรารี
- การรักษา สมดุลระหว่างความครอบคลุมกับความกระชับ เป็นสิ่งสำคัญ
- ในตัวอย่าง มีการส่งเอกสารอย่าง
@prompts/How_To_Write_Views.md, @prompts/The_API_File.md ให้ LLM เพื่อชี้นำการพัฒนาฟีเจอร์
- พรอมป์ต์ควรเฉพาะเจาะจงเพียงพอ แต่ก็ยังต้อง ตรวจทานทุกบรรทัดของโค้ดที่สร้างขึ้น
สภาพแวดล้อมและคุณภาพโค้ด
- โค้ดเบสที่มี technical debt จำนวนมากจะลดประสิทธิภาพการใช้ LLM
- มีการกล่าวถึงกรณีของ Meta ว่า technical debt ทำให้บรรลุเป้าหมายด้านอัตโนมัติได้ยาก
- โค้ดที่สะอาด การแยกเป็นโมดูล การตั้งชื่อที่ชัดเจน และโครงสร้างที่เรียบง่าย จะช่วยเพิ่มความเข้าใจและความแม่นยำของ LLM
- ในตัวอย่าง Django มีการกำหนดให้แต่ละแอปมีจุดเข้าใช้งานผ่านไฟล์
_api.py เพื่อ จัดโครงสร้างให้ LLM หาฟังก์ชันที่ต้องการได้อย่างรวดเร็ว
- ตัวอย่างเช่น
visit_api.handoff_to_doctor(user) เป็นการรวมการเข้าถึงจากภายนอกไว้ที่จุดเดียว
- มีการระบุแพตเทิร์น
_api ไว้ในไลบรารีพรอมป์ต์ เพื่อชี้นำให้ LLM อ้างอิงตำแหน่งที่ถูกต้อง
การลงทุนด้านการกำกับดูแล
- การทำงานอัตโนมัติด้วย LLM ควรถูกมองในมุมของ การเสริมศักยภาพทีม มากกว่าการแทนที่วิศวกร
- การกำกับดูแลนำไปสู่การลงทุนใน ทีม การจัดแนว(alignment) และเวิร์กโฟลว์
- ในระดับทีม การพัฒนาความสามารถด้านการออกแบบ เป็นเรื่องสำคัญ และสิ่งนี้เชื่อมต่อไปยังคุณภาพของสถาปัตยกรรม
- วิธี เสริมทักษะด้านการออกแบบ ที่เสนอไว้ ได้แก่ การอ่านหนังสือ บล็อก และโค้ด การคัดลอกงานชั้นครู และการฝึกลงมือสร้างด้วยตนเอง
- ตัวอย่างเช่น การวิเคราะห์โค้ดของ TLDraw, SerenityOS Jakt เพื่อขยายสัญชาตญาณด้านการออกแบบ
การกำกับดูแลแบบอัตโนมัติ
- การตรวจสอบความถูกต้องของงานออกแบบบางส่วนสามารถ ทำให้เป็นอัตโนมัติด้วยโปรแกรม ได้
- ตัวอย่างเช่น ให้สภาพแวดล้อมส่ง feedback ทันทีเมื่อเกิด type error หรือการละเมิดกฎ
- ‘ความปลอดภัย(safety)’ คือการปกป้อง abstraction
- ตามนิยามของ Pierce ภาษาที่ปลอดภัยจะรับประกันว่าโปรแกรมเมอร์จะไม่ทำลาย abstraction โดยไม่ได้ตั้งใจ
- ตัวอย่าง: ทำกฎห้ามเข้าถึงไฟล์ภายในของ Django app โดยตรงระหว่างแอปต่าง ๆ ให้เป็นอัตโนมัติด้วย สคริปต์ตรวจสอบบนพื้นฐาน AST
- ใช้เพื่อตรวจจับการเข้าถึงที่ผิดกฎในรูปแบบ
from visit import logic.internal_file
การตรวจสอบ(Verification)
- นอกเหนือจากการออกแบบและการพัฒนาแล้ว ขั้นตอนการตรวจสอบ เช่น code review และ QA ก็จำเป็นต่อการรักษาคุณภาพ
- เมื่อปริมาณงานเพิ่มขึ้น ความเร็วในการตรวจสอบจะกลายเป็นคอขวด จึงมีข้อเสนอแนวทางปรับปรุงดังนี้
- ลดอุปสรรคในการทำ QA เพื่อให้สามารถทดสอบได้แม้ไม่มีสภาพแวดล้อมการพัฒนา
- สร้างสภาพแวดล้อมที่ทำให้ การเขียนเทสต์ง่ายขึ้น เช่น การสร้างข้อมูลทดสอบ
- จัดทำเอกสาร feedback ใน PR ที่เกิดซ้ำ เพื่อให้ LLM ช่วยทำรีวิวบางส่วนแบบอัตโนมัติ ได้
- ฝังกฎความปลอดภัยไว้เป็นค่าเริ่มต้นของเฟรมเวิร์ก
บทสรุปและข้อสังเกตเพิ่มเติม
- LLM ทำงานได้ดีเป็นพิเศษกับ โปรเจกต์ใหม่(greenfield)
- เพราะยังไม่มีบริบทเดิม และมีความต้องการด้านความสม่ำเสมอน้อยกว่า
- ยิ่งโปรเจกต์ใหญ่ขึ้น ความสม่ำเสมอและการแยกเป็นโมดูล จะยิ่งเป็นตัวกำหนดประสิทธิภาพการทำงาน
- โครงสร้างแบบโมดูลที่นำองค์ประกอบที่ผ่านการตรวจสอบแล้วกลับมาใช้ซ้ำ คือหัวใจของการพัฒนาอย่างมีประสิทธิภาพ
1 ความคิดเห็น
ความเห็นจาก Hacker News
เมื่อโมเดลดีขึ้นเรื่อย ๆ ก็เริ่มจัดการกับ codebase ที่ซับซ้อนหรือไฟล์ยาว ๆ ได้
เลยทำ framework loop แบบง่าย ๆ ที่ใช้ซ้ำขึ้นมา
ถ้าปล่อยให้ลูปนี้ทำงานสัก 20~30 นาที ก็ได้ผลลัพธ์ที่ใช้ได้พอสมควร สุดท้ายหัวใจสำคัญคือการจัดการ context และการทำ test feedback loop
ถ้าเริ่มสำรวจด้วยคีย์เวิร์ด “explore” ก็ทำ Research ได้โดยไม่ต้องเขียนแผนแยกหรือรีเซ็ต context
แต่ก็มักจะสมมติว่าภาษาโค้ดเป็น C หรือ Python เลยชอบสร้าง โค้ดที่ไม่มีโครงสร้าง เช่น แยกเป็นฟังก์ชันห้าตัวแทนที่จะห่อสถานะไว้ใน object
อีกอย่างคือ claude มักจะไม่สนใจ CLAUDE.md ดังนั้นถ้าให้มันอ่านไฟล์นั้นก่อนแล้วค่อยสั่ง “explore” จะเสถียรกว่า
โมเดลรุ่นใหม่ทิ้ง context ที่ไม่จำเป็นได้ดี แต่โมเดลเก่า ๆ บางครั้งวิธีที่อิงเอกสารแผนก็ยังดีกว่า
มันมักทำตามแผนและ guideline แบบตรงข้าม หรืออ่านประโยคเดิมซ้ำแล้วยังสรุปกลับด้าน
ช่วงหนึ่งเคยเชื่อว่าสามารถสร้าง process ที่มี LLM เป็นศูนย์กลางได้ แต่ตอนนี้มั่นใจน้อยลงแล้ว
ตอนที่โมเดลอยู่ใน “สภาพที่ดี” มันก็โอเค แต่การทำให้มันอยู่ในสภาพนั้นยังคง ขึ้นกับดวง
เพิ่ม คำสั่งแบบกำหนดเอง อย่าง
/research_codebase,/create_plan,/implement_planเข้าไปใน Claude Codeถ้าตรวจรีวิวและแก้ให้ละเอียดมันทำงานได้ดีมาก แต่ก็ยังขยายไปใช้ทั้งทีมไม่ได้
จะรีเซ็ต context ก็ต่อเมื่อทำฟีเจอร์ใหม่ทั้งหมดเท่านั้น ใน Codespaces ใช้ได้โอเค แต่ฟีเจอร์ Tasks แทบไม่มีประโยชน์
ถ้าสั่งงานใหญ่ ๆ มันก็อาจหลงทางได้ เลยต้อง คอยเฝ้าดูตลอด
ยังมีประโยชน์กับ การ re-prime context ด้วย เลยใช้บ่อยมาก
ถ้าจะทำให้ prompt library มีประโยชน์จริง ต้องมี การปรับปรุงแบบวนซ้ำ
ทุกครั้งที่ LLM คลาดไปนิดหนึ่ง ฉันจะถามตัวเองว่า “มีอะไรที่ควรทำให้ชัดกว่านี้ไหม?” แล้วเอาคำตอบไปเพิ่มใน prompt
ถ้าแค่กด enter อย่างเดียวหรือ auto-approve ก็มีแต่เปลือง token ควรสังเกตแทนว่า LLM ติดตรงไหน แล้วจดสั้น ๆ ลงใน CLAUDE.md
ถ้าไฟล์ context ใหญ่เกินไปก็แยกตามประเภทงาน
use case หลักของฉันคือการสำรวจ codebase, ตามรอย execution path และสรุปไฟล์ที่จำเป็นให้ ถ้าระบุ รูปแบบการส่งผลลัพธ์ ตามประเภทคำถามไว้ จะมีประสิทธิภาพขึ้นมาก
ฉันเรียกสิ่งนี้ว่า “Student Pattern (Fresh Eyes)” เป็นวิธีที่ subagent อ่านเอกสารหรือโค้ดด้วยสายตาแบบมือใหม่แล้วหา จุดที่สับสน ความขัดแย้ง หรือข้อมูลที่ขาดหาย
มันเก่งมากในการจับความรู้โดยนัยที่นักพัฒนามักมองข้าม มีประโยชน์มากเป็นขั้นก่อนหน้าการรีวิวเอกสารใหม่หรือประเมิน prompt
ต่อให้สั่งให้มันอ่าน CLAUDE.md หลายรอบ มันก็มักจะเมิน และแม้แต่ช่วงเริ่ม session ใหม่ก็ยังหลุดแบบสุ่ม
ต่อให้เตรียมเอกสารกับคำสั่งครบแล้ว มันก็ยัง “ลืม” อยู่บ่อย ๆ
กำลังทดลอง จัดโครงสร้างให้ codebase เป็นมิตรกับ agent มากขึ้น
แยกโปรเจกต์ออกเป็น กราฟมีทิศทาง บนพื้นฐาน nix flakes โดยให้แต่ละ node มี development environment ของตัวเองแบบอิสระ
ถ้ารัน Claude Code ใน flake devshell มันจะมองเห็นเฉพาะขอบเขตนั้น จึงช่วยกัน context overload ได้
ให้แต่ละ flake ร่วมงานกันผ่าน input/output และส่งคำขอฟีเจอร์กับการทดสอบหากัน
ฉันคิดว่า การแบ่ง context แบบนี้คือกุญแจในการลดปัญหา token พุ่ง
แทนที่จะเอาแต่ปรับ workflow เดิม เราน่าจะต้องออกแบบโครงสร้างใหม่ที่ LLM ขยายต่อได้ง่าย
กำลังสำรวจความสัมพันธ์ระหว่างคุณสมบัติอย่าง “ความทดสอบได้ ความขยายได้ ความปลอดภัย” กับโครงสร้างโค้ด
ฉันเองก็เคยทดลองคล้าย ๆ กันในโปรเจกต์ที่ใช้ Docker และอยากให้มีเครื่องมือที่ช่วยทำสิ่งนี้แบบอัตโนมัติ
LLM อธิบายหัวข้อที่ฉันไม่ค่อยรู้ได้ดีมาก แต่พอเป็น สาขาที่เชี่ยวชาญ กลับผิดแบบมั่นใจ
ฉันมองอีกแบบ วิธีที่ดีที่สุดในการเพิ่มประสิทธิภาพ LLM คือ ฝังความหมายไว้ในตัว codebase เอง
กล่าวคือ โค้ดที่มีโครงสร้างแบบ DDD(Domain-Driven Design) จะอ่านเข้าใจง่ายสำหรับ LLM ด้วย
การพยายามฝืนใช้เครื่องมือไปจัดการโค้ดซับซ้อนคือ การเสียเงินเปล่า
ท้ายที่สุด สิ่งที่ LLM พิสูจน์ก็คือแนวคิด DDD ที่เน้น “ภาษาและความหมาย” นั้นถูกต้อง
บทความที่เกี่ยวข้อง: DDD & the Simplicity Gospel
สำหรับคำถามว่า “ทำไม LLM ถึงทำงานได้ดีใน โปรเจกต์ greenfield?” ฉันกลับมีประสบการณ์ตรงกันข้าม
ถ้าใน codebase มีแพตเทิร์นซ้ำสัก 2~3 ครั้ง LLM จะเรียนรู้แล้วคัดลอกอย่างสม่ำเสมอ
แต่ “ความสม่ำเสมอ” ไม่ได้แปลว่า “คุณภาพ” ถ้าไล่ตามแค่ความสม่ำเสมอโดยไม่มีมาตรฐาน สุดท้ายจะกลายเป็น โค้ดที่บำรุงรักษาไม่ได้
คำพูดที่ว่า “โค้ดที่วิศวกรไม่เข้าใจ LLM ก็ไม่เข้าใจ” นั้นจริง แต่กลับกันไม่จริงเสมอไป
หลายครั้งมนุษย์เข้าใจได้ แต่ agent กลับไม่เข้าใจ
การทำให้ codebase เข้าใจง่ายสำหรับ agent ยากกว่าการทำให้มนุษย์เข้าใจ
ยังมีคนบอกว่า “ถ้าย้าย feedback ไปให้คอมพิวเตอร์ โอกาสสำเร็จแบบ one-shot จะสูงขึ้น” แต่ฟังดูคล้ายการอ้างว่า P=NP
การตรวจสอบง่าย ไม่ได้แปลว่าการหาคำตอบจะง่าย
ภาษาอย่าง ATS หรือ Idris สามารถเขียน การพิสูจน์ความถูกต้อง ไปพร้อมกับโค้ดได้
ถ้าข้ออ้างนั้นจริง LLM ก็ควรทำผลงานได้ดีที่สุดในภาษาเหล่านี้
แต่ความจริงไม่ใช่แบบนั้น สุดท้ายตอนนี้ฉันคิดว่า รอให้โมเดลดีกว่านี้ ยังจะเหมาะกว่า
เพราะปัญหาแบบนี้ ฉันเลยคิดว่า framework ที่มีแนวทางชัดเจน จะช่วยเพิ่ม productivity ของการเขียนโค้ดด้วย AI
เพราะ LLM รู้กฎของ framework อยู่แล้ว จึงไม่ต้องมี guideline เพิ่มเติม
แต่ Go, Rust, Elixir, C# ต้องใช้ dependency และคำสั่งมากกว่ามาก
Rust ให้ผลลัพธ์ดี แต่ดึงแพ็กเกจมาเกิน 200 ตัว จนกลายเป็นภาระมาก
หลัก “Garbage in, garbage out” ก็จริง แต่ใช้กับ LLM ไม่ได้ทั้งหมด
ถึงจะฝึกจาก ข้อมูลที่มี noise ของทั้งอินเทอร์เน็ต มันก็ยังทำงานได้ค่อนข้างดี
ภาพหลอน (hallucination) เกิดจาก context ที่ไม่แม่นยำ บ่อยกว่าจาก noise ธรรมดา
ต่อให้ codebase โครงสร้างเละ แต่ถ้ามีข้อมูลเยอะ ก็ยังให้ context ที่มีประโยชน์ได้
สุดท้ายแล้วผู้คนก็กำลังกลับไปเรียนรู้หลักพื้นฐานกันใหม่
เริ่มตระหนักอีกครั้งว่าเอกสารประกอบ (=prompt library) และ โครงสร้างโค้ดที่เป็นระเบียบ ช่วยให้พัฒนาได้เร็วขึ้น