Yapay zekâ API'sinde araç çağırma (function calling) nasıl yapılır?
Kısaca: İsteğe tools alanında fonksiyonlarının adını, açıklamasını ve parametrelerini (JSON Schema) koyarsın. Model gerekli görürse metin yerine tool_calls döner: hangi fonksiyonu hangi argümanlarla çağırmak istediğini söyler. Fonksiyonu sen çalıştırırsın, sonucu role: "tool" mesajıyla geri gönderirsin, model son cevabı yazar. Wiozen API'de bu, OpenAI ve Anthropic biçiminde aynı anahtarla çalışır.
Araç çağırma nasıl işler?
Model senin fonksiyonunu çalıştırmaz, API de çalıştırmaz. Model yalnız "şu fonksiyonu şu argümanlarla çağır" diye bir istek yazar. Çağrıyı yapan, sonucu alan ve modele geri veren senin kodundur. Bu yüzden veritabanına, iç servislerine ya da dosyalarına erişimi tamamen sen yönetirsin.
Bir tur şöyle gider:
- Kullanıcının mesajını ve
toolslistesini gönderirsin. - Model ya doğrudan cevap verir ya da
tool_callsdöner. İkinci durumdafinish_reason"tool_calls"olur. - Her çağrı için fonksiyonu çalıştırırsın.
- Modelin mesajını ve her sonucu, çağrının
id'siyle eşleşen birrole: "tool"mesajı olarak geçmişe ekleyip isteği yeniden gönderirsin. - Model sonuçlara bakarak son cevabı yazar ya da yeni bir araç çağrısı ister.
Model tek turda birden çok çağrı döndürebilir, örneğin iki şehrin havasını aynı anda isteyebilir. tool_calls bir dizidir; her elemanı ayrı çalıştırıp her birine kendi tool_call_id'siyle cevap ver.
Python ile örnek
OpenAI'nin resmi Python kütüphanesi yeterli; yalnız base_url değişir. Aşağıdaki kod modele bir hava durumu fonksiyonu tanıtır, model çağrı isterse fonksiyonu çalıştırır ve sonucu geri gönderir:
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.wiozen.com/v1", api_key="sk-gw-...")
def get_weather(city: str) -> dict:
# Gerçek uygulamada burada bir hava durumu servisini çağırırsın.
return {"city": city, "temp_c": 14, "sky": "bulutlu"}
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Bir şehrin şu anki hava durumunu döndürür",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
messages = [{"role": "user", "content": "Bursa'da hava nasıl?"}]
first = client.chat.completions.create(model="deepseek-v4.1-flash", messages=messages, tools=tools)
reply = first.choices[0].message
if reply.tool_calls:
messages.append(reply)
for call in reply.tool_calls:
args = json.loads(call.function.arguments)
result = get_weather(**args)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
final = client.chat.completions.create(model="deepseek-v4.1-flash", messages=messages, tools=tools)
print(final.choices[0].message.content)
else:
print(reply.content)arguments bir JSON metnidir, nesne değil; json.loads ile çözmen gerekir. Model bazen eksik ya da yanlış biçimli argüman yazabilir. Çözmeyi try içine al ve hata olursa bunu araç sonucu olarak modele bildir; çoğu model bir sonraki denemede düzeltir.
Parametre açıklamaları modelin doğru argümanı seçmesinde büyük fark yaratır. description alanına fonksiyonun ne zaman kullanılacağını ve birimleri ("santigrat", "ISO tarih") düz bir cümleyle yaz.
Anthropic biçiminde ve Responses API'de
Anthropic biçimini (/v1/messages) kullanıyorsan araçlar yine tools alanında tanımlanır, ama şema input_schema adını alır. Model çağrı isteyince yanıtta type: "tool_use" bloğu ve stop_reason: "tool_use" gelir; argümanlar hazır çözülmüş bir nesne olarak input alanındadır. Sonucu bir sonraki kullanıcı mesajında tool_result bloğuyla, aynı tool_use_id'yle geri gönderirsin.
Wiozen bu biçimde iki şeyi garanti eder. Yanıtta bir tool_use bloğu varsa stop_reason her zaman "tool_use" olur, yani döngünü bu alana göre kurabilirsin. Modelin yazdığı argüman geçerli JSON değilse input boş nesne ({}) olarak gelir; boş input'u eksik argüman gibi ele al.
OpenAI'nin Responses biçiminde (/v1/responses) çağrılar output dizisinde type: "function_call" öğeleri olarak döner. İki biçim arasındaki genel farkları Anthropic Messages mı, Chat Completions mı yazısında anlattık.
Akışlı ve akışsız istekte ne değişir?
stream: true ile araç çağrısı parça parça gelir: fonksiyon adı ilk parçada, argümanlar sonraki parçalarda delta.tool_calls içinde, index alanıyla. Parçaları index'e göre birleştirmek senin işin; SDK'ların akış yardımcıları bunu kendileri yapar.
Akışsız istekte Wiozen parçaları senin yerine birleştirir ve tek bir tool_calls dizisi döner. Bu durumda message.content boş metin değil null olabilir. Kodun içeriği okurken null'ı hesaba katsın; yukarıdaki örnek bu yüzden önce tool_calls'a bakıyor.
Araç çağrısı nasıl ücretlenir?
Ayrı bir araç ücreti yok; her şey token olarak sayılır. tools listesi her istekte modele gider ve girdi tokenı olarak ücretlenir. Modelin yazdığı çağrı (fonksiyon adı ve argümanlar) çıktı tokenıdır. Fonksiyonun sonucu da bir sonraki istekte girdi olarak geri gider.
Bu yüzden bir araç turu en az iki istektir ve ikincisi birincinin bütün geçmişini taşır. Uzun bir araç sonucu (örneğin bütün bir web sayfası ya da yüzlerce satırlık sorgu çıktısı) her turda yeniden ücretlenir. Sonucu modele vermeden önce gereken alanlara indir. Ayrıntılı hesap için API maliyeti nasıl hesaplanır yazısına bak.
Yalnız araç çağrısından oluşan, hiç metin içermeyen bir yanıt gerçek bir cevaptır ve normal ücretlenir. Wiozen'de ücretsiz kapanan "boş cevap" durumu, modelin ne metin ne de araç çağrısı üretmediği yanıtlar içindir; o durum düşünen modeller yazısında anlatılıyor.
Sık sorulan sorular
Model fonksiyonumu kendisi çalıştırır mı?
Hayır. Model yalnız hangi fonksiyonu hangi argümanlarla çağırmak istediğini yazar. Çalıştırmak ve sonucu geri göndermek senin kodunun işi.
Araç çağırma hangi uçlarda çalışıyor?
/v1/chat/completions, /v1/messages ve /v1/responses. Üçü de aynı anahtarla ve aynı model adlarıyla kullanılır.
tools listesi ücretli mi?
Evet, her istekte girdi tokenı olarak sayılır. Kullanmadığın fonksiyonları listeden çıkarmak her isteği biraz ucuzlatır.
Akışsız istekte message.content neden null geliyor?
Model metin yerine araç çağrısı döndüğünde içerik boş kalır ve null olarak gelir. Önce tool_calls alanına bak.
Model argümanı yanlış yazarsa ne olur?
OpenAI biçiminde arguments metni olduğu gibi gelir, çözerken hata alabilirsin. Anthropic biçiminde geçersiz argüman boş nesne olarak gelir. İki durumda da hatayı araç sonucu olarak modele bildirmek genelde yeterli.
Anahtarını Anahtarlar sayfasından al ve yukarıdaki örneği tek bir fonksiyonla dene. Bütün parametreler belgelerde.
Diğer rehberler: Türkiye'den kredi kartı olmadan yapay zekâ API'si nasıl kullanılır? · OpenAI uyumlu bir API mevcut bir araca nasıl bağlanır? · Yapay zekâ API maliyeti nasıl hesaplanır? · Yapay zekâ API anahtarım sızdıysa ne yapmalıyım? · Yapay zekâ API'siyle görsel nasıl üretilir ve görsel başı maliyeti ne kadar? · Ses dosyasını yazıya çeviren API'nin dakikası kaç dolar, ücret nasıl hesaplanıyor? · Yapay zekâ API'si neden 429 hatası veriyor, nasıl düzeltilir? · Uzun yanıt bekleyen API isteği neden zaman aşımına düşer: akışlı mı, akışsız mı? · Anthropic Messages API mı, OpenAI Chat Completions mı: hangisini kullanmalıyım? · Bağlam penceresi (context window) nedir, 1 milyon token ne işe yarar? · Hangi yapay zekâ modelini seçmeliyim: fiyat, bağlam ve kaliteye göre karar · Düşünen (reasoning) model neden boş cevap döner, düşünme tokenları neden ücretlenir? · API bakiyem neden beklediğimden hızlı bitiyor? Harcamayı istek istek takip etmek · Bir web sayfası yapay zekâya vermek için Markdown'a nasıl çevrilir? · WordPress'te yapay zekâyla otomatik makale nasıl yazdırılır? · Blog için RSS ve Google Trends'ten konu nasıl bulunur? · Yapay zekâyla yazılan içerik Google'da ve yapay zekâ yanıtlarında görünür mü? · WordPress'te yapay zekâyla yazılan makalelere iç bağlantı nasıl ekletilir? · WordPress'te her yazıya birbirine benzemeyen öne çıkan görsel yapay zekâyla nasıl ürettirilir? · Yapay zekâya blog yazısı yazdırırken içerik tarifi (brief) nasıl yazılır? · Yemek tarifi sitesine yapay zekâyla tarif yazdırırken nelere dikkat etmeli? · WordPress eklentisini yapay zekâ API hesabına bağlarken çıkan hatalar nasıl çözülür? · WordPress'te yapay zekâ yazı botu neden yarıda kalıyor? "Tur takıldı" uyarısı ve LiteSpeed · WordPress'te otomatik yazılar neden geç çıkıyor? WP-Cron ve gerçek sunucu cron'u · Yapay zekâ yazı botuyla İngilizce ya da başka dilde blog yazısı nasıl yazdırılır? · "İçerik Botu yazı üretemiyor" uyarısı ne demek? Bot günlüğündeki satırları okumak · WordPress yapay zekâ yazı eklentisini silersem yazdığı yazılar da silinir mi? · Yapay zekâ API bakiyemi koddan nasıl sorgularım, bakiye azalınca nasıl uyarı alırım?