Menu

Structured Output: JSON yang Andal dari LLM

Output terstruktur (structured output) berarti meminta jawaban dari model dalam bentuk yang sudah ditetapkan, seperti JSON, tabel, atau template, supaya program atau orang bisa langsung memakainya tanpa membentuk ulang. Berikan skemanya, sebutkan apa yang harus dilakukan dengan nilai yang tidak ada, dan validasi hasilnya di kode.

Setiap prompt di bawah bisa diedit: ubah, lalu buka di ChatGPT, Claude, atau aplikasi AI lain.

Output terstruktur (structured output) adalah jawaban dalam bentuk yang sudah kamu tentukan sebelumnya: objek JSON dengan key yang bernama, tabel dengan kolom yang tetap, atau template dengan judul yang sama setiap kali. Kamu membutuhkannya setiap kali program membaca jawabannya, dan bentuk ini juga membantu ketika yang membaca adalah orang, karena setiap jawaban jadi terlihat sama dan mudah dipindai atau dibandingkan.

Kuncinya adalah menjelaskan bentuknya dengan sangat tepat sampai model tidak punya pilihan lagi. Kata "JSON" saja bukanlah sebuah penjelasan. Blok di bawah ini mengambil detail dari sebuah laporan bug. Bandingkan permintaan untuk "detail-detail pentingnya" dengan permintaan yang menjabarkan skemanya.

Ambil detail-detail penting dari laporan bug ini: "Sejak update kemarin aplikasinya crash setiap kali aku mengetuk Ekspor di proyek yang berisi lebih dari 50 foto. Proyek yang lebih kecil bisa diekspor dengan lancar. Aku pakai Android 14, versi aplikasi 3.2.0. Ini menghambat pengiriman ke klienku."
Try it
Example replyReplies vary between models and runs.

Berikut detail-detail penting dari laporan bug tersebut:

  • Masalah: Aplikasi crash saat mengekspor proyek
  • Pemicu: Mengetuk Ekspor pada proyek yang berisi lebih dari 50 foto
  • Mulai terjadi: Setelah update terakhir
  • Platform: Android 14
  • Versi aplikasi: 3.2.0
  • Dampak: Tinggi, karena menghambat pengiriman ke klien

Proyek yang lebih kecil tampaknya bisa diekspor tanpa masalah.

Jawaban teks bebas itu akurat dan enak dibaca, tapi tidak akan ada dua percobaan yang memakai label yang sama, tingkat keparahannya berupa kalimat dan bukan nilai, dan program harus menebak di mana setiap field dimulai. Jawaban JSON bisa langsung masuk ke bug tracker. Perhatikan bahwa balasannya tetap datang di dalam code fence: aplikasi chat biasanya membungkus JSON dengan cara itu, dan ini penting saat kamu mem-parse-nya di kode.

Cara meminta JSON

Permintaan JSON yang bagus menjawab setiap pertanyaan yang kalau tidak akan dijawab model untukmu:

  • Setiap key, dieja dengan tepat. Tulis nama-nama key di dalam tanda kutip persis seperti yang harus muncul. Sebutkan "tepat key-key berikut" supaya model tidak menambahkan key lain.
  • Tipe setiap nilai. String, angka, boolean, array berisi string, objek bersarang.
  • Nilai yang diperbolehkan untuk field yang pilihannya tetap, seperti tingkat keparahan atau kategori. Tanpa daftar itu, kamu akan mendapat "High", "high", "severe", dan "P1" dalam empat percobaan.
  • Apa yang harus dilakukan kalau input-nya tidak punya sebuah nilai. Kalau kamu tidak menyebutkan "null kalau tidak disebutkan", model cenderung mengisi celahnya dengan tebakan yang masuk akal, dan versi aplikasi hasil tebakan terlihat persis seperti versi yang asli.
  • Tidak ada apa pun di sekitarnya. "Kembalikan JSON-nya saja, tanpa teks sebelum atau sesudahnya" menghilangkan kalimat pembuka yang ramah.

Ketika bentuknya bersarang atau tidak biasa, menunjukkan satu contoh objek yang lengkap lebih berhasil daripada menjelaskannya. Itulah few-shot prompting yang diterapkan pada format. Buat nilai-nilai di contoh itu jelas berbeda dari input yang sebenarnya supaya model tidak menyalinnya.

Prompt ekstraksi yang bisa dipakai ulang

Blok ini berisi permintaan yang sama tapi dipecah menjadi beberapa bagian. Matikan bagian format dan model tetap mengembalikan JSON, karena batasannya memintanya, tapi model memilih nama key-nya sendiri, seperti title alih-alih job_title, dan kode yang mengharapkan key-key milikmu jadi rusak. Bagian batasan yang mencegahnya melengkapi nomor telepon yang setengah tertulis atau menebak nama perusahaan dari domain email. Tempel tanda tangan email sungguhan ke kolom input untuk mengujinya.

Ambil detail kontak sebagai JSON
Fill in
Parts
Ambil detail kontak dari tanda tangan email di bawah ini.
Kembalikan objek JSON dengan tepat key-key berikut: { "name": "string", "job_title": "string or null", "company": "string or null", "email": "string or null", "phone": "string or null" }
Pakai null untuk nilai apa pun yang tidak ada di teks. Jangan menebak atau melengkapi nilai yang tidak lengkap. Kembalikan JSON-nya saja.
Priya Nair | Head of Data, Northwind Labs | priya.nair@northwind.example
Try it
Example replyReplies vary between models and runs.
{
  "name": "Priya Nair",
  "job_title": "Head of Data",
  "company": "Northwind Labs",
  "email": "priya.nair@northwind.example",
  "phone": null
}

Tabel dan template tetap

Output terstruktur bukan hanya untuk program. Ketika kamu sendiri yang membaca jawabannya, tabel markdown atau template tetap memberimu manfaat yang sama: kamu sudah tahu di mana setiap informasi berada sebelum melihatnya.

Tabel
Bandingkan list, tuple, dan set di Python dalam tabel markdown dengan kolom-kolom ini: Tipe, Berurutan, Bisa diubah, Boleh duplikat, Penggunaan umum. Satu baris per tipe. Tidak ada teks di luar tabel.
Try it
Example replyReplies vary between models and runs.
TipeBerurutanBisa diubahBoleh duplikatPenggunaan umum
listYaYaYaUrutan data yang bisa ditambah, dikurangi, atau diurutkan
tupleYaTidakYaSekelompok nilai yang tetap, seperti koordinat
setTidakYaTidakMenghapus duplikat dan mengecek keanggotaan dengan cepat

Template bekerja dengan cara yang sama untuk teks yang lebih panjang: berikan judul-judulnya secara berurutan dan sebutkan apa yang ada di bawah masing-masing. "Jawab dengan tiga label tebal: Penyebab, Perbaikan, Cara mengecek" menghasilkan tiga label yang sama setiap kali, sehingga sekumpulan jawaban mudah dibandingkan.

JSON mode di API

Beberapa API model punya pengaturan yang memaksa output berupa JSON yang valid secara sintaks. Di SDK Python milik OpenAI, pengaturannya adalah response_format. JSON mode mensyaratkan kata "JSON" muncul di suatu tempat di pesan-pesanmu, jadi prompt sistem di bawah menyebutnya dan mendaftarkan key-key-nya.

import json
from openai import OpenAI

client = OpenAI()
MODEL = "your-model-id"  # e.g. from your provider's model list

report_text = "Since yesterday's update the app crashes when I tap Export..."

response = client.chat.completions.create(
    model=MODEL,
    response_format={"type": "json_object"},
    messages=[
        {
            "role": "system",
            "content": (
                "Extract the bug report into JSON with the keys "
                "summary (string), severity (one of low, medium, high, critical) "
                "and steps_to_reproduce (array of strings)."
            ),
        },
        {"role": "user", "content": report_text},
    ],
)

data = json.loads(response.choices[0].message.content)

JSON mode memastikan teksnya bisa di-parse (kecuali balasannya terpotong di batas token), bukan memastikan teksnya cocok dengan skemamu. Sebuah key masih bisa hilang atau tingkat keparahannya masih bisa berisi "urgent". Beberapa penyedia juga menerima JSON Schema lengkap, sebagai format output atau sebagai skema input dari definisi tool (function), dan beberapa mode ini membatasi jawabannya sesuai skema. Cek dokumentasi penyediamu untuk parameter yang tepat, karena fitur-fitur ini berbeda di setiap API.

Validasi hasilnya di kode

Perlakukan JSON dari model seperti kamu memperlakukan input apa pun dari luar programmu: parse dulu, lalu cek. Parsing menangkap sintaks yang rusak. Pengecekan menangkap objek yang valid tapi isinya salah.

ALLOWED_SEVERITIES = {"low", "medium", "high", "critical"}

def problems(data):
    if not isinstance(data, dict):
        return ["the answer must be a JSON object"]
    found = []
    if not isinstance(data.get("summary"), str):
        found.append("summary must be a string")
    if data.get("severity") not in ALLOWED_SEVERITIES:
        found.append("severity must be low, medium, high or critical")
    steps = data.get("steps_to_reproduce")
    if not isinstance(steps, list) or not all(isinstance(s, str) for s in steps):
        found.append("steps_to_reproduce must be an array of strings")
    return found

Ketika pengecekannya gagal, satu kali percobaan ulang sering kali sudah memperbaikinya: kirim output model itu sendiri bersama daftar masalahnya, lalu minta JSON yang sudah diperbaiki. Batasi jumlah percobaan ulangnya, dan catat kegagalannya, karena field yang sering gagal menandakan prompt-nya kurang jelas. Di proyek yang lebih besar, library validasi seperti Pydantic atau validator JSON Schema menggantikan fungsi yang ditulis manual.

Ada dua kebiasaan lagi yang mencegah error yang tidak terlihat. Atur batas token output cukup tinggi untuk jawaban terbesar yang kamu perkirakan, karena objek yang terpotong tidak akan pernah bisa di-parse. Lalu, ketika input-nya panjang atau berasal dari pengguna, pisahkan dari instruksimu dengan delimiter atau tag XML supaya teks di dalamnya tidak mudah terbaca sebagai instruksi. Kalau satu prompt harus bernalar sekaligus menghasilkan JSON, pertimbangkan prompt chaining: biarkan satu langkah berpikir dalam teks bebas dan langkah kedua mengubah hasilnya menjadi struktur.

Pertanyaan yang sering diajukan

Bagaimana cara membuat ChatGPT menghasilkan output JSON?

Sebutkan bahwa jawabannya harus JSON, daftarkan setiap key beserta tipenya, dan berikan nilai-nilai yang diperbolehkan untuk field yang pilihannya tetap. Tambahkan "Kembalikan JSON-nya saja, tanpa teks sebelum atau sesudahnya." Di API, aktifkan juga JSON mode dengan response_format={"type": "json_object"}, yang mensyaratkan kata JSON muncul di pesan-pesanmu.

Kenapa model menambahkan teks di sekitar JSON-nya?

Model chat dilatih untuk bercakap-cakap, jadi model sering membuka dengan kalimat seperti "Ini JSON-nya" atau membungkus objeknya dalam code fence markdown. Minta JSON-nya saja, dan di kode pakai JSON mode dari API atau buang code fence di sekelilingnya sebelum parsing.

Apa itu JSON mode?

JSON mode adalah pengaturan API yang membuat model menghasilkan JSON yang valid secara sintaks, selama balasannya tidak terpotong oleh batas token output. JSON mode tidak membuat model mengikuti skemamu: key masih bisa hilang, salah eja, atau bertipe salah. Beberapa penyedia juga menawarkan mode yang lebih ketat yang menerima JSON Schema lengkap dan membatasi output-nya sesuai skema itu.

Apakah LLM selalu bisa mengembalikan JSON yang valid?

Tidak kalau hanya mengandalkan prompt. Instruksi yang jelas pun sesekali gagal, dan jawaban yang terpotong oleh batas token output pasti tidak valid. Parse setiap respons dengan parser JSON sungguhan, cek field yang kamu butuhkan, dan ulangi permintaannya atau gagalkan secara jelas kalau pengecekannya tidak lolos.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai