Ana içeriğe geç

GPT-5 Fonksiyon Çağırma Eğitimi

JSON-şema fonksiyonlarından serbest biçimli araçlara, Lark/CFG kısıtlarına, ön notlara ve araç izin listelerine kadar GPT-5 fonksiyon çağırmaya yönelik pratik bir rehber.
· 11 dk. oku

Yapay Zeka ile Keşfedin

GPT-5’in piyasaya çıkışıyla, OpenAI API’de araç/fonksiyon çağırmayı serbest biçimli araç çağrılarını (ham metin, JSON yok), Lark/CFG ile dil bilgisi kısıtlarını, araç izin listelerini ve geliştirilmiş araç kullanımı akıl yürütmesini kapsayacak şekilde genişletti. Birlikte ele alındığında, bunlar GPT-5’i gerçekten ajan benzeri bir modele dönüştürüyor; Yanıtlar API’sine API’leri, veritabanlarını ve özel araçları bağlayabilir, temellendirilmiş yanıtlar üretebilir veya hatta iş akışlarını otomatikleştirebilirsiniz.

Bu eğitimde fonksiyon araçları, özel araçlar, dil bilgisi kısıtları, araç izin listeleri ve ön notlar konularını, nasıl çalıştıklarına ve ne zaman kullanılması gerektiğine dair açık açıklamalar ve kod örnekleriyle ele alacağım.

GPT-5’te Fonksiyon Çağırma: Nedir ve Neden

GPT-5’te Fonksiyon Çağırma, modeli uygulamanızın veri ve eylemleriyle zenginleştirmenize olanak tanır. Model bir aracı ne zaman çağıracağını belirleyebilir; siz ise mantığı yönetip sonuçları son, temellendirilmiş yanıta geri döndürürsünüz. 

Fonksiyon Çağırma Türleri:

  1. Fonksiyon Araçları (JSON Şeması): Modelin hassas şekilde çağırabileceği yapılandırılmış giriş ve çıkışlar sunar.
  2. Özel Araçlar (Serbest Biçim): Yapılandırılmamış entegrasyonlar için esnek metin tabanlı giriş ve çıkışlar sağlar.

Fonksiyon çağırma nedir?

GPT-5, dış çalışma zamanlarıyla sorunsuz entegrasyon için JSON Şeması kullanan yapılandırılmış fonksiyon araçlarını ve SQL, betikler veya yapılandırmalar gibi serbest biçimli metin yüklerini kabul eden özel araçları destekler. 

Fonksiyon araçları JSON Şeması ile tanımlanır; bu, modelin hangi argümanları ileteceğini tam olarak anlamasını ve sıkı girdi doğrulamasını sağlar. Daha fazlasını OpenAI Fonksiyon Çağırma eğitimimizde okuyabilirsiniz.

Neden fonksiyon çağırma kullanılır?

  • Esneklik: Serbest biçimli araçlar, katı JSON kısıtları olmadan sisteminizin ihtiyaç duyduğu tam metni üretmeyi sağlar; bu da kod, sorgular veya yapılandırmalar için idealdir.
  • Güvenilirlik ve Kontrol: Fonksiyon araçları yapılandırılmış argümanları zorunlu kılar; bu da öngörülebilirliği artırır ve ayrıştırma hatalarını azaltır.
  • Ajan Benzeri İş Akışları: GPT-5, araçların çok adımlı kullanımı ve kodlama görevleri için tasarlanmıştır; bu nedenle araç çağırma birincil özelliktir.

Fonksiyon çağırma nasıl çalışır?

  1. Tüm kullanılabilir araçları içeren bir istem gönderin.
  2. Model bir araç çağrısı yapar (argümanlarla veya serbest biçimli metinle).
  3. Uygulamanız aracı çalıştırır (Python fonksiyonunu yürütün).
  4. Araçtan çıkan çıktıyı modele geri döndürün.
  5. Model daha sonra yanıt verir veya ek araçlar çağırabilir.

Kaynak: Fonksiyon çağırma - OpenAI API

Ne zaman Fonksiyon Araçları, ne zaman Özel Araçlar?

  • Fonksiyon araçlarını kullanın JSON Şeması üzerinden sıkı doğrulama ve öngörülebilir, türü belirli argümanlar istediğinizde.
  • Özel araçları (serbest biçim) kullanın çalışma zamanınız ham metin gerektirdiğinde (betikler, SQL veya yapılandırmalar gibi) ya da şemasız hızlı yinelemelere ihtiyaç duyduğunuzda.

Fonksiyon Araçları (JSON Şeması): Yapılandırılmış Veri Gönderin

JSON Şeması ile Fonksiyon Araçlarını kullanmak, modelden öngörülebilir ve yapılandırılmış sonuçlar elde etmenizi sağlar. Model, tanımladığınız araçları değerlendirir, ne zaman kullanılacağını belirler, JSON ile doğrulanmış argümanlar önerir ve ardından kodunuzda ilgili fonksiyonu çalıştırır. 

Bundan sonra, modelden yalnızca araçtan dönen veriye dayanarak bir yanıt üretmesini isteyebilirsiniz; bu da çıktının temellendirilmiş, makinece okunabilir ve entegre edilmesi kolay olmasını sağlar.

Bu örnek birkaç temel kavramı gösterir:

  • Araç keşfi ve argüman üretimi: Model uygun aracı seçer ve JSON türündeki argümanlarını otomatik doldurur.
  • Araç yürütme döngüsü: Uygulamanız istenen araç(lar)ı çalıştırır ve sonuçları modele geri gönderir.
  • Şemaya uygun son yanıt: Son yanıt yalnızca araçlardan gelen çıktılara dayanır; bu da hataları en aza indirir ve güvenilirlik sağlar.

1. Kurulum

  1. Bir OpenAI hesabı oluşturun ve platform panosunda bir API anahtarı üretin. Panoda API bölümünü açın, ardından “View API keys”e gidip “Create new secret key”e tıklayın.
  2. API çağrılarının çalışabilmesi için hesabınıza bir ödeme yöntemi veya kredi ekleyin; kullanım, istek yaptıkça ön ödemeli bakiyenizden düşer.
  3. Uygulamanızı başlatmadan önce API anahtarınızı OPENAI_API_KEY adlı bir ortam değişkeni olarak kaydedin. 
  4. Resmi OpenAI Python SDK’sını pip install openai ile kurun.

2. Araçları tanımlayın

Bir ad, açıklama ve parametreler için JSON Şeması ile bir araç listesi sağlarsınız. Şema, modelin düzgün biçimlendirilmiş argümanlar üretmesine yardımcı olur.

  • make_coffee tek bir dize parametre bekler: coffee_type.
  • random_coffee_fact parametre almaz (boş nesne). Bu tanımlar, modelin nelerin mevcut olduğunu bilmesi için API çağrısında tools argümanı üzerinden iletilir.
import os
from openai import OpenAI
import json

client = OpenAI(api_key = os.environ["OPENAI_API_KEY"])

tools = [
    {
        "type": "function",
        "name": "make_coffee",
        "description": "Gives a simple recipe for making a coffee drink.",
        "parameters": {
            "type": "object",
            "properties": {
                "coffee_type": {
                    "type": "string",
                    "description": "The coffee drink, e.g. espresso, cappuccino, latte"
                }
            },
            "required": ["coffee_type"],
        },
    },
    {
        "type": "function",
        "name": "random_coffee_fact",
        "description": "Returns a fun fact about coffee.",
        "parameters": {"type": "object","properties":{}}
    }
]

3. Araçları uygulayın

Asıl işi yapan Python fonksiyonlarını siz uygularsınız:

  • make_coffee(coffee_type), istenen içeceğe göre kısa bir tarif dizesi döndürür.
  • random_coffee_fact() küçük bir bilgi yükü döndürür. 

Her ikisi de modele geri beslemek için ideal olan JSON’a serileştirilebilir sözlükler döndürür.

def make_coffee(coffee_type):
    recipes = {
        "espresso": "Grind fine, 18g coffee → 36g espresso in ~28s.",
        "cappuccino": "Brew 1 espresso shot, steam 150ml milk, pour and top with foam.",
        "latte": "Brew 1 espresso shot, steam 250ml milk, pour for silky texture.",
    }
    return {"coffee_type": coffee_type, "recipe": recipes.get(coffee_type.lower(), "Unknown coffee type!")}

def random_coffee_fact():
    return {"fact": "Coffee is the second most traded commodity in the world, after oil."}

4. Bir konuşma başlatın

Kullanıcının sorusuyla konuşmayı başlatın: {"role": "user", "content": "How do I make a latte?"}

Model, function_call öğesi içeren iletiler döndürebilir; örneğin make_coffee ve {"coffee_type":"latte"}. Daha sonra modelin iletilerini input_list: input_list += response.output ile tekrar eklemelisiniz. Bu, bir sonraki tur için konuşma durumunu korumaya yardımcı olur.

# Track used tools
used_tools = []

input_list = [{"role": "user", "content": "How do I make a latte?"}]

response = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=input_list,
)
input_list += response.output

5. Araç çağrılarını yürütün ve çıktıları ekleyin

response.output üzerinde yineleme yapmalı ve item.type değerinin "function_call" olduğu öğeleri belirlemelisiniz. Bu öğeler için item.arguments değerini ayrıştırın ve istekleri Python fonksiyonlarınıza yönlendirin. 

make_coffee fonksiyonu için make_coffee(args["coffee_type"]) ile çağırın. random_coffee_fact için doğrudan random_coffee_fact() çağrısı yeterlidir. 

Fonksiyonları çalıştırdıktan sonra, aşağıdakileri içeren bir function_call_output mesajı ekleyin: 

  • call_id (bu çıktıyı modelin isteğine bağlar) 
  • output (fonksiyon sonucunuzun JSON dizesi).
for item in response.output:
    if getattr(item, "type", "") == "function_call":
        used_tools.append(item.name)
        args = json.loads(item.arguments or "{}")

        if item.name == "make_coffee":
            result = make_coffee(args["coffee_type"])
        elif item.name == "random_coffee_fact":
            result = random_coffee_fact()
        else:
            result = {"error": f"Unknown tool {item.name}"}

        input_list.append({
            "type": "function_call_output",
            "call_id": item.call_id,
            "output": json.dumps(result)
        })

6. Son yanıtı üretin

Güncellenmiş ve artık araç çıktılarının yer aldığı input_list’i geçirerek ikinci bir client.responses.create çağrısı yaparsınız.

used_tools değişkeni, modelin fonksiyon çağrılarında görünen araçların adlarını yakalar. Hangi araçların kullanıldığını göstermek için bunu kullanacağız. 

final = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=input_list,
    instructions="Answer using only the tool results."
)

print("Final output:\n", final.output_text)

print("\n--- Tool Usage ---")
for t in tools:
    status = "USED ✅" if t["name"] in used_tools else "NOT USED ❌"
    print(f"{t['name']}: {status}")

Kullanıcı latte hakkında sorduğu için, model make_coffee’i coffee_type = "latte" ile seçti, kodunuz bunu çalıştırdı ve son yanıt yalnızca bu araç sonucundan oluşturuldu.

Final output:
 {"coffee_type":"latte","recipe":"Brew 1 espresso shot, steam 250ml milk, pour for silky texture."}

--- Tool Usage ---
make_coffee: USED ✅
random_coffee_fact: NOT USED ❌

Özel Araçlar (Serbest Biçim): Ham Metin Gönderin

Modelin JSON Şemasına gerek duymadan kod, SQL, kabuk komutları veya basit CSV gibi ham metni doğrudan aracınıza göndermesine izin vermek için GPT-5’in serbest biçimli özel araçlarını kullanın. 

Bu yetenek, eski yalnızca JSON tabanlı fonksiyon çağrılarının ötesine geçerek yürütücüler, sorgu motorları veya alan-özel dil (DSL) yorumlayıcıları ile entegrasyon için daha fazla esneklik sağlar. 

Serbest biçim modunda model, çalışma zamanınıza yönlendirebileceğiniz yapılandırılmamış metin yüküne sahip özel bir araç çağrısı üretir. Daha sonra sonucu, modelin kullanıcıya dönük nihai yanıtı tamamlaması için geri döndürürsünüz.

Şimdi, modelin uygun araçları seçmesini ve çıktı olarak yapılandırılmamış ham metin döndürmesini sağlayan kodu yazacağız. Bu çıktı, bir sonuç üretmek için bir Python fonksiyonuna aktarılacaktır. Böylece kullanıcı elindeki malzemeleri sağlayabilir ve model ihtiyaçlarına göre uyarlanmış tarifler üretebilir.

Bu örnek kodda şunlar var:

  1. OpenAI istemcisi başlatıldı ve ham metin girdisi kabul eden tek bir özel araç olan meal_planner tanımlandı.
  2. Virgülle ayrılmış bir malzeme dizgesini alıp bir yemek fikri döndüren Python plan_meal oluşturuldu.
  3. Kullanıcı mesajı ile mevcut malzemeleri listeleyerek konuşma başlatıldı.
  4. Modelin yalnızca temiz bir malzeme listesi kullanarak aracı çağırması talimatıyla ilk model çağrısı yapıldı ve model çıktısı konuşma geçmişine eklendi.
  5. Yayımlanan özel araç çağrısı bulunarak ham virgülle ayrılmış girdi dizesi çıkarıldı.
  6. Liste plan_meal’e iletilerek araç çalıştırıldı; ardından sonuç, call_id üzerinden bağlanan bir function_call_output olarak modele geri gönderildi.
  7. Son olarak, aracın ham fikrini 3–4 adımlı kısa bir tarife dönüştürmek için bir model çağrısı yapıldı ve hem araç çağrısı ayrıntıları hem de son çıktı yazdırıldı.
from openai import OpenAI
import json
import random

client = OpenAI()

# --- Custom tool ---
tools = [
    {
        "type": "custom",
        "name": "meal_planner",
        "description": "Takes ONLY a comma-separated list of ingredients and suggests a meal idea."
    }
]

# --- Fake meal planner ---
def plan_meal(ingredients: str) -> str:
    ideas = [
        f"Stir-fry: {ingredients} with garlic & soy sauce.",
        f"One-pot rice: cook {ingredients} together in broth until fluffy.",
        f"Soup: simmer {ingredients} in stock with herbs.",
        f"Sheet-pan bake: roast {ingredients} at 200°C for ~20 min."
    ]
    return random.choice(ideas)

# --- Start conversation ---
messages = [
    {"role": "user", "content": "I only have chicken, rice, and broccoli. Any dinner ideas?"}
]

# 1) Ask model with clear instruction
resp = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=messages,
    instructions="If the user mentions ingredients, call the meal_planner tool with ONLY a comma-separated list like 'chicken, rice, broccoli'."
)

messages += resp.output

# 2) Find the tool call
tool_call = next((x for x in resp.output if getattr(x, "type", "") == "custom_tool_call"), None)
assert tool_call, "No tool call found!"

# Get clean CSV input
ingredients_csv = tool_call.input.strip()

# 3) Run the tool
meal_result = plan_meal(ingredients_csv)

# 4) Send tool output back
messages.append({
    "type": "function_call_output",
    "call_id": tool_call.call_id,
    "output": meal_result
})

# 5) Final model response
final = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=messages,
    instructions="Turn the meal idea into a short recipe with 3-4 steps."
)

print("\n--- Tool Call ---")
print("Name:", tool_call.name)
print("Input:", ingredients_csv)
print("Output:", meal_result)


print("\n--- Final Output ---\n", final.output_text)

Sonuç olarak, kullanılan araçlara ilişkin kurulum, girdi ve çıktılar dahil istatistikleri aldık. Ek olarak, son çıktı yemeğin nasıl yapılacağına dair eksiksiz bir tarif sunuyor.

--- Tool Call ---
Name: meal_planner
Input: chicken, rice, broccoli
Output: One-pot rice: cook chicken, rice, broccoli together in broth until fluffy.

--- Final Output ---
 One-Pot Chicken, Rice & Broccoli

- Season bite-size chicken pieces with salt and pepper; sear in a little oil in a pot until lightly browned.
- Add 1 cup rinsed rice and 2 cups broth (or water + salt). Bring to a boil, then cover and simmer on low for 12 minutes.
- Scatter 2 cups small broccoli florets on top, cover, and cook 5-7 more minutes until rice is fluffy and broccoli is tender.
- Rest 5 minutes off heat, fluff, and adjust seasoning. Optional: stir in a knob of butter or a splash of soy.

Dil Bilgisi Kısıtları (Lark): Araç Çıktılarını Kısıtlayın

GPT-5 artık çıktı formatlarının sıkı şekilde kontrol edilmesini sağlamak için bağlamdan bağımsız dil bilgisi (CFG) destekliyor. 

Yanıtlara SQL veya alan-özel bir dil (DSL) gibi bir dil bilgisi uygulayarak, GPT-5 çıktılarının sürekli olarak gereken yapıyı izlemesini garanti eder. CFG, otomatik süreçler ve kritik iş akışları için özellikle önemlidir. 

GPT-5, üretim sırasında aracın çıktısını kısıtlamak için Lark gibi formatlarda tanımlanan dil bilgilerini kullanabilir. Bu kısıtlı kod çözme yaklaşımı, biçim kaymasını engelleyerek ve yapısal tutarlılığı güvence altına alarak güvenilirliği artırır.

Şimdi modelin bir araç seçeceği ve YALNIZCA dil bilgisine uygun bir aritmetik ifade çıktısı üreteceği, ardından bu ifadenin Python’da değerlendirileceği, sonucun konuşmaya geri döndürüleceği ve son yanıtın doğal bir dille açıkça sunulacağı kodu yazacağız.

Bu örnek kodda şunlar var:

  1. OpenAI istemcisi başlatıldı ve YALNIZCA dil bilgisine uygun bir aritmetik ifade (Lark CFG) çıktısı üretmesi gereken math_solver adlı özel araç tanımlandı.
  2. Kullanıcıdan doğal dille bir matematik sorusu ile konuşma başlatıldı.
  3. GPT-5’in dil bilgisine uyan bir ifadeyle math_solver’ı çağırması talimatıyla ilk model çağrısı yapıldı.
  4. Yayımlanan araç çağrısı bulunarak araç yükünden ham ifade dizesi çıkarıldı.
  5. İfade, kısıtlı bir ortamda yerel olarak değerlendirilerek somut bir sonuç üretildi.
  6. Araç yürütme sonucu, özgün call_id ile bağlanarak konuşmaya geri döndürüldü.
  7. Değerlendirilen sonuç, son bir model çağrısıyla doğal bir dille açıkça sunuldu.
from openai import OpenAI
import json

client = OpenAI()

# --- Local fake evaluator ---
def eval_expression(expr: str) -> str:
    try:
        # Evaluate safely using Python's eval on restricted globals
        result = eval(expr, {"__builtins__": {}}, {})
        return f"{expr} = {result}"
    except Exception as e:
        return f"Error evaluating expression: {e}"

# --- Custom tool with grammar constraint ---
tools = [
    {
        "type": "custom",
        "name": "math_solver",
        "description": "Solve a math problem by outputting ONLY a valid arithmetic expression.",
        "format": {
            "type": "grammar",
            "syntax": "lark",
            "definition": r"""
start: expr

?expr: term
     | expr "+" term   -> add
     | expr "-" term   -> sub

?term: factor
     | term "*" factor -> mul
     | term "/" factor -> div

?factor: NUMBER
       | "(" expr ")"

%import common.NUMBER
%ignore " "
"""
        },
    }
]

# --- User asks ---
msgs = [
    {"role": "user", "content": "What is (12 + 8) * 3 minus 5 divided by 5?"}
]

# 1) First model call: GPT-5 must emit a grammar-valid expression
resp = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=msgs,
    instructions="Always call the math_solver tool with a grammar-valid arithmetic expression like '(12 + 8) * 3 - 5 / 5'."
)

msgs += resp.output

tool_call = next(
    x for x in resp.output
    if getattr(x, "type", "") in ("custom_tool_call", "tool_call", "function_call")
)

expr = getattr(tool_call, "input", "") or getattr(tool_call, "arguments", "")
print("\n=== Grammar-Constrained Expression ===")
print(expr)

# 2) Run the local evaluator
tool_result = eval_expression(expr)
print("\n=== Tool Execution Result ===")
print(tool_result)

# 3) Return tool output
msgs.append({
    "type": "function_call_output",
    "call_id": tool_call.call_id,
    "output": tool_result
})

# 4) Final pass: GPT-5 presents answer nicely
final = client.responses.create(
    model="gpt-5",
    input=msgs,
    tools=tools,
    instructions="Present the evaluated result clearly in natural language."
)

print("\n=== Final Output ===")
print(final.output_text)

Görüldüğü gibi model aracı seçti ve ardından dil bilgisiyle kısıtlanmış bir ifade üretti. Sonrasında bu ifade, yanıt üretmek üzere Python fonksiyonundan geçirildi. En sonunda doğal bir dille düzgün bir yanıt elde ettik.

=== Grammar-Constrained Expression ===
(12 + 8) * 3 - 5 / 5

=== Tool Execution Result ===
(12 + 8) * 3 - 5 / 5 = 59.0

=== Final Output ===
59

Araç İzin Listeleri: Modelin Kullanabileceklerini Güvenle Sınırlandırın

allowed_tools ayarı, modeli tam araç setinizden güvenli bir seçimle sınırlamanıza olanak tanır. Bu, öngörülebilirliği artırır ve istenmeyen araç çağrılarını önler; model ise izin verilen küme içinde esnekliğini korur. 

Modelin izin verilen araçlar arasında seçim yapmasına izin verebilir veya birini kullanmasını zorunlu kılabilirsiniz; bu, diğer yığınlarda görülen “aracı zorla” davranışlarını yansıtır ve araç çağırma orkestrasyonu için genel en iyi uygulamalarla uyumludur.

Şimdi tek bir araca izin verdiğimiz, modelin yalnızca bu aracı çağırdığı, çalıştırdığımız, sonuçları geri beslediğimiz ve ardından kısa bir kullanıcıya dönük özet ürettiğimiz kodu yazacağız.

Not: Lütfen ücretsiz bir Firecrawl hesabı oluşturun, bir API anahtarı üretin, bunu FIRECRAWL_API_KEY ortam değişkeni olarak kaydedin ve Firecrawl Python SDK’sını pip install firecrawl-py ile kurun.

Bu örnek kodda şunlar var:

  1. Hem dummy_web_search hem de firecrawl_search ile tam bir araç seti tanımlandı.
  2. Model, yalnızca tool_choice = { type: "allowed_tools", mode: "required", tools: [...] } ile firecrawl_search kullanımına zorlandı.
  3. İlk model çağrısı yapıldı, araç çağrısının adı ve argümanları yakalanıp görünürlük için yazdırıldı.
  4. firecrawl_search çağrıldığında, argümanlar ayrıştırıldı, Firecrawl çalıştırıldı, yanıt JSON’a serileştirilebilir bir sözlüğe dönüştürüldü ve güvenli veri yükü çıkarıldı.
  5. Araç sonuçları call_id ile bağlanan function_call_output kullanılarak konuşmaya geri beslenip, ardından 3–4 madde halinde Markdown bağlantılarıyla özetlemek için son bir model çağrısı yapıldı.
  6. İzin listesi bu çalışmada engellese de yalancı aracı çalıştıracak bir geri dönüş dalı eklendi.
  7. Son doğal dil yanıtı yazdırıldı.
from openai import OpenAI
from firecrawl import Firecrawl
import json
import os

client = OpenAI()
firecrawl = Firecrawl(api_key=os.environ["FIRECRAWL_API_KEY"])

# --- Full toolset ---
tools = [
    {
        "type": "function",
        "name": "dummy_web_search",
        "description": "A fake web search that always returns static dummy results.",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {"type": "string"},
                "limit": {"type": "integer"}
            },
            "required": ["query"]
        },
    },
    {
        "type": "function",
        "name": "firecrawl_search",
        "description": "Perform a real web search using Firecrawl.",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {"type": "string"},
                "limit": {"type": "integer"}
            },
            "required": ["query"]
        },
    },
]

# --- Dummy implementation ---
def dummy_web_search(query, limit=3):
    return {
        "query": query,
        "results": [f"[Dummy] Result {i+1} for '{query}'" for i in range(limit)]
    }

# --- User asks ---
messages = [
    {"role": "user", "content": "Find me the latest info about the stock market."}
]

# --- Restrict to Firecrawl only ---
resp = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=messages,
    instructions="Only the firecrawl_search tool is allowed. Do not use dummy_web_search.",
    tool_choice={
        "type": "allowed_tools",
        "mode": "required",  # force Firecrawl
        "tools": [{"type": "function", "name": "firecrawl_search"}],
    },
)

for item in resp.output:
    if getattr(item, "type", "") in ("function_call", "tool_call"):
        print("\n--- Tool Call ---")
        print("Tool name:", item.name)
        print("Arguments:", item.arguments)

        if item.name == "firecrawl_search":
            args = json.loads(item.arguments)

            # Firecrawl returns a SearchData object → convert it
            results_obj = firecrawl.search(
                query=args["query"],
                limit=args.get("limit", 3),
            )

            # 🔥 Convert to JSON-serializable dict
            if hasattr(results_obj, "to_dict"):
                results = results_obj.to_dict()
            elif hasattr(results_obj, "dict"):
                results = results_obj.dict()
            else:
                results = json.loads(results_obj.json()) if hasattr(results_obj, "json") else results_obj

            print("\n--- Firecrawl Raw Results ---")
            print(json.dumps(results, indent=2)[:500])

            # ✅ Extract only the data portion for summarization
            safe_results = results.get("data", results)

            # Feed back to GPT
            messages += resp.output
            messages.append({
                "type": "function_call_output",
                "call_id": item.call_id,
                "output": json.dumps(safe_results)  # now safe
            })

            # Final pass
            final = client.responses.create(
                model="gpt-5",
                tools=tools,
                input=messages,
                instructions="Summarize the Firecrawl search results into 3-4 bullet points with clickable [Title](URL) links."
            )

            print("\n--- Final Natural Language Answer ---")
            print(final.output_text)

        elif item.name == "dummy_web_search":
            args = json.loads(item.arguments)
            results = dummy_web_search(args["query"], args.get("limit", 3))
            print("\n--- Dummy Web Search Results ---")
            print(json.dumps(results, indent=2))

Firecrawl araması seçildi ve bunu kullanarak son yanıtı markdown formatında üretti.

Ön Notlar: Modele Araçları Nasıl Çağıracağını Söyleyin

Ön notlar, modelin bir aracı çağırmadan önce çağrının nedenini açıklamak için ürettiği kısa açıklamalardır. Şeffaflığı artırır, kullanıcı güveni oluşturur ve karmaşık iş akışlarında hata ayıklama netliğini geliştirir. “Bir aracı çağırmadan önce açıkla” gibi basit bir talimatla etkinleştirebilir, genellikle fark edilir bir gecikme eklemeden kullanabilirsiniz. 

Şimdi modelin, bir aracı neden çağırdığını açıklayan kısa bir “Ön Not:” satırı ürettiği, ardından aracı çağırdığı, sizin bunu yerelde çalıştırdığınız, sonucu geri döndürdüğünüz ve modelin net bir son yanıt ürettiği kodu yazacağız.

Bu örnek kodda şunlar var:

  1. OpenAI istemcisi başlatıldı ve JSON Şeması ile sıkı tür denetimine sahip bir fonksiyon aracı (medical_advice) tanımlandı.
  2. Modele, herhangi bir araç çağrısından önce tek satırlık bir “Ön Not:” çıktısı üretmesini söyleyen bir sistem talimatı eklendi.
  3. Konuşma, kullanıcının semptom sorusuyla başlatıldı.
  4. Ön notu ve araç çağrısını argümanlarıyla birlikte almak üzere ilk model çağrısı yapıldı.
  5. Araç çıkarıldı ve yerelde çalıştırılarak öneri üretildi.
  6. Aracın çıktısı call_id üzerinden bağlanarak modele geri döndürüldü.
  7. GPT‑5’in sonucu kısa ve kullanıcı dostu bir yanıt olarak sunması için son bir model çağrısı yapıldı.
from openai import OpenAI
import json
import random

client = OpenAI()

# --- Fake tool implementation ---
def medical_advice(symptom: str):
    remedies = {
        "headache": "You can take acetaminophen (paracetamol) or ibuprofen, rest in a quiet room, and stay hydrated.",
        "cough": "Drink warm fluids, use honey in tea, and consider over-the-counter cough syrup.",
        "fever": "Use acetaminophen to reduce fever, stay hydrated, and rest. See a doctor if >39°C.",
    }
    return {"advice": remedies.get(symptom.lower(), "Please consult a healthcare provider for guidance.")}

# --- Tool definition ---
tools = [{
    "type": "function",
    "name": "medical_advice",
    "description": "Provide safe, general over-the-counter advice for common symptoms.",
    "parameters": {
        "type": "object",
        "properties": {"symptom": {"type": "string"}},
        "required": ["symptom"],
        "additionalProperties": False
    },
    "strict": True,
}]

# --- Messages (system preamble instruction) ---
messages = [
    {"role": "system", "content": "Before you call a tool, explain why you are calling it in ONE short sentence prefixed with 'Preamble:'."},
    {"role": "user", "content": "What should I take for a headache?"}
]

# 1) First call: expect preamble + tool call
resp = client.responses.create(model="gpt-5", input=messages, tools=tools)
print("=== First Response ===")
for item in resp.output:
    t = getattr(item, "type", None)
    if t == "message":
        # Extract just the model's text
        content = getattr(item, "content", None)
        text = None
        if isinstance(content, list):
            text = "".join([c.text for c in content if hasattr(c, "text")])
        elif content:
            text = str(content)
        if text:
            # ✅ Only print once
            print(text)
    if t in ("function_call", "tool_call", "custom_tool_call"):
        print("Tool:", getattr(item, "name", None))
        print("Args:", getattr(item, "arguments", None))

# Extract tool call
tool_call = next(x for x in resp.output if getattr(x, "type", None) in ("function_call","tool_call","custom_tool_call"))
messages += resp.output

# 2) Execute tool locally
args = json.loads(getattr(tool_call, "arguments", "{}"))
symptom = args.get("symptom", "")
tool_result = medical_advice(symptom)

# 3) Return tool result
messages.append({
    "type": "function_call_output",
    "call_id": tool_call.call_id,
    "output": json.dumps(tool_result)
})

# 4) Final model call → natural answer
final = client.responses.create(model="gpt-5", input=messages, tools=tools)
print("\n=== Final Answer ===")
print(final.output_text)

Bir aracı çağırmadan önce, neden çağırdığını açıklayan bir bilgilendirme sağladığını görebilirsiniz. Bu, gözlemlenebilirlik ve hata ayıklama için iyidir.

Özet

GPT-5, özellikle kodlama ve ajan tabanlı iş akışlarında üstün olan, OpenAI’nin bugüne kadarki en gelişmiş modelidir. En son API özellikleri, baştan sona üretim düzeyinde sistemlerin doğrudan geliştirilmesini mümkün kılar.

Bu eğitimde şunları öğrendiniz:

  1. Yapılandırılmış çıktılar döndürmek için Fonksiyon Araçları ve JSON Şeması kullanarak aşağı akış otomasyonunu güvenilir kılmak.
  2. Serbest biçimli yürütmeyi etkinleştirmek için Özel Araçlar (ham metin) ile modelin yalnızca JSON çağrılarının ötesinde kod, SQL, kabuk betikleri ve CSV dosyaları üretmesini sağlamak.
  3. Kısıtlı formatlar için matematik, SQL veya alan-özel diller (DSL) gibi durumlarda hassasiyet gerektiğinde Lark dil bilgisi kısıtlarını kullanmak.
  4. Araç erişimini kısıtlamak için izin listeleri (veya tek bir aracı zorlayarak) kullanarak güvenliği, kontrolü ve determinizmi artırmak.
  5. Şeffaflığı artırmak için modelin belirli bir aracı neden çağırdığını açıklayan kısa ön notlarla gözlemlenebilirliği ve hata ayıklamayı desteklemek.

OpenAI’nin çeşitli araçlarıyla neler yapabileceğiniz hakkında daha fazla bilgi edinmek için OpenAI Fundamentals beceri yolumuzu ve Working with the OpenAI API kursunu öneririm.

Abid Ali Awan

Yazar

Abid Ali Awan

Sertifikalı bir veri bilimcisi olarak, yenilikçi makine öğrenimi uygulamaları oluşturmak için en son teknolojileri kullanmaya büyük ilgi duyuyorum. Konuşma tanıma, veri analizi ve raporlama, MLOps, konuşma yapay zekası ve NLP alanlarında güçlü bir geçmişe sahip olarak, gerçek bir etki yaratabilecek akıllı sistemler geliştirme becerilerimi geliştirdim. Teknik uzmanlığımın yanı sıra, karmaşık kavramları açık ve özlü bir dille ifade etme yeteneğine sahip, becerikli bir iletişimciyim. Sonuç olarak, veri bilimi konusunda aranan bir blog yazarı oldum ve giderek büyüyen veri profesyonelleri topluluğuyla görüşlerimi ve deneyimlerimi paylaşıyorum. Şu anda, içerik oluşturma ve düzenlemeye odaklanıyorum. Büyük dil modelleriyle çalışarak, hem işletmelerin hem de bireylerin verilerinden en iyi şekilde yararlanmalarına yardımcı olabilecek güçlü ve ilgi çekici içerikler geliştiriyorum.

Konular

İlgili