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

# Mengapa Output JSON Terstruktur Rusak Setelah Migrasi API LLM?

> JSON terstruktur biasanya rusak setelah migrasi API LLM karena stack lama dan baru menerapkan kontrak yang berbeda. Bandingkan skema permintaan, mode respons, perilaku streaming, envelope pemanggilan alat, penolakan, dan aturan validasi sebelum menyalahkan prompt.

Migrasi mengubah lebih dari sekadar hostname. Migrasi dapat mengubah model, serialisasi SDK, kata kunci skema yang didukung, urutan peristiwa streaming, nilai sampling default, perilaku keamanan, dan lokasi persis payload yang dihasilkan. Permintaan yang tampak ekuivalen dalam kode aplikasi karena itu dapat merepresentasikan kontrak yang berbeda di wire.

Diagnosis tercepat adalah menyimpan satu permintaan yang gagal dan responsnya yang tidak diubah dari kedua penyedia. Bandingkan body HTTP yang sebenarnya, bukan objek pembungkus yang diekspos SDK Anda. Perbandingan itu biasanya mengungkap apakah kegagalan terjadi sebelum generasi, selama generasi, atau saat aplikasi Anda mengekstrak dan memvalidasi hasil.

## Pisahkan kegagalan sintaks dari kegagalan kontrak

"JSON rusak" dapat menggambarkan beberapa cacat berbeda. Memperlakukannya sebagai satu masalah menyebabkan penyuntingan prompt yang menyembunyikan penyebab sebenarnya.

* Kegagalan sintaks menghasilkan teks yang tidak dapat dibaca parser JSON.
* Kegagalan skema menghasilkan JSON valid dengan kunci, tipe, penyarangan, atau nilai enum yang salah.
* Kegagalan ekstraksi terjadi ketika data terstruktur yang valid ada di field respons yang berbeda.
* Kegagalan streaming terjadi ketika potongan parsial diurai sebagai dokumen lengkap.
* Kegagalan penolakan atau pemotongan menggantikan objek yang diharapkan dengan pesan keamanan atau payload yang tidak lengkap.
* Kegagalan tool-call mengembalikan argumen dalam envelope alat sementara aplikasi mengharapkan teks asisten.

Catat kategori ini secara terpisah. Pengecualian parser, field wajib yang hilang, dan `400` tingkat API tidak boleh berbagi satu penghitung retry generik.

## Bandingkan dua kontrak permintaan

Mulailah dengan matriks migrasi field demi field. Nama yang tampak serupa tidak selalu berarti hal yang sama.

| Area kontrak | Stack lama | Stack baru | Pertanyaan pengujian |
|---|---|---|---|
| Mode output | Objek JSON | Objek terikat skema | Apakah hanya menjamin sintaks atau skema penuh? |
| Lokasi skema | Parameter alat | Format respons | Apakah skema dilampirkan ke field permintaan yang benar? |
| Keketatan | Implisit | Flag eksplisit | Apakah mode ketat harus diaktifkan? |
| Kata kunci tidak didukung | Diabaikan | Ditolak | Apakah union, format, default, atau referensi diterima? |
| Kunci tambahan | Diizinkan | Diblokir | Apakah `additionalProperties` ditangani secara konsisten? |
| Streaming | Delta teks | Peristiwa bertipe | Peristiwa mana yang berisi objek selesai? |
| Penolakan | Teks asisten | Field khusus | Dapatkah ekstraktor membedakan penolakan dari output? |

Tangkap permintaan terserialisasi final setelah pemrosesan SDK. Default yang diperkenalkan klien lama mungkin hilang selama migrasi. Sebaliknya juga terjadi: SDK baru mungkin menambahkan flag ketat atau mengganti nama field format respons tanpa error aplikasi yang jelas.

## Kecilkan skema sebelum mengubah prompt

Uji skema terkecil yang mungkin terlebih dahulu. Mulailah dengan satu string wajib dan tanpa cabang opsional. Tambahkan integer, array, objek bersarang, enum, dan struktur kondisional satu per satu. Ini mengisolasi fitur yang tidak didukung jauh lebih cepat daripada berulang kali menulis ulang prompt produksi.

Misalnya, baseline portabel mungkin terlihat seperti ini:

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

Jika ini berhasil, jalur transportasi dan penegakan dasar sudah sehat. Jika skema produksi gagal setelah menambahkan satu fitur, Anda memiliki pertanyaan kompatibilitas yang spesifik alih-alih masalah kualitas model yang kabur.

## Periksa di mana payload terstruktur berada

Migrasi penyedia sering merusak kode ekstraksi. Satu stack mungkin mengembalikan JSON dalam pesan asisten, yang lain dalam properti kenyamanan yang telah diuraikan, dan yang lain sebagai argumen alat yang di-stringify. Streaming mungkin mengekspos urutan peristiwa bertipe alih-alih delta teks biasa.

Buat hasil internal yang dinormalisasi sebelum bagian lain aplikasi melihat respons:

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

Pertahankan `raw` selama periode migrasi. Itu adalah bukti yang diperlukan untuk membedakan cacat output model dari cacat adaptor. Lakukan redaksi konten sensitif sebelum menyimpan log, dan tetapkan periode retensi yang sesuai untuk aplikasi Anda.

## Jangan mengurai stream yang belum selesai

Dokumen JSON umumnya tidak valid sampai byte terakhirnya tiba. Mengurai setiap delta teks akan menghasilkan error yang diharapkan tetapi tampak seperti kegagalan produksi. Entah buffer output lengkap, gunakan parser JSON inkremental yang didukung penyedia, atau konsumsi peristiwa terdokumentasi yang merepresentasikan respons terstruktur yang telah difinalisasi.

Uji streaming Anda harus mencakup lebih dari jalur normal:

* string yang terbelah di antara chunk;
* tanda kutip yang di-escape dan karakter Unicode;
* array dengan banyak elemen;
* pemutusan koneksi sebelum kurung kurawal penutup;
* peristiwa penolakan;
* objek final yang valid diikuti metadata penggunaan;
* argumen alat yang dikirim dalam beberapa delta.

Perlakukan gangguan jaringan sebagai generasi yang tidak lengkap, bukan sebagai output model yang cacat. Mencoba lagi bisa aman untuk permintaan klasifikasi hanya-baca, tetapi mungkin tidak aman jika hasilnya memicu efek samping eksternal.

## Validasi dua kali, tetapi perbaiki dengan hati-hati

Penyedia mungkin menegakkan skema, tetapi aplikasi Anda tetap harus memvalidasi hasil yang dinormalisasi di batas kepercayaannya. Ini melindungi Anda dari kesalahan adaptor, regresi fitur, dan asumsi yang tidak pernah dijanjikan penyedia.

Urutan yang praktis adalah:

1. Konfirmasi bahwa permintaan HTTP berhasil.
2. Deteksi penolakan, pemotongan, atau penyelesaian tool-call secara eksplisit.
3. Ekstrak payload terstruktur yang telah selesai.
4. Urai sekali.
5. Validasi dengan versi skema aplikasi.
6. Tolak nilai yang tidak dikenal atau tidak aman sebelum logika bisnis berjalan.

Hindari loop "perbaiki JSON ini" tanpa batas. Model perbaikan dapat mengubah makna saat membuat sintaks menjadi valid. Jika perbaikan dapat diterima, batasi menjadi satu percobaan, berikan error validasi, pertahankan output asli, dan validasi objek yang diperbaiki lagi. Untuk tindakan berdampak tinggi, kirim kasus ke peninjauan.

## Bangun suite replay migrasi

Sebelum merutekan lalu lintas produksi, susun korpus ringkas dari bentuk permintaan nyata. Hapus data pribadi atau rahasia, lalu sertakan kasus yang menguji batas kontrak Anda.

| Grup kasus | Yang disertakan | Kondisi lulus |
|---|---|---|
| Normal | Input pendek umum | Objek valid dengan nilai yang diharapkan |
| Field opsional | Varian hilang dan ada | Perilaku wajib dan opsional sesuai kontrak |
| Ambigu | Input yang bertentangan atau kurang spesifik | Objek valid plus status ketidakpastian yang diizinkan |
| Konteks panjang | Mendekati maksimum normal aplikasi | Tidak ada pemotongan dan ekstraksi valid |
| Adversarial | Teks yang meminta model mengabaikan skema | Skema tetap utuh |
| Penolakan | Permintaan yang tidak diizinkan atau tidak aman | Penolakan terdeteksi tanpa kebingungan parser |
| Streaming | Batas chunk dan pemutusan | Hanya payload selesai yang mencapai validasi |

Jalankan kedua penyedia dengan parameter stabil dan catat tingkat validitas, kesepakatan semantik, tingkat penolakan, tingkat pemotongan, latensi, dan jumlah retry. Kesetaraan semantik yang persis tidak selalu diharapkan, tetapi validitas skema harus menjadi gerbang wajib.

## Tempatkan kompatibilitas di belakang adaptor

Jangan biarkan tipe respons penyedia merembes ke seluruh basis kode. Adaptor kecil harus memiliki konstruksi permintaan, pemeriksaan kemampuan skema, ekstraksi respons, alasan selesai, field penggunaan, dan normalisasi error. Bagian lain aplikasi harus mengonsumsi satu antarmuka internal.

Gateway yang kompatibel dengan OpenAI seperti [Atlas Cloud](https://www.atlascloud.ai/?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=structured-json-output-after-llm-api-migration) dapat mengurangi pekerjaan integrasi berulang ketika aplikasi menggunakan model teks, gambar, dan video. Kompatibilitas di lapisan transportasi berguna, tetapi tidak menghilangkan pengujian tingkat model. Pertahankan flag kemampuan untuk output terstruktur, alat, streaming, dan fitur skema alih-alih mengasumsikan setiap model di balik endpoint yang kompatibel berperilaku identik.

Versikan adaptor dan skema bersama-sama. Ketika skema berubah, simpan versi skema bersama output agar layanan hilir mengetahui kontrak mana yang mereka terima.

## Gunakan peluncuran bertahap dengan kondisi berhenti yang jelas

Mulailah dengan replay offline, lalu lalu lintas bayangan, lalu persentase live kecil. Jangan hanya mengandalkan keberhasilan agregat. Tingkat validitas 99% masih bisa tidak dapat diterima jika 1% kegagalan mengelompok pada permintaan pembayaran, moderasi, atau otorisasi.

Tentukan kondisi berhenti sebelum pengujian:

* enum yang tidak aman mencapai logika bisnis;
* tingkat validitas skema turun di bawah baseline saat ini;
* penanganan penolakan menjadi ambigu;
* pemotongan meningkat melampaui ambang yang disepakati;
* retry meningkatkan biaya atau latensi melampaui anggaran aplikasi;
* respons mentah tidak dapat direkonsiliasi dengan output yang dinormalisasi.

Lakukan rollback melalui konfigurasi perutean alih-alih deployment kode darurat jika memungkinkan. Pertahankan adaptor lama tetap tersedia sampai jalur baru bertahan dari beban puncak dan kelas input yang jarang.

## Intinya

Kegagalan JSON terstruktur setelah migrasi API LLM biasanya merupakan ketidakcocokan kontrak, kesalahan ekstraksi, atau logika streaming yang tidak lengkap, bukan bukti bahwa model baru tidak dapat mengikuti instruksi. Bandingkan payload wire, kecilkan skema, normalisasi respons, validasi di batas aplikasi, dan replay korpus yang representatif sebelum mengalihkan lalu lintas. API yang kompatibel dapat menyederhanakan perpindahan, tetapi pengujian kemampuan yang eksplisit tetap menjadi cara andal untuk melindungi perilaku produksi.

## FAQ

### Mengapa prompt JSON yang sama berhasil di satu model tetapi gagal di model lain?

Pilihan kata dalam prompt hanyalah satu lapisan. Model dan penyedia berbeda dalam mode JSON native, dukungan skema, tokenisasi, perilaku penolakan, dan seberapa ketat mereka mematuhi batasan.

### Apakah mode JSON sama dengan penegakan JSON Schema?

Tidak. Mode JSON hanya dapat menjamin JSON yang valid secara sintaksis, sedangkan penegakan skema juga membatasi kunci, tipe, bidang yang wajib, dan terkadang properti tambahan.

### Haruskah saya mengurai JSON yang di-stream token per token?

Biasanya tidak. Buffer payload terstruktur lengkap atau gunakan event structured-streaming yang didokumentasikan penyedia, lalu validasi setelah event terakhir.

### Bisakah API yang kompatibel dengan OpenAI menghilangkan pekerjaan migrasi?

Ini dapat mengurangi perubahan transport dan SDK, tetapi Anda tetap perlu memverifikasi fitur skema khusus model, alasan penghentian, format pemanggilan alat, dan perilaku error.

### Apa yang harus terjadi ketika validasi gagal?

Tangkap respons mentah, klasifikasikan kegagalan, coba ulang hanya kasus transien yang aman, dan arahkan perbaikan deterministik melalui langkah validasi yang berbatas alih-alih diam-diam menerima data yang cacat.

### Apa uji praproduksi tercepat?

Jalankan ulang korpus tetap yang terdiri atas permintaan normal, ambigu, adversarial, penolakan, konteks panjang, dan streaming terhadap kedua stack, lalu bandingkan output yang telah divalidasi field demi field.
