Güvenilir bir şekilde yapılandırılmış veri döndüren LLM ajanları oluşturmak, yapay zeka mühendisliğindeki en yaygın sorunlardan biridir. Büyük Dil Modelleri (LLM) yaratıcı metin üretiminde mükemmel olsa da, katı JSON üretme görevlerinde halüsinasyon ve biçimlendirme hatalarına yatkındır. Geleneksel yaklaşımlar genellikle ham metni ayrıştıran kırılgan düzenli ifadeler (regular expressions) veya yeniden deneme döngüleri içerir ve bu da istikrarsız üretim sistemlerine yol açar.
İşte PydanticAI, LLM'lerle çalışmayı güvenli, öngörülebilir ve geliştirici dostu hale getirmek için tasarlanmış bir Python ajan çerçevesi. Pydantic modellerinin gücünden yararlanarak PydanticAI, LLM çıktılarının uygulamanıza döndürülmeden önce katı şemalarla doğrulandığından emin olur. Bu gönderi, PydanticAI'ı kullanarak yapılandırılmamış metinden karmaşık, iç içe geçmiş JSON yapılarını çıkarabilen tip güvenli ajanlar oluşturmanın nasıl yapılacağını inceliyor.
LLM Boru Hatlarında Tip Güvenliğinin Neden Önemli Olduğu
Python gibi dinamik dillerde, prototipleme için genellikle "duck typing" (ördek biçimlendirme) yeterlidir. Ancak, bir LLM çıktısı aşağı akışta bir veritabanı yazma işlemi, API çağrısı veya iş mantığı motorunun girdisi olarak kullanıldığında, belirsizlik ölümcül olabilir. Model, bir tam sayı beklenirken bir dize döndürürse veya zorunlu bir alanı kaçırırsa, uygulamanız çökebilir veya daha kötüsü, bozuk verilerle sessizce başarısız olabilir.
PydanticAI, şema doğrulamasını doğrudan ajanın çalışma döngüsüne entegre ederek bunu çözer. Modelden "biraz JSON" istemek yerine, Pydantic kullanarak bir Python sınıfı tanımlarsınız. PydanticAI, bu sınıf tanımını otomatik olarak LLM'in anlayabileceği bir JSON Şeması'na çevirir. LLM'in yanıtı şemayla eşleşmezse, PydanticAI otomatik olarak bir kendini düzeltme döngüsü başlatabilir ve veriler uygulamanıza maruz kalmadan önce modelin hatalarını düzeltmesini sağlar.
Karmaşık Çıktı Yapılarını Tanımlama
PydanticAI'ın öne çıkan özelliklerinden biri, karmaşık Pydantic modellerini desteklemesidir. LLM'in çıktısına doğrudan iş mantığı kurallarını uygulamak için iç içe geçmiş modeller, sayısal sabitler (enums) ve özel doğrulayıcılar kullanabilirsiniz.
Bir e-postadan fatura detaylarını çıkarmamız gereken bir senaryoyu ele alalım. Veriler, bir müşteri adı, hesaplanmış toplamları içeren bir satır kalemleri listesi ve bir tarihi içerir. Bu yapıyı tam tip güvenliğiyle şu şekilde tanımlayabiliriz:
from pydantic import BaseModel, Field, field_validator
from datetime import date
from pydantic_ai import Agent
class LineItem(BaseModel):
description: str = Field(..., description="Kalemin kısa açıklaması")
quantity: int = Field(..., gt=0)
price: float = Field(..., ge=0)
def total(self) -> float:
return self.quantity * self.price
class InvoiceData(BaseModel):
customer_name: str = Field(..., description="Müşterinin tam yasal adı")
invoice_date: date
line_items: list[LineItem]
total_amount: float
@field_validator('total_amount')
@classmethod
def check_total(cls, v: float, info) -> float:
if 'line_items' in info.data:
calculated = sum(item.total() for item in info.data['line_items'])
if abs(v - calculated) > 0.01:
raise ValueError("Toplam tutar, satır kalemlerinin toplamıyla eşleşmiyor")
return v
agent = Agent("openai:gpt-4o", result_type=InvoiceData)
@field_validator'a dikkat edin. Bu sadece veri şekli için değil; mantıksal tutarlılığı da uygular. LLM, satır kalemlerinin toplamıyla eşleşmeyen bir toplam halüsinasyonu yaratırsa, doğrulama başarısız olur ve PydanticAI modeli yeniden düşünmeye teşvik eder.
Ajanı Çalıştırma ve Yanıtları İşleme
Ajan tanımlandıktan sonra, çalıştırması basittir. run metodu tiplemiş bir nesne döndürür, bu da IDE'nizde tam IDE desteği ve tip denetimi anlamına gelir. data['customer_name'] kullanmanıza gerek yoktur; data.customer_name kullanabilirsiniz.
import asyncio
email_text = """
Konu: Fatura #12345
Merhaba John,
Ekim ayı faturası aşağıdadır.
Kalem 1: Widget A x2 @ $50.00
Kalem 2: Widget B x1 @ $100.00
Toplam: $200.00
Tarih: 2023-10-27
"""
async def main():
result = await agent.run(email_text)
# result.data, tamamen doğrulanmış bir InvoiceData nesnesidir
print(f"Müşteri: {result.data.customer_name}")
print(f"Toplam: {result.data.total_amount}")
# KeyError veya AttributeError olmadan iç içe verilere güvenli erişim
for item in result.data.line_items:
print(f"- {item.description}: {item.total()}")
asyncio.run(main())
Karmaşık Dışa Aktarımlar İçin En İyi Uygulamalar
- Modelleri Mümkün Olduğu Kadar Düz Tutun: İç içe geçme desteklenmekle birlikte, derin iç içe geçmiş yapılar bazen LLM'leri karıştırabilir. Mantıksal olarak izin verildiğinde şemayı düzleştirmek genellikle doğruluğu artırır.
- Açıklayıcı Alan Açıklamaları Kullanın: LLM'ler, bağlamı anlamak için Pydantic alanlarındaki
descriptionparametresine güvenir. Biçim gereksinimleri konusunda açık olun (ör. "ISO 8601 tarihi"). - Sayısal Sabitlerden (Enumerations) Yararlanın: Bir alanın sabit bir değer kümesi varsa (durum kodları gibi), Python
enumsınıflarını kullanın. Bu, geçersiz kategorik veri olasılığını büyük ölçüde azaltır.
Sonuç
PydanticAI, LLM uygulamalarını üretim ortamına hazır hale getirme konusunda önemli bir ilerlemeyi temsil ediyor. Veri doğrulama yükünü sonradan yapılan ayrıştırma işleminden öncelikli tip denetimine kaydırarak, tüm bir çalışma zamanı hata sınıfını ortadan kaldırırsınız. Yapılandırılmış veri boru hatlarıyla etkileşime girmesi gereken ajanlar geliştiren geliştiriciler için PydanticAI, temiz, Pythonik ve sağlam bir çözüm sunar. Tip güvenliğini benimseyin ve LLM ajanlarınız size güvenilir ve öngörülebilir çıktılarla teşekkür edecek.