Günümüz büyük dil modellerinden (LLM) beklenenler, sadece akıcı metinler üretmekle sınırlı değil. Artık bu güçlü yapay zekaların, uygulamalarımızla kusursuzca entegre olabilmesi için belirli bir formatta, yani yapılandırılmış çıktılar sunması kritik bir gereklilik haline geldi. Peki, OpenAI, Google Gemini, Anthropic Claude, Mistral AI ve AWS Bedrock gibi önde gelen sağlayıcılar bu konuda hangi yetenekleri sunuyor ve biz geliştiriciler en uygun çözümü nasıl seçmeliyiz? Bu makalede, farklı LLM sağlayıcılarının yapılandırılmış çıktı yöntemlerini derinlemesine inceleyecek, pratik örneklerle karşılaştıracak ve gerçek dünya senaryolarında nasıl kullanabileceğimizi adım adım keşfedeceğiz. Hazırsanız, bu heyecan verici yolculuğa çıkalım!
Büyük Dil Modelleri (LLM’ler), son yılların en dönüştürücü teknolojilerinden biri olarak hayatımıza girdi. Doğal dili anlama, üretme ve işleme konusundaki inanılmaz yetenekleri sayesinde, sohbet botlarından içerik oluşturmaya, kod yazmaktan veri analizine kadar geniş bir yelpazede devrim niteliğinde uygulamalara imza attılar. Ancak, LLM’lerin sunduğu bu esnekliğin bir de madalyonun diğer yüzü var: ham, serbest metin formatındaki çıktılar, her zaman programatik tüketim için uygun olmayabilir. Bir LLM’den aldığınız yanıtı başka bir sisteme, örneğin bir veritabanına, bir API’ye veya bir kullanıcı arayüzüne aktarmak istediğinizde, bu metni önce anlamlı ve işlenebilir bir yapıya dönüştürmeniz gerekir. İşte tam bu noktada “yapılandırılmış çıktı” kavramı devreye giriyor.
Bir düşünün: Bir e-ticaret siteniz var ve ürün açıklamalarını otomatik olarak oluşturmak için bir LLM kullanıyorsunuz. Açıklamalar harika, ama aynı zamanda ürünün fiyatını, stok kodunu, kategorisini ve özelliklerini de belirli bir JSON formatında almak istiyorsunuz ki bunları doğrudan ürün veritabanınıza işleyebilesiniz. Ya da bir müşteri destek botu geliştiriyorsunuz. Müşterinin sorusunu anlayan LLM, sadece yanıt vermekle kalmayıp, aynı zamanda sorunun türünü (örneğin, “iade”, “teknik destek”, “sipariş takibi”) ve ilgili sipariş numarasını da yapılandırılmış bir veri olarak döndürmeli. Böylece bu veriyi doğrudan ilgili departmana yönlendirebilir veya otomatik bir süreç başlatabilirsiniz. Bu tür senaryolarda, LLM’in rastgele bir metin yerine, önceden tanımlanmış bir şemaya (örneğin, JSON Schema) uygun, kolayca ayrıştırılabilir ve kullanılabilir bir çıktı üretmesi hayati önem taşır. Aksi takdirde, çıktıyı manuel olarak veya karmaşık düzenli ifadelerle (regex) ayrıştırmak zorunda kalırsınız ki bu hem hata eğilimli hem de bakımı zor bir yöntemdir.
Yapılandırılmış çıktılar, LLM’lerin sadece metin tabanlı etkileşimlerin ötesine geçerek, gerçek dünya uygulamalarının vazgeçilmez bir parçası olmasını sağlar. Bu sayede LLM’ler, veri çıkarma, otomasyon, API entegrasyonu, form doldurma ve iş akışı yönetimi gibi birçok alanda güçlü birer araç haline gelir. Bu makale boyunca, popüler LLM sağlayıcılarının bu kritik ihtiyacı nasıl karşıladığını, hangi mekanizmaları sunduklarını ve her birinin avantajlarını, dezavantajlarını ve kullanım senaryolarını detaylı bir şekilde ele alacağız. Amacımız, geliştiricilere ve karar vericilere, projeleri için en uygun yapılandırılmış çıktı yaklaşımını seçmelerinde rehberlik etmektir. Öyleyse, yapılandırılmış çıktının temel kavramlarını daha yakından inceleyelim.
Yapılandırılmış Çıktı Nedir ve LLM’lerdeki Temel Kavramları Nelerdir?
Yapılandırılmış çıktı, bir Büyük Dil Modelinden (LLM) beklediğimiz bilginin, serbest metin yerine önceden tanımlanmış, makine tarafından kolayca ayrıştırılabilir bir formatta sunulması anlamına gelir. En yaygın yapılandırılmış çıktı formatları arasında JSON (JavaScript Object Notation), XML (Extensible Markup Language) ve bazen YAML (YAML Ain’t Markup Language) bulunur. Bu formatlar, verileri anahtar-değer çiftleri, listeler veya hiyerarşik yapılar şeklinde düzenleyerek, programatik erişimi ve manipülasyonu son derece kolaylaştırır.
LLM bağlamında yapılandırılmış çıktı elde etmek için birkaç temel kavram ve mekanizma öne çıkar:
- Prompt Mühendisliği (Prompt Engineering): En temel düzeyde, LLM’den belirli bir formatta çıktı almasını istemek için prompt’unuzu dikkatlice tasarlarsınız. Örneğin, “Aşağıdaki metindeki kişileri ve yaşlarını bir JSON listesi olarak döndür.” gibi yönergeler kullanabilirsiniz. Ancak bu yöntem, LLM’nin her zaman doğru formatı garantilemediği durumlarda hata eğilimli olabilir. LLM, beklenen JSON formatını bazen bozabilir, ekstra metin ekleyebilir veya eksik alanlar bırakabilir.
- Şema Tanımlaması (Schema Definition) ve Doğrulama (Validation): Güvenilir yapılandırılmış çıktı almanın anahtarlarından biri, LLM’ye çıktının beklenen yapısını açıkça bildirmektir. Bu genellikle JSON Schema gibi standartlarla yapılır. JSON Schema, bir JSON belgesinin yapısını (hangi alanların olması gerektiği, veri türleri, minimum/maksimum değerler vb.) tanımlayan güçlü bir dil sunar. LLM API’leri, bu şemaları doğrudan girdi olarak kabul edebilir ve çıktıyı bu şemaya uygun hale getirmeye çalışır. Çıktı alındıktan sonra, şema doğrulayıcılar kullanılarak çıktının beklenen formata uygun olup olmadığı kontrol edilir.
- Fonksiyon Çağrıları (Function Calling) veya Araç Kullanımı (Tool Use): OpenAI’nin öncülük ettiği ve diğer sağlayıcıların da hızla benimsediği bu özellik, LLM’in doğal dil anlayışını, dışarıdaki bir fonksiyonu çağırmak için gerekli parametreleri yapılandırılmış bir şekilde döndürme yeteneğiyle birleştirir. Geliştirici olarak, LLM’ye hangi fonksiyonların mevcut olduğunu (fonksiyon adı, açıklaması ve beklediği parametrelerin JSON Schema tanımı ile birlikte) anlatırsınız. LLM, bir kullanıcının isteğini analiz ettiğinde, eğer bu isteğin yerine getirilmesi için bir fonksiyon çağrılması gerekiyorsa, o fonksiyonun adını ve gerekli parametreleri JSON formatında döndürür. Bu, doğrudan bir yapılandırılmış çıktı talebi olmasa da, belirli bir eylemi tetiklemek için yapılandırılmış veri elde etmenin son derece güçlü bir yoludur.
- Özel Çıktı Modları (Specific Output Modes): Bazı LLM sağlayıcıları, özellikle JSON çıktısı için özel modlar sunar. Örneğin, OpenAI’nin
response_format={"type": "json_object"}parametresi, modelin çıktıyı her zaman geçerli bir JSON objesi olarak üretmesini sağlamaya çalışır. Bu modlar, prompt mühendisliğinden daha güvenilir bir yöntem sunar çünkü model, çıktıyı bu formata uydurmak için daha fazla içsel mekanizma kullanır.
Bu temel kavramları anladıktan sonra, artık popüler LLM sağlayıcılarının bu yetenekleri kendi API’lerinde nasıl somutlaştırdığını ve her birinin kendine özgü yaklaşımlarını nasıl kullandığını detaylı bir şekilde incelemeye hazırız. Bir sonraki bölümde, her bir sağlayıcının sunduğu yapılandırılmış çıktı mekanizmalarını örneklerle karşılaştıracağız.
Popüler LLM Sağlayıcılarında Yapılandırılmış Çıktı Yöntemleri Nasıl Karşılaştırılır?
Farklı Büyük Dil Modeli (LLM) sağlayıcıları, yapılandırılmış çıktı elde etmek için benzer ama kendine özgü yaklaşımlar sunar. Bu bölümde, OpenAI, Google Gemini, Anthropic, Mistral ve AWS Bedrock gibi başlıca platformların yapılandırılmış çıktı mekanizmalarını adım adım inceleyecek ve her biri için pratik kod örnekleri sunacağız.
OpenAI: Function Calling ve JSON Modu
OpenAI, yapılandırılmış çıktı konusunda sektördeki en gelişmiş ve yaygın olarak benimsenen yaklaşımlardan birini sunar: Function Calling. Bu özellik, modelin doğal dil sorgularından bir veya daha fazla fonksiyon çağrısı döndürmesini sağlar. Geliştiriciler, LLM’ye mevcut araçları ve bunların JSON Schema tanımlarını sağlarlar. Model, kullanıcının isteğine göre bu araçlardan hangisinin çağrılması gerektiğini ve hangi parametrelerle çağrılması gerektiğini belirler.
Ayrıca, OpenAI son zamanlarda sadece JSON çıktısı almak isteyen senaryolar için özel bir JSON modunu da tanıttı. Bu mod, modelin çıktıyı her zaman geçerli bir JSON nesnesi olarak döndürmesini garanti etmeye çalışır.
Örnek Senaryo: Ürün Bilgisi Çıkarma (JSON Modu)
Bir ürün açıklamasından ürün adını, fiyatını ve kategorisini JSON formatında çıkarmak istediğimizi varsayalım.
from openai import OpenAI
import json
client = OpenAI(api_key="SİZİN_OPENAI_ANAHTARINIZ")
product_description = """
Harika bir kablosuz kulaklık! 40 saate kadar pil ömrü, aktif gürültü engelleme ve su geçirmezlik özelliği ile sporcular için ideal. Fiyatı sadece ₺1999.
"""
response = client.chat.completions.create(
model="gpt-4o", # veya gpt-3.5-turbo-0125
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Verilen ürün açıklamasından ürün adını, fiyatını ve kategorisini içeren bir JSON nesnesi döndür. Fiyatı sayısal bir değer olarak formatla."},
{"role": "user", "content": f"Açıklama: {product_description}"}
]
)
try:
product_info = json.loads(response.choices[0].message.content)
print("Yapılandırılmış Ürün Bilgisi:")
print(json.dumps(product_info, indent=2, ensure_ascii=False))
except json.JSONDecodeError as e:
print(f"JSON Ayrıştırma Hatası: {e}")
print(f"Ham Çıktı: {response.choices[0].message.content}")
Bu örnekte response_format={"type": "json_object"} parametresi, modelin geçerli bir JSON çıktısı üretmesini zorlar. Ardından, döndürülen metni json.loads() ile ayrıştırırız.
Google Gemini: Function Calling ve Şema Tanımlamaları
Google Gemini modelleri de OpenAI'ye benzer bir "Function Calling" mekanizması sunar. Geliştiriciler, Python veya diğer dillerdeki istemci kütüphaneleri aracılığıyla modellerine araçlar (fonksiyonlar) tanımlayabilirler. Gemini, doğal dil sorgularını analiz ederek bu tanımlanmış araçlardan hangisinin çağrılması gerektiğini ve hangi parametrelerle çağrılması gerektiğini belirler.
Örnek Senaryo: Müşteri Geri Bildirimi Kategorizasyonu
Müşteri geri bildirimlerini kategorize eden bir fonksiyonumuz olduğunu varsayalım. Gemini'den geri bildirim metninden uygun kategoriyi ve duygu durumunu çıkarmasını isteyeceğiz.
import google.generativeai as genai
import json
# API anahtarınızı burada ayarlayın
genai.configure(api_key="SİZİN_GOOGLE_GEMINI_ANAHTARINIZ")
# Modelinizi başlatın
model = genai.GenerativeModel('gemini-pro')
def categorize_feedback(category: str, sentiment: str):
"""
Müşteri geri bildirimini kategorize eder ve duygu durumunu belirler.
Args:
category (str): Geri bildirimin kategorisi (ör: 'teknik_destek', 'ürün_önerisi', 'şikayet', 'genel_soru').
sentiment (str): Geri bildirimin duygu durumu (ör: 'olumlu', 'olumsuz', 'nötr').
Returns:
dict: Kategorize edilmiş geri bildirim.
"""
return {"category": category, "sentiment": sentiment}
# Modeli araç ile yapılandırın
tools = [
{
"function_declarations": [
{
"name": "categorize_feedback",
"description": "Müşteri geri bildirimini kategorize eder ve duygu durumunu belirler.",
"parameters": {
"type": "object",
"properties": {
"category": {"type": "string", "enum": ["teknik_destek", "ürün_önerisi", "şikayet", "genel_soru"]},
"sentiment": {"type": "string", "enum": ["olumlu", "olumsuz", "nötr"]},
},
"required": ["category", "sentiment"],
},
}
]
}
]
customer_feedback = "Yeni güncellemeyle birlikte uygulama çok yavaş çalışmaya başladı. Bu kabul edilemez!"
response = model.generate_content(
f"Müşteri geri bildirimi: '{customer_feedback}'\n\nBu geri bildirimi kategorize et ve duygu durumunu belirle.",
tools=tools
)
# Yanıtta araç çağrısı olup olmadığını kontrol edin
if response.candidates[0].content.parts[0].function_call:
function_call = response.candidates[0].content.parts[0].function_call
print("Gemini Fonksiyon Çağrısı:")
print(f"Fonksiyon Adı: {function_call.name}")
print(f"Parametreler: {json.dumps(function_call.args, indent=2, ensure_ascii=False)}")
# Gerçek fonksiyon çağrısı burada yapılabilirdi
# categorized_data = categorize_feedback(**function_call.args)
# print(f"Kategorize Edilmiş Veri: {categorized_data}")
else:
print("Gemini araç çağrısı yapmadı.")
print(f"Ham yanıt: {response.candidates[0].content.parts[0].text}")
Bu örnekte, categorize_feedback fonksiyonunu ve parametrelerini Gemini'ye tanıttık. Model, müşteri geri bildirimini analiz ederek bu fonksiyonu çağırmak için gerekli parametreleri döndürdü.
Anthropic (Claude): Araç Kullanımı (Tool Use) ve Gelişmiş Prompt Mühendisliği
Anthropic'in Claude modelleri de benzer bir yetenek olan "Tool Use" (Araç Kullanımı) mekanizması sunar. OpenAI ve Gemini'deki Function Calling'e benzer şekilde, geliştiriciler Claude'a hangi araçların mevcut olduğunu ve bu araçların nasıl çağrılacağını açıklar. Claude, bu tanımlamalara dayanarak, doğal dil isteklerini işleyebilir ve bir aracı çağırmak için gerekli parametreleri içeren yapılandırılmış bir çıktı üretebilir.
Anthropic'in yaklaşımı, özellikle XML etiketleri kullanarak fonksiyon ve parametre tanımlarını modelin bağlamına yerleştirmeye odaklanır. Bu, gelişmiş prompt mühendisliği ile birleştiğinde oldukça güçlü sonuçlar verebilir.
Örnek Senaryo: Rapor Özeti ve Anahtar Bilgi Çıkarma
Bir raporun özetini ve rapordaki anahtar rakamları (örneğin, gelir, kar marjı) yapılandırılmış bir şekilde çıkarmak istediğimizi düşünelim.
from anthropic import Anthropic
import json
client = Anthropic(api_key="SİZİN_ANTHROPIC_ANAHTARINIZ")
report_text = """
2023 yılı finansal raporumuz, şirketimizin rekor bir büyüme kaydettiğini göstermektedir. Toplam gelirimiz 500 milyon dolara ulaştı, bu geçen yıla göre %20'lik bir artış anlamına geliyor. Net kar marjımız %15 seviyesinde gerçekleşti. Ar-Ge yatırımlarımız ise 50 milyon doları aştı.
"""
# Claude'a fonksiyon tanımını XML formatında veriyoruz
tools_definition = """
def extract_report_summary(summary: str, total_revenue: float, net_profit_margin: float, r_and_d_investment: float):
\"\"\"
Bir finansal raporun özetini ve anahtar finansal rakamlarını çıkarır.
:param summary: Raporun kısa özeti.
:param total_revenue: Şirketin toplam geliri (milyon dolar cinsinden).
:param net_profit_margin: Şirketin net kar marjı (yüzde cinsinden).
:param r_and_d_investment: Ar-Ge yatırımları (milyon dolar cinsinden).
\"\"\"
pass
"""
# Prompt içinde tool tanımını ve isteği birleştiriyoruz
prompt_template = f"""
{tools_definition}
{report_text}
Yukarıdaki finansal rapordan önemli bilgileri aracı ile çıkarın ve bana JSON olarak döndürün. Raporun özetini ve belirtilen finansal metrikleri toplayın.
"""
response = client.messages.create(
model="claude-3-opus-20240229", # veya claude-3-sonnet-20240229
max_tokens=1000,
messages=[
{"role": "user", "content": prompt_template}
]
)
# Tool use çıktısını kontrol et
if response.stop_reason == "tool_use":
tool_call = response.content[0]
if tool_call.type == "tool_use":
print("Anthropic Tool Use Çağrısı:")
print(f"Araç Adı: {tool_call.name}")
print(f"Parametreler: {json.dumps(tool_call.input, indent=2, ensure_ascii=False)}")
else:
print("Beklenmedik tool use türü:", tool_call.type)
else:
print("Anthropic Tool Use yapmadı.")
print(f"Ham Yanıt: {response.content[0].text}")
Claude'da tool tanımı genellikle prompt'un bir parçası olarak verilir ve model, bir aracı çağırması gerektiğinde etiketleri içinde yapılandırılmış bir çıktı döndürür.
Mistral AI: Tool Use ve JSON Mode
Mistral AI modelleri, özellikle performans ve maliyet etkinliği açısından popülerlik kazanmaktadır. Onlar da benzer bir "Tool Use" veya "Function Calling" yeteneği sunarlar. Mistral'ın API'si, OpenAI'ye oldukça benzer bir yapıda olup, tools parametresi aracılığıyla fonksiyon tanımlamalarını kabul eder. Ayrıca, tıpkı OpenAI gibi, Mistral modelleri de belirli bir JSON formatında çıktı almak için özel bir modu destekler.
Örnek Senaryo: Yapılacaklar Listesi Oluşturma (JSON Modu)
Kullanıcının bir doğal dil isteğinden bir yapılacaklar listesi (task, priority, deadline) çıkarmak istediğimizi düşünelim.
from mistralai.client import MistralClient
from mistralai.models.chat import ChatMessage
import json
client = MistralClient(api_key="SİZİN_MISTRAL_ANAHTARINIZ")
user_request = "Yarın için market alışverişi yapmalıyım, en önemli şey. Gelecek hafta sonuna kadar proje raporunu bitir ve bir de arkadaşımı ara."
messages = [
ChatMessage(role="system", content="Verilen isteği bir yapılacaklar listesine dönüştür. Her öğe için 'task', 'priority' (yüksek, orta, düşük) ve 'deadline' (kısa, orta, uzun) alanlarını içeren bir JSON dizisi döndür."),
ChatMessage(role="user", content=user_request)
]
# JSON modunu kullanarak çıktıyı JSON olarak istiyoruz
response = client.chat(
model="mistral-large-latest", # veya mistral-medium-latest
messages=messages,
response_format={"type": "json_object"}
)
try:
todo_list = json.loads(response.choices[0].message.content)
print("Mistral Yapılandırılmış Yapılacaklar Listesi:")
print(json.dumps(todo_list, indent=2, ensure_ascii=False))
except json.JSONDecodeError as e:
print(f"JSON Ayrıştırma Hatası: {e}")
print(f"Ham Çıktı: {response.choices[0].message.content}")
Mistral da OpenAI gibi response_format={"type": "json_object"} kullanarak çıktıların geçerli bir JSON nesnesi olmasını sağlıyor. Bu, özellikle tam JSON çıktısı beklediğiniz durumlarda çok kullanışlıdır.
AWS Bedrock: Farklı Modellerin Entegrasyonu ve Agents for Bedrock
AWS Bedrock, tek bir API aracılığıyla Amazon, Anthropic, AI21 Labs, Cohere, Meta ve Mistral gibi önde gelen yapay zeka şirketlerinin çeşitli Büyük Dil Modellerine erişim sağlayan yönetilen bir hizmettir. Bu, Bedrock'u yapılandırılmış çıktı konusunda benzersiz kılar çünkü kullandığınız temel modele bağlı olarak farklı yaklaşımlar benimsemeniz gerekebilir.
Ancak Bedrock, bu modellerin ötesinde "Agents for Bedrock" adında güçlü bir özellik sunar. Agents for Bedrock, kullanıcıların doğal dil isteklerini analiz edip, belirli görevleri yerine getirmek için LLM'leri harici sistemlerle (API'ler, veritabanları vb.) entegre eden otomatikleştirilmiş iş akışları oluşturmasına olanak tanır. Bu, Function Calling mekanizmasının daha üst düzey bir soyutlamasıdır.
Örnek Senaryo: E-ticaret Sipariş İşleme (Agents for Bedrock ile Fonksiyon Tanımı)
Bir e-ticaret uygulamasında, müşterinin doğal dil isteğinden sipariş bilgilerini çıkarıp bir sipariş işleme API'sini çağırmak istediğimizi düşünelim. Agents for Bedrock ile bu süreci nasıl yapılandıracağımızı basitçe tanımlayabiliriz. (Gerçek bir Agent kurulumu daha karmaşık olsa da, konsepti vurgulayalım.)
import boto3
import json
# Bedrock client'ını başlatın
# client = boto3.client(
# service_name="bedrock-runtime",
# region_name="us-east-1" # Kullandığınız bölgeye göre değiştirin
# )
# Bu örnek, bir Bedrock Agent'ının nasıl bir çıktı vereceğini simüle eder.
# Gerçek bir Agent'ı kurmak AWS konsolunda veya boto3 ile karmaşık bir süreçtir.
# Bir fonksiyon tanımı (Agent'a sağlanacak)
order_processing_tool = {
"name": "process_order",
"description": "Yeni bir e-ticaret siparişini işlemek için kullanılır.",
"input_schema": {
"type": "object",
"properties": {
"customer_id": {"type": "string", "description": "Müşterinin benzersiz ID'si."},
"product_name": {"type": "string", "description": "Sipariş edilen ürünün adı."},
"quantity": {"type": "integer", "description": "Sipariş edilen ürün adedi."},
"shipping_address": {"type": "string", "description": "Siparişin gönderileceği adres."},
},
"required": ["customer_id", "product_name", "quantity", "shipping_address"]
}
}
user_query = "Müşteri ID 12345 için 'Kablosuz Klavye'den 2 adet, '123 Ana Cadde, Ankara' adresine sipariş oluştur."
# Bir Bedrock Agent'ından beklenen hipotetik çıktı formatı
# Bu, agent'ın bir aracı çağırması gerektiğinde döndüreceği format olacaktır.
simulated_agent_output = {
"action_group": "OrderManagement", # Agent içinde tanımlı aksiyon grubu
"function": "process_order",
"parameters": {
"customer_id": "12345",
"product_name": "Kablosuz Klavye",
"quantity": 2,
"shipping_address": "123 Ana Cadde, Ankara"
}
}
print("AWS Bedrock Agent (Simüle Edilmiş) Yapılandırılmış Çıktısı:")
print(json.dumps(simulated_agent_output, indent=2, ensure_ascii=False))
# Gerçek kullanımda, bu çıktıyı alıp ilgili fonksiyona iletirdiniz.
# response = client.invoke_agent(...)
Bedrock'ta, doğrudan model API'si üzerinden Function Calling veya JSON modu kullanmak yerine (ki bu temel modele göre değişir), genellikle Agents for Bedrock aracılığıyla daha karmaşık iş akışlarını yapılandırırsınız. Agent, kullanıcının isteğini anlayıp önceden tanımlanmış araçları (fonksiyonları) çağırmak için gereken yapılandırılmış veriyi döndürür.
Bu karşılaştırmalı bölümde, her bir sağlayıcının yapılandırılmış çıktıya yaklaşımını ve kod örneklerini gördük. Her birinin kendi API tasarımı ve en iyi uygulamaları olsa da, temel fikir benzerdir: modele beklenen çıktı yapısını bildirmek ve modelin bu yapıya uymasını sağlamak. Şimdi gerçek dünya senaryolarında bu tekniklerin nasıl kullanıldığına daha yakından bakalım.
Gerçek Dünya Senaryolarında Yapılandırılmış Çıktı Uygulamaları: Vaka Analizleri
Yapılandırılmış çıktılar, Büyük Dil Modellerini (LLM) soyut birer metin üreticisinden, iş süreçlerini otomatikleştiren ve verileri anlamlandıran güçlü araçlara dönüştürür. İşte bazı gerçek dünya senaryoları ve yapılandırılmış çıktıların bu alanlarda nasıl fark yarattığına dair vaka analizleri.
1. E-ticaret Ürün Bilgisi Çıkarma ve Güncelleme
Problem: E-ticaret platformları, milyonlarca ürünle çalışır ve her bir ürünün detaylı açıklamaları, fiyatları, stok kodları, kategorileri ve özellikleri vardır. Tedarikçilerden gelen ham ürün metinleri veya kullanıcı tarafından girilen açıklamalar, veritabanına işlenmeden önce bu yapılandırılmış alanlara ayrıştırılmalıdır. Manuel veri girişi zaman alıcı, hata eğilimli ve ölçeklenemez bir çözümdür.
Çözüm: LLM'ler ve yapılandırılmış çıktı mekanizmaları bu problemi etkin bir şekilde çözebilir. Bir LLM'e (örneğin, OpenAI'nin JSON modu veya Gemini'nin Function Calling'i) ürün açıklamasını veririz ve ondan belirli bir JSON şemasına uygun olarak ürün adı, SKU, fiyat, kategori, mevcut stok durumu gibi bilgileri çıkarmasını isteriz.
# OpenAI ile ürün bilgisi çıkarma (daha önceki örnekten geliştirilmiş hali)
import json
from openai import OpenAI
client = OpenAI(api_key="SİZİN_OPENAI_ANAHTARINIZ")
product_description_long = """
Yepyeni "Ultra Konfor" Akıllı Koltuk! Bu ergonomik koltuk, saatlerce süren çalışma veya oyun seansları için tasarlandı.
Dahili masaj özelliği ve ayarlanabilir bel desteği ile maksimum konfor sunar.
Kumaş rengi: Gri, Malzeme: Nefes alabilen file.
Stok Kodu: UK001GR.
Fiyatı: 499.99 USD.
Kategori: Ofis Mobilyaları.
Garanti: 2 Yıl.
"""
response = client.chat.completions.create(
model="gpt-4o",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": """Verilen ürün açıklamasından aşağıdaki JSON şemasına uygun verileri çıkar:
{
"type": "object",
"properties": {
"product_name": {"type": "string", "description": "Ürünün tam adı."},
"sku": {"type": "string", "description": "Ürünün stok kodu."},
"price": {"type": "number", "description": "Ürünün fiyatı, sayısal değer."},
"currency": {"type": "string", "description": "Fiyatın para birimi."},
"category": {"type": "string", "description": "Ürünün ana kategorisi."},
"features": {"type": "array", "items": {"type": "string"}, "description": "Ürünün ana özellikleri listesi."}
},
"required": ["product_name", "sku", "price", "currency", "category"]
}
"""},
{"role": "user", "content": f"Açıklama: {product_description_long}"}
]
)
try:
product_data = json.loads(response.choices[0].message.content)
print("Çıkarılan Ürün Verileri:")
print(json.dumps(product_data, indent=2, ensure_ascii=False))
# Bu veriyi doğrudan bir veritabanına veya ERP sistemine gönderebilirsiniz
except json.JSONDecodeError as e:
print(f"JSON Ayrıştırma Hatası: {e}")
Bu yaklaşım, ürün ekleme sürecini hızlandırır, insan hatasını azaltır ve e-ticaret platformlarının dinamik envanter yönetimini kolaylaştırır.
2. Müşteri Geri Bildirimi ve Destek Talebi Kategorizasyonu
Problem: Müşterilerinizden gelen binlerce e-posta, sohbet mesajı veya yorumu manuel olarak okuyup ilgili departmana yönlendirmek veya kategorize etmek, müşteri destek ekipleri için büyük bir yüktür. Bu süreç, yanıt sürelerini uzatır ve müşteri memnuniyetini düşürebilir.
Çözüm: LLM'ler, doğal dildeki müşteri geri bildirimlerini analiz edebilir ve bunları önceden tanımlanmış kategorilere (örneğin, "Teknik Destek", "Fatura Sorunu", "Ürün İadesi", "Genel Sorgu") ve duygu durumlarına ("Olumlu", "Olumsuz", "Nötr") ayırarak yapılandırılmış bir çıktı üretebilir. Bu, gelen taleplerin otomatik olarak doğru ekibe yönlendirilmesini veya önceliklendirilmesini sağlar.
# Google Gemini ile müşteri geri bildirim kategorizasyonu (daha önceki örnekten geliştirilmiş hali)
import google.generativeai as genai
import json
genai.configure(api_key="SİZİN_GOOGLE_GEMINI_ANAHTARINIZ")
model = genai.GenerativeModel('gemini-pro')
def categorize_and_sentiment(category: str, sentiment: str, priority: str):
"""
Müşteri geri bildirimini kategorize eder, duygu durumunu ve önceliğini belirler.
:param category: Geri bildirimin kategorisi.
:param sentiment: Geri bildirimin duygu durumu.
:param priority: Talebin önceliği (yüksek, orta, düşük).
"""
return {"category": category, "sentiment": sentiment, "priority": priority}
tools_for_feedback = [
{
"function_declarations": [
{
"name": "categorize_and_sentiment",
"description": "Müşteri geri bildirimini kategorize eder, duygu durumunu ve önceliğini belirler.",
"parameters": {
"type": "object",
"properties": {
"category": {"type": "string", "enum": ["teknik_destek", "fatura_sorunu", "ürün_iadesi", "genel_sorgu", "ürün_önerisi"]},
"sentiment": {"type": "string", "enum": ["olumlu", "olumsuz", "nötr"]},
"priority": {"type": "string", "enum": ["yüksek", "orta", "düşük"]}
},
"required": ["category", "sentiment", "priority"],
},
}
]
}
]
customer_email = """
Merhaba, dün aldığım 'X' model kablosuz farem çalışmıyor. Sanırım bir teknik arıza var. Acilen yardımınıza ihtiyacım var, proje teslim tarihim yaklaşıyor!
"""
response = model.generate_content(
f"Müşteri e-postası: '{customer_email}'\n\nBu e-postayı kategorize et, duygu durumunu ve önceliğini belirle.",
tools=tools_for_feedback
)
if response.candidates[0].content.parts[0].function_call:
function_call_data = response.candidates[0].content.parts[0].function_call.args
print("Müşteri Geri Bildirim Analizi:")
print(json.dumps(function_call_data, indent=2, ensure_ascii=False))
# Buradan sonra, kategorize_and_sentiment(**function_call_data) çağrısı ile
# otomatik olarak destek bileti oluşturabilir veya ilgili departmana yönlendirebilirsiniz.
else:
print("LLM araç çağrısı yapmadı veya metin yanıtı döndürdü.")
print(response.candidates[0].content.parts[0].text)
Bu senaryo, müşteri hizmetleri verimliliğini önemli ölçüde artırırken, müşterilere daha hızlı ve kişiselleştirilmiş destek sunulmasına olanak tanır.
3. Otomatik API Çağrısı Tetikleme ve İş Akışı Otomasyonu
Problem: Birçok işletme uygulaması, kullanıcıdan doğal dilde gelen bir talebi alıp, bunu arka uç sistemlerdeki belirli API çağrılarına dönüştürme ihtiyacı duyar. Örneğin, bir kullanıcının "yarın için New York hava durumu" gibi bir isteği, bir hava durumu API'sinin çağrılması ve doğru şehir ile tarih parametrelerinin geçirilmesi anlamına gelir.
Çözüm: LLM'lerin Function Calling yetenekleri, bu tür otomasyon senaryoları için idealdir. LLM'ye hangi API'lerin mevcut olduğunu ve her birinin hangi parametreleri beklediğini açıklayan araç tanımları sağlanır. LLM, kullanıcının isteğini yorumlayarak, hangi API'nin çağrılması gerektiğini ve bu API'ye hangi yapılandırılmış parametrelerin iletilmesi gerektiğini belirler.
# Mistral AI ile hava durumu API'si çağırma (Basitleştirilmiş simülasyon)
from mistralai.client import MistralClient
from mistralai.models.chat import ChatMessage
import json
client = MistralClient(api_key="SİZİN_MISTRAL_ANAHTARINIZ")
# Hava durumu API'mizi simüle eden bir fonksiyon tanımlayalım
def get_current_weather(location: str):
"""Belirtilen konumun güncel hava durumu bilgilerini getirir."""
# Gerçek uygulamada burada harici bir hava durumu API'si çağrılırdı
weather_data = {
"İstanbul": {"temperature": "22°C", "conditions": "Güneşli", "humidity": "60%"},
"Ankara": {"temperature": "18°C", "conditions": "Parçalı Bulutlu", "humidity": "75%"}
}
return weather_data.get(location, {"error": "Bilinmeyen konum"})
# Mistral'a tanıtacağımız araç (fonksiyon) tanımı
tools_for_weather = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Belirtilen konumun güncel hava durumu bilgilerini getirir.",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "Hava durumu bilgisi istenen şehir adı."},
},
"required": ["location"],
},
},
}
]
user_query_weather = "İstanbul'da hava nasıl?"
messages_weather = [
ChatMessage(role="user", content=user_query_weather)
]
response_weather = client.chat(
model="mistral-large-latest",
messages=messages_weather,
tools=tools_for_weather, # Araçları modele tanıtıyoruz
tool_choice="auto" # Modelin uygun aracı seçmesine izin veriyoruz
)
# Modelin yanıtını işleme
tool_calls = response_weather.choices[0].message.tool_calls
if tool_calls:
for tool_call in tool_calls:
if tool_call.function.name == "get_current_weather":
location = tool_call.function.arguments["location"]
weather_info = get_current_weather(location) # Simüle edilen fonksiyonu çağır
print(f"Mistral'dan Hava Durumu Bilgisi İçin API Çağrısı:")
print(f"Konum: {location}, Hava Durumu: {json.dumps(weather_info, indent=2, ensure_ascii=False)}")
# Sonraki adımda, bu hava durumu bilgisini LLM'e geri besleyip kullanıcıya doğal dilde yanıt verebilirsiniz.
# Örneğin: "İstanbul'da hava şu anda 22°C ve güneşli."
else:
print(f"Mistral araç çağırmadı. Yanıt: {response_weather.choices[0].message.content}")
Bu yetenek, sanal asistanlar, chatbotlar ve karmaşık iş akışlarını otomatikleştiren uygulamalar için temel bir yapı taşıdır. Kullanıcının doğal dilindeki niyetini yapılandırılmış bir API çağrısına dönüştürerek, uygulamaların çok daha akıllı ve etkileşimli olmasını sağlar.
Bu vaka analizleri, yapılandırılmış çıktıların yalnızca bir teknik detay olmadığını, aynı zamanda LLM'lerin gerçek dünyadaki iş problemlerini çözmek için nasıl kullanılabileceğini gösteren güçlü bir mekanizma olduğunu ortaya koymaktadır. Her senaryo, LLM'in esnek doğal dil anlama yeteneğini, kesin ve programatik olarak işlenebilir veri çıktılarıyla birleştirerek değer yaratır.
Performans Optimizasyonu ve Güvenilirlik İçin İleri Düzey İpuçları Nelerdir?
Yapılandırılmış çıktıları LLM'lerden almak harika bir başlangıç, ancak uygulamalarınızı üretimde güvenilir ve verimli bir şekilde çalıştırmak için bazı ileri düzey tekniklere ve optimizasyonlara ihtiyacınız olacak. İşte dikkate almanız gereken bazı önemli ipuçları:
1. Kapsamlı Şema Tanımlamaları ve Geri Besleme Döngüleri
Modele sağladığınız JSON Schema veya fonksiyon tanımı ne kadar detaylı olursa, modelin beklenen çıktıyı üretme olasılığı o kadar artar. Her alanın veri tipini, açıklamasını, kabul edilebilir değerlerini (enum'lar), zorunlu olup olmadığını ve format kısıtlamalarını (regex desenleri) açıkça belirtin. Hatta bazı durumlarda, şemayı doğrudan isteminize gömerek modelin çıktıyı o şemaya uygun hale getirmesi için daha güçlü bir ipucu sağlayabilirsiniz. Yanlış çıktılar aldığınızda, şemanızı veya isteminizi güncelleyerek bir geri besleme döngüsü oluşturun.
2. Sağlam Hata İşleme ve Yeniden Deneme Mekanizmaları
LLM'ler, ne kadar iyi prompt'lar veya araç tanımları kullansanız da, bazen geçersiz JSON veya yanlış formatta çıktı üretebilirler. Bu nedenle, uygulamanızda sağlam hata işleme mekanizmaları bulundurmak hayati önem taşır. Çıktıyı her zaman bir try-except bloğu içinde ayrıştırın ve json.JSONDecodeError gibi hataları yakalayın.
import json
llm_output = "Bu bir {geçersiz JSON}"
try:
parsed_data = json.loads(llm_output)
except json.JSONDecodeError as e:
print(f"JSON Ayrıştırma Hatası: {e}. Yeniden deneme veya alternatif yöntem uygulanıyor.")
# Burada modelden çıktıyı tekrar isteme, prompt'u ayarlama veya varsayılan değer kullanma gibi
# bir yeniden deneme stratejisi uygulayabilirsiniz.
Ayrıca, belirli bir sayıda başarısız denemeden sonra farklı bir model veya fallback mekanizması kullanmayı düşünebilirsiniz. Örneğin, daha küçük, daha hızlı bir modelden alınan çıktı başarısız olursa, daha yetenekli ama yavaş bir modele geçiş yapmak.
3. Token Maliyetleri ve Verimlilik Yönetimi
Fonksiyon tanımları ve JSON şemaları, modele gönderilen token sayısını artırır, bu da maliyetleri ve gecikmeyi etkileyebilir. Gereksiz derecede karmaşık şemalardan kaçının. Yalnızca gerçekten ihtiyacınız olan alanları ve doğrulama kurallarını ekleyin. Modelleri, kullanıcının isteği için gerekli olan en az miktarda bilgiyi döndürmeye teşvik eden prompt'lar yazın. Özellikle uzun belgelerden veri çıkarırken, belgeyi parçalara ayırıp ilgili kısımları LLM'ye göndermek (chunking) veya RAG (Retrieval Augmented Generation) gibi teknikleri kullanarak bağlam penceresi kullanımını optimize edebilirsiniz.
4. Model Seçimi ve İnce Ayar Potansiyeli
Tüm modeller yapılandırılmış çıktı konusunda aynı performansı göstermez. Daha büyük ve daha yetenekli modeller (örneğin, GPT-4o, Claude 3 Opus) genellikle daha iyi ve daha güvenilir yapılandırılmış çıktı üretme eğilimindedir. Ancak bu modeller daha pahalıdır. Projenizin ihtiyaçlarına ve bütçesine göre doğru modeli seçmek önemlidir. Çok özel veya niş bir yapılandırılmış çıktı formatına ihtiyacınız varsa, kendi verilerinizle (örneğin, doğru JSON çıktıları içeren örneklerle) bir modeli ince ayar (fine-tuning) yapmayı düşünebilirsiniz. Bu, modelin istenen formatı tutarlı bir şekilde üretme yeteneğini önemli ölçüde artırabilir.
5. Mobil Uygulamalar İçin Duyarlı Çıktı Yönetimi
LLM'lerden alınan yapılandırılmış çıktılar genellikle arka uçta işlenir, ancak sonuçlar mobil uygulamalarda veya web arayüzlerinde gösterilebilir. Bu çıktıların farklı cihaz boyutlarına ve yönelimlerine uygun şekilde görüntülenmesi için duyarlı tasarım prensipleri uygulanmalıdır. Özellikle uzun JSON çıktıları veya tablolar, küçük ekranlarda okunması zor olabilir. CSS media query'leri, bu tür durumlarda kullanıcı deneyimini iyileştirmek için kullanılabilir.
Ürün Adı
Fiyat
Kategori
Kablosuz Kulaklık
1999 TL
Elektronik
Akıllı Saat
3500 TL
Giyilebilir Teknoloji
Yukarıdaki CSS medya sorgusu örneği, bir tablonun mobil cihazlarda nasıl daha okunabilir hale getirilebileceğini göstermektedir. Bu tür teknikler, LLM'lerden alınan yapılandırılmış verilerin son kullanıcıya sunulduğu her durumda düşünülmelidir.
Bu ileri düzey ipuçları, LLM tabanlı uygulamalarınızın sadece işlevsel olmasını değil, aynı zamanda üretim ortamında sağlam, verimli ve kullanıcı dostu olmasını sağlayacaktır. Yapılandırılmış çıktılarla çalışırken, bu konulara dikkat etmek, uzun vadede size zaman ve kaynak kazandıracaktır.
Sonuç: Doğru LLM ve Yaklaşımı Seçmek İçin Neler Bilmeliyiz?
Bu makale boyunca, OpenAI, Google Gemini, Anthropic Claude, Mistral AI ve AWS Bedrock gibi önde gelen Büyük Dil Modeli (LLM) sağlayıcılarının yapılandırılmış çıktı yeteneklerini ayrıntılı bir şekilde inceledik. Gördüğümüz gibi, her sağlayıcı, temel Function Calling veya JSON moduna benzer mekanizmalar sunsa da, API tasarımları, prompt etkileşimleri ve ek servisler (örneğin, AWS Bedrock'taki Agents) açısından farklılıklar gösterir. Peki, projeniz için en doğru LLM'yi ve yapılandırılmış çıktı yaklaşımını nasıl seçmelisiniz?
Öncelikle, uygulamanızın spesifik ihtiyaçlarını net bir şekilde tanımlayın. Sadece basit bir JSON objesine mi ihtiyacınız var, yoksa karmaşık iş akışlarını tetikleyecek, birden fazla parametreye sahip fonksiyon çağrılarına mı ihtiyacınız var? Çıktının güvenilirliği ne kadar kritik? Gecikme ve maliyet kısıtlamalarınız nelerdir? Bu soruların yanıtları, size yol gösterecektir.
- Basit JSON Çıktıları İçin: OpenAI (GPT-4o, GPT-3.5 Turbo) ve Mistral AI (Mistral Large, Mistral Medium) gibi sağlayıcıların sunduğu özel JSON modları, genellikle en kolay ve güvenilir çözümleri sunar.
response_format={"type": "json_object"}gibi parametreler, modelin geçerli JSON üretmesini zorlayarak hata oranını düşürür. - Karmaşık İş Akışları ve API Entegrasyonları İçin: OpenAI'nin Function Calling, Google Gemini'nin Function Calling ve Anthropic'in Tool Use mekanizmaları, kullanıcının doğal dil isteğinden belirli bir fonksiyonu çağırmak için gerekli yapılandırılmış parametreleri çıkarmak için son derece güçlüdür. AWS Bedrock'taki Agents, bu yeteneği daha da ileriye taşıyarak çok adımlı, otomatikleştirilmiş iş akışları oluşturmanıza olanak tanır.
- Maliyet ve Performans Dengesi İçin: Mistral AI modelleri genellikle maliyet etkinliği ve yüksek performans dengesi sunar. OpenAI'nin turbo modelleri de benzer şekilde uygun maliyetli olabilirken, GPT-4o ve Claude 3 Opus gibi daha yetenekli modeller, daha yüksek maliyetle daha iyi doğruluk ve karmaşık görevleri yerine getirme yeteneği sunar.
- Ekosistem ve Esneklik İçin: AWS Bedrock, tek bir API üzerinden birden fazla model sağlayıcısına erişim imkanı sunarak, size en iyi modeli seçme konusunda büyük esneklik sağlar. Zaten AWS ekosisteminde çalışıyorsanız, Bedrock entegrasyonu oldukça doğal olacaktır.
Unutmayın ki LLM teknolojileri hızla gelişmektedir. Sağlayıcılar sürekli olarak yeni özellikler ekliyor, mevcut olanları geliştiriyor ve performanslarını artırıyorlar. Bu nedenle, seçiminizi yaparken güncel dokümantasyonları ve duyuruları takip etmek önemlidir. En iyi uygulama, projenizin gereksinimlerine en uygun olan birkaç sağlayıcıyı veya modeli denemek ve kendi test verilerinizle performanslarını karşılaştırmaktır. Bu "deneme yanılma" yaklaşımı, hem teknik uygunluk hem de maliyet etkinliği açısından en doğru kararı vermenizi sağlayacaktır.
Sonuç olarak, yapılandırılmış çıktılar, LLM'lerin sadece akıllı sohbet arkadaşları olmanın ötesine geçerek, iş süreçlerini dönüştüren ve uygulamalarımıza derinlemesine entegre olan temel bir bileşen haline gelmesini sağlamıştır. Bu yetenekleri ustaca kullanarak, daha akıllı, daha otomatik ve daha kullanıcı dostu çözümler geliştirebiliriz. Gelecek, Büyük Dil Modelleri ve yapılandırılmış verilerin ortaklaşa çalıştığı otomasyonlarla şekillenecek!
Sıkça Sorulan Sorular (SSS)
- 1. Yapılandırılmış çıktı almak için prompt mühendisliği tek başına yeterli midir?
- Hayır, genellikle yeterli değildir. Prompt mühendisliği, modelin belirli bir formatta çıktı üretmesini sağlamak için ilk adımdır, ancak LLM'lerin doğasındaki nondeterministiklik nedeniyle her zaman güvenilir sonuçlar vermez. Function Calling, JSON modu veya şema tanımlamaları gibi daha sağlam mekanizmalar, tutarlı ve geçerli yapılandırılmış çıktı elde etmek için tercih edilmelidir.
- 2. Hangi LLM sağlayıcısı en iyi yapılandırılmış çıktı özelliklerine sahiptir?
- En iyi sağlayıcı, projenizin spesifik ihtiyaçlarına bağlıdır. OpenAI (GPT-4o) ve Google Gemini, Function Calling konusunda çok yetenekli ve geniş kabul görmüştür. Mistral AI, iyi performans/maliyet dengesi sunarken, Anthropic Claude'un Tool Use yetenekleri ve AWS Bedrock'un geniş model desteği ve Agent'ları kendi benzersiz avantajlarını sunar. Her birinin API tasarımını ve entegrasyon kolaylığını göz önünde bulundurarak test etmeniz en iyisidir.
- 3. Yapılandırılmış çıktılarımı her zaman doğrulamalı mıyım?
- Evet, kesinlikle! LLM'ler bazen geçersiz veya yanlış formatta çıktılar üretebilir. Bu nedenle, JSON ayrıştırma hatalarını yakalamak ve gerektiğinde bir JSON Schema doğrulayıcı kullanarak çıktının beklenen yapıya uygun olup olmadığını kontrol etmek kritik öneme sahiptir. Bu, uygulamanızın güvenilirliğini artırır.
- 4. Yapılandırılmış çıktı kullanmak LLM çağrılarının maliyetini artırır mı?
- Evet, genellikle artırır. Fonksiyon tanımları ve detaylı JSON şemaları, modele gönderilen toplam token sayısını artırır. Daha fazla token kullanımı, daha yüksek maliyet ve potansiyel olarak daha uzun gecikme anlamına gelir. Bu nedenle, şema ve prompt'larınızı mümkün olduğunca verimli tutmaya çalışmalısınız.
- 5. İnce ayar (fine-tuning) yapılandırılmış çıktıları iyileştirebilir mi?
- Evet, ince ayar, modelin belirli bir formatta veya belirli bir görev için yapılandırılmış çıktılar üretme yeteneğini önemli ölçüde artırabilir. Eğer model mevcut yöntemlerle bile istenen tutarlılığı sağlayamıyorsa ve yeterli miktarda kaliteli veri setiniz varsa, ince ayar güçlü bir çözüm olabilir. Ancak ince ayar, veri hazırlığı ve ek maliyet gerektiren ileri düzey bir konudur.