เมื่อคุณเริ่มสร้างสรรค์สิ่งต่างๆ ด้วยปัญญาประดิษฐ์ (AI) เป็นครั้งแรก เสียงที่ดังที่สุดมักจะชี้ไปที่จุดเดียวกัน นั่นคือ ตัวโมเดล พวกเขาบอกว่า แค่เลือกโมเดลที่ใช่ ทุกอย่างก็จะลงตัวเอง แต่หลังจากได้ทดลองด้วยตัวเองมาไม่กี่สัปดาห์ ผมบอกคุณได้เลยว่ามันไม่เป็นความจริงแบบนั้น การเลือกใช้ Large Language Models ที่มีอยู่นั้นสำคัญ แต่คิดเป็นเพียงแค่ประมาณ 20% ของงานทั้งหมด ส่วนที่เหลือคืองานด้านระบบ (systems work) มันคือการวางโครงสร้างพื้นฐาน งานฝีมือ และการทดสอบอย่างไม่ลดละ ความเข้าใจนี้เกิดขึ้นกับผมตั้งแต่เนิ่นๆ และมันได้เปลี่ยนวิธีที่ผมเข้าถึงทุกโปรเจกต์นับตั้งแต่นั้นมา
โมเดลเป็นเพียงจุดเริ่มต้นเท่านั้น
เข้าใจได้ไม่ยากว่าทำไมมือใหม่ถึงหมกมุ่นอยู่กับเรื่องโมเดล บันทึกการอัปเดต (release notes) มักจะสัญญาเรื่องการใช้เหตุผลที่ดีขึ้น หน้าต่างบริบท (context windows) ที่ใหญ่ขึ้น และผลลัพธ์ที่สะอาดตาขึ้น การพัฒนาเหล่านั้นเป็นเรื่องจริง แต่ก็เป็นไปเพื่อการใช้งานทั่วไป (general-purpose) โมเดลที่ล้ำสมัยที่สุดก็ไม่สามารถรู้โยบายการคืนเงินของบริษัทคุณได้โดยอัตโนมัติ มันจะไม่สามารถจัดรูปแบบคำตอบสำหรับแอปมือถือของคุณได้อย่างแม่นยำ เว้นแต่คุณจะบอกวิธีทำ และมันไม่สามารถดึงข้อมูลสต็อกสินค้าแบบเรียลไทม์ออกมาจากความว่างเปล่าได้
ผมเรียนรู้เรื่องนี้ด้วยบทเรียนราคาแพง โปรโตไทป์แรกของผมใช้โมเดลที่มีความสามารถสูง และสร้างย่อหน้าที่ดูสวยงามและมั่นใจ แต่บางครั้งก็ผิดพลาดอย่างสิ้นเชิง ข้อความฟังดูเป็นมืออาชีพเพราะโมเดลเชี่ยวชาญเรื่องน้ำเสียง (tone) แต่โมเดลกลับเข้าไม่ถึงข้อมูลที่เป็นปัจจุบัน ผมเสียเวลาหลายวันไปกับการเปรียบเทียบ benchmark ของโมเดล ทั้งที่จริงๆ แล้วผมควรจะไปคิดเรื่อง data pipelines และการฉีดบริบท (context injection) แทน ตัวโมเดลไม่ได้เสีย แต่ระบบที่อยู่รอบๆ มันต่างหากที่ไม่สมบูรณ์ ความแตกต่างนี้คือหัวใจสำคัญเมื่อคุณเปลี่ยนจากการทำเดโมไปสู่ซอฟต์แวร์ที่ผู้คนใช้งานจริง
Prompt คือโค้ด ไม่ใช่แค่คำแนะนำ
Prompt ที่มีคุณภาพสูงคือหัวใจสำคัญของแอปพลิเคชัน AI ที่เชื่อถือได้ ในช่วงแรก ผมปฏิบัติกับ prompt เหมือนกับคำค้นหา (search queries) คือสั้นๆ เป็นกันเอง และคาดหวังในแง่ดี ผมจะสั่งโมเดลว่า "สรุปสิ่งนี้ให้หน่อย" หรือ "ช่วยหน่อยนะ" แล้วก็หวังว่าผลลัพธ์จะออกมาดีที่สุด ผลลัพธ์ที่ได้แกว่งไปมาระหว่างที่มีประโยชน์กับที่ไม่เกี่ยวข้องเลย และผมก็ไม่รู้เลยว่าทำไม
ตอนนี้ผมปฏิบัติกับ prompt เหมือนกับโปรแกรมขนาดเล็ก (lightweight programs) Prompt ที่ดีจะกำหนดบทบาท (role) ระบุรูปแบบผลลัพธ์ (output format) ใส่ตัวอย่างเมื่อจำเป็น และกำหนดขอบเขต (boundaries) ถ้าผมต้องการ JSON ผมจะสั่งขอ JSON และแสดง schema ให้ดู ถ้าผมต้องการคำตอบที่กระชับ ผมจะกำหนดความยาวอย่างชัดเจนและสั่งห้ามเขียนคำเกริ่นนำ (preamble) การทำซ้ำ (iteration) เป็นเรื่องสำคัญ ผมจะเก็บ log ของ prompt และผลลัพธ์เอาไว้ โดยเปลี่ยนตัวแปรทีละอย่าง คำคุณศัพท์ที่กำกวมเพียงคำเดียวใน prompt สามารถเปลี่ยนพฤติกรรมของ workflow ทั้งหมดได้ ความละเอียดอ่อนนี้ต้องการความเข้มงวด ไม่ใช่การเดาสุ่ม
ข้อมูลขยะย่อมได้ผลลัพธ์ที่เป็นขยะ (Garbage In, Garbage Out)
การดึงข้อมูล (data retrieval) ที่เชื่อถือได้คือจุดที่โปรเจกต์ AI จำนวนมากค่อยๆ ล้มตายลงอย่างเงียบๆ Retrieval-Augmented Generation หรือ RAG ได้กลายเป็นรูปแบบมาตรฐานในการทำให้โมเดลเข้าถึงข้อมูลส่วนตัวหรือข้อมูลปัจจุบันได้ แนวคิดนั้นตรงไปตรงมา: ดึงเอกสารที่เกี่ยวข้อง ใส่เข้าไปใน context window ของโมเดล และปล่อยให้โมเดลใช้เหตุผลจากข้อเท็จจริงเหล่านั้น แต่ในทางปฏิบัติมันยุ่งเหยิงกว่านั้นมาก
ผมเสียเวลาไปกับการแก้บั๊ก (debugging) ฐานความรู้ (knowledge base) ง่ายๆ ที่คอยแต่จะคืนผลลัพธ์ที่ไม่เกี่ยวข้องออกมา โมเดลนั้นปกติดี แต่เลเยอร์การดึงข้อมูล (retrieval layer) ต่างหากที่ล้มเหลว การแบ่งส่วนข้อมูล (chunks) ของผมเล็กเกินไปจนขาดบริบท ส่วน embeddings ก็ถูกสร้างขึ้นโดยไม่ได้ทำความสะอาดหัวข้อที่ซ้ำซ้อน การค้นหาความคล้ายคลึง (similarity search) ไปเจอข้อความที่มีความใกล้เคียงทางเทคนิค แต่กลับตอบคำถามผิดประเด็น การแก้ไขหมายถึงการต้องคิดกลยุทธ์การทำ chunking ใหม่ เพิ่มตัวกรอง metadata และเพิ่มขั้นตอนการจัดลำดับใหม่ (re-ranking) เมื่อการดึงข้อมูลเริ่มเสถียร คำตอบของโมเดลก็ดีขึ้นทันที บทเรียนนี้ชัดเจนมาก: คุณไม่สามารถแก้ปัญหาการดึงข้อมูลที่แย่ด้วยการใช้โมเดลที่ดีกว่าได้ แต่คุณต้องสร้าง pipeline ให้ถูกต้องตั้งแต่แรก
คุณไม่สามารถปรับปรุงสิ่งที่คุณไม่ได้วัดผล
การประเมินผลอย่างต่อเนื่องคือพฤติกรรมที่แยก "การทดลอง" ออกจาก "ผลิตภัณฑ์" ตอนที่ผมเริ่มใหม่ๆ ผมประเมินผลตามความรู้สึก (vibe) ผมจะอ่านผลลัพธ์สักห้าอัน พยักหน้าเห็นด้วย แล้วก็ผ่านไป มันใช้ได้ผลจนกระทั่งผู้ใช้ถามคำถามที่หก แล้วได้รับคำตอบที่แปลกประหลาดออกมา
ตอนนี้ผมสร้างชุดประเมินผล (evaluation sets) ขนาดเล็กสำหรับทุกฟีเจอร์ ผมรวบรวมคำถามจริงจากผู้ใช้ ระบุพฤติกรรมที่คาดหวัง และรันการตรวจสอบแบบอัตโนมัติเทียบกับสิ่งเหล่านั้น ผมคอยเฝ้าระวังการเปลี่ยนแปลง (drift): prompt ที่เคยใช้ได้ดีเมื่อเดือนที่แล้วอาจเสื่อมประสิทธิภาพลงหลังจากการอัปเดตโมเดล หรือหลังจากข้อมูลพื้นฐานเปลี่ยนไป ผมแยกการประเมินด้านสไตล์ออกจากความถูกต้องของข้อเท็จจริง การดูเป็นมืออาชีพนั้นเป็นเรื่องดี แต่การถูกต้องนั้นเป็นเรื่องจำเป็น หากไม่มีวงจรนี้ คุณกำลังปล่อยผลิตภัณฑ์ออกไปโดยอาศัยเพียงความหวัง และความหวังไม่ใช่กลยุทธ์การทดสอบ
รู้ขีดจำกัดของเครื่องจักร
การเข้าใจข้อจำกัดของโมเดลช่วยให้ผมไม่ต้องรับปากเกินจริงแล้วทำไม่ได้ตามที่สัญญาไว้ ระบบเหล่านี้มีข้อจำกัดที่แท้จริง แม้ว่า Context window จะใหญ่ขึ้นกว่าเมื่อก่อน แต่ก็ยังมีขีดจำกัดอยู่ และการยัดข้อมูลจนเต็มจะทำให้ประสิทธิภาพลดลงเมื่อเข้าใกล้ขีดจำกัด โมเดลสามารถเกิดอาการหลอน (hallucinate) ได้ โดยเฉพาะในหัวข้อเฉพาะทางที่มีข้อมูลสำหรับฝึกฝนน้อย พวกมันยังประสบปัญหาเรื่องการคำนวณที่แม่นยำและตรรกะแบบหลายขั้นตอนบางประเภท รวมถึงมีความอ่อนไหวต่อการใช้คำพูดด้วย
ต้นทุนและความเร็วก็เป็นข้อจำกัดเช่นกัน โมเดลที่สร้างงานเขียนที่สมบูรณ์แบบได้ในสิบวินาทีอาจใช้งานไม่ได้เลยในอินเทอร์เฟซแชทแบบเรียลไทม์ ตอนนี้ผมจึงกำหนดฟีเจอร์ต่างๆ ให้สอดคล้องกับงบประมาณด้านความหน่วง (latency budget) ตั้งแต่เนิ่นๆ หากงานใดต้องการการตอบสนองภายในเสี้ยววินาที ผมอาจจะใช้วิธีคำนวณคำตอบไว้ล่วงหน้า (precompute), ทำการแคช (cache) อย่างหนัก หรือใช้โมเดลขนาดเล็กสำหรับร่างแรกและใช้โมเดลขนาดใหญ่เฉพาะตอนขัดเกลาเท่านั้น การทำงานภายใต้ข้อจำกัดคือมาตรฐานทางวิศวกรรม และ AI ก็ไม่ต่างกัน
สร้างเพื่อผู้ใช้งานจริง
ตอนนี้ผมกำลังศึกษาเรื่องแอปพลิเคชัน LLM และวิศวกรรมซอฟต์แวร์ด้วยเป้าหมายง่ายๆ คือ: สร้างเครื่องมือที่ผู้คนใช้งานได้ทุกวัน ฟังดูเหมือนเป็นเรื่องปกติ แต่ช่องว่างระหว่างตัวต้นแบบ (prototype) ที่ดูเจ๋ง กับเครื่องมือที่ใช้งานได้จริงในทุกวันนั้นกว้างมหาศาล การสาธิต (demo) อาจทนกับการหยุดชะงักสี่สิบวินาทีหรือคำตอบที่เยิ่นเย้อได้ แต่คนที่กำลังพยายามทำงานให้เสร็จก่อนเริ่มประชุมนั้นทำไม่ได้
เครื่องมือที่ใช้ในชีวิตประจำวันจำเป็นต้องมีการจัดการข้อผิดพลาด (error handling), มีระบบสำรอง (fallbacks) และมี UI ที่ชัดเจนเมื่อโมเดลไม่แน่ใจ พวกมันต้องสามารถผสานเข้ากับเวิร์กโฟลว์ที่มีอยู่เดิมได้ แทนที่จะเป็นการบังคับให้ใช้เวิร์กโฟลว์ใหม่ ตอนนี้ผมเริ่มคิดถึงกรณีขอบเขต (edge cases) แล้ว เช่น จะเกิดอะไรขึ้นเมื่อโมเดลปฏิเสธที่จะตอบ, เมื่อบริบท (context) ล้น หรือเมื่อ API หมดเวลา (timeout)? การส่งมอบซอฟต์แวร์ AI หมายถึงการตอบคำถามเหล่านั้นด้วยโค้ด ไม่ใช่แค่การมองโลกในแง่ดี
มาแบ่งปันสิ่งที่เราเรียนรู้กันเถอะ
ผมอยากเชื่อมต่อกับนักพัฒนาคนอื่นๆ ที่กำลังเดินบนเส้นทางเดียวกัน สาขานี้ก้าวไปอย่างรวดเร็ว และแนวทางปฏิบัติที่ดีที่สุด (best practices) ก็ยังคงถูกเขียนขึ้นใหม่เสมอ ไม่มีใครที่มีคำตอบสำหรับทุกอย่าง ไม่ว่าคุณจะกำลังต่อสู้กับการออกแบบ prompt, การจัดการ retrieval pipelines หรือการหาวิธีประเมินผลลัพธ์ในระดับสเกล ปัญหาเหล่านี้จะแก้ไขได้ดีกว่าหากทำร่วมกัน
มาแบ่งปันสิ่งที่เราเรียนรู้กันเถอะ ไม่ใช่การพูดในงานสัมมนาที่ขัดเกลามาอย่างดี แต่เป็นช่วงเวลาที่วุ่นวายและยุ่งเหยิง ทั้ง pipeline ที่พัง, การปรับแต่ง prompt ที่ในที่สุดก็ใช้งานได้, หรือการทดสอบการประเมินผลที่ตรวจพบข้อผิดพลาดก่อนการเปิดตัว การแลกเปลี่ยนที่ละเอียดและตรงไปตรงมาเช่นนี้เองที่จะเปลี่ยนการทดลองส่วนบุคคลให้กลายเป็นองค์ความรู้ส่วนรวม
บทสรุปที่แท้จริง
หากคุณกำลังเริ่มต้นพัฒนา AI จงใช้เวลาน้อยลงในการค้นหา
