Prompt Engineering
Prompt Engineering 14: Output Terstruktur dan Validasi
Program butuh data yang bisa diproses, bukan paragraf. Pelajari cara meminta JSON sesuai skema, memakai fitur output terstruktur di API, memvalidasi hasil, dan menangani keluaran yang tidak sesuai.

Diperiksa terakhir: 16 Oktober 2026. Nama field dan batasan skema dicocokkan dengan dokumentasi resmi pada tanggal tersebut.
Di materi 05 kita meminta JSON lewat prompt. Untuk dipakai manusia, cara itu cukup. Untuk program, satu koma yang hilang atau satu kalimat pembuka ("Berikut JSON-nya:") sudah cukup membuat aplikasi error. Materi ini membahas cara mendapatkan data terstruktur yang andal: skema yang jelas, fitur output terstruktur di API, dan validasi di kode.
Yang akan dipelajari
- Mendefinisikan bentuk data dengan JSON Schema
- Tiga tingkat keandalan: prompt saja, mode JSON, dan output terstruktur
- Memvalidasi hasil di kode
- Menangani keluaran yang tidak sesuai: coba ulang dan perbaikan
- Merancang skema yang membantu model
JSON Schema singkat
JSON Schema adalah cara standar mendeskripsikan bentuk data JSON. Contoh skema untuk ekstraksi data paper:
{
"type": "object",
"properties": {
"judul": { "type": "string" },
"tahun": { "type": ["integer", "null"] },
"metode": { "type": "array", "items": { "type": "string" } },
"dataset_publik": { "type": "string", "enum": ["ya", "tidak", "tidak_jelas"] }
},
"required": ["judul", "tahun", "metode", "dataset_publik"],
"additionalProperties": false
}
Hal yang perlu diperhatikan:
"type": ["integer", "null"]mengizinkannulljika tahun tidak ditemukan, sehingga model tidak dipaksa mengarang.enummembatasi nilai ke pilihan tertentu, sehingga mudah diproses program."additionalProperties": falsemelarang field tambahan.
Tiga tingkat keandalan
| Cara | Bagaimana | Keandalan |
|---|---|---|
| Prompt saja | Jelaskan format di prompt (materi 05) | Biasanya berhasil, tetapi bisa ada teks tambahan atau JSON rusak |
| Mode JSON | Opsi API yang memastikan output berupa JSON valid | JSON pasti valid, tetapi strukturnya belum tentu sesuai skema |
| Output terstruktur | Kirim JSON Schema ke API; model dibatasi agar output sesuai skema | Paling andal, tetapi ada batasan fitur skema |
Per tanggal pemeriksaan, ketiga penyedia besar menyediakan output terstruktur berbasis JSON Schema:
| Penyedia | Field di request |
|---|---|
| OpenAI (Responses API) | text.format dengan type: "json_schema", name, schema, strict: true |
| Anthropic (Messages API) | output_config.format dengan type: "json_schema", schema |
| Google (Interactions API) | response_format dengan mime_type: "application/json" dan schema |
Setiap penyedia mendukung subset JSON Schema yang berbeda. Contohnya, dokumentasi Anthropic mewajibkan additionalProperties: false pada objek dan tidak mendukung batasan angka seperti minimum/maximum. Baca bagian batasan di dokumentasi penyedia sebelum merancang skema.
Tetap validasi di kode
Bahkan dengan output terstruktur, validasi tetap wajib:
- Output bisa terpotong karena batas token, sehingga JSON tidak lengkap.
- Model bisa menolak permintaan (misalnya karena kebijakan keamanan), dan teks penolakan tidak mengikuti skema.
- Skema hanya memeriksa bentuk, bukan kebenaran.
"tahun": 2031valid secara skema walaupun salah.
Alur yang aman di aplikasi:
1. Periksa alasan berhenti (selesai normal? terpotong? menolak?)
2. Parse JSON
3. Validasi terhadap skema (mis. dengan pustaka jsonschema atau Pydantic)
4. Validasi aturan bisnis (tahun <= tahun sekarang, angka dalam rentang wajar)
5. Jika gagal: coba ulang atau perbaiki (lihat bagian berikut)
Langkah 4 juga tempat untuk aturan yang tidak didukung skema penyedia, seperti batas minimum/maksimum.
Menangani keluaran yang tidak sesuai
| Masalah | Penanganan |
|---|---|
| Terpotong (batas token) | Naikkan batas token output, atau perkecil tugas |
| JSON rusak/tidak sesuai skema | Coba ulang sekali; jika masih gagal, kirim pesan error validasi ke model dan minta perbaikan |
| Melanggar aturan bisnis | Kirim aturan yang dilanggar beserta nilainya, minta perbaikan; atau tandai untuk ditinjau manusia |
| Menolak | Catat dan tangani di UI; jangan diulang terus-menerus |
Contoh pesan perbaikan:
JSON sebelumnya tidak valid:
- "tahun": 2031 melebihi tahun sekarang (2026).
- "metode" kosong, padahal abstrak menyebut metode.
Perbaiki berdasarkan abstrak yang sama dan kembalikan JSON lengkap.
Batasi jumlah percobaan (misalnya maksimal 2 kali) agar tidak terjadi loop yang mahal.
Merancang skema yang membantu model
- Nama field yang jelas.
tahun_terbitlebih jelas daripadath. - Tambahkan
descriptionpada field yang ambigu:"description": "Tahun terbit paper, bukan tahun data dikumpulkan". - Sediakan jalan keluar.
null,"tidak_jelas", atau array kosong untuk data yang tidak ada. - Urutan berpikir. Jika perlu penalaran, letakkan field
alasansebelum fieldkeputusan, karena model mengisi field sesuai urutan. - Jangan terlalu dalam. Struktur bersarang yang rumit lebih rawan salah; pecah menjadi beberapa panggilan bila perlu (materi 06).
Catatan bahasa Inggris
Nama field skema yang dipakai di kode sebaiknya berbahasa Inggris dan snake_case (misalnya publication_year) agar konsisten dengan kode program. Isi description boleh berbahasa Indonesia; model memahaminya.
Kesalahan yang sering terjadi
| Kesalahan | Akibat |
|---|---|
| Hanya mengandalkan instruksi "kembalikan JSON" | Aplikasi sesekali error saat parsing |
| Tidak memeriksa alasan berhenti | JSON terpotong menyebabkan error yang membingungkan |
Semua field wajib tanpa opsi null |
Model dipaksa mengarang data yang tidak ada |
| Menganggap valid skema = benar | Data salah tetapi berbentuk benar masuk ke database |
| Coba ulang tanpa batas | Biaya membengkak |
Latihan
- Rancang JSON Schema untuk mengekstrak data lowongan magang dari teks: posisi, perusahaan, lokasi, apakah berbayar, tenggat pendaftaran.
- Aplikasimu sesekali gagal parse JSON walaupun sudah memakai output terstruktur. Sebutkan dua kemungkinan penyebab dan cara memeriksanya.
- Kamu ingin model mengklasifikasi abstrak sebagai "relevan" atau "tidak relevan" sekaligus memberi alasan. Bagaimana urutan field yang baik dan kenapa?
Contoh jawaban
Latihan 1
{
"type": "object",
"properties": {
"position": { "type": "string" },
"company": { "type": "string" },
"location": {
"type": ["string", "null"],
"description": "Kota atau 'remote'; null jika tidak disebutkan"
},
"paid": { "type": "string", "enum": ["yes", "no", "unknown"] },
"deadline": {
"type": ["string", "null"],
"description": "Format YYYY-MM-DD; null jika tidak disebutkan"
}
},
"required": ["position", "company", "location", "paid", "deadline"],
"additionalProperties": false
}
Alasannya: paid memakai enum dengan opsi unknown karena banyak lowongan tidak menyebutnya; deadline diberi format tanggal yang jelas dan bisa null.
Latihan 2
(1) Output terpotong: periksa alasan berhenti di response; jika karena batas token, naikkan batasnya. (2) Model menolak: periksa alasan berhenti atau field penolakan (nama field berbeda per penyedia) dan isi teksnya. Kemungkinan lain: kode membaca blok konten yang salah. Cetak response mentah untuk memastikan.
Latihan 3
Letakkan alasan sebelum relevan:
{ "alasan": "string", "relevan": "boolean" }
Alasannya: model mengisi field berurutan. Dengan alasan ditulis lebih dulu, keputusan dibangun di atas penalaran (materi 06), bukan keputusan dulu lalu alasan yang dicocok-cocokkan.
Lampiran: contoh Python dengan validasi
Contoh berikut memakai Anthropic. Pola validasinya sama untuk penyedia lain; yang berbeda hanya field request dan cara membaca teks dari response (lihat tabel di atas dan materi 13).
import json
import anthropic
from jsonschema import validate, ValidationError # pip install jsonschema
SCHEMA = {
"type": "object",
"properties": {
"judul": {"type": "string"},
"tahun": {"type": ["integer", "null"]},
"metode": {"type": "array", "items": {"type": "string"}},
},
"required": ["judul", "tahun", "metode"],
"additionalProperties": False,
}
client = anthropic.Anthropic()
def ekstrak(abstrak: str) -> dict:
response = client.messages.create(
model="<nama-model>",
max_tokens=1024,
messages=[{
"role": "user",
"content": f"Ekstrak data dari abstrak berikut. Gunakan null jika tidak ada.\n\n<abstrak>\n{abstrak}\n</abstrak>",
}],
output_config={"format": {"type": "json_schema", "schema": SCHEMA}},
)
if response.stop_reason != "end_turn":
raise RuntimeError(f"Tidak selesai normal: {response.stop_reason}")
text = next(block.text for block in response.content if block.type == "text")
data = json.loads(text)
validate(data, SCHEMA) # melempar ValidationError jika tidak sesuai
if data["tahun"] is not None and data["tahun"] > 2026:
raise ValueError("Tahun tidak masuk akal")
return data
Diskusi (0)
Kami menyimpan nama (opsional), komentar, dan hash teknis (bukan alamat IP asli) untuk mencegah spam. Cookie fungsional dipakai agar Anda dapat mengedit atau menghapus komentar sendiri dari browser ini. Untuk permintaan penghapusan, gunakan halaman kontak.
Belum ada komentar. Mulai diskusinya.