CCA · Foundations

nullable/optional field กันการกุค่า และ enum other สำหรับหมวดที่ขยายได้

แนวคิด

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

เหตุผลตรงไปตรงมา เมื่อ field เป็น required และ schema ถูกบังคับด้วย strict tool use โมเดลต้องกรอกค่าให้ครบเพื่อให้ output ผ่าน schema ถ้าเอกสารไม่มีข้อมูลนั้นจริง โมเดลจะถูกกดดันให้กุค่าขึ้นมาเติมช่อง เพราะการปล่อยว่างจะทำให้ไม่ผ่าน การทำให้ field เป็น optional หรือยอมรับ null จึงเปิดทางให้โมเดลบอกว่า "ไม่มีข้อมูล" ได้อย่างซื่อสัตย์ แทนการประดิษฐ์ค่าปลอม

ทำไมสำคัญ

การกุค่าในงาน extraction อันตรายกว่าการปล่อยว่าง เพราะ null บอกความจริงว่าไม่พบข้อมูล ส่วนค่าปลอมดูเหมือนข้อมูลจริงและไหลเข้าสู่ระบบปลายทางโดยไม่มีใครสงสัย due_date ที่กุขึ้นมาอาจทำให้ระบบทวงเงินผิดวัน ในขณะที่ due_date เป็น null จะกระตุ้นให้ระบบไปหาข้อมูลเพิ่มหรือส่งให้คนตรวจ การออกแบบ field ให้สื่อ "ไม่มี" ได้ จึงเป็นการป้องกัน hallucination ที่ระดับ schema

อีกรูปแบบที่ควรรู้คือการจัดหมวดที่ขยายได้ เวลาต้องจัดประเภทข้อมูลที่อาจโผล่ประเภทใหม่ที่ไม่ได้คาดไว้ ถ้าใช้ enum ปิดตายด้วยค่าที่รู้แค่ตอนนี้ โมเดลจะถูกบังคับให้ยัดข้อมูลแปลกใหม่เข้าหมวดที่ไม่ตรง ทางแก้คือเพิ่มค่า enum พิเศษอย่าง "other" คู่กับ field detail ที่เป็นข้อความอิสระ ให้โมเดลเลือก other แล้วอธิบายรายละเอียดของประเภทใหม่ลงใน detail แทนที่จะบิดให้เข้าหมวดเดิม แนวปฏิบัติที่ดีคือแนะนำค่าอย่าง "unclear" สำหรับเคสที่ตัดสินไม่ได้ด้วย

รายละเอียดเพิ่มที่เอกสาร structured outputs ระบุคือ ลำดับ property ใน output จะยก required ขึ้นก่อน แล้วตามด้วย optional เสมอ ถ้าโค้ดฝั่งคุณพึ่งลำดับ field ให้เผื่อเรื่องนี้ไว้ หรือทำทุก field เป็น required แล้วยอมรับ null แทน ทั้งหมดนี้ประกอบกันเป็นหลักออกแบบ schema ที่สื่อความไม่แน่นอนได้ตรงตามความจริงของเอกสาร

ตัวอย่าง

{
  "type": "object",
  "properties": {
    "invoice_number": { "type": "string" },
    "due_date":       { "type": ["string", "null"] },
    "category":       { "type": "string", "enum": ["service", "goods", "other"] },
    "category_detail":{ "type": ["string", "null"] }
  },
  "required": ["invoice_number", "category"],
  "additionalProperties": false
}
// due_date เป็น optional/nullable → เอกสารไม่ระบุ ก็ใส่ null ได้ ไม่ต้องกุ
// category enum มี "other" + category_detail → รับประเภทใหม่ที่ไม่เคยคาด

ลองปรับ field ในซิมด้านล่างเพื่อดูว่า schema ที่ต่างกันส่งผลต่อการดึงค่าและการปล่อย null อย่างไร

fieldมีในต้นฉบับ?schemaค่าที่สกัดได้
invoice_number<value from source>
due_datenull
po_number⚠️ (แต่งขึ้น)

ฟิลด์ที่ ไม่มีในต้นฉบับ + required คือจุดเสี่ยง: schema บังคับให้ต้องมีค่า แต่ต้นฉบับไม่มีข้อมูลนั้นจริง ๆ โมเดลเลยถูกกดดันให้ 'แต่งขึ้น' แทนที่จะบอกว่าไม่รู้

เปลี่ยนฟิลด์นั้นให้เป็น nullable แล้วดูผลลัพธ์เปลี่ยนเป็น null — การอนุญาตให้เป็น null คือสิ่งที่ป้องกันการแต่งข้อมูลขึ้นมา

เช็คความเข้าใจ

ทำไมการตั้ง field ที่เอกสารอาจไม่มีข้อมูลให้เป็น required จึงเสี่ยงต่อการ fabrication

จะออกแบบ schema อย่างไรให้จัดหมวดที่อาจมีประเภทใหม่โผล่มาโดยไม่บิดข้อมูลเข้าหมวดเดิม

อ่านต่อ