<!-- Canonical URL: https://ask.atlascloud.ai/th/structured-json-output-after-llm-api-migration -->

# ทำไม Structured JSON Output ถึงพังหลังการย้าย LLM API?

> JSON ที่มีโครงสร้างมักแตกหลังการย้าย API ของ LLM เพราะสแต็กเก่าและใหม่บังคับใช้สัญญาที่ต่างกัน เปรียบเทียบสคีมาคำขอ โหมดการตอบสนอง พฤติกรรมการสตรีม ซองการเรียกเครื่องมือ การปฏิเสธ และกฎการตรวจสอบความถูกต้อง ก่อนที่จะโทษพรอมป์ต์

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

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

## แยกความล้มเหลวทางไวยากรณ์ออกจากความล้มเหลวของสัญญา

"JSON พัง" สามารถอธิบายข้อบกพร่องที่แตกต่างกันหลายแบบ การมองว่าเป็นปัญหาเดียวกันจะนำไปสู่การแก้พรอมป์ตที่ซ่อนสาเหตุที่แท้จริง

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

บันทึกหมวดหมู่เหล่านี้แยกกัน ข้อยกเว้นของตัวแยกวิเคราะห์ ฟิลด์ที่จำเป็นที่ขาดหาย และ `400` ระดับ API ไม่ควรใช้ตัวนับการลองใหม่แบบทั่วไปตัวเดียวกัน

## เปรียบเทียบสัญญาคำขอทั้งสอง

เริ่มด้วยเมทริกซ์การย้ายระบบทีละฟิลด์ ชื่อที่ดูคล้ายกันไม่ได้หมายความว่ามีความหมายเดียวกันเสมอ

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

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

## ลดสคีมาก่อนเปลี่ยนพรอมป์ต

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

ตัวอย่างเช่น ฐานรากที่พกพาได้อาจมีลักษณะเช่นนี้:

```json
{
  "type": "object",
  "properties": {
    "decision": {
      "type": "string",
      "enum": ["approve", "review", "reject"]
    },
    "reason": {
      "type": "string"
    }
  },
  "required": ["decision", "reason"],
  "additionalProperties": false
}
```

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

## ตรวจสอบว่าข้อมูลที่มีโครงสร้างอยู่ที่ใด

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

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

```ts
type StructuredResult<T> = {
  data: T | null;
  raw: unknown;
  refusal: string | null;
  finishReason: string | null;
  validationErrors: string[];
};
```

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

## อย่าแยกวิเคราะห์สตรีมที่ยังไม่เสร็จ

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

การทดสอบสตรีมมิงของคุณควรครอบคลุมมากกว่าเส้นทางที่ราบรื่น:

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

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

## ตรวจสอบสองครั้ง แต่นำซ่อมอย่างระมัดระวัง

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

ลำดับที่ใช้ได้จริงคือ:

1. ยืนยันว่าคำขอ HTTP สำเร็จ
2. ตรวจจับการปฏิเสธ การตัดทอน หรือการเสร็จสิ้นการเรียกเครื่องมืออย่างชัดเจน
3. แยกเพย์โหลดที่มีโครงสร้างที่เสร็จสมบูรณ์
4. แยกวิเคราะห์หนึ่งครั้ง
5. ตรวจสอบด้วยเวอร์ชันสคีมาของแอปพลิเคชัน
6. ปฏิเสธค่าที่ไม่รู้จักหรือไม่ปลอดภัยก่อนลอจิกธุรกิจทำงาน

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

## สร้างชุดรีเพลย์สำหรับการย้ายระบบ

ก่อนส่งทราฟฟิกโปรดักชัน ให้รวบรวมคลังข้อมูลขนาดกะทัดรัดจากรูปร่างคำขอจริง ลบข้อมูลส่วนบุคคลหรือข้อมูลความลับ แล้วรวมกรณีที่ทดสอบขอบเขตของสัญญา

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

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

## ซ่อนความเข้ากันได้ไว้หลังอะแดปเตอร์

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

เกตเวย์ที่เข้ากันได้กับ OpenAI เช่น [Atlas Cloud](https://www.atlascloud.ai/?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=structured-json-output-after-llm-api-migration) สามารถลดงานผสานรวมซ้ำ ๆ เมื่อแอปพลิเคชันใช้โมเดลข้อความ รูปภาพ และวิดีโอ ความเข้ากันได้ในชั้นขนส่งมีประโยชน์ แต่ไม่ได้ลบการทดสอบระดับโมเดล เก็บแฟล็กความสามารถสำหรับเอาต์พุตที่มีโครงสร้าง เครื่องมือ สตรีมมิง และคุณสมบัติสคีมา แทนที่จะสมมติว่าโมเดลทุกตัวหลังปลายทางที่เข้ากันได้มีพฤติกรรมเหมือนกัน

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

## ใช้การเปิดตัวแบบเป็นขั้นตอนพร้อมเงื่อนไขหยุดที่ชัดเจน

เริ่มจากรีเพลย์ออฟไลน์ จากนั้นทราฟฟิกเงา แล้วจึงเปอร์เซ็นต์ไลฟ์เล็ก ๆ อย่าพึ่งความสำเร็จแบบรวมเท่านั้น อัตราความถูกต้อง 99% อาจยังยอมรับไม่ได้ หากความล้มเหลว 1% กระจุกอยู่ที่คำขอชำระเงิน การกลั่นกรอง หรือการอนุญาต

กำหนดเงื่อนไขหยุดก่อนทดสอบ:

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

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

## สรุปสำคัญ

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

## FAQ

### ทำไมพรอมต์ JSON เดียวกันจึงใช้ได้กับโมเดลหนึ่งแต่กลับล้มเหลวกับอีกโมเดลหนึ่ง?

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

### โหมด JSON เหมือนกับการบังคับใช้ JSON Schema หรือไม่

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

### ควรแยกวิเคราะห์ JSON ที่สตรีมมาแบบทีละโทเคนหรือไม่

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

### API ที่เข้ากันได้กับ OpenAI สามารถขจัดงานการย้ายระบบได้หรือไม่

มันสามารถลดการเปลี่ยนแปลงด้าน transport และ SDK ได้ แต่คุณยังต้องตรวจสอบคุณสมบัติสคีมาเฉพาะโมเดล เหตุผลการสิ้นสุด รูปแบบการเรียกใช้เครื่องมือ และพฤติกรรมการเกิดข้อผิดพลาด

### ควรเกิดอะไรขึ้นเมื่อการตรวจสอบไม่ผ่าน

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

### การทดสอบก่อนการผลิตที่เร็วที่สุดคืออะไร

รีเพลย์ชุดข้อมูลคงที่ของคำขอประเภทปกติ กำกวม เชิงโจมตี แบบปฏิเสธ บริบทยาว และสตรีมมิ่ง กับทั้งสองสแตก แล้วเปรียบเทียบเอาต์พุตที่ผ่านการตรวจสอบแล้วทีละฟิลด์
