Yapılandırılmış Çıktılar: Güvenilir JSON için Şema-Güdümlü Prompting (2026)
Üretimde LLM'den güvenilir JSON almak prompt'la bitmiyor. JSON mode, structured outputs, kısıtlı kod çözme ve fonksiyon çağırma ile şemaya uyumu nasıl garanti edersiniz?
TL;DR — Üretim sistemlerinde LLM'den "güzel bir paragraf" değil, koda doğrudan verilebilecek geçerli JSON istiyorsunuz. Sahada gördüğüm en pahalı hataların çoğu, modele "JSON döndür" deyip sonucun içine markdown çitleri, fazladan açıklama cümleleri, uydurulmuş alanlar ya da bozuk virgüller karışmasından çıkıyor. Çözüm, güvenmek değil, garantiye bağlamak. En zayıftan en güçlüye doğru dört yaklaşım var: (1) prompt'la "JSON iste" (kırılgan), (2) JSON mode (sözdizimi geçerli ama şemanız değil), (3) Structured Outputs / şema-kısıtlı çözümleme (JSON Schema'ya uyumu üretici tarafında garanti eder), (4) function/tool calling (model, tanımladığınız şemaya uyan argümanlar üretir). Doğru reçete: düz ve tipli şemalar, enum'larla kısıtlanmış kategoriler, açık zorunlu/opsiyonel ayrımı, şema içi alan açıklamaları, doğrula-ve-geri-besle döngüsü, ve "önce düşün, sonra temiz JSON üret" ayrımı. Türkçe belgelerden (fatura, sözleşme) veri çıkarırken KVKK ve Türkçe enum etiketleri ayrı bir dikkat istiyor. Bu yazıda bütün bunu sahadan örneklerle açıyorum.
Önce Dürüst Bir İtiraf: Prose Güzeldir, Ama Kod Onu Yiyemez
Kurumsal projelerde LLM'i ilk kez üretime alan ekiplerin en sık düştüğü tuzak şu: demo aşamasında model harika çalışır. Sohbet ekranında sorarsınız, güzel bir cevap gelir, herkes mutludur. Sonra o modeli bir boru hattının (pipeline) ortasına koyarsınız — çıktısını başka bir servis okuyacak, bir veritabanına yazılacak, bir API'ye gönderilecek. İşte o an her şey değişir.
Çünkü bir insan için "İşte istediğiniz üç madde: birincisi..." diye başlayan bir cevap gayet nettir. Ama bu cevabı JSON.parse() ile ayrıştırmaya çalışan bir kod parçası için bu bir felakettir. Kod, prose okumaz. Kod, kesin bir yapı bekler: hangi alanlar var, tipleri ne, hangileri zorunlu. Bir tek fazladan kelime, bir tek eksik tırnak, bir tek markdown çiti (```json) ve program çöker.
Sahada onlarca sistem kurduktan sonra size çok net söyleyebilirim: üretimdeki LLM entegrasyonlarının en zayıf halkası, çoğu zaman modelin zekâsı değil, çıktısının biçimidir. Model doğru cevabı biliyor olabilir; ama o cevabı kodun sindirebileceği bir kalıba dökemiyorsa, o cevabın hiçbir değeri yoktur.
Bunu bir benzetmeyle anlatayım. Diyelim çok yetenekli bir uzmanınız var, sorularınıza mükemmel cevaplar veriyor — ama cevaplarını her seferinde farklı bir kâğıda, bazen daktiloyla, bazen el yazısıyla, bazen kenarına notlar düşerek getiriyor. Siz bu cevapları otomatik bir tarayıcıya sokmak istiyorsunuz. Uzman ne kadar akıllı olursa olsun, formatı standart değilse tarayıcı boğulur. Structured outputs meselesi tam olarak budur: uzmanı değil, cevabın kalıbını standartlaştırmak.
"JSON Döndür" Demenin Neden Yetmediğini Sahadan Anlatayım
En yaygın başlangıç noktası şudur: prompt'un sonuna "Cevabını JSON olarak ver" yazarsınız. Bu, işe yarayabilir. Sorun şu ki, işe yaramadığı zaman sessizce yaramaz ve genelde en kötü anda, üretimde, gerçek trafikte.
Sahada gördüğüm klasik başarısızlık desenleri:
- Markdown çitleri: Model cevabı
```json ... ```bloğuna sarar. Kodunuz düz JSON beklerken başında üç ters tırnak bulur. - Giriş cümlesi: "Elbette, işte istediğiniz veriler:" diye başlar. Geçerli bir JSON değildir artık.
- Kapanış açıklaması: JSON'dan sonra "Umarım yardımcı olmuştur!" ekler.
- Bozuk sözdizimi: Son elemandan sonra fazladan virgül, tırnak yerine kesme işareti, kaçırılmamış özel karakter.
- Uydurulmuş alanlar: Şemanızda olmayan alanlar ekler ya da isimlerini keyfî değiştirir (
total_amountyerinetotalAmount). - Tip kayması: Sayı beklediğiniz yere
"1.250,00 TL"gibi bir string koyar.
Bunların hepsi tek tek yönetilebilir görünür. "Regex ile temizleriz, çitleri sileriz" dersiniz. Bir süre idare eder. Ama ölçek büyüdükçe, bu temizleme katmanı bir teknik borç yumağına döner. Her yeni model sürümü, her yeni prompt değişikliği, kenar durumlarını yeniden kırar. Ben buna "JSON ayıklama cehennemi" diyorum ve pek çok ekibin haftalarını burada yaktığını gördüm.
İşin özü şu: prompt'la JSON istemek bir ricadır, garanti değil. Üretim sistemleri ricayla ayakta durmaz. Bize garanti lazım.
Şunu da ekleyeyim: bu hatalar tek başına gelmez, dalga hâlinde gelir. Sistem düşük trafikte iyi çalışır, siz de güvenirsiniz. Sonra bir kampanya günü trafik on kata çıkar, modele daha uzun ve daha çeşitli girdiler gelir, ve o güne kadar hiç görmediğiniz kenar durumları bir anda patlar. Bir müşterimde tam olarak bunu yaşadık: aylarca sorunsuz çalışan bir çıkarım servisi, alışılmadık bir belge formatı geldiğinde modelin başına uzun bir açıklama cümlesi eklemesiyle çöktü. Log'lara baktığımızda hata oranı gece yarısı yüzde yarımdan yüzde sekize fırlamıştı. O gece kimse uyumadı. Structured outputs'a geçtikten sonra o sınıf hataların tamamı ortadan kalktı — çünkü artık modelin fazladan cümle ekleme ihtimali yapısal olarak yoktu.
Bir noktanın altını çizeyim: bu "temizleme katmanı" yaklaşımının en sinsi tarafı, çalışıyormuş gibi görünmesidir. Regex'iniz bilinen vakaların yüzde 95'ini yakalar ve siz işi bitmiş sanırsınız. Ama o yüzde 5, tam da en önemli, en beklenmedik girdilerde saklanır. Ve bu tür sistemlerde bir başarısızlık genelde sessiz olmaz — yanlış ayrıştırılmış bir tutar, bir veritabanına yanlış yazılmış bir kimlik numarası, bir sonraki adıma taşınan bozuk bir kayıt olarak yayılır.
Dört Yaklaşım: Zayıftan Güçlüye Bir Merdiven
Bu meseleyi bir merdiven gibi düşünün. Her basamak, bir öncekinin bıraktığı boşluğu kapatır.
1. Basamak — Sadece Prompt ("JSON döndür")
Modelden nazikçe JSON istersiniz. Hiçbir teknik garanti yoktur. Model iyi niyetle uyar ama uymadığında haber vermez. Prototip için kabul edilebilir, üretim için tehlikeli. Tek başına asla önermem.
Yine de bu basamağın bir değeri var: hızlı bir fikir doğrulaması (proof of concept) yaparken, henüz altyapı kurmaya değmeyecek bir aşamada, "acaba model bu veriyi doğru çıkarabiliyor mu?" sorusunu ucuza yanıtlar. Ama bir kez "evet, çıkarabiliyor" cevabını aldığınızda, hemen bir üst basamağa geçmelisiniz. Bu basamakta kalıp üretime çıkmak, deprem bölgesinde geçici bir çadırı kalıcı ev sanmak gibidir.
2. Basamak — JSON Mode
Birçok sağlayıcı "JSON mode" sunar. Bu, modelin çıktısının geçerli JSON sözdizimi olacağını garanti eder. Yani ayrıştırılabilir, dengeli parantezli, geçerli bir JSON alırsınız. Bu büyük bir adım — markdown çitleri ve giriş cümleleri sorunu ortadan kalkar.
Ama dikkat: JSON mode sizin şemanıza uyumu garanti etmez. Geçerli JSON gelir, ama içinde hangi alanların olduğu, tiplerinin ne olduğu size bağlı değildir. {"cevap": "bilmiyorum"} da geçerli JSON'dur. Yani sözdizimi çözülür, ama anlam sözleşmesi hâlâ garantisizdir.
Sahada JSON mode'u genelde bir ara istasyon olarak görüyorum: ayrıştırma hatalarını (parse error) büyük ölçüde bitirir, ama doğrulama hatalarını (validation error) bitirmez. Yani kodunuz artık JSON.parse() aşamasında çökmez, ama beklediğiniz toplam_tutar alanı hiç gelmediğinde ya da yanlış tipte geldiğinde bir alt katmanda patlamaya devam eder. Eğer sağlayıcınız gerçek şema-kısıtlı çözümleme sunuyorsa, JSON mode'da durmak için bir sebep yok; doğrudan bir üst basamağa çıkın.
"JSON mode, "cümle gramatik olarak doğru olacak" demektir. "Cümle senin istediğin şeyi söyleyecek" demek değildir.
3. Basamak — Structured Outputs / Şema-Kısıtlı Çözümleme
İşte gerçek sıçrama burada. Structured Outputs (kimi sağlayıcıda bu adla, kimi API'de farklı adla) bir JSON Schema verirsiniz ve sağlayıcı, üretilen çıktının o şemaya birebir uyacağını garanti eder. Alanlar tam olarak istediğiniz gibi, tipler doğru, zorunlu alanlar hep dolu.
Bunu mümkün kılan mekanizmaya kısıtlı çözümleme (constrained/guided decoding) deniyor. Kabaca şöyle çalışır: model bir sonraki token'ı seçerken, çözücü (decoder) bir maske uygular — o an şemaya/gramere göre geçerli olmayan tüm token'lar sıfır olasılığa çekilir. Yani model, şemayı ihlal eden bir token'ı fiziksel olarak seçemez. Sonuç: geçersiz çıktı üretmek yapısal olarak imkânsız hâle gelir.
Bu incelik önemli: burada modele "lütfen şemaya uy" demiyoruz, uymamayı imkânsız kılıyoruz. Fark, ricayla garanti arasındaki farktır.
4. Basamak — Function / Tool Calling
En üst basamak, aslında 3. basamağın özel bir uygulamasıdır. Function calling (ya da tool use) ile modele bir "araç" tanımlarsınız; bu aracın argümanları bir JSON Schema ile tarif edilir. Model bir aracı çağırmaya karar verdiğinde, o argümanları şemaya uygun biçimde üretir.
Bu, ajan (agent) mimarilerinin bel kemiğidir. Model "hava durumunu getir" aracını çağırırken {"sehir": "İstanbul", "gun": "yarin"} gibi temiz, tipli argümanlar üretir. Sadece veri çıkarımı değil, eylem tetikleme için de aynı şema garantisini kullanırsınız.
| Yaklaşım | Neyi Garanti Eder | Neyi Etmez | Ne Zaman Kullanılır |
|---|---|---|---|
| Sadece prompt | Hiçbir şey | Sözdizimi, şema, tip — hepsi riskli | Sadece hızlı prototip |
| JSON mode | Geçerli JSON sözdizimi | Sizin şemanız, alanlar, tipler | Serbest yapılı ama geçerli JSON yeter ise |
| Structured Outputs | Şemaya birebir uyum | (Gerçekliği garanti etmez — bkz. halüsinasyon) | Üretimde veri çıkarımı, sınıflandırma |
| Function/tool calling | Şemaya uygun argümanlar | İşin doğru araç olduğunu | Ajanlar, eylem tetikleme, çok araçlı akış |
Bir uyarı: şema garantisi, çıktının biçimini garanti eder, doğruluğunu değil. Model, şemaya kusursuz uyan ama içerik olarak yanlış (halüsinasyon) bir değer üretebilir. Structured outputs "format sorununu" çözer; "gerçeklik sorununu" değil. Bu ikisini karıştırmayın.
Kısıtlı Çözümleme Perde Arkası: Maske Nasıl Çalışıyor?
Biraz teknik derinleşelim çünkü bu mekanizmayı anlayan ekipler çok daha isabetli tasarım yapıyor.
Bir dil modeli metni token token üretir. Her adımda, tüm kelime dağarcığı üzerinde bir olasılık dağılımı hesaplar ve buradan bir token seçer. Kısıtlı çözümlemede araya bir katman girer: o anki JSON Schema durumuna göre, hangi token'ların geçerli olduğunu bir gramer/otomat belirler. Geçerli olmayan token'ların olasılığı sıfırlanır (maskelenir), kalanlar arasından seçim yapılır.
Örnek: model bir alan adı yazdı, : koydu, ve şemaya göre bu alan bir tam sayı (integer) olmalı. O noktada çözücü, tırnak işaretini, harfleri, { gibi karakterleri yasaklar; sadece rakamların ve işaretin gelmesine izin verir. Böylece model o alana asla bir string yazamaz.
Açık kaynak dünyasında bu iş için gramer tabanlı örnekleme (grammar-based sampling) araçları var; yerel modelleri kendi sunucunuzda çalıştırıp aynı garantiyi elde edebilirsiniz. KVKK dünyasında bu önemli bir seçenek — veriyi dışarı çıkarmadan, kendi ortamınızda şema garantisi almak mümkün.
Bu mekanizmayı anlamanın pratik bir faydası daha var: neyin kısıtlanabilir olduğunu, neyin olmadığını görmenizi sağlar. Çözücü, "bu alan integer olmalı" gibi yapısal kuralları garanti edebilir. Ama "bu tutar belgedeki gerçek tutar olmalı" gibi anlamsal bir kuralı garanti edemez — çünkü bu, token'ların biçimiyle değil, içeriğin gerçekliğiyle ilgilidir. Gramer, hangi karakter dizilerinin geçerli olduğunu bilir; ama o karakterlerin doğru bilgiyi taşıyıp taşımadığını bilemez. Bu ayrımı içselleştiren ekipler, "şema garantisi kurdum, artık her şey doğru" yanılgısına düşmüyor. Şema, formu doğru doldurmayı garanti eder; formdaki bilginin doğruluğunu değil.
Bir örnekle netleştireyim. Diyelim bir faturadan vergi_no alanını çıkarıyorsunuz ve şemada bunu on haneli bir sayı olarak tanımladınız. Kısıtlı çözümleme, çıktının on haneli bir sayı olmasını garanti eder — ama modelin, belgeyi yanlış okuyup on haneli başka bir sayı üretmesini engellemez. Yapı kusursuz, içerik yanlış olabilir. İşte bu yüzden şema garantisinin yanına her zaman bir gerçeklik kontrolü (doğrulama, insan gözden geçirmesi, çapraz kontrol) koymak gerekir.
Küçük ama kritik bir yan etki: aşırı kısıtlama, modelin muhakeme kalitesini düşürebilir. Model her token'da dar bir koridora sıkıştırılırsa, bazen "düşünecek yer" bulamaz. Bu yüzden çözüm, muhakemeyi ve çıktıyı ayırmaktır — birazdan geleceğim.
Şema Tasarımının Sahadan Kuralları
Structured outputs'un başarısı, büyük ölçüde şemanızın kalitesine bağlı. Kötü tasarlanmış bir şema, en güçlü kısıtlı çözümlemeyi bile boğar. İşte sahada damıttığım kurallar.
Şemayı düz ve tipli tutun. Derin iç içe (nested) yapılar, hem modelin doğruluğunu düşürür hem de hata ayıklamayı zorlaştırır. Üç-dört katman derinliğe indiğinizde çıkarım kalitesinin gözle görülür düştüğünü defalarca ölçtüm. Mümkünse yapıyı yassılaştırın; gerçekten gerekmedikçe iç içe nesne kullanmayın. Bir sözleşmeden hem tarafların bilgilerini hem de maddeleri çıkarmanız gerekiyorsa, tek bir dev iç içe yapı yerine iki ayrı, daha yassı çıkarım çağrısı çoğu zaman daha isabetli sonuç verir. Modelin her seferinde tek bir net görevi olması, hem doğruluğu artırır hem de hatayı izole etmenizi kolaylaştırır.
Kategorileri enum ile kısıtlayın. Bir alan yalnızca belli değerler alabiliyorsa (örneğin belge türü), bunu serbest metne bırakmayın. enum ile olası değerleri sayın. Böylece model "fatura", "Fatura", "invoice", "fatura belgesi" gibi varyasyonlar arasında sürüklenmez; tam sizin tanımladığınız etiketi üretir.
{
"type": "object",
"properties": {
"belge_turu": {
"type": "string",
"enum": ["fatura", "sozlesme", "makbuz", "diger"],
"description": "Belgenin türü. Emin değilsen 'diger' kullan."
},
"toplam_tutar": {
"type": "number",
"description": "KDV dahil toplam tutar, sadece sayı (TL sembolü veya ayraç olmadan)."
},
"kdv_orani": {
"type": "integer",
"enum": [1, 10, 20],
"description": "Yüzde olarak KDV oranı."
}
},
"required": ["belge_turu", "toplam_tutar"]
}
Zorunlu ve opsiyonel ayrımını açık yapın. required listesini bilinçli doldurun. Bir alan her zaman dolmak zorunda değilse zorunlu yapmayın — aksi hâlde model, boş bir değeri doldurmak için uydurmaya (halüsinasyona) itilir. "Bilinmiyorsa boş bırak" davranışını şema ve açıklama ile açıkça teşvik edin.
Alan açıklamalarını modelin okuduğu dokümantasyon gibi kullanın. JSON Schema'daki description alanları sadece geliştirici için not değildir; model bunları okur ve davranışını buna göre şekillendirir. "Sadece sayı, ayraç yok", "emin değilsen 'diger' kullan", "tarih ISO 8601 formatında" gibi net talimatları şema içine gömün. Bu, prompt'u şişirmeden davranışı yönlendirmenin en temiz yoludur.
Türkçe etiketlerde tutarlı olun. Enum değerlerini Türkçe mi İngilizce mi tutacağınıza en baştan karar verin ve tutarlı kalın. Karışık dilli enum'lar (bazı değerler Türkçe, bazıları İngilizce) hem modeli hem de sonraki kodu şaşırtır. Türkçe karakterleri (ç, ş, ğ, ı, ö, ü) enum değerlerinde kullanacaksanız, bunların tüm sistemde tutarlı biçimde kodlandığından emin olun.
Güvenilirlik Taktikleri: Garanti Yetmediğinde
Şema garantisi biçimi kurtarır ama üretimde bundan fazlası gerekir. İşte sahada olmazsa olmaz saydığım taktikler.
Doğrula ve Geri Besle
Şema-kısıtlı çözümleme kullanamadığınız durumlar olur (bazı sağlayıcı/model kombinasyonları, bazı yerel kurulumlar). O zaman doğrulama + tekrar deneme deseni devreye girer:
- Çıktıyı alın, bir şema doğrulayıcıdan (Pydantic, JSON Schema validator) geçirin.
- Geçerse iş biter.
- Geçmezse, doğrulama hatasını modele geri besleyin: "Şu alan eksik / şu tip yanlış, düzelt ve sadece geçerli JSON döndür."
- Sınırlı sayıda (genelde 1-2) tekrar deneyin.
Doğrulama hatasını modele geri beslemek şaşırtıcı derecede etkili. Model çoğu zaman ilk denemedeki hatayı, somut hata mesajını görünce hemen düzeltir. Ama tekrar denemelerin bir maliyeti (para ve gecikme) olduğunu unutmayın; sonsuz döngüye izin vermeyin. Ben pratikte iki denemeyle sınırlıyorum: ikinci denemede de düzelmeyen bir çıktı, genelde modelin o girdiyle gerçekten zorlandığını gösterir ve o vakayı bir insan kuyruğuna (human review) düşürmek, üçüncü kez denemekten daha akıllıcadır. Her tekrar denemesini de loglayın — hangi girdilerin sürekli tekrar gerektirdiği, şemanızın ya da prompt'unuzun neresinin zayıf olduğunu size fısıldar.
Muhakemeyi ve Nihai Cevabı Ayırın
En sevdiğim taktik bu. Modelden hem düşünmesini hem de kusursuz JSON üretmesini aynı anda beklemek, ikisini de zayıflatır. Bunun yerine ayırın:
- Bir yol: Şemaya bir
dusunce(scratchpad) alanı ekleyin. Model önce oraya serbestçe düşünsün, sonrasonucalanına temiz cevabı yazsın. Kısıtlı çözümleme yine tüm yapıyı garanti eder ama modele nefes alacak yer verirsiniz. - Diğer yol (iki geçiş): İlk çağrıda model serbest metinle düşünsün/analiz etsin. İkinci çağrıda, o analizi verip "şimdi bunu şu şemaya dök" deyin. Ayrı geçiş, temiz JSON üretimini muhakemeden izole eder.
Sahada ikinci geçiş yaklaşımının, özellikle karmaşık çıkarımlarda doğruluğu belirgin artırdığını gördüm. Maliyeti iki çağrı olması; ama hata oranındaki düşüş genelde buna değer.
Az-Örnekli (Few-Shot) Örnekler ve Düşük Sıcaklık
Prompt'a, tam olarak istediğiniz şemayı gösteren bir-iki örnek koyun. Model, soyut bir şema tanımından çok, somut bir örnekten öğrenir. Girdi-çıktı çiftini gösterin; model kalıbı yakalar.
Çıkarım (extraction) işlerinde sıcaklığı (temperature) düşürün. Yaratıcılık istemiyorsunuz; belirlilik istiyorsunuz. Düşük sıcaklık, modelin aynı belgeden her seferinde aynı yapıyı çıkarmasını sağlar ve varyansı azaltır. Aynı belgeyi üç kez işlediğinizde üç farklı sonuç alıyorsanız, üretime çıkamazsınız — çünkü hangisinin doğru olduğunu bilemezsiniz. Düşük sıcaklık, bu tekrarlanabilirliği (determinism) size geri verir. Deterministik çıktı ayrıca test yazmayı da mümkün kılar: bir örnek belge için beklenen çıktıyı sabitleyip, her yeni sürümde bunun bozulup bozulmadığını otomatik kontrol edebilirsiniz.
Bir uyarı daha: few-shot örnekleriniz gerçek üretim verisini yansıtsın, ideal ve temiz uydurma örnekler değil. Model, örneklerinizdeki dünyayı gerçek dünya sanır. Eğer örnekleriniz hep tertemiz, eksiksiz belgelerse, ama üretimde yarısı silik, eksik, bozuk belgeler geliyorsa, model bu kenar durumlara hazırlıksız yakalanır. Örneklerinize bilinçli olarak birkaç "zor" vaka koyun — eksik alanı olan, muğlak bir belge — ve modele o durumda ne yapması gerektiğini (örneğin alanı boş bırakması) gösterin.
Ödünleşimler: Bedava Öğle Yemeği Yok
Structured outputs güçlüdür ama her mühendislik kararı gibi bedelleri var. Bunları açıkça bilmek, hangi basamağı seçeceğinize karar vermenizi kolaylaştırır.
- Aşırı kısıtlama muhakemeyi kısabilir. Modeli çok dar bir koridora sokarsanız, düşünme kalitesi düşebilir. Çözüm: muhakemeye alan bırakan şema tasarımı (scratchpad, iki geçiş).
- Tekrar denemelerin maliyeti var. Doğrula-ve-geri-besle döngüsü güvenlidir ama para ve gecikme ekler. Sınır koyun.
- Şema kayması ve sürümleme. Şemanız zamanla değişir. Yeni alan eklersiniz, bir enum'a değer katarsınız. Eski verilerle, eski istemci koduyla uyumu düşünmelisiniz. Şemalarınızı sürümleyin, değişiklikleri geriye dönük uyumlu tutmaya çalışın.
- Sağlayıcı bağımlılığı. Structured outputs'un uygulanış biçimi sağlayıcıdan sağlayıcıya değişir. Taşınabilirlik istiyorsanız, soyutlama katmanı düşünün.
"Bir ilkeyi hep akılda tutun: şema garantisi size geçerli bir cevap verir, doğru bir cevap değil. Doğruluğu ayrıca değerlendirmeniz gerekir.
Kullanım Alanları: Bu Nerede İşe Yarıyor?
Structured outputs teorik bir güzellik değil; günlük üretimde en çok değer kattığı yerler net:
- Veri çıkarımı (extraction): Belgeden, e-postadan, formdan yapılandırılmış alanlar çekmek. Fatura kalemleri, sözleşme tarafları, tutarlar.
- Sınıflandırma ve yönlendirme (routing): Gelen bir talebi kategorilere ayırıp doğru ekibe/akışa yöneltmek. Enum'lar burada baş kahraman.
- Ajan/araç argümanları: Modelin bir aracı doğru parametrelerle çağırması. Tüm ajan mimarilerinin temeli.
- Form doldurma: Serbest metinden yapılandırılmış bir formu otomatik doldurmak.
- LLM-as-judge / değerlendirme: Bir cevabı belli kriterlere göre puanlamak.
{"dogruluk": 4, "gerekce": "..."}gibi yapılandırılmış skorlar. - Belgelerden ETL: PDF/tarama belgelerinden yapılandırılmış veriyi çıkarıp veritabanına akıtmak.
Türkçe ve KVKK Açısı: Sahadan Uyarılar
Türkçe belgelerle çalışırken birkaç ek katman devreye giriyor ve bunları atlayan ekiplerin canı yanıyor.
Türkçe belgelerden çıkarım özen ister. Türk faturalarında tutar formatı (1.250,00 — nokta binlik ayracı, virgül ondalık) İngilizce konvansiyonun tersidir. Şema açıklamalarında bunu net belirtin: "tutarı sayıya çevirirken Türkçe ondalık formatını dikkate al, çıktıda sadece ondalık nokta kullan". Sözleşmelerde taraf isimleri, T.C. kimlik numaraları, vergi numaraları gibi alanların formatını enum ya da desen (pattern) ile kısıtlayın.
Türkçe enum etiketleri. Belge türü, departman, durum gibi kategorik alanlarda Türkçe etiketler kullanacaksanız, büyük/küçük harf ve Türkçe karakter tutarlılığına dikkat edin. "İ/ı" ve "i/I" dönüşümü Türkçe'de klasik bir tuzaktır; enum değerlerinizi normalize edin ve sonraki kodun bu normalize hâliyle eşleştiğinden emin olun.
KVKK ve kişisel veri. İşte en kritik nokta. Yapılandırılmış çıkarım çoğu zaman kişisel veri üretir — isim, T.C. kimlik, adres, telefon. Bu veriyi bir şemaya döküp veritabanına yazdığınız an, KVKK kapsamına girersiniz. Sorular net: Bu veriyi işlemek için hukuki dayanağınız var mı? Veri hangi ortamda işleniyor — yönetilen bir yurt dışı API'de mi, yoksa kendi sunucunuzda çalışan yerel bir modelde mi? Kişisel veri içeren alanlar için, veriyi ortamdan çıkarmayan kısıtlı çözümleme çözümleri (açık kaynak, yerel) ciddi bir avantaj sağlar. Şemanızı tasarlarken, gerçekten gerekmeyen kişisel veri alanlarını hiç çıkarmamak da bir stratejidir — veri minimizasyonu ilkesi.
Nereden Başlamalı: Bu Hafta Uygulayabileceğiniz Adımlar
Teoriyi bırakıp sahaya inelim. Elinizde bir LLM entegrasyonu varsa, şu sırayı izleyin:
- Mevcut çıktınızı ölçün. Bir hafta boyunca üretimdeki JSON çıktılarını loglayın ve kaçının ayrıştırma/doğrulama hatası verdiğini sayın. Sorunun büyüklüğünü rakamla görün.
- Basamağı yükseltin. Hâlâ "prompt'la JSON istiyorum" seviyesindeyseniz, sağlayıcınızın Structured Outputs veya function calling özelliğine geçin. Bu tek adım çoğu ayrıştırma hatasını sıfırlar.
- Şemayı düzenleyin. Şemanızı yassılaştırın, kategorileri enum'a çevirin, her alana net bir
descriptionyazın, zorunlu/opsiyonel ayrımını gözden geçirin. - Doğrulama katmanı koyun. Şema garantisi olsa bile, Pydantic/JSON Schema ile bir doğrulama kapısı ekleyin ve başarısızlıkta 1-2 kez geri besleyerek tekrar deneyin.
- Muhakemeyi ayırın. Karmaşık çıkarımlarda scratchpad alanı ya da iki geçişli akış deneyin; hata oranındaki düşüşü ölçün.
- KVKK'yı en baştan tasarlayın. Şemanızda hangi kişisel veri alanları var, hukuki dayanağınız ne, işleme nerede oluyor — bunları koda değil, tasarıma yazın.
Sahadan son bir gözlem: structured outputs'a geçen ekiplerin çoğu, en büyük kazancın "daha az bug" değil, "daha az korku" olduğunu söylüyor. Çıktının biçimini garanti altına aldığınızda, üretimde gece yarısı çalan alarmların büyük kısmı sessizleşiyor. Ve mühendislik enerjiniz, JSON ayıklamaktan gerçek işe kayıyor.
Danismanlik Baglantilari
Bu yazıya en yakın consulting sayfaları
Bu içerikten sonraki mantıklı adım için en ilgili solution, role ve industry landing'lerini burada görebilirsin.
Kurumsal RAG Sistemleri Gelistirme
Sirket ici bilgiye kaynakli, guvenli ve denetlenebilir erisim saglayan uretim seviyesinde RAG mimarileri.
AI Agent ve Workflow Otomasyonu
Tek adimli chatbot'larin otesine gecen; arac, kural ve insan onayi ile ilerleyen AI destekli is akislarina gecis.
CTO'lar icin Kurumsal AI Mimari Danismanligi
PoC seviyesinde kalan AI girisimlerini guvenli, olceklenebilir ve production-ready mimarilere tasimak icin teknik liderlik danismanligi.