การพัฒนา Agent ที่ขับเคลื่อนด้วยการประเมินผล: วิธีที่ผมเลิกปรับจูน Prompt ตามความรู้สึก

ผมเปลี่ยน Prompt แล้วการรันครั้งถัดมาก็ดูดีขึ้น การเปลี่ยนแปลงนั้นช่วยได้จริง หรือผมแค่โชคดีกันแน่?

เป็นเวลานานที่คำตอบของผมคือ "ผมคิดว่าอย่างนั้น" ผมจะปรับแต่งคำสั่ง รัน pipeline ดูว่ามันสำเร็จ แล้วก็ส่งงานออกไป นี่คือวิศวกรรมที่ใช้ความรู้สึกเป็นหลัก (vibes-based engineering) เกือบทุกคนที่สร้าง Agent ก็ทำแบบนี้ เพราะทางเลือกอื่นนั้นดูเหมือนจะยากเกินไป

แต่ Coding Agent นั้นมีความไม่แน่นอน (non-deterministic) คุณสามารถรันงานเดิมสองครั้งแล้วได้ผลลัพธ์ที่ต่างกัน การรันสำเร็จเพียงครั้งเดียวไม่ได้บอกอะไรคุณเลย คุณไม่สามารถบอกได้ว่าการเปลี่ยนแปลงของคุณได้ผลจริง หรือแค่ทอยลูกเต๋าได้แต้มดี

ผมแก้ปัญหานี้โดยการใช้ระเบียบวินัยแบบ Machine Learning ผมสร้าง Evaluation Framework ขึ้นมาเพื่อครอบคลุมทั้งระบบของผม

นี่คือวิธีการทำงานของ Framework:

• Target: ชุดโค้ดที่คงที่ (frozen codebase) สิ่งนี้จะไม่มีการเปลี่ยนแปลงเพื่อให้คะแนนยังคงนำมาเปรียบเทียบกันได้ • Task: รายการ Benchmark เฉพาะเจาะจงที่มี Prompt และ Oracle • Oracle: การตรวจสอบแบบแน่นอน (deterministic check) ซึ่งเป็น shell commands ที่ต้องผ่านการทดสอบ • Variant: การเปลี่ยนแปลงเฉพาะเจาะจงที่คุณกำลังทดสอบ เช่น Planner ตัวใหม่ • Trial: การรันหนึ่งครั้ง ผมจะรันทุกงานหลายๆ ครั้งเพื่อชดเชยความไม่แน่นอน (randomness)

ผมใช้การให้คะแนนสองประเภทเพื่อตรวจจับความล้มเหลวในรูปแบบที่ต่างกัน:

  • Code Graders (Deterministic): ตรวจสอบอัตราการผ่านการทดสอบ, ต้นทุน, เวลา และการเปลี่ยนแปลงของไฟล์
  • LLM Judge (Probabilistic): โมเดลแยกต่างหากที่ถูกกำหนดไว้ตายตัว เพื่อให้คะแนนคุณภาพของข้อกำหนด (spec quality) และความถูกต้องแม่นยำในการนำไปใช้งาน (implementation fidelity)

Code Graders จะบอกคุณว่าโค้ดรันได้ไหม ส่วน Judge จะบอกคุณว่าโค้ดนั้นดีหรือไม่ คุณจำเป็นต้องมีทั้งคู่

ผมเลิกใช้ค่าเฉลี่ยด้วย เพราะค่าเฉลี่ย (means) มักจะหลอกลวงเราเกี่ยวกับ Agent หากงานหนึ่งสำเร็จ 2 ใน 3 ครั้ง มันอาจจะดูเหมือนโอเค แต่มันไม่น่าเชื่อถือ แทนที่จะทำแบบนั้น ผมใช้ตัวชี้วัดสองตัวแทน:

  • pass@k: Agent ทำสำเร็จอย่างน้อยหนึ่งครั้งหรือไม่? (ความสามารถ - Capability)
  • pass^k: Agent ทำสำเร็จทุกครั้งหรือไม่? (ความน่าเชื่อถือ - Reliability)

การที่ค่า pass^k เพิ่มขึ้นคือชัยชนะที่แท้จริง มันหมายความว่าคุณทำให้ Agent มีความสม่ำเสมอ ไม่ใช่แค่โชคดี

เพื่อทำให้ระบบเฉียบคมอยู่เสมอ ผมจะเพิ่มงานที่ยากซึ่งต้องใช้ความเข้าใจอย่างลึกซึ้ง เมื่อ Agent ล้มเหลวกับบั๊กที่เกิดขึ้นจริง ผมจะเปลี่ยนความล้มเหลวนั้นให้กลายเป็นงานถาวร สิ่งนี้สร้างวงจรปิด (closed loop) ขึ้นมา โดย Benchmark จะยากขึ้นเรื่อยๆ เมื่อ Agent เก่งขึ้น

โครงสร้างพื้นฐานนี้ต้องใช้แรงเยอะมาก แต่มันคือสิ่งที่สร้างผลลัพธ์ได้คุ้มค่าที่สุด (highest leverage) ที่ผมเคยสร้างมา มันเปลี่ยนจากคำว่า "ผมคิดว่าอันนี้ดีกว่า" เป็น "อันนี้มีความน่าเชื่อถือเพิ่มขึ้น 20% ในต้นทุนที่ต่ำลง"

Coding Agent นั้นสาธิต (demo) ได้ง่าย แต่สร้างความเชื่อมั่นได้ยาก หากคุณต้องการก้าวข้ามแค่การสาธิต คุณต้องตัดสินใจที่จะวัดผล

Source: https://dev.to/rickjms/eval-driven-agent-development-how-i-stopped-tuning-prompts-on-vibes-1189

Optional learning community: https://t.me/GyaanSetuAi