OpenAI Functions nedir?

Mirkan
7 min readAug 3, 2023

OpenAI 1 ay kadar önce devrim niteliğinde yeni bir özellik getirdi, fakat gördüğüm kadarıyla çok da konuşulmadı.

Hangi problemi çözüyor?

Kısa cevap: Asıl kullanım alanı farklı olsa da, yapılandırılmış verileri metinden ayıklamak için ideal.

Daha kısa cevap: JSON alabiliyoruz.

GPT API’leri ile uğraşmış insanların en büyük sorunlarından biri de geçerli bir JSON yapısı alabilmek. Diyelim ki çocuk masalları yaratan bir uygulama yazıyorsunuz, chat completion API kullanıyorsunuz, arayüzden aldığınız seçenekleri(karakterler, tema, anafikir) güzelce prompt’unuza koydunuz gönderdiniz, masal da yazı olarak geldi, ekranda gösterdiniz. Buraya kadar bir sıkıntı yok.

Fakat eğer diyorsanız ki, ben bu istek ile sadece masalı almayayım, aynı zamanda veritabanım için gerekli diğer verileri de çekeyim, misal başlık, kahramanlar, mekanlar, bunları parse edebilmek için JSON veya alternatifleri halinde almanız gerek. Chat completion ise virgülü, tırnağı, parantezi unutup geçerli olmayan bir JSON döndürüyor bazen ve uygulamanız işleyemiyor. Diyelim ki şemanız bu:

{
"title": "Story of Mr. Bunny",
"story" :"Mr. Bunny discovered that his special gift was growing the juiciest, crunchiest carrots in the whole forest. With a hop, skip, and a joyful heart, he began to share his carrots with all his friends, spreading happiness everywhere, and understood that giving his gift away was his true life's purpose.",
"characters": [
"Mr. Bunny",
"Mr. Bunny's friends"
],
"quote": "The meaning of life is to find your gift. The purpose of life is to give it away."
}

Her seferinde bu şemayı almak için çeşitli çözümler ve eforlar var.

  1. Şemanın boş halini de prompt ile göndermek.
  2. “JSON olacak, valid JSON olacak ha” falan diye prompt’un her yerinde rastgele yalvarmak.
  3. Parse ederken hata alınca, “valid JSON” yap gibi bir prompt ile tekrar göndermek (try-catch mantığı).

Fonksiyonlara gelelim

Aslında fonksiyonların amacı JSON şeklinde datayı almak değil.

(Haydaa, ne anlatıyorsun oğlum o zaman ya masaldı bilmemneydi)

Fonksiyonlar çok daha fazlasını sunuyor.
Basitçe açıklamak gerekirse, chat completion isteği atarken, sisteminizdeki fonksiyonu da gönderiyorsunuz, o istek için bu fonksiyonun kullanılması gerekiyorsa size söylüyor. Fonksiyon nerede çalışıyor, kim yazıyor cevaplayacağım.

Dökümandaki örnek ile başlayalım, sonra örneğimize gelelim.

ChatGPT veya Chat Completion API size saati, hava durumunu vs. vermez. Bunun için hava durumu API’si kullanmamız gerek. Fakat sıradan bir hava durumu uygulaması yapmıyoruz, chat arayüzü olan bir uygulama yapıyoruz. Yani kullanıcı gelip de “İzmir’de hava kaç santigrat?" yazdığında, bunu bir fonksiyona çevirip çağırmamız gerek. Bu fonksiyon da artık open weather olur, accuweather olur, hangi servisi kullanıyorsanız isteği atar, size gerekli veriyi döner.

get_current_weather(location: string, unit: ‘celsius’ | ‘fahrenheit’).

Böyle bir fonksiyonumuz olsun. Bunu çağırabilmek için “İzmir’de hava kaç santigrat?” komutundan “izmir” ve “ celcius” parametrelerini alabilmemiz gerek.

curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
"model": "gpt-3.5-turbo-0613",
"messages": [
{"role": "user", "content": "What is the weather like in Boston?"}
],
"functions": [
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
]
}'

Benim ilk anlarken kafam çok karışmıştı diye biraz sanırım ben de açıklarken döngüye girdim. Kısa bir Sıkça Sorulanlar kısmı:

1. Fonksiyonu göndermek = ismini, açıklamasını ve parametrelerin tipini, ismini, açıklamasını üstteki şema halinde isteğe eklemek. Fonksiyonun gerçekten sisteminizde olması gerekmiyor.

2. Fonksiyon, OpenAI sunucularında çağırılmıyor veya GPT tarafından gövdesi(body) yazılmıyor. Size sadece bu fonksiyon arrayindeki fonksiyonlardan herhangi biri, bu senaryoda kullanılmalı mı, nasıl kullanılmalı, bu prompt için hangi parametreler gerekli onu iletiyor. Gerisi sizde.

Cevap geldi, evet bir function call yapalım dedi. get_current_weather fonksiyonunu location: İzmir, TR parametresi ile çağır diyor.

{
"id": "chatcmpl-123",
...
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"function_call": {
"name": "get_current_weather",
"arguments": "{ \"location\": \"Izmir, TR\"}"
}
},
"finish_reason": "function_call"
}]
}

Projenizde get_current_weather(location: "Izmir, TR") çağırdınız, o da https://weatherapi istek atıyor sonucu döndürüyor.

Bu noktada yapılabilecek 2 adım var. İster bu isteğin sonucunu ekrana basın, işte artık oradan nem, rüzgar oranından ikona kadar her şey dönüyordur, arayüzde göstermek elinizde. İster gelen veri ile tekrar OpenAI completion API’lerine istek atıp mesaj gibi yazdırın.

curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
"model": "gpt-3.5-turbo-0613",
"messages": [
{"role": "user", "content": "What is the weather like in Izmir?"},
{"role": "assistant", "content": null, "function_call": {"name": "get_current_weather", "arguments": "{ \"location\": \"Izmir, TR\"}"}},
{"role": "function", "name": "get_current_weather", "content": "{\"temperature\": "22", \"unit\": \"celsius\", \"description\": \"Sunny\"}"}
],
"functions": [
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
]
}'

messages kısmına 2 mesaj daha eklendi. İlki(2.) asistandan dönen function_call, en sondaki ise fonksiyondan dönen içerik, 22, celcius, güneşli.

Bunun cevabı da aşağıda:

{
"id": "chatcmpl-123",
...
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "The weather in Izmir is currently sunny with a temperature of 22 degrees Celsius.",
},
"finish_reason": "stop"
}]
}

Cümle içine koydu özetle, bunu da chat arayüzünde veya ses olarak(tts) çalarak kullanıcıya verebiliriz.

Başka kullanım alanlarına bakarsak:
Mirkan’a toplantı için bir e-posta at dediğinde, send_email(to: mirkan, content: “Toplantı başlıyor”),

A şirketinin bu çeyrekteki gelirleri nasıl dediğinde sql_query(type: “revenue”, company: "A") şeklinde fonksiyonların bu parametrelerle çağırılması gerektiği bilgisini verebilir.

Kendi veremeyeceği bilgileri, sizin sisteminizden nasıl elde etmesi gerektiğini söylüyor aslında.

JSON, Çocuk masalı??

Fonksiyonu ve parametreleri tanımladığımızda, bu fonksiyon hangi parametrelerle çağırılmalı bilgisi bize GPT API’sinden geldi.

Önemli kısımlar şunlar:
1. Fonksiyon tamamen uydurma olabilir.
2. Parametreler, açıklamasına ve veri tipine göre geldiği için JSON haline getirmek kolay.

"arguments": "{ \"location\": \"Izmir, TR\"}"

required parameter olarak sadece location’ı eklediğimiz için location geldi.*

Çocuk masalına dönersek, create_story diye bir fonksiyon tanımlayabilirim.

messages kısmına user rolünde bir mesaj verdim. Basitçe biraz hikayeye yön vermek adına, sanki kullanıcıdan veya arayüzden karakter, tema seçtirmişiz gibi hemen karakter ve temayı gönderdim mesaj ile.

{
"model": "gpt-3.5-turbo-0613",
"messages": [
{
"role": "user",
"content": "main character: Mirkan the Bunny. main idea: world-class software engineering"
}
],
"functions": [
{
"name": "create_story",
"description": "Create bedtime story about the information that user provided.",
"parameters": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Title of the story"
},
"story": {
"type": "string",
"description": "Detailed bedtime story, rich with characters, no more than 5 paragraphs"
},
"location": {
"type": "string",
"description": "Location of the story(e.g forest, ocean, sky city)"
},
"characters": {
"type": "array",
"description": "list of characters from the story",
"items": {
"type": "string",
"description": "all the characters' name from the story"
}
},
"quote": {
"type": "string",
"description": "One quote that summarizes the story"
}
},
"required": [
"title",
"story",
"location",
"characters",
"quote"
],
"function_call": {
"name": "create_story"
}
}
}
]
}

Fonksiyon ve fonksiyonun tanımı, parametreler ve tanımları, fonksiyon çağırma otomatik mi yoksa her koşulda çağırmalı mı gibi alanları doldurduk. Alttaki kısmı auto bırakabilirdik, fonksiyonun ismini verdik ki hep çağırsın. Çünkü örnekte birden çok fonksiyon yok ve hep çağırılmalı. Fonksiyon çağırılmazsa direkt content olarak gönderecek.

"function_call": {
"name": "create_story"
}

Çıktı aşağıda

{
"id": "chatcmpl-7jNye6aMMeEdtS8caAKax8xWjgrZs",
"object": "chat.completion",
"created": 1691051284,
"model": "gpt-4-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"function_call": {
"name": "create_story",
"arguments": "{\n \"title\": \"Mirkan the Bunny: The Code Whisperer\",\n \"story\": \"Once upon a time, in a bustling city filled with towering skyscrapers and buzzing technology, lived a unique bunny named Mirkan. Unlike other bunnies, Mirkan had a peculiar interest in software engineering. He spent his days and nights learning different programming languages, mastering algorithms, and solving complex problems. His dedication and passion made him a world-class software engineer, respected and admired by all in the city.\\n\\nOne day, a massive problem arose. The city's central computer system, which controlled everything from traffic lights to water supply, crashed. Panic ensued as the city's life came to a standstill. The city's best engineers tried to fix the problem but to no avail. Hearing about the crisis, Mirkan decided to help.\\n\\nWith his exceptional skills, Mirkan started debugging the system. He worked tirelessly, his paws dancing over the keyboard, his eyes scanning lines of code. After hours of hard work, Mirkan found the bug - a tiny error in the system's core algorithm. With a few strokes on the keyboard, he fixed the error and rebooted the system. The city sprang back to life, and the crisis was averted.\\n\\nMirkan's heroics made him a city legend. He was hailed as the 'Code Whisperer', the bunny who could speak to machines. His story inspired many young ones in the city to take up software engineering, making the city a hub of technological innovation.\\n\\nAnd so, Mirkan continued to live his life, coding, learning, and inspiring others. His story is a testament to the power of dedication, passion, and the magic of software engineering.\",\n \"location\": \"Bustling city\",\n \"characters\": [\"Mirkan the Bunny\", \"City's best engineers\"],\n \"quote\": \"In the world of code, even a bunny can become a hero.\"\n}"
}
},
"finish_reason": "function_call"
}
],
"usage": {
"prompt_tokens": 126,
"completion_tokens": 811,
"total_tokens": 937
}
}

Konfor alanımda kalmak için Dart dilini kullanıyorum.

Mirkan the Bunny: The Code Whisperer

[Mirkan the Bunny, City’s best engineers]

Bustling city

In the world of code, even a bunny can become a hero.

--

--