Tüm yazılar
Teknik
  • #structured-output
  • #reliability

Structured output güvenilirliği

18.07.2026·13 dk

Structured output güvenilirliği

Structured Outputs · 19-c05

26 Haziran 2026 · Sağlamlık notları

Aynı JSON Schema'yı üç farklı modele verdiğinizde üç farklı sonuç alabilirsiniz: biri tam uyar, biri sessizce alanları düşürür, biri kısıtlamayı yok sayar. "Structured output" artık her büyük sağlayıcıda var, ama "garanti" kelimesi her birinde aynı şeyi anlatmıyor. Portability bedava değildir: şemanızı her sağlayıcıda ayrı test edin.

Soru
şema her yerde aynı mı?
Katman
syntax vs semantics
Mekanizma
constrained decoding
Tuzak
tek şemaya güvenmek

Bu yazıdaki kavramlar

  • structured output
  • JSON Schema
  • constrained decoding
  • strict mode
  • schema coverage
  • portability
  • JSONSchemaBench

Bir LLM'in çıktısını bir koda, bir API çağrısına ya da bir veritabanı kaydına bağladığınızda, o çıktının her seferinde aynı şekli tutması gerekir. Sağlayıcılar bunun için "structured output" özellikleri sundu: bir JSON Schema verirsiniz, model de o şemaya uyan bir cevap döndürür. Kulağa taşınabilir bir sözleşme gibi geliyor. Pratikte öyle değil.

Bu yazıda aynı şemanın neden her model ve sağlayıcıda aynı davranmadığını çiziyorum. Sağlayıcı-içi (native) modlar (OpenAI Structured Outputs, Anthropic, Google Gemini) ile kütüphane tarafı constrained decoding (Outlines, XGrammar, automata) arasındaki farkı, "garanti" kelimesinin sağlayıcıya göre ne anlama geldiğini ve JSONSchemaBench'in ölçtüğü kanıtı ele alıyorum. Şemalar kendi başına sürekli oynayarak her mekanizmayı gösteriyor.

01/08

Aynı şema, üç sonuç

Tek bir JSON Schema yazarsınız: birkaç zorunlu alan, bir optional alan, bir enum, biraz da iç içe yapı. Sonra onu üç sağlayıcıya gönderirsiniz. Sonuçlar çoğu zaman aynı olmaz. Birinde çıktı şemaya tam uyar (pass). Birinde JSON geçerlidir ama şemanın bir kısmı sessizce kaybolmuştur, örneğin desteklenmeyen bir kısıtlama atlanmıştır (partial). Birinde ise model kısıtlamayı tutturamaz (fail).

Bunun nedeni "structured output"un tek bir standart olmaması. Her sağlayıcı JSON Schema'nın farklı bir alt kümesini destekliyor, farklı bir motorla zorluyor ve desteklemediği özelliği farklı bir şekilde ele alıyor. JSONSchemaBench bu tabloyu net gösteriyor: en iyi framework en kötüsünün kabaca iki katı kadar gerçek dünya şemasını destekliyor.

Aşağıda tek bir şema üç sağlayıcıya açılıyor ve her biri farklı bir sonuç hücresinde duruyor. Aynı girdi, farklı çıktı. Yazının geri kalanı bu farkın nereden geldiğini açıklıyor.

tek şema · üç sağlayıcı · üç sonuç
şema
  • · zorunlu alanlar
  • · optional alan
  • · enum
  • · iç içe nesne
Sağlayıcı Apass
Sağlayıcı Bpartial
Sağlayıcı Cfail
şemaya tam uyar JSON geçerli, kısıtlama düşmüş şema tutmadı
02/08

"Garanti" tam olarak neyi garanti eder?

Sağlayıcılar "şema-uyumlu cevap garanti ediyoruz" derken iki çok farklı şeyi karıştırmak kolay. Birincisi syntactic (sözdizimsel) doğruluk: çıktı geçerli bir JSON mu, zorunlu alanlar var mı, enum değerleri tanımlı kümeden mi, tipler doğru mu? İkincisi semantic (anlamsal) doğruluk: alanların içindeki değerler gerçekten doğru mu, mantıklı mı, kullanıcının istediğini karşılıyor mu?

Constrained decoding yalnızca birincisini garanti eder. OpenAI ve Anthropic, structured output'un şema-geçerli bir cevap ürettiğini söyler; ama bu, içeriğin doğru olduğu anlamına gelmez. Google Gemini dokümantasyonu bunu açıkça uyarır: sözdizimsel olarak doğru JSON bile uygulama tarafında değer doğrulaması ve şemaya uygun ama anlamsal olarak yanlış değerler için sağlam hata yönetimi gerektirir.

Yani "garanti" şeklin garantisidir, içeriğin değil. Aşağıda iki kapı var: structured output ilk kapıyı (geçerli şekil) her zaman geçirir, ama ikinci kapıyı (doğru değer) geçirmez, onu sizin doğrulamanız gerekir.

garanti edilen katman · şekil ≠ içerik
syntactic katman

geçerli JSON · zorunlu alanlar · enum · tipler

constrained decoding burayı garanti eder

semantic katman

değerler doğru mu, mantıklı mı, hedefi karşılıyor mu

bunu uygulama doğrular

şema-geçerli bir cevap, yanlış bir cevap olabilir

03/08

Mekanizma: constrained decoding

Native modların ve açık kaynak motorların çoğunun altında aynı fikir yatar: constrained decoding. Model her adımda kelime dağarcığındaki (vocabulary) bir sonraki token için olasılıklar üretir. Constrained decoding, o anki kısmi çıktıyı şema-geçersiz hale getirecek tüm tokenları maskeler, yani onların olasılığını sıfırlar. Model yalnızca şemayı geçerli tutan tokenlardan birini seçebilir.

OpenAI'nin anlattığı tablo şudur: yalnızca model eğitimi yeterli değildi (kendi değerlendirmelerinde eğitim tek başına %93'te kalmış), bu yüzden eğitimi deterministik constrained decoding ile birleştirdiler. Aynı yaklaşım Willard ve Louf'un Outlines çalışmasında model-bağımsız olarak formüle edilir: yöntem yeniden eğitim gerektirmez, birçok modelin ve onları tüketen sistemlerin arasına oturabilir.

Aşağıda iki üretim hattı yan yana. Üstteki kısıtsız hat bazen şema-dışı bir token (kırmızı) emisyona izin verir ve çıktı kırılır. Alttaki kısıtlı hat aynı geçersiz tokenı maskeler (üzeri çizili), o yüzden hiçbir zaman geçersiz bir token üretmez.

kısıtsız vs kısıtlı token akışı
kısıtsız
{ "qty":12,abc}

geçersiz token emisyona girer, çıktı kırılır

kısıtlı
{ "qty":12,abc}

geçersiz token maskelenir, akış şema-geçerli kalır

geçerli token geçersiz token maskelenmiş token
04/08

Native modlar: aynı isim, farklı sözleşme

Üç büyük sağlayıcı da artık bir JSON Schema arayüzü sunuyor, ama her biri farklı bir operasyonel sözleşmeyle. OpenAI iki yüzey verir: strict tool/function calling ve final cevap için response_format ile json_schema. Çalışması için strict: true gerekir, tüm alanlar zorunlu olmalı (optionality, içinde null olan union tipiyle taklit edilir) ve nesneler additionalProperties: false kullanmalıdır.

Anthropic, final cevabın şekli için "JSON outputs" ile doğrulanmış tool adları/girdileri için "strict tool use"u ayırır; ikisi bağımsız ya da birlikte kullanılabilir. Yapılı çıktıların constrained decoding ile şema-uyumlu olduğunu söyler, ama SDK'ları desteklenmeyen kısıtlamaları dönüştürebilir: minimum, maximum, minLength gibi kısıtları kaldırıp açıklamalara metin olarak gömer ve cevabı orijinal şemaya karşı istemci tarafında doğrular. Bu, naif portability varsayımını zayıflatır.

Google Gemini, structured output'u tahmin edilebilir bir cevap şekli için, function calling'i ise konuşma sırasında aksiyon almak için konumlandırır. Gemini de JSON Schema'nın bir alt kümesini destekler ve dokümantasyon yine de değer doğrulaması yapmanızı önerir. Üç sağlayıcı da JSON Schema'ya yaklaşıyor, ama hiçbiri tamamını desteklemiyor ve dönüşüm davranışları birbirinden farklı.

üç native mod · ne garanti ediliyor, ne dönüştürülüyor
OpenAIstrict: true · tüm alanlar zorunlu · additionalProperties:false
AnthropicJSON outputs + strict tool use · SDK kısıt dönüştürür
Geminiresponse schema · JSON Schema alt kümesi · değeri doğrula

üçü de JSON Schema'ya yakınsıyor, üçü de farklı bir alt küme ve farklı dönüşüm uyguluyor

05/08

Şema özellik boşlukları ve portability

Asıl portability sorunu burada: "JSON Schema desteği" tek tip bir şey değil. OpenAI binlerce nesne özelliğine ve birkaç düzey iç içe yapıya kadar destek verir, ama tüm alanların zorunlu olmasını ve nesnelerin kapalı (additionalProperties: false) olmasını ister. Anthropic SDK'ları numerik ve uzunluk kısıtlarını sessizce kaldırabilir. Gemini yalnızca seçili nesne, string, sayı ve dizi özelliklerini kabul eder.

Sonuç şu: bir sağlayıcıda kusursuz çalışan bir şema, başka bir sağlayıcıda ya reddedilir ya da sessizce budanır. Sessiz budama daha sinsidir, çünkü çıktı geçerli görünür ama beklediğiniz kısıt (örneğin minimum: 0) hiç uygulanmamıştır. Bunu test etmeden fark edemezsiniz.

Pratik çıkış yolu, şemayı en küçük ortak payda etrafında tasarlamaktır: zorunlu alanlar, açıkça kapalı nesneler, sığ yapı, basit tipler ve enumlar, ve sayısal/anlamsal kısıtları dışarıda, kendi doğrulama katmanınızda kontrol etmek. Aşağıda zengin bir şema sağlayıcıların alt kümelerinden geçiyor; her sağlayıcıda farklı bir özellik düşüyor, ortada kalan çekirdek her yerde taşınabilir olan kısımdır.

şema özellikleri · sağlayıcı eleğinden geçince
zorunlu alanlarher sağlayıcıda taşınabilir
enumher sağlayıcıda taşınabilir
kapalı nesneher sağlayıcıda taşınabilir
sığ iç içeher sağlayıcıda taşınabilir
minimum / maximumsağlayıcıya göre budanır / reddedilir
minLength / patternsağlayıcıya göre budanır / reddedilir
derin iç içe yapısağlayıcıya göre budanır / reddedilir

en küçük ortak payda: çekirdeği şemaya, geri kalanı kendi doğrulamanıza koyun

06/08

Açık kaynak motorlar birbirinin yerine geçmez

Sağlayıcı dışına çıkıp kendi constrained decoding'inizi çalıştırdığınızda da iş bitmiyor. Outlines, XGrammar, llama.cpp ve benzeri motorlar aynı garantiyi vaat eder ama grammar sınıfı, tokenizer ele alışı, şema kapsamı, derleme gecikmesi ve token başına maliyet bakımından çok farklıdır. Outlines, guided generation'ı sonlu durum makineleri (finite-state machine) üzerinde state geçişleri olarak formüle eder ve vocabulary indeksleme ile regex için ortalama O(1) maskeleme sağlar.

Koo, Liu ve He'nin automata tabanlı çalışması altta yatan zorluğu netleştirir: subword tokenizerlar belirsizdir ve formal grammar tokenlarıyla hizalı değildir, bu yüzden naif hizalama ya kaliteyi bozar ya da çok sayıda özel durum yaratır. Automata ve finite-state transducer ile bu problemi temizler ve kısıtları kabaca 7000 kat daha hızlı derlediklerini, üstelik provably correct olduğunu bildirirler.

XGrammar başka bir ekseni vurgular: maliyet. CFG tabanlı esnek yapılı üretim pahalı olabilir; XGrammar, vocabulary tokenlarını önceden kontrol edilebilen (context-independent) ve runtime'da yığın durumuna bakılması gereken (context-dependent) tokenlara ayırarak mevcut çözümlere göre 100 kata kadar hızlanma bildirir. Yani "şema desteği" bir commodity değil: motor tasarımı hem güvenilirliği hem gecikmeyi belirler.

motor tasarımı · garanti aynı, maliyet farklı
Outlines · FSMregex/CFG · vocabulary indeks · ortalama O(1) maske
Automata · FSTtokenizer hizalama · ~7000× hızlı derleme · provably correct
XGrammar · CFGcontext-bağımsız/bağımlı token ayrımı · ~100× hızlanma

göreli derleme/çalışma maliyeti (düşük = daha iyi)

hepsi syntax garanti eder; fark hızda ve şema kapsamında

Structured output bir taşınabilir sözleşme değil, sağlayıcıya bağlı bir davranıştır. Garanti edilen şekildir, içerik değil; ve şeklin bedeli her motorda farklıdır.

07/08

Kanıt: JSONSchemaBench

Bu farkları somutlaştıran şey JSONSchemaBench. Çalışma, 10 binden fazla gerçek dünya JSON şemasını resmî JSON Schema Test Suite ile eşleştirir; bu, el seçimi oyuncak şemalardan çok daha sert bir test ortamıdır. Guidance, Outlines, llama.cpp, XGrammar, OpenAI ve Gemini'yi üç eksende karşılaştırır: verimlilik, JSON Schema özellik kapsamı ve çıktı kalitesi.

Üç eksen ayrı ayrı okunmalı, çünkü farklı şeyleri ölçerler. Şema uyumu (çıktı şemayı tutuyor mu), şema özellik kapsamı (framework gerçek dünya şemasını ne kadar destekliyor) ve görev kalitesi (anlamsal olarak doğru mu) bağımsız sinyallerdir. Bir framework yüksek uyum gösterip düşük kapsamda kalabilir, yani az şemayı destekler ama desteklediğini iyi tutar.

Raporlanan başlıca bulgular: constrained decoding bazı ayarlarda üretimi yaklaşık %50 hızlandırabiliyor; framework'ler arasında gerçek şema desteği ciddi biçimde değişiyor (en iyi, en kötünün kabaca iki katı); ve downstream görev doğruluğu raporlanan görevlerde %4'e kadar iyileşiyor. Aşağıda kapsam barları sağlayıcı/yöntem başına doluyor; üstte üç değerlendirme ekseni ayrı kutularda.

JSONSchemaBench · ayrı ölçülen üç eksen
08/08

Şemanızı her sağlayıcıda test edin

Toparlarsak: structured output, sağlayıcılar arasında taşınabilir bir standart değil. Aynı şema bir yerde tam uyar, başka yerde sessizce budanır, üçüncüsünde reddedilir. "Garanti" şeklin garantisidir; anlamsal doğruluğu hâlâ siz doğrularsınız. Native modlar ve açık kaynak motorlar aynı constrained decoding fikrini paylaşır ama farklı şema alt kümeleri, farklı dönüşümler ve farklı maliyetlerle gelir.

Pratik kural basit: şemayı en küçük ortak payda etrafında tasarlayın, sayısal ve anlamsal kısıtları kendi doğrulama katmanınıza koyun, ve en önemlisi, her hedef sağlayıcıda gerçek şemanızla gerçek bir test koşturun. Portability bedava değildir; ama hangi özelliğin nerede düştüğünü ölçerseniz, taşınabilir olanı seçebilirsiniz.

şema özellikleri · sağlayıcı eleğinden geçince
zorunlu alanlar + kapalı nesneher sağlayıcıda en güvenli temel01
sığ iç içe yapıderin nesting yer yer reddedilir02
sayısal/uzunluk kısıtları dışarıdaSDK'lar bunları sessizce düşürebilir03
değer doğrulaması her zaman açıkşema-geçerli ≠ anlamsal doğru04
her sağlayıcıda gerçek şemayla testportability'yi ölç, varsayma05

Şema bir sözleşme gibi görünür, ama sağlayıcı sınırında yeniden müzakere edilir.

Bu yüzden "şema garanti ediliyor" demeden önce sorun: hangi sağlayıcıda, hangi alt kümeyle, hangi dönüşümle ve ne pahasına garanti ediliyor?