Claude และ OpenAI ต่างพัฒนาวิธีบังคับให้โมเดลสร้าง JSON ที่ถูกต้องตามรูปแบบ — นี่คือความแตกต่างระหว่างสองแนวทาง
ตอนนี้ทั้งสองค่ายมีโหมดเข้มงวด (strict mode) ที่รับประกันผลลัพธ์ตรงตามสคีมาแทนที่จะหวังให้โมเดลจัดรูปแบบถูกต้องเอง กฎการตั้งค่ามีความเฉพาะเจาะจง และคำแนะนำอย่างเป็นทางการของ OpenAI ยังคงจำกัดจำนวนเครื่องมือที่ส่งให้โมเดลใช้ในคราวเดียว
คำตอบโดยย่อ
Claude และ OpenAI แนะนำวิธีใดในการได้มาซึ่งผลลัพธ์แบบมีโครงสร้างที่ไม่ต้องตรวจสอบและลองใหม่ซ้ำ
ทั้งสองแพลตฟอร์มมีโหมดเข้มงวดให้ใช้ นั่นคือ `strict: true` บนคำนิยามเครื่องมือของ Claude และ Structured Outputs ของ OpenAI ที่ใส่ `strict: true` ในรูปแบบการตอบกลับ OpenAI กำหนดให้ต้องมี `additionalProperties: false` และระบุทุกฟิลด์ไว้ใน required โดยฟิลด์ที่เป็นทางเลือกให้กำหนดเป็น nullable แทนการละไว้ คำแนะนำของทั้งสองรายยังเตือนตรงกันว่า คำอธิบายฟังก์ชันที่คลุมเครือและจำนวนเครื่องมือที่มากเกินไปจะบั่นทอนความแม่นยำโดยไม่รู้ตัว
ประเด็นสำคัญ
- Structured Outputs ฝั่ง OpenAI และโหมดเครื่องมือแบบเข้มงวดฝั่ง Claude ต่างรับประกันความสอดคล้องกับสคีมา ซึ่ง "JSON mode" แบบเดิมทำไม่ได้ และยังอาจคืนผลลัพธ์ที่ผิดรูปแบบได้
- สคีมาเข้มงวดของ OpenAI กำหนดให้ต้องมี `additionalProperties: false` และระบุทุกฟิลด์ไว้ใน required โดยไม่มีสิ่งที่เรียกว่าฟิลด์ทางเลือกที่ถูกละไว้จากรายการนี้ คุณต้องกำหนดให้เป็น nullable แทน
- คำแนะนำของ OpenAI เองระบุให้จำกัดจำนวนฟังก์ชันที่ใช้งานได้ไว้ต่ำกว่า 20 รายการเมื่อเริ่มต้นแต่ละเทิร์น เพราะคำนิยามแต่ละตัวถูกนับเป็นโทเคนอินพุต และตัวเลือกที่มากขึ้นจะลดความแม่นยำ
- เอกสารของ Claude ระบุช่องว่างด้านความน่าเชื่อถือระหว่างโมเดลไว้จริง เมื่อพารามิเตอร์ที่จำเป็นหายไปจากพรอมป์ Opus มีแนวโน้มถามกลับมากกว่า ส่วน Sonnet มีแนวโน้มเดาค่าที่ดูสมเหตุสมผลขึ้นมาเองมากกว่า
- ทั้งสองแพลตฟอร์มคิดค่าใช้จ่ายคำนิยามเครื่องมือ/ฟังก์ชันเป็นโทเคนอินพุตปกติในทุกการเรียกใช้ และ Claude เผยแพร่ตัวเลขภาระโทเคนต่อโมเดลไว้อย่างชัดเจน
การให้ LLM เรียกใช้ฟังก์ชันหรือคืนค่าเป็น JSON นั้นทำงานถูกต้อง "เกือบตลอดเวลา" มาโดยตลอด ซึ่งที่จริงแล้วเป็นปัญหาที่แย่ยิ่งกว่าการที่มันไม่ทำงานเลยเสียอีก เพราะความล้มเหลวจะไปโผล่ที่ปลายทาง ในตัวแยกวิเคราะห์ (parser) ที่พังตอนเรียกใช้งานครั้งที่หมื่น ไม่ใช่ในเก้าสิบเก้าครั้งที่คุณทดสอบด้วยมือ ตอนนี้ทั้ง Claude และ OpenAI ต่างเผยแพร่โหมดที่ตัดคำว่า "เกือบตลอดเวลา" ออกจากสมการนี้ และกฎการตั้งค่าอย่างเป็นทางการของแต่ละฝ่ายก็เจาะจงพอที่จะทำตามได้โดยตรง ไม่ต้องเดาสุ่ม
โหมดเข้มงวด บนทั้งสองแพลตฟอร์ม
ฝั่ง Claude: เพียงเพิ่ม strict: true เข้าไปในคำนิยามเครื่องมือแบบกำหนดเอง การเรียกใช้เครื่องมือของ Claude ก็จะรับประกันว่าตรงกับสคีมาแน่นอน ส่วนฝั่ง OpenAI เรียกฟีเจอร์นี้ว่า Structured Outputs ตั้งค่าผ่าน text: { format: { type: "json_schema", strict: true, schema: … } } โดย OpenAI นิยามฟีเจอร์นี้อย่างชัดเจนว่าเป็นทายาทของ "JSON mode" แบบเดิม เพราะ JSON mode ไม่เคยรับประกันว่าสคีมาของคุณจะถูกปฏิบัติตามจริง แต่ Structured Outputs รับประกันได้
เขียนคำอธิบายฟังก์ชันราวกับอธิบายให้คนแปลกหน้าฟัง
คำแนะนำของ OpenAI เองระบุว่าให้เขียนชื่อฟังก์ชัน คำอธิบายพารามิเตอร์ และคำแนะนำการใช้งานให้ชัดเจนพอจะผ่านสิ่งที่เรียกว่า "บททดสอบเด็กฝึกงาน" นั่นคือพนักงานใหม่ต้องสามารถใช้ฟังก์ชันนั้นได้อย่างถูกต้องจากเอกสารเพียงอย่างเดียว โดยไม่ต้องมีบริบทอื่นใดเพิ่มเติม ซึ่งรวมถึงการระบุอย่างชัดเจนในพรอมป์ระบบว่าเมื่อใดควรเรียกใช้ฟังก์ชันและเมื่อใดไม่ควร พร้อมยกตัวอย่างกรณีคาบเกี่ยว ไม่ใช่แค่บอกว่าฟังก์ชันทำอะไรในกรณีที่ชัดเจนอยู่แล้วว่าควรเรียกใช้
เครื่องมือน้อยลง ความแม่นยำสูงขึ้น
เป็นเรื่องน่าดึงดูดที่จะยื่นเครื่องมือทั้งหมดที่คุณมีให้โมเดลแล้วปล่อยให้มันเลือกเองว่าอันไหนเหมาะสม แต่คำแนะนำของ OpenAI คัดค้านแนวทางนี้อย่างตรงไปตรงมา โดยแนะนำให้จำกัดจำนวนฟังก์ชันที่ใช้งานได้ไว้ที่ราว 20 รายการหรือต่ำกว่าเมื่อเริ่มต้นแต่ละเทิร์น เพื่อความแม่นยำที่สูงขึ้น และควรจำไว้ว่าคำนิยามฟังก์ชันทุกตัวจะถูกนับเป็นโทเคนอินพุต ไม่ว่าจะถูกเรียกใช้ในเทิร์นนั้นหรือไม่ก็ตาม หากมีชุดฟังก์ชันที่ถูกเรียกใช้ตามลำดับเดิมทุกครั้ง OpenAI แนะนำให้รวมฟังก์ชันเหล่านั้นเข้าเป็นการดำเนินการเดียว แทนที่จะให้โมเดลต้องเรียกใช้หลายครั้งอย่างถูกต้องเป๊ะทุกครั้งไป
โมเดลของ Claude ไม่ได้ล้มเหลวแบบเดียวกันทั้งหมด
เอกสารของ Claude มีข้อสังเกตด้านความน่าเชื่อถือเฉพาะรายโมเดลที่ควรวางแผนรับมือไว้ล่วงหน้า มากกว่าจะไปพบเจอเอาตอนใช้งานจริง นั่นคือเมื่อพารามิเตอร์ที่จำเป็นหายไปจากสิ่งที่ผู้ใช้พิมพ์จริง Opus มีแนวโน้มสูงกว่ามากที่จะสังเกตเห็นช่องว่างนั้นและถามคำถามเพื่อขอความชัดเจน ในขณะที่ Sonnet มีแนวโน้มที่จะเดาค่าที่ดูสมเหตุสมผลขึ้นมาเอง เช่น เดาสถานที่แทนที่จะถามว่าหมายถึงที่ไหน พฤติกรรมนี้ไม่ได้การันตีว่าจะเป็นไปในทิศทางใดทิศทางหนึ่งเสมอไป แต่เป็นแนวโน้มที่แต่ละโมเดลเอนเอียงไป และยิ่งแย่ลงเมื่อพรอมป์คลุมเครือและใช้โมเดลที่มีความสามารถต่ำกว่า
การบังคับเรียกใช้เครื่องมือ และการรันหลายรายการพร้อมกัน
ทั้งสองแพลตฟอร์มเปิดให้คุณข้ามการตัดสินใจเริ่มต้นของ Claude หรือ OpenAI ว่าจะใช้เครื่องมือหรือไม่ Claude เปิดพารามิเตอร์ tool_choice เพื่อบังคับให้เรียกใช้เครื่องมือ แทนที่จะปล่อยไว้ที่ค่าเริ่มต้น {"type": "auto"} ส่วน OpenAI รองรับการเรียกใช้ฟังก์ชันแบบขนานบน GPT-5 และรุ่นถัดไปสำหรับเครื่องมือในตัว และมี parallel_tool_calls: false หากต้องการให้เรียกใช้ได้อย่างมากหนึ่งครั้งต่อเทิร์นโดยเฉพาะ ทั้งนี้เครื่องมือในตัวไม่สามารถจัดกลุ่มให้รันแบบขนานได้ ไม่ว่าจะตั้งค่านี้อย่างไรก็ตาม
ตรวจสอบวันที่ให้ดี เอกสารของ OpenAI เองแนะนำให้ใช้ gpt-5.6 สำหรับโปรเจกต์ Structured Outputs ใหม่ และระบุว่าฟีเจอร์ค้นหาเครื่องมือใช้ได้เฉพาะกับ gpt-5.4 ขึ้นไปเท่านั้น ส่วนภาระโทเคนจากการใช้เครื่องมือของ Claude ก็เผยแพร่ไว้ตามรุ่นโมเดลปัจจุบัน ตัวเลขทั้งสองชุดนี้เปลี่ยนแปลงได้เมื่อมีโมเดลใหม่เปิดตัว จึงควรอ่านจากหน้าเอกสารต้นทางโดยตรง แทนที่จะยึดตัวเลขข้างต้นว่าคงที่ตลอดไป
คำถามที่พบบ่อย
- Structured Outputs เหมือนกับ JSON mode แบบเดิมหรือไม่
- ไม่เหมือนกัน OpenAI อธิบายว่า Structured Outputs เป็นวิวัฒนาการของ JSON mode โดย JSON mode ไม่รับประกันว่าสคีมาของคุณจะถูกปฏิบัติตาม แต่ Structured Outputs รับประกันได้ ตารางเปรียบเทียบของ OpenAI เองแนะนำให้ใช้ JSON mode แบบเก่าเฉพาะกับโมเดลที่ออกก่อน gpt-4o-2024-08-06 เท่านั้น
- โหมดเข้มงวดกำหนดอะไรบ้างในสคีมา
- สำหรับ OpenAI ต้องมี `additionalProperties: false` ในทุกอ็อบเจกต์ และระบุคุณสมบัติทุกตัวไว้ใน required โดยฟิลด์ที่เป็นทางเลือกจะแสดงเป็นชนิดข้อมูลแบบ nullable แทนการตัดออกจากรายการ required สำหรับ Claude เพียงเพิ่ม `strict: true` เข้าไปในคำนิยามเครื่องมือ
- การมีเครื่องมือให้เลือกใช้มากขึ้นย่อมช่วยให้โมเดลทำงานดีขึ้นเสมอหรือไม่
- ไม่เสมอไป คำแนะนำของ OpenAI ระบุชัดเจนว่าควรจำกัดจำนวนฟังก์ชันที่ใช้งานได้ไว้ที่ราว 20 รายการต่อเทิร์นเพื่อความแม่นยำ และระบุว่าคำนิยามแต่ละตัวจะถูกคิดเป็นโทเคนอินพุต ไม่ว่าจะถูกเรียกใช้ในเทิร์นนั้นหรือไม่
- ฉันสามารถบังคับให้โมเดลเรียกใช้เครื่องมือใดเครื่องมือหนึ่งได้หรือไม่
- ได้ทั้งสองแพลตฟอร์ม Claude เปิดให้ทำผ่านพารามิเตอร์ `tool_choice` ซึ่งมีอธิบายไว้ในหัวข้อการบังคับใช้เครื่องมือ ส่วนการตั้งค่า `parallel_tool_calls: false` ของ OpenAI ก็สามารถใช้ร่วมกับการระบุเครื่องมือแบบชัดเจนเพื่อให้ได้การเรียกใช้เพียงครั้งเดียวเช่นกัน
แหล่งข้อมูล
- Tool use with Claude — Anthropic
- Function calling — OpenAI
- Structured model outputs — OpenAI
- Introduction to Structured Outputs — OpenAI