API & Backend
LLM Yapılandırılmış Çıktılar: Pydantic v2, JSON Schema ve Instructor ile Sıfır Hatalı Veri Çıkarma
LLM çıktılarının kırılmasını önlemek için Pydantic v2, Instructor ve yerel JSON Schema modları ile %100 tip güvenli veri çıkarma rehberi.
Özet & Doğrudan Çözüm (TL;DR)
LLM Structured Outputs; yapay zeka modellerinin serbest metin üretmek yerine katı bir JSON Schema veya Pydantic modeline kesin olarak uymasını sağlayan gramer kısıtlı kod çözme (grammar-constrained decoding) teknolojisidir. Modelin çıktı olasılık dağılımındaki (logits) şema dışı belirteçler matematiksel olarak maskelendiği için bozuk JSON, eksik alanlar veya yanlış veri tipleri %100 oranında engellenir.
Önemli Çıkarımlar:
- Gramer Kısıtlı Kod Çözme: Model şemaya uymayan geçersiz token'ları fiziksel olarak üretemez; sıfır sözdizim (syntax) hatası.
- Pydantic v2 Performansı: Rust tabanlı pydantic-core çekirdeği ile mikrosaniye düzeyinde veri doğrulama ve serileştirme.
- Instructor Kütüphanesi: OpenAI, Anthropic ve Gemini API'lerinde otomatik şema dönüştürme ve doğrulamadan geçmeyen yanıtlarda otomatik retry döngüsü.
- İç İçe Nesneler & Validatörler: Regex kontrolleri, sayısal aralıklar (gt=0), enum listeleri ve özel iş mantığı kurallarının LLM seviyesinde işletilmesi.
1. Prompt ile JSON İstemek Neden Üretimde Çöker?
Geleneksel yaklaşımlarda sistem promptuna 'Lütfen sadece geçerli bir JSON objesi döndür, markdown tırnağı koyma' yazılır. Ancak bu yöntem üretim ortamında kaçınılmaz olarak çöker.
LLM'ler öngörülemeyen durumlarda JSON öncesine selamlaşma metinleri ekler, nesne sonlarına fazladan virgül bırakır veya sayı beklenen alana metin yazar. Structured Outputs mimarisinde ise çıkarım motoru (inference engine), her token üretim adımında JSON şemasının izin verdiği karakterlerin logit skorlarını 1 yapar, kalan tüm olasılıkları negatif sonsuza çeker. Böylece geçersiz bir karakterin seçilmesi imkansız hale gelir.
2. Pydantic v2 ve Instructor ile Üretim Seviyesinde Uygulama
Aşağıdaki Python betiği, karmaşık bir B2B fatura metninden iç içe kalemleri, vergi tutarlarını ve satıcı bilgilerini tip güvenli olarak çeken eksiksiz bir örnektir:
from typing import List
from pydantic import BaseModel, Field, field_validator
import instructor
from openai import OpenAI
class InvoiceItem(BaseModel):
description: str = Field(description="Hizmet veya ürün açıklaması")
unit_price: float = Field(gt=0, description="Birim fiyat (pozitif sayı)")
quantity: int = Field(gt=0, default=1, description="Adet miktarı")
total: float = Field(gt=0, description="Kalem toplam tutarı")
class InvoiceExtraction(BaseModel):
vendor_name: str = Field(min_length=2, description="Faturayı kesen şirket adı")
tax_id: str = Field(description="Vergi kimlik veya VKN numarası")
items: List[InvoiceItem]
grand_total: float = Field(gt=0, description="KDV dahil genel toplam")
@field_validator("grand_total")
@classmethod
def validate_total(cls, v, values):
items = values.data.get("items", [])
calculated = sum(item.total for item in items)
if abs(v - calculated) > 1.0:
raise ValueError(f"Toplam tutar kalemler toplamıyla uyuşmuyor: {v} != {calculated}")
return v
client = instructor.from_openai(OpenAI())
raw_ocr_text = """
VERGİ FATURASI: Bulut Bilişim A.Ş. VKN: 1928374650
1. 12 Aylık Dedicated Sunucu Barındırma - 12 x 1500 TL = 18000 TL
2. SSL ve Güvenlik Duvarı Lisansı - 1 x 2000 TL = 2000 TL
TOPLAM: 20000 TL
"""
invoice = client.chat.completions.create(
model="gpt-4o-mini",
response_model=InvoiceExtraction,
max_retries=3,
messages=[{"role": "user", "content": raw_ocr_text}]
)
print(f"Başarıyla Çıkarıldı: {invoice.vendor_name} | Kalem Sayısı: {len(invoice.items)}")3. Hata Yönetimi ve Otomatik Kendini İyileştirme (Self-Healing)
Instructor kütüphanesinin en büyük gücü max_retries mekanizmasıdır. Eğer Pydantic validatörü bir veri hatası fırlatırsa (örneğin kalemler toplamı fatura genel toplamına eşit çıkmazsa), hata mesajı otomatik olarak bir sonraki prompta eklenir ve modelden yalnızca hatalı alanı düzelterek yeniden üretmesi istenir. Bu döngü sistemin insan müdahalesine gerek kalmadan %99.9 doğrulukla çalışmasını sağlar.
Sıkça Sorulan Sorular
Structured outputs ilk token süresini (TTFT) yavaşlatır mı?
OpenAI ve Gemini'nin yerel JSON şema motorlarında şemanın gramer tablosu ilk çağrıda derlenir ve belleğe alınır. İlk istekte küçük bir gecikme (100-200ms) yaşansa da sonraki tüm istekler standart hızda çalışır.
LangChain veya LlamaIndex yerine doğrudan Instructor kullanmak neden avantajlıdır?
Instructor, gereksiz karmaşık soyutlamalar yerine doğrudan saf Python ve Pydantic v2 kullanır. Bu sayede hata ayıklaması kolaydır, kütüphane boyutu küçüktür ve performans kaybı yaşanmaz.
Doğrulanmış Kaynaklar ve Dokümantasyon
- OpenAI Structured Outputs Guide & JSON Schema SpecResmi Doküman
- Pydantic v2 Documentation & Performance BenchmarksResmi Doküman
- Instructor: Structured LLM Outputs in PythonResmi Doküman
İlgili Teknik Rehberler
Bu mimariyle bağlantılı diğer üretim odaklı rehber ve vaka analizlerini inceleyin:
FastAPI ve Gemini 3.7 API ile Gerçek Zamanlı Streaming ve Function Calling
Python FastAPI backend kullanarak Google Gemini API ile Server-Sent Events (SSE) tabanlı gerçek zamanlı yapay zekâ streaming ve araç çağırma (function calling) mimarisi.
FastAPI Async Mimarisi: Asyncio Event Loop ve Yüksek Eşzamanlılık (Concurrency)
FastAPI'de async def ve def fonksiyonlarının nasıl çalıştığını, threadpool tuzaklarını ve saniyede on binlerce isteği bloklanmadan yönetme tekniklerini öğrenin.
FastAPI Dependency Injection (DI) ile Temiz ve Test Edilebilir Mimari Kurulumu
FastAPI'nin Depends mekanizmasını kullanarak veritabanı oturumlarını, kimlik doğrulama katmanlarını ve servis bağımlılıklarını izole etme rehberi.