Skip to content
เครื่องมือและผลิตภัณฑ์

วิเคราะห์: การดึงผลลัพธ์ที่เครื่องอ่านได้จากโมเดลภาษา และเหตุใดคำสั่งว่า 'ให้ตอบเป็น JSON' จึงไม่ใช่ข้อกำหนดที่เพียงพอ

ผลิตภัณฑ์ทุกตัวที่นำโมเดลภาษาไปฝังไว้ในไปป์ไลน์ ในที่สุดแล้วย่อมต้องการผลลัพธ์ที่มีโครงสร้างแน่นอนและเชื่อถือได้ รูปแบบความล้มเหลวที่พบบ่อยนั้นเป็นที่เข้าใจกันดีอยู่แล้ว ส่วนวิธีแก้ก็ไม่ใช่เรื่องหวือหวาแต่อย่างใด นี่คือคู่มือภาคสนามสำหรับเรื่องนี้

โดย DigitalNeuron Deskอ่าน 1 นาที

คำตอบโดยย่อ

จะทำอย่างไรให้โมเดลภาษาส่งคืนข้อมูลที่มีโครงสร้างได้อย่างน่าเชื่อถือ?

ควรใช้ระบบถอดรหัสแบบมีข้อจำกัด (constrained decoding) หรือโหมดบังคับสคีมาที่แพลตฟอร์มมีให้ใช้งาน เพราะวิธีนี้ทำให้ไวยากรณ์ที่ผิดรูปแบบเกิดขึ้นไม่ได้เลย แทนที่จะเป็นเพียงแค่ลดโอกาสเกิดขึ้น จากนั้นให้ออกแบบสคีมาโดยคำนึงถึงตัวโมเดลเป็นหลัก นั่นคือโครงสร้างที่แบนราบ มีฟิลด์บังคับให้น้อยที่สุด กำหนดค่าที่เป็นไปได้ (enum) อย่างชัดเจน มีวิธีระบุความไม่แน่นอนอย่างชัดแจ้ง และไม่มีฟิลด์ใดที่ต้องอาศัยการคำนวณทางคณิตศาสตร์ ต้องตรวจสอบทุกคำตอบเทียบกับสคีมาเสมอ และควรมองว่าความถูกต้องเชิงความหมาย นั่นคือค่าที่ถูกต้องจริง ไม่ใช่แค่รูปแบบที่ถูกต้อง เป็นปัญหาอีกเรื่องหนึ่งที่การตรวจสอบสคีมาเพียงอย่างเดียวไม่สามารถแก้ไขได้

ประเด็นสำคัญ

  • การถอดรหัสแบบจำกัดด้วยสคีมาแก้ปัญหาเรื่องไวยากรณ์ ไม่ใช่ความหมาย คำตอบอาจเป็น JSON ที่ถูกต้องสมบูรณ์แบบ แต่ผิดโดยสิ้นเชิงในเนื้อหา
  • การออกแบบสคีมาคือการออกแบบพรอมป์ ชื่อฟิลด์ ค่าของ enum และคำอธิบายทุกตัวล้วนเป็นคำสั่งที่โมเดลอ่านและตีความ
  • ต้องเปิดทางให้โมเดลบอกได้ว่า 'ไม่มีข้อมูล' หรือ 'ไม่แน่ใจ' อย่างถูกต้องตามหลัก หากไม่มีทางออกนี้ ฟิลด์ที่บังคับกรอกจะกลายเป็นคำเชิญให้โมเดลกุข้อมูลขึ้นมาเอง
  • อย่าให้โมเดลคำนวณผลรวม เปอร์เซ็นต์ หรือวันที่ที่สามารถคำนวณได้เอง ควรดึงเฉพาะข้อมูลตั้งต้นออกมา แล้วไปคำนวณด้วยโค้ด
  • ตรวจสอบความถูกต้องก่อน แล้วค่อยขอให้โมเดลลองใหม่อีกครั้งพร้อมแนบข้อผิดพลาดจากการตรวจสอบ การซ่อมแซมแบบเจาะจงเพียงรอบเดียวจะแก้ไขความผิดพลาดที่หลงเหลืออยู่ส่วนใหญ่ได้ในต้นทุนที่ต่ำกว่าการวนลูปลองซ้ำ

ทันทีที่โมเดลภาษาเลิกเขียนให้มนุษย์อ่านและเริ่มเขียนให้โปรแกรมใช้ ข้อกำหนดอีกชุดหนึ่งก็เข้ามาแทนที่ ร้อยแก้วอาจถูกต้องโดยประมาณได้ แต่ฟิลด์ชื่อ total_amount จะเป็นเช่นนั้นไม่ได้

ทีมส่วนใหญ่มักค้นพบเรื่องนี้ตามลำดับเดียวกัน พวกเขาระบุในพรอมป์ให้ส่งออกเป็น JSON แล้วมันก็ใช้ได้ จึงนำขึ้นใช้งานจริง หนึ่งสัปดาห์ต่อมา พาร์เซอร์เกิดข้อผิดพลาดเพราะโมเดลครอบออบเจ็กต์ไว้ในกรอบโค้ด เติมประโยคเป็นมิตรก่อนหน้า หรือใส่จุลภาคส่วนเกินท้ายรายการ พวกเขาจึงเพิ่มฟังก์ชันทำความสะอาด แล้วมันก็ใช้ได้ หนึ่งเดือนต่อมา ฟิลด์ที่ควรเป็น null กลับมีค่าที่แต่งขึ้นอย่างแนบเนียน และระบบไม่ล่มเลย ซึ่งเลวร้ายกว่ามาก

ความล้มเหลวสองอย่างนี้แตกต่างกันโดยสิ้นเชิง และการเหมารวมว่าเป็นปัญหาเดียวกันคือเหตุผลที่ทำให้ใช้เวลานานกว่าจะแก้ได้

สองปัญหาภายใต้ชื่อเดียวกัน

ความล้มเหลวทางไวยากรณ์ คือผลลัพธ์ที่พาร์สไม่ได้หรือไม่ตรงตามสคีมา ปัญหานี้เห็นได้ชัด เกิดขึ้นทันที และแก้ไขได้อย่างสมบูรณ์

ความล้มเหลวทางความหมาย คือผลลัพธ์ที่พาร์สได้อย่างสมบูรณ์แต่ให้ข้อมูลผิด เช่น วันที่ที่กล่าวอย่างมั่นใจทั้งที่ไม่เคยปรากฏในเอกสาร หมวดหมู่ที่อยู่ใน enum แต่ไม่ตรงกับเนื้อหา หรือยอดรวมที่ไม่สอดคล้องกับรายการย่อย

การถอดรหัสแบบมีข้อจำกัด ซึ่งเป็นโหมดบังคับใช้สคีมาที่แพลตฟอร์มรายใหญ่ทุกแห่งมีให้ในปัจจุบัน กำจัดปัญหาประเภทแรกได้เกือบทั้งหมด วิธีนี้จำกัดโทเค็นที่อนุญาตในแต่ละขั้นตอนของการสร้าง เพื่อไม่ให้เกิดผลลัพธ์ที่อยู่นอกไวยากรณ์ นี่คือการเปลี่ยนแปลงครั้งสำคัญอย่างแท้จริงเมื่อเทียบกับการขอผ่านพรอมป์ ซึ่งเป็นเพียงคำแนะนำที่โมเดลมักปฏิบัติตาม และความแตกต่างจะปรากฏชัดในกรณีส่วนน้อยสุดขั้ว เพราะคำขอหนึ่งครั้งในพันครั้งที่เคยล้มเหลวนั่นเองคือครั้งที่ทำให้ต้องเรียกคนมารับมือ

วิธีนี้ไม่ช่วยแก้ปัญหาประเภทที่สองแต่อย่างใด และผลทางจิตวิทยาที่ตามมามีความเสี่ยงอยู่จริง ทีมที่นำการบังคับใช้สคีมามาใช้มักเลิกตรวจสอบความถูกต้อง เพราะแพลตฟอร์ม “รับประกัน” สคีมา แต่สิ่งที่รับประกันคือรูปแบบเท่านั้น คำถามที่เหลือทั้งหมด ไม่ว่าจะเป็นค่านี้ถูกต้องหรือไม่ ฟิลด์เหล่านี้สอดคล้องกันหรือไม่ หรือวันที่นี้อยู่ในช่วงที่สมเหตุสมผลหรือไม่ ยังคงเป็นความรับผิดชอบของคุณ

สคีมาเป็นส่วนหนึ่งของพรอมป์

นี่คือการปรับกรอบความคิดที่มีประโยชน์ที่สุด แต่กลับถูกมองข้ามอยู่เสมอ โมเดลอ่านสคีมา ชื่อฟิลด์ ค่า enum คำอธิบาย และลำดับ ล้วนเป็นคำสั่ง และทั้งหมดแข่งขันกับพรอมป์ระบบในการชี้นำโมเดล

นั่นหมายความว่าการตัดสินใจออกแบบสคีมาส่งผลต่อคุณภาพ

ตั้งชื่อฟิลด์แบบเดียวกับที่คุณจะอธิบายให้คนฟัง is_urgent ให้ผลลัพธ์ดีกว่า flag2 คำอธิบายในฟิลด์ เช่น “เป็น true เฉพาะเมื่อลูกค้าระบุกำหนดเวลาภายใน 48 ชั่วโมง” มักมีประสิทธิผลมากกว่าการใส่ประโยคเดียวกันไว้ในพรอมป์ระบบ เพราะอยู่ติดกับจุดที่ต้องตัดสินใจ

ใช้ enum แทนสตริงอิสระทุกครั้งที่ขอบเขตของค่ามีจำกัด ฟิลด์ category แบบข้อความอิสระจะสร้างคำพ้องหรือคำใกล้เคียงสารพัดแบบในกรณีส่วนน้อย ซึ่งโค้ดปลายทางของคุณต้องคอยปรับให้เป็นมาตรฐานไปตลอด การใช้ enum ทำให้การตัดสินใจเกิดขึ้นตั้งแต่ขั้นตอนการสร้างผลลัพธ์

รักษาโครงสร้างให้แบนราบ ออบเจ็กต์ที่ซ้อนกันหลายชั้นเพิ่มทั้งโอกาสเกิดข้อผิดพลาดทางโครงสร้างและขอบเขตความเสียหายเมื่อแขนงหนึ่งผิดพลาด หากโดเมนมีลำดับชั้นอย่างแท้จริง การเรียกสองครั้งมักเชื่อถือได้มากกว่าการตอบกลับครั้งเดียวที่ซ้อนกันหลายชั้น และยังประเมินได้ง่ายกว่า เพราะมองเห็นได้ว่าขั้นตอนไหนล้มเหลว

จัดลำดับฟิลด์ให้การให้เหตุผลมาก่อนข้อสรุป สคีมาที่วางฟิลด์ reasoning หรือ evidence_quote ไว้ก่อน classification ให้ผลการจำแนกที่ดีขึ้นอย่างวัดผลได้เมื่อเทียบกับลำดับตรงกันข้าม เพราะโมเดลสร้างข้อความจากซ้ายไปขวา และฟิลด์ก่อนหน้าจะกำหนดเงื่อนไขให้ฟิลด์ถัดไป นี่เป็นจุดเดียวที่ร้อยแก้วสั้น ๆ ซึ่งโมเดลสร้างขึ้นให้ความคุ้มค่าภายในคำตอบที่มีโครงสร้าง

เปิดทางให้โมเดลตอบว่าไม่มีข้อมูล

สาเหตุที่พบบ่อยที่สุดของค่าที่แต่งขึ้นคือสคีมาไม่มีทางเลือกที่ชอบธรรมอื่นนอกจากการแต่งค่า

หาก contract_end_date เป็นสตริงบังคับที่ห้ามเป็น null แต่สัญญาไม่ได้ระบุวันที่สิ้นสุด โมเดลก็จำเป็นต้องสร้างค่าใดค่าหนึ่งขึ้นมา และจะสร้างค่าที่ดูสมเหตุสมผล โดยไม่มีส่วนใดในไปป์ไลน์คัดค้าน

วิธีแก้คือทำให้สามารถแสดงการไม่มีข้อมูลได้ ไม่ว่าจะใช้ฟิลด์ที่เป็น null ได้ เพิ่มสมาชิก enum ชื่อ not_stated อย่างชัดเจน หรือใช้บูลีนแยกต่างหากเพื่อควบคุมว่าค่านั้นควรมีหรือไม่ เมื่อใช้ควบคู่กับคำสั่งที่ชัดเจนว่าการไม่มีข้อมูลเป็นคำตอบที่ยอมรับได้และคาดหมายไว้ วิธีนี้จะขจัดค่าฟิลด์ที่หลอนขึ้นมาได้เป็นสัดส่วนมาก โดยมีต้นทุนเพียงหนึ่งบรรทัดในสคีมา

ตรรกะเดียวกันนี้ใช้กับระดับความเชื่อมั่นได้ด้วย enum ชื่อ confidence ที่มีสามค่า ได้แก่ สูง ปานกลาง และต่ำ มีประโยชน์กว่าคะแนนตัวเลข เพราะโมเดลปรับเทียบการประเมินตนเองเชิงตัวเลขได้ไม่ดีนัก แต่ค่อนข้างสม่ำเสมอในการเลือกกลุ่มแบบหยาบ ส่งกรณีที่มีความเชื่อมั่นต่ำให้มนุษย์ตรวจสอบ เท่านี้คุณก็เปลี่ยนปัญหาความแม่นยำให้เป็นปัญหาปริมาณงาน ซึ่งเป็นปัญหาที่รับมือได้ดีกว่ามาก

อย่าให้โมเดลคำนวณเลข

สคีมาที่มี subtotal, tax และ total กำลังขอค่าสามค่า ทั้งที่ค่าหนึ่งคำนวณได้จากค่าอื่น โมเดลจะกรอกครบทั้งสามค่า และบางครั้งค่าเหล่านั้นจะไม่สอดคล้องกัน

ให้สกัดเฉพาะอินพุต แล้วคำนวณค่าที่หาได้จากค่าอื่นในโค้ด กฎเดียวกันนี้ใช้กับการคำนวณวันที่ เปอร์เซ็นต์ จำนวน และทุกอย่างที่ต้องแปลงหน่วย ประเด็นนี้ไม่ได้หมายความว่าโมเดลไม่มีความสามารถ แต่การคำนวณแบบกำหนดแน่นอนมีอัตราความผิดพลาดเป็นศูนย์ ขณะที่ค่าที่สร้างขึ้นไม่มี และไม่มีเหตุผลที่จะยอมรับวิธีหลังเมื่อวิธีแรกพร้อมใช้งาน

การตรวจสอบความถูกต้องและการซ่อมแซมเพียงรอบเดียว

ตรวจสอบทุกคำตอบ รวมถึงคำตอบจากเอนด์พอยต์ที่บังคับใช้สคีมา เมื่อการตรวจสอบล้มเหลว วิธีรับมือที่มีประสิทธิผลที่สุดคือ ลองซ่อมแซมหนึ่งครั้งโดยระบุข้อผิดพลาดอย่างเจาะจง ไม่ใช่ลองใหม่โดยไม่ให้ข้อมูล การส่งข้อความกลับไปว่า “ฟิลด์ priority ต้องเป็นค่าใดค่าหนึ่งใน low, medium, high แต่คุณส่งกลับมาเป็น 'urgent'” แก้ความล้มเหลวที่หลงเหลืออยู่ส่วนใหญ่ได้ภายในการโต้ตอบเพิ่มเพียงรอบเดียว

จำกัดไว้ที่หนึ่งครั้ง วงจรลองใหม่ไม่จำกัดเมื่อพบอินพุตที่เป็นปฏิปักษ์หรือกำกวมอย่างแท้จริง จะเปลี่ยนความล้มเหลวที่มองเห็นได้ให้เป็นต้นทุนที่มองไม่เห็น และกลบสัญญาณสำคัญที่สุดที่คุณต้องการ นั่นคืออินพุตนี้มีบางอย่างไม่เข้ากับสคีมาที่คุณออกแบบไว้

หลังจากลองใหม่แล้ว ต้องมีทางเลือกสำรองแบบกำหนดแน่นอน เช่น ระเบียนค่าเริ่มต้นที่ทำเครื่องหมายไว้ให้ตรวจสอบ เส้นทางที่อิงกฎ หรือคิวสำหรับมนุษย์ ไปป์ไลน์ที่มีวิธีรับมือความล้มเหลวเพียง “ลองอีกครั้ง” เท่ากับไม่มีวิธีรับมือความล้มเหลวเลย ซึ่งเป็นข้อบกพร่องด้านการออกแบบ ไม่ใช่คุณสมบัติ

การประเมินผลลัพธ์แบบมีโครงสร้าง

ผลลัพธ์แบบมีโครงสร้างประเมินได้ง่ายเป็นพิเศษ และทีมควรใช้ประโยชน์จากจุดนี้

เนื่องจากผลลัพธ์อยู่ในรูปแบบที่เครื่องอ่านได้ การตรวจสอบส่วนใหญ่จึงทำได้อย่างแม่นยำ ได้แก่ ความถูกต้องตามสคีมา การเป็นสมาชิก enum การมีฟิลด์บังคับครบถ้วน ความสอดคล้องข้ามฟิลด์ และความแม่นยำระดับฟิลด์เมื่อเทียบกับชุดข้อมูลที่ติดป้ายกำกับไว้ ความแม่นยำต่อฟิลด์คือเมตริกที่ควรติดตาม ไม่ใช่ความแม่นยำของทั้งระเบียน เพราะการให้คะแนนระเบียนเป็นหน่วยเดียวบดบังว่าฟิลด์ใดกำลังมีคุณภาพลดลง และโดยมากปัญหาเกิดกับฟิลด์เดียว ไม่ใช่การสกัดข้อมูลทั้งหมด

ติดตามอัตรา null ด้วย หากจำนวนค่า null ลดลงอย่างฉับพลันหลังเปลี่ยนพรอมป์หรือโมเดล มักหมายความว่าโมเดลเริ่มแต่งค่าในจุดที่ก่อนหน้านี้เคยงดตอบ และปัญหานี้จะไม่ปรากฏในการตรวจสอบใด ๆ ที่พิจารณาเฉพาะระเบียนที่ถูกต้อง

บทสรุปที่ไม่หวือหวา

เรื่องนี้ไม่มีเทคนิคอันชาญฉลาด เปิดใช้การถอดรหัสแบบมีข้อจำกัด ออกแบบสคีมาโดยถือว่าโมเดลจะอ่าน เพราะมันอ่านจริง เปิดโอกาสให้ตอบว่า “ไม่ทราบ” เก็บการคำนวณไว้ในโค้ด ตรวจสอบความถูกต้องอยู่ดี ซ่อมแซมหนึ่งครั้ง แล้วใช้ทางเลือกสำรอง

ทุกข้อมีต้นทุนต่ำ และเมื่อรวมกันแล้ว สิ่งเหล่านี้คือความแตกต่างระหว่างโมเดลที่เป็นส่วนประกอบหนึ่งของระบบ กับโมเดลที่คอยสร้างเรื่องเหนือความคาดหมายขึ้นมาในระบบเป็นครั้งคราว

คำถามที่พบบ่อย

การถอดรหัสแบบจำกัด (constrained decoding) เหมือนกับการขอให้โมเดลตอบเป็น JSON ในพรอมป์หรือไม่
ไม่เหมือนกัน คำขอในพรอมป์เป็นเพียงข้อเสนอแนะที่โมเดลมักจะทำตาม แต่การถอดรหัสแบบจำกัดจะจำกัดโทเคนที่สามารถสร้างขึ้นได้ในแต่ละขั้นตอน ทำให้ผลลัพธ์ที่อยู่นอกไวยากรณ์ที่กำหนดเป็นไปไม่ได้เลย ความแตกต่างนี้จะปรากฏชัดในกรณีขอบ (tail) ซึ่งเป็นจุดที่ความล้มเหลวในระบบจริงมักเกิดขึ้น
เหตุใดโมเดลจึงกุข้อมูลขึ้นมาเองสำหรับฟิลด์ที่ฉันกำหนดให้บังคับกรอก
เพราะฟิลด์ที่บังคับกรอกโดยไม่มีค่าว่างที่ได้รับอนุญาต ก็คือคำสั่งให้ผลิตข้อมูลบางอย่างขึ้นมาเสมอ ควรปรับให้ฟิลด์นั้นสามารถเป็นค่าว่างได้ หรือเพิ่มค่า enum ที่ระบุชัดเจนว่า 'ไม่พบข้อมูล' ซึ่งโดยทั่วไปจะช่วยให้การกุข้อมูลหยุดลง
ควรใช้สคีมาที่ซ้อนกันหลายชั้นหรือไม่
ควรเลือกโครงสร้างแบบแบนราบมากกว่า การซ้อนชั้นลึกจะเพิ่มทั้งโอกาสเกิดข้อผิดพลาดด้านโครงสร้างและต้นทุนเมื่อเกิดความล้มเหลวบางส่วน หากโดเมนข้อมูลมีลักษณะเป็นลำดับชั้นจริง ๆ ควรพิจารณาแยกเป็นสองการเรียกใช้งานแทนที่จะรวมไว้ในคำตอบเดียวที่ซ้อนกันลึก
การลองใหม่ (retry) ควรทำงานอย่างไร
ควรมีการซ่อมแซมเพียงหนึ่งครั้งซึ่งแนบข้อผิดพลาดจากการตรวจสอบที่เจาะจงไปด้วย จากนั้นจึงเปลี่ยนไปใช้เส้นทางที่กำหนดแน่นอนหรือส่งต่อให้มนุษย์ตัดสินใจ การลองใหม่แบบไม่จำกัดจำนวนครั้งจะเปลี่ยนคำตอบที่แย่ให้กลายเป็นค่าใช้จ่ายที่แย่ และยังปิดบังปัญหาที่แท้จริงไว้ด้วย
หากเอพีไอรับประกันเรื่องสคีมาอยู่แล้ว ยังจำเป็นต้องตรวจสอบความถูกต้องอีกหรือไม่
จำเป็น การรับประกันนั้นครอบคลุมเพียงรูปแบบโครงสร้าง ไม่ใช่คุณค่าของข้อมูล การตรวจสอบสมาชิกใน enum ความสอดคล้องกันระหว่างฟิลด์ ช่วงค่าที่ยอมรับได้ และการอ้างอิงข้อมูลข้ามกัน ล้วนยังเป็นความรับผิดชอบของคุณอยู่เช่นเดิม

แหล่งข้อมูล

  1. JSON Schema specification — JSON Schema
  2. Model Context Protocol — specification — Model Context Protocol
  3. OpenAPI Specification — OpenAPI Initiative
แท็กstructured outputJSON schematool usereliabilityintegration

อ่านเพิ่มเติม

AWS เพิ่มโมเดล Beam แบบโอเพนเวตของ Reflection AI สำหรับการเขียนโค้ดเชิงเอเจนต์

AWS เผยแพร่คู่มือเชิงเทคนิคสำหรับการนำโมเดล Beam ของ Reflection AI ซึ่งเป็นโมเดลแบบผสมผู้เชี่ยวชาญ (mixture-of-experts) แบบโอเพนเวต สำหรับการเขียนโค้ดเชิงเอเจนต์ ไปใช้งานบน Amazon SageMaker โมเดล Beam มีพารามิเตอร์รวมทั้งหมด 501 พันล้านตัว พารามิเตอร์ที่ใช้งานจริง 23 พันล้านตัว และมีความยาวบริบทที่รายงานไว้ถึง 1 ล้านโทเคน โดยเปิดเผยน้ำหนักโมเดลบน Hugging Face ภายใต้สัญญาอนุญาต Apache 2.0

อ่าน 5 นาที

Meta's Muse Spark Open Coding Model Lands in Amazon SageMaker JumpStart

AWS announced that Meta's Muse Spark Open, a coding-optimized open-weight model with a 1 million-token context window, is now available in Amazon SageMaker JumpStart. Customers can deploy BF16 or NVFP4 quantized variants to a SageMaker AI endpoint in their own AWS account for coding agents and multimodal engineering tasks.

อ่าน 3 นาที