เริ่มด้วย eval set เล็กๆ
บทที่แล้วเราได้เครื่องมือตัดสินมาสองแบบ — ตัวเช็คแบบ deterministic กับ LLM-as-judge ที่ต้อง calibrate ก่อนถึงจะเชื่อถือได้ แต่เครื่องมือตัดสินไม่มีค่าอะไรเลยถ้าไม่มีเคสให้ตัดสิน คำถามของบทนี้คือ: จะเริ่มสร้างชุดเคสวัดผลจากตรงไหน สัญชาตญาณแรกของทีมส่วนใหญ่คือ “ขอรวบรวมให้ครบเป็นร้อยเคสก่อนค่อยเริ่ม eval” — ซึ่งเป็นกับดักที่ทำให้ไม่ได้เริ่มสักที ข้อเสนอของบทนี้ตรงข้าม: เริ่มเล็ก เริ่มจากของจริง เริ่มวันนี้
บทนี้เดินเรื่องด้วย ops-copilot agent ที่คืนเงินออเดอร์ใน domain Order จาก repo kaen-food-ordering (กำลังจัดทำ) — เป็นบทเชิงวิธีการ สเก็ตช์ dataset ที่เห็นเป็นภาพร่างของโครงเคสวัดผล เพื่อสื่อไอเดีย ไม่ใช่ eval harness ที่รันได้ทันที
20–50 เคสจากความล้มเหลวจริง คือจุดเริ่มที่ดี
หัวข้อที่มีชื่อว่า “20–50 เคสจากความล้มเหลวจริง คือจุดเริ่มที่ดี”Anthropic พูดตรงๆ ว่า “20-50 simple tasks drawn from real failures is a great start” — เคสง่ายๆ 20–50 เคสที่ดึงมาจากความล้มเหลวจริงคือจุดเริ่มที่ดีมาก (ดู Anthropic, “Demystifying evals for AI agents”) ชุดเคสเริ่มต้นแบบนี้แหละคือสิ่งที่เราจะเรียกว่า Golden DatasetGolden Datasetชุด input พร้อมคำตอบ/พฤติกรรมที่ถูกต้อง (Ground Truth) ซึ่งมนุษย์ตรวจแล้ว ใช้เป็นหลักอ้างอิงตายตัวสำหรับรัน eval ซ้ำก่อนปล่อยแต่ละ version — เริ่มจากเคสจริงหลักสิบเคสที่เคยพังมาก่อนก็พอ ไม่ต้องรอให้มีเป็นร้อยเคสก่อนเริ่ม eval แต่ต้องมาจากความล้มเหลวจริง ไม่ใช่เคสที่จินตนาการขึ้นเองProcess: ชุด input พร้อมพฤติกรรมที่ถูกต้องซึ่งมนุษย์ตรวจแล้ว ใช้เป็นหลักอ้างอิงตายตัวสำหรับรัน eval ซ้ำก่อนปล่อยแต่ละ version — และมันไม่จำเป็นต้องใหญ่ตั้งแต่วันแรก
นี่ไม่ใช่แค่คำแนะนำลอยๆ ทีมที่สร้าง multi-agent research system ของ Anthropic เล่าว่าพวกเขา “started evaluating immediately” ด้วย “about 20 queries representing real usage patterns” — เริ่มวัดผลทันทีด้วยราว 20 คำถามที่สะท้อนรูปแบบการใช้งานจริง แทนที่จะรอให้มีชุดเป็นร้อยเคสก่อน (ดู Anthropic, “How we built our multi-agent research system” — อ้างเพื่อ วิธีการ เริ่มเล็ก ไม่ใช่เพื่อตัวเลขประสิทธิภาพใน post นั้น)
ทำไมแค่ 20–50 ถึงพอตอนเริ่ม — effect size ยังใหญ่
หัวข้อที่มีชื่อว่า “ทำไมแค่ 20–50 ถึงพอตอนเริ่ม — effect size ยังใหญ่”เหตุผลที่ชุดเล็กใช้ได้ผลตอนเริ่มไม่ใช่เพราะเรามักง่าย แต่เพราะ ตอนแรกความเปลี่ยนแปลงมันตัวโต ระบบที่เพิ่งเริ่มมักมี bug ก้อนใหญ่ที่พังชัดๆ การแก้ prompt หนึ่งครั้งอาจดันอัตราสำเร็จจาก 30% ขึ้นเป็น 80% ได้ — ส่วนต่างขนาดนั้น (นี่เป็นตัวเลข ตัวอย่างเชิงประกอบ เพื่อให้เห็นภาพ ไม่ใช่ผลวัดจากระบบจริง) เห็นได้ชัดตั้งแต่เคสไม่กี่สิบเคส ไม่ต้องใช้เป็นพันเคสมายืนยัน
พูดอีกแบบ: จำนวนเคสที่ต้องใช้ขึ้นกับขนาดของสิ่งที่อยากตรวจจับ ถ้าอยากรู้ว่าการเปลี่ยนครั้งใหญ่ทำให้ดีขึ้นชัดๆ หรือเปล่า เคสหลักสิบก็ตอบได้ แต่พอระบบนิ่งขึ้นแล้วเราไปไล่จับส่วนต่างเล็กๆ (เช่นดีขึ้นอีก 2%) ตอนนั้นแหละถึงต้องการเคสมากขึ้นเพื่อให้มั่นใจว่าไม่ใช่ความบังเอิญ นั่นคือเหตุผลว่าทำไม 20–50 ถึง “พอ” เฉพาะช่วงเริ่ม ไม่ใช่ตลอดไป
เคสควรมาจากไหน — สองแหล่งของความล้มเหลวจริง
หัวข้อที่มีชื่อว่า “เคสควรมาจากไหน — สองแหล่งของความล้มเหลวจริง”หัวใจอยู่ที่คำว่า real failures เคสในชุดเริ่มต้นต้องมาจากความล้มเหลวจริง ไม่ใช่เคสที่เรานั่งจินตนาการขึ้นเอง แล้วความล้มเหลวจริงหาได้จากไหน มีสองแหล่งหลักตามช่วงชีวิตของระบบ:
- ก่อนปล่อย — จากสิ่งที่คุณทดสอบด้วยมืออยู่แล้ว ก่อนปล่อยทุก version เรามักลองสั่ง agent ด้วยมือแล้วดูว่ามันพังตรงไหน เคสที่คุณลองด้วยมือซ้ำๆ ก่อนกดปล่อยนั่นคือคือเคส eval ชุดแรก — แค่จดมันลงเป็นชุดที่รันซ้ำได้ แทนที่จะลองแล้วลืม
- หลังปล่อย — จาก bug tracker กับคิว support พอขึ้นโปรดักชัน ทุก bug ที่ผู้ใช้แจ้งเข้ามาและทุกตั๋วในคิว support คือเคสจริงที่ราคาแพงเพราะมีคนเจอไปแล้ว ดึงมันกลับมาเป็นเคสใน Golden Dataset เพื่อกันไม่ให้ความพังแบบเดิมหลุดซ้ำ
สำหรับ ops-copilot คืนเงินของเรา เคสจริงหน้าตาแบบนี้: “คืนเงิน ฿100 ทั้งที่ควรเป็น ฿120”, “คืนเงินผิดออเดอร์”, “บอกว่าคืนเงินแล้วแต่ฐานข้อมูลไม่ขยับ” — แต่ละอันเคยเกิดจริงและมีคนเจอจริง
จุดที่ต้องย้ำ: เกณฑ์ผ่านของแต่ละเคสต้องเป็น outcome ที่ตรวจสอบได้ ไม่ใช่คำบอกเล่าของ agent เอง สำหรับเคสคืนเงินออเดอร์ #123 เกณฑ์ผ่านคือ “มีแถวคืนเงินของออเดอร์ #123 ในฐานข้อมูลจริง จำนวน ฿120” ไม่ใช่ “agent พิมพ์ว่า ‘คืนเงินเรียบร้อย’” — ถ้าเกณฑ์ผูกกับคำพูดของ agent เคสทั้งชุดก็ผ่านลวงตาได้หมด
# สเก็ตช์ golden dataset เพื่อสื่อไอเดีย ไม่ใช่ file ที่รันได้จริง# แต่ละเคส "มาจากของจริง" และมี outcome ที่ตรวจสอบได้ ไม่อิงคำพูด agent- id: refund-wrong-amount source: bug-tracker#412 # เคยพังจริง ผู้ใช้แจ้งเข้ามา input: "คืนเงินออเดอร์ 123" expect_db: # เช็คสถานะจริงของฐานข้อมูล ไม่ใช่ agentReply refunds: { orderId: 123, amount: 120 }- id: refund-wrong-order source: support-queue#88 input: "คืนเงินออเดอร์ล่าสุดของลูกค้าคนนี้" expect_db: refunds: { orderId: 501, amount: 90 } # ต้องเป็น 501 ไม่ใช่ออเดอร์อื่น- id: refund-says-done-but-noop source: manual-test # เจอตอนลองด้วยมือก่อนปล่อย input: "คืนเงินออเดอร์ 777" expect_db: refunds: { orderId: 777, amount: 250 } # ต้องมีแถวจริง ไม่ใช่แค่ข้อความเป็นจุดเริ่ม ไม่ใช่จุดจบ
หัวข้อที่มีชื่อว่า “เป็นจุดเริ่ม ไม่ใช่จุดจบ”ต้องเห็นภาพให้ชัดว่า “20 เคสก็พอ” เป็น จุดเริ่มต้น ไม่ใช่ปลายทาง ชุด 20–50 เคสมีไว้จับ bug ก้อนใหญ่ที่ effect size โตพอจะเห็นได้เร็ว มันไม่ใช่ชุดที่พอไปตลอด พอผ่านช่วงแรก วินัย eval ชุดเดียวกันนี้จะเรียกร้องให้เราขยับไปอ่าน trace จริงเป็นร้อยๆ เคสในทุกรอบของ error analysis (บทที่ 6) — ที่นั่น Golden Dataset จะโตขึ้นเรื่อยๆ จากเคสพังจริงที่อ่านเจอ ไม่ใช่หยุดที่ 20
กลไกที่ทำให้มันโตคือวงป้อนกลับ: ทุกความล้มเหลวใหม่ที่เจอ — ไม่ว่าจาก support, จากการอ่าน trace, หรือจาก version ใหม่ที่ทำเคสเก่าพัง — ถูกดึงกลับมาเป็นเคสใหม่ในชุด ชุดจึงค่อยๆ ครอบคลุมความจริงมากขึ้นตามอายุของระบบ
flowchart LR F["failure จริง<br/>manual test ก่อนปล่อย<br/>+ bug tracker + คิว support"] F --> G["golden set เล็ก<br/>20-50 เคส<br/>แต่ละเคสมี outcome ที่ตรวจได้"] G --> E["รัน eval แล้วแก้ prompt หรือ model<br/>effect size ใหญ่ จับ bug ก้อนโตได้เร็ว"] E --> B6["บทที่ 6 error analysis<br/>อ่าน trace จริง 100+ เคส"] B6 -->|เคสพังใหม่ป้อนกลับเข้าชุด| G classDef start fill:#16a34a,stroke:#065f46,color:#f8fafc; classDef grow fill:#2563eb,stroke:#1e3a8a,color:#f8fafc; class F start; class B6 grow;
คำบรรยายภาพ: สายธารของ eval set เริ่มจากความล้มเหลวจริง (เขียว) — จาก manual test ก่อนปล่อยและจากคิว bug/support — กลั่นเป็น golden set เล็กๆ 20–50 เคสที่แต่ละเคสมี outcome ตรวจได้ ใช้ชุดนี้รัน eval แล้วแก้ prompt/model จับ bug ก้อนใหญ่ได้เร็วเพราะ effect size ยังโต จากนั้น (น้ำเงิน) บทที่ 6 พาไปอ่าน trace จริงเป็นร้อยเคส และเคสพังใหม่ที่เจอถูกป้อนกลับเข้าชุด ทำให้ Golden Dataset โตขึ้นเรื่อยๆ ไม่ใช่หยุดนิ่งที่ 20
เริ่มด้วย eval set เล็กๆ 20–50 เคส เพราะตอนแรก effect size ยังใหญ่ ชุดหลักสิบเคสก็จับ bug ก้อนโตได้ ไม่ต้องรอสร้างชุดสมบูรณ์ก่อนจึงเริ่ม เคสต้องมาจากความล้มเหลวจริง — สิ่งที่คุณทดสอบด้วยมือก่อนปล่อย และตั๋วใน bug tracker/คิว support — ไม่ใช่เคสที่จินตนาการเอา และแต่ละเคสต้องผูกกับ outcome ที่ตรวจสอบได้จริง เช่นแถวคืนเงินในฐานข้อมูล ไม่ใช่คำพูดของ agent สุดท้าย 20 เคสคือจุดเริ่ม ไม่ใช่จุดจบ บทที่ 6 จะพาชุดนี้โตขึ้นด้วย error analysis บน trace จริงเป็นร้อยเคส
บทนี้สังเคราะห์จากสองแหล่งหลัก อ่านต่อได้ที่ต้นทางโดยตรง:
- Anthropic, “Demystifying evals for AI agents” — “20-50 simple tasks drawn from real failures is a great start” และที่มาของเคสจาก manual test ก่อนปล่อยกับ bug tracker/คิว support
- Anthropic, “How we built our multi-agent research system” — ทีมจริง “started evaluating immediately” ด้วย “about 20 queries representing real usage patterns” (อ้างเพื่อวิธีการเริ่มเล็ก ไม่ใช่ตัวเลขประสิทธิภาพ)
เช็กความเข้าใจ — บทที่ 5
ข้อ 1 / 3ทำไมชุดแค่ 20–50 เคสถึง 'พอ' ตอนเริ่มต้น?