Yapılandırılmış çıktı, önceden karar verdiğin bir şekildeki cevaptır: adlandırılmış anahtarları olan bir JSON nesnesi, sabit sütunlu bir tablo ya da her seferinde aynı başlıkları taşıyan bir şablon. Cevabı bir program okuyacaksa ona ihtiyacın var; bir insan okuyacaksa da işe yarar, çünkü her cevap aynı görünür ve taraması ya da karşılaştırması kolay olur.
İşin püf noktası, şekli modele seçecek hiçbir şey bırakmayacak kadar net tarif etmektir. Tek başına "JSON" kelimesi bir tarif değildir. Aşağıdaki blok bir hata raporundan ayrıntıları çıkarıyor. "Önemli ayrıntılar" isteğini şemayı açıkça yazan bir istekle karşılaştır.
Hata raporundaki önemli ayrıntılar şunlar:
- Sorun: Uygulama projeleri dışa aktarırken çöküyor
- Tetikleyici: 50'den fazla fotoğraf içeren projelerde Dışa Aktar'a dokunmak
- Başlangıç: Son güncellemeden sonra
- Platform: Android 14
- Uygulama sürümü: 3.2.0
- Etki: Yüksek, çünkü bir müşteri teslimatını engelliyor
Daha küçük projeler sorunsuz dışa aktarılıyor gibi görünüyor.
Serbest metin cevabı doğru ve okunaklı, ama iki deneme aynı etiketleri kullanmaz, önem derecesi bir değer değil bir cümledir ve bir program her alanın nerede başladığını tahmin etmek zorunda kalır. JSON cevabı doğrudan bir hata takip aracına girebilir. Yanıtın yine de bir kod bloğunun içinde geldiğine dikkat et: sohbet uygulamaları JSON'u genellikle böyle sarar ve bu, onu kodda ayrıştırırken önemlidir.
JSON nasıl istenir
İyi bir JSON isteği, modelin aksi hâlde senin yerine cevaplayacağı her soruyu cevaplar:
- Her anahtar, tam yazılışıyla. Anahtar adlarını görünmeleri gereken şekilde tırnak içinde yaz. Modelin fazladan anahtar eklememesi için "tam olarak şu anahtarlar" de.
- Her değerin tipi. String, sayı, boolean, string dizisi, iç içe nesne.
- İzin verilen değerler, önem derecesi ya da kategori gibi sabit bir kümesi olan her alan için. Liste olmadan dört denemede "High", "high", "severe" ve "P1" alırsın.
- Girdide bir değer yoksa ne yapılacağı. "Belirtilmemişse null" demezsen model boşluğu makul bir tahminle doldurmaya eğilimlidir ve tahmin edilmiş bir uygulama sürümü gerçeğinin tıpatıp aynısı gibi görünür.
- Etrafında hiçbir şey olmaması. "Sadece JSON'u döndür, öncesinde ya da sonrasında metin olmasın" dost canlısı açılış cümlesini kaldırır.
Şekil iç içe ya da alışılmadıksa tam bir örnek nesne göstermek onu tarif etmekten daha iyi çalışır. Bu, biçime uygulanmış few-shot prompting demektir. Modelin kopyalamaması için örneğin değerlerini gerçek girdiden açıkça farklı tut.
Tekrar kullanılabilir bir çıkarma promptu
Bu blok aynı isteği parçalara bölünmüş hâlde içeriyor. Biçim parçasını kapatırsan model yine JSON döndürür, çünkü kısıtlar onu istiyor, ama kendi anahtar adlarını seçer, örneğin job_title yerine title, ve senin anahtarlarını bekleyen kod bozulur. Kısıtlar parçası da yarım yazılmış bir telefon numarasını tamamlamasını ya da bir e-posta alan adından şirket çıkarmasını engelleyen şeydir. Test etmek için girdi alanına gerçek bir imza yapıştır.
{
"name": "string",
"job_title": "string ya da null",
"company": "string ya da null",
"email": "string ya da null",
"phone": "string ya da null"
}{
"name": "Ayşe Demir",
"job_title": "Veri Direktörü",
"company": "Kuzeyrüzgarı Labs",
"email": "ayse.demir@kuzeyruzgari.example",
"phone": null
}
Tablolar ve sabit şablonlar
Yapılandırılmış çıktı sadece programlar için değildir. Cevabı kendin okuduğunda bir markdown tablosu ya da sabit bir şablon aynı faydayı sağlar: bakmadan önce her bilginin nerede olacağını bilirsin.
| Tür | Sıralı | Değiştirilebilir | Tekrara izin verir | Tipik kullanım |
|---|---|---|---|---|
| list | Evet | Evet | Evet | Eleman eklediğin, çıkardığın ya da sıraladığın bir dizi |
| tuple | Evet | Hayır | Evet | Koordinatlar gibi sabit bir değer grubu |
| set | Hayır | Evet | Hayır | Tekrarları kaldırmak ve hızlı üyelik kontrolü |
Şablon daha uzun metinler için de aynı şekilde çalışır: başlıkları sırayla ver ve her birinin altına ne geleceğini söyle. "Üç kalın başlıkla cevap ver: Sebep, Çözüm, Nasıl kontrol edilir" her seferinde aynı üç başlığı üretir, bu da bir dizi cevabı karşılaştırmayı kolaylaştırır.
API'de JSON mode
Birçok model API'sinde sözdizimi açısından geçerli JSON'u zorunlu kılan bir ayar vardır. OpenAI Python SDK'sında bu response_format'tır. JSON mode mesajlarında bir yerde "JSON" kelimesinin geçmesini gerektirir, bu yüzden aşağıdaki sistem promptu onu adıyla anıyor ve anahtarları listeliyor.
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 metnin ayrıştırılabilmesini sağlar (yanıt token sınırında kesilmedikçe), şemana uymasını değil. Bir anahtar yine eksik olabilir ya da önem derecesi yine "urgent" olabilir. Birçok sağlayıcı tam bir JSON Schema'yı da kabul eder; bir çıktı biçimi olarak ya da bir araç (function) tanımının girdi şeması olarak. Bu modların bazıları cevabı şemaya göre kısıtlar. Bu özellikler API'ler arasında farklı olduğu için tam parametre için sağlayıcının dokümantasyonuna bak.
Sonucu kodda doğrula
Modelin JSON'una programının dışından gelen her girdiye davrandığın gibi davran: ayrıştır, sonra kontrol et. Ayrıştırma bozuk sözdizimini yakalar. Kontrol ise yanlış içerikli geçerli bir nesneyi yakalar.
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
Kontrol başarısız olduğunda tek bir yeniden deneme çoğu zaman sorunu çözer: modele kendi çıktısını sorunların listesiyle birlikte gönder ve düzeltilmiş JSON iste. Yeniden deneme sayısını sınırla ve başarısızlıkları logla, çünkü sık başarısız olan bir alan promptun belirsiz olduğunun işaretidir. Daha büyük projelerde Pydantic gibi bir doğrulama kütüphanesi ya da bir JSON Schema doğrulayıcı elle yazılan fonksiyonun yerini alır.
İki alışkanlık daha sessiz hataları önler. Çıktı token sınırını beklediğin en büyük cevaba yetecek kadar yüksek tut, çünkü kesilmiş bir nesne asla ayrıştırılamaz. Girdi uzunsa ya da kullanıcılardan geliyorsa, içindeki metnin talimat olarak okunma ihtimalini azaltmak için onu talimatlarından ayırıcılar ya da XML etiketleriyle ayır. Tek bir prompt hem akıl yürütüp hem JSON üretmek zorundaysa prompt zincirlemeyi düşün: bir adım serbest metinle düşünsün, ikinci adım sonucu yapıya çevirsin.
Sıkça Sorulan Sorular
ChatGPT'den nasıl JSON çıktısı alırım?
Cevabın JSON olması gerektiğini söyle, her anahtarı tipiyle listele ve sabit bir değer kümesi olan her alan için izin verilen değerleri ver. "Sadece JSON'u döndür, öncesinde ya da sonrasında metin olmasın" cümlesini ekle. API'de ayrıca response_format={"type": "json_object"} ile JSON mode'u aç; bu mod mesajlarında JSON kelimesinin geçmesini gerektirir.
Model neden JSON'un etrafına metin ekliyor?
Sohbet modelleri sohbet eder gibi konuşmak üzere eğitilir, bu yüzden çoğu zaman "İşte JSON" gibi bir cümleyle başlar ya da nesneyi bir markdown kod bloğuna sarar. Sadece JSON'u iste ve kodda ya API'nin JSON mode'unu kullan ya da ayrıştırmadan önce çevreleyen kod bloğunu temizle.
JSON mode nedir?
JSON mode, yanıt çıktı token sınırında kesilmediği sürece modelin sözdizimi açısından geçerli JSON üretmesini sağlayan bir API ayarıdır. Modelin senin şemana uymasını sağlamaz: anahtarlar yine eksik, yanlış yazılmış ya da yanlış tipte olabilir. Bazı sağlayıcılar tam bir JSON Schema alan ve çıktıyı ona göre kısıtlayan daha katı bir mod da sunar.
Bir LLM her zaman geçerli JSON döndürebilir mi?
Sadece promptla hayır. Net bir talimat bile ara sıra başarısız olur ve çıktı token sınırında kesilen bir cevap her zaman geçersizdir. Her yanıtı gerçek bir JSON ayrıştırıcıyla ayrıştır, ihtiyacın olan alanları kontrol et ve kontrol geçmezse yeniden dene ya da açıkça hata ver.