Kurs
Ağustos 2024’te OpenAI, API’sine güçlü bir özellik ekledi — Structured Outputs. Adından da anlaşılacağı üzere, bu özellikle LLM’lerin yalnızca sizin belirlediğiniz biçimde yanıt üretmesini sağlayabilirsiniz. Bu yetenek, kesin veri biçimlendirmesi gerektiren uygulamalar geliştirmeyi önemli ölçüde kolaylaştıracaktır.
Bu eğitimde, OpenAI Structured Outputs’a nasıl başlayacağınızı, yeni sözdizimini nasıl kullanacağınızı ve temel kullanım alanlarını keşfedeceksiniz.
Yapay Zeka Uygulamaları Geliştirin
Yapay Zekâ Uygulamalarında Structured Outputs’un Önemi
Deterministik yanıtlar, yani tutarlı biçimlendirmeye sahip yanıtlar; veri girişi, bilgi alma, soru cevaplama, çok adımlı iş akışları gibi pek çok görev için kritik öneme sahiptir. Muhtemelen, aynı istemi kullansanız bile LLM’lerin çok farklı biçimlerde çıktılar üretebildiğine şahit oldunuz.
Örneğin, GPT-4o tarafından desteklenen bu basit classify_sentiment işlevini düşünün:
# List of hotel reviews
reviews = [
"The room was clean and the staff was friendly.",
"The location was terrible and the service was slow.",
"The food was amazing but the room was too small.",
]
# Classify sentiment for each review and print the results
for review in reviews:
sentiment = classify_sentiment(review)
print(f"Review: {review}\nSentiment: {sentiment}\n")
Çıktı:
Review: The room was clean and the staff was friendly.
Sentiment: Positive
Review: The location was terrible and the service was slow.
Sentiment: Negative
Review: The food was amazing but the room was too small.
Sentiment: The sentiment of the review is neutral.
İlk iki yanıt tek kelimelik aynı biçimdeyken, sonuncusu tüm bir cümle. Yukarıdaki kodun çıktısına bağımlı başka bir aşağı akış uygulaması olsaydı, tek kelimelik bir yanıt beklediğinden büyük olasılıkla hata verirdi.
Bunu bir miktar prompt engineering ile düzeltebiliriz; ancak bu zaman alan, yinelemeli bir süreçtir. Mükemmel bir istemle bile, gelecekteki isteklerde yanıtların biçimimize %100 uyacağının garantisi yoktur. Tabii Structured Outputs kullanmadığımız sürece:
def classify_sentiment_with_structured_outputs(review):
"""Sentiment classifier with Structured Outputs"""
...
# Classify sentiment for each review with Structured Outputs
for review in reviews:
sentiment = classify_sentiment_with_structured_outputs(review)
print(f"Review: {review}\nSentiment: {sentiment}\n")
Çıktı:
Review: The room was clean and the staff was friendly.
Sentiment: {"sentiment":"positive"}
Review: The location was terrible and the service was slow.
Sentiment: {"sentiment":"negative"}
Review: The food was amazing but the room was too small.
Sentiment: {"sentiment":"neutral"}
Yeni classify_sentiment_with_structured_outputs işleviyle yanıtların tümü aynı biçimdedir.
Dil modellerini katı bir biçime zorlayabilme yeteneği son derece değerlidir; sayısız saatlik prompt engineering uğraşından veya başka açık kaynak araçlara bağımlılıktan sizi kurtarır.
OpenAI Structured Outputs ile Başlarken
Bu bölümde, yapılandırılmış çıktıları duygu analizörü işlevi örneği üzerinden adım adım ele alacağız.
Ortamınızı Hazırlama
Önkoşullar
Başlamadan önce aşağıdakilere sahip olduğunuzdan emin olun:
- Sisteminizde yüklü Python 3.7 veya üzeri.
- Bir OpenAI API anahtarı. Bunu OpenAI web sitesi üzerinden kaydolarak edinebilirsiniz.
OpenAI API’yi Kurma
1. OpenAI Python paketini kurun: Terminalinizi açın ve OpenAI Python paketini en son sürüme kurmak veya güncellemek için aşağıdaki komutu çalıştırın:
$ pip install -U openai
2. API anahtarınızı ayarlayın: API anahtarınızı bir ortam değişkeni olarak veya doğrudan kodunuzda ayarlayabilirsiniz. Ortam değişkeni olarak ayarlamak için şunu çalıştırın:
$ export OPENAI_API_KEY='your-api-key'
3. Kurulumu doğrulayın: Kurulumu doğrulamak için basit bir Python betiği oluşturun:
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Say hello!"}
],
max_tokens=5
)
>>> print(response.choices[0].message.content.strip())
Hello! How can I
Her şeyin doğru kurulduğundan emin olmak için betiği çalıştırın. Terminalde modelin yanıtını görmelisiniz.
OpenAI paketine ek olarak, Structured Outputs için JSON şemalarını tanımlayıp doğrulamak amacıyla Pydantic kütüphanesine de ihtiyaç duyacaksınız. Pip ile kurun:
$ pip install pydantic
Bu adımlarla, ortamınız artık OpenAI’nin Structured Outputs özelliğini kullanmaya hazır.
Pydantic ile Çıktı Şeması Tanımlama
Structured Outputs’u kullanmak için beklenen çıktı yapısını Pydantic modelleriyle tanımlamanız gerekir. Pydantic, Python için bir veri doğrulama ve ayar yönetimi kütüphanesidir; Python tür açıklamalarını kullanarak veri modelleri tanımlamanıza olanak tanır. Bu modeller, OpenAI’nin ürettiği çıktılara bir yapı dayatmak için kullanılabilir.
İnceleme duygu sınıflandırıcımız için biçimi belirleyen örnek bir Pydantic modeli şöyledir:
from pydantic import BaseModel
from typing import Literal
class SentimentResponse(BaseModel):
sentiment: Literal["positive", "negative", "neutral"]
Bu örnekte:
SentimentResponsebeklenen çıktı yapısını tanımlayan bir Pydantic modelidir.- Modelde yalnızca tek bir alan vardır:
sentiment. Bu alan yalnızca şu üç değerden birini alabilir: "positive", "negative" veya "neutral".
Bu modeli OpenAI API isteklerimizin bir parçası olarak ilettiğimizde, çıktılar yalnızca verdiğimiz sözcüklerden biri olacaktır.
Nasıl olduğuna bakalım.
parse Yardımcı İşlevini Kullanma
Pydantic şemamızı OpenAI isteklerinde zorunlu kılmak için tek yapmamız gereken, bunu sohbet tamamlama API’sinin response_format parametresine iletmektir. Yaklaşık olarak şöyle görünür:
response = client.beta.chat.completions.parse(
model=MODEL,
messages=[...],
response_format=SentimentResponse
)
Fark ettiğiniz üzere, client.chat.completions.create yerine client.beta.chat.completions.parse yöntemini kullanıyoruz. .parse(), özellikle Structured Outputs için yazılmış, Sohbet Tamamlama API’sindeki yeni bir yöntemdir.
Şimdi, her şeyi bir araya getirerek inceleme duygu sınıflandırıcısını Structured Outputs ile yeniden yazalım. Önce gerekli içe aktarmaları yapar, Pydantic modelini, sistem istemini ve istem şablonunu tanımlarız:
from openai import OpenAI
from pydantic import BaseModel
from typing import Literal
class SentimentResponse(BaseModel):
sentiment: Literal["positive", "negative", "neutral"]
client = OpenAI()
MODEL = "gpt-4o-mini"
SYSTEM_PROMPT = "You are a sentiment classifier assistant."
PROMPT_TEMPLATE = """
Classify the sentiment of the following hotel review as positive, negative, or neutral:\n\n{review}
"""
Ardından, .parse() yardımcı yöntemini kullanan yeni bir işlev yazarız:
# Function to classify sentiment using OpenAI's chat completions API with structured outputs
def classify_sentiment_with_structured_outputs(review):
response = client.beta.chat.completions.parse(
model=MODEL,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": PROMPT_TEMPLATE.format(review=review)},
],
response_format=SentimentResponse
)
return response.choices[0].message
İşlevdeki kritik satır response_format=SentimentResponse satırıdır; Structured Outputs’u etkinleştiren budur.
Bunu incelemelerden biri üzerinde test edelim:
# List of hotel reviews
reviews = [
"The room was clean and the staff was friendly.",
"The location was terrible and the service was slow.",
"The food was amazing but the room was too small.",
]
result = classify_sentiment_with_structured_outputs(reviews[0])
>>> print(result.content)
{"sentiment":"positive"}
Burada, result bir ileti nesnesidir:
>>> type(result)
openai.types.chat.parsed_chat_completion.ParsedChatCompletionMessage[SentimentResponse]
Yanıtı getiren .content özniteliğine ek olarak, ayrıştırılmış bilgiyi bir sınıf olarak döndüren .parsed özniteliğine de sahiptir:
>>> result.parsed
SentimentResponse(sentiment='positive')
Görüldüğü gibi, SentimentResponse sınıfının bir örneğini elde ettik. Bu da, .sentiment özniteliğini kullanarak duygu değerine sözlük yerine dize olarak erişebileceğimiz anlamına gelir:
>>> result.parsed.sentiment
'positive'
Karmaşık Şemalar Tanımlamak İçin Pydantic Modellerini İç İçe Kullanma
Bazı durumlarda, iç içe geçmiş verileri içeren daha karmaşık çıktı yapıları tanımlamanız gerekebilir. Pydantic, modelleri birbirinin içinde tanımlamanıza olanak tanır; böylece çeşitli kullanım senaryolarını kaldırabilecek ayrıntılı şemalar oluşturabilirsiniz. Bu, özellikle hiyerarşik verilerle çalışırken veya karmaşık çıktılar için belirli bir yapıyı zorunlu kılmanız gerektiğinde faydalıdır.
Örneğin, kullanıcının adı, iletişim bilgileri ve adres listesini içeren ayrıntılı kullanıcı bilgilerini çıkarmamız gereken bir durumu ele alalım. Her adres sokak, şehir, eyalet ve posta kodu alanlarını içermelidir. Doğru şemayı oluşturmak için birden fazla Pydantic modeli gerekir.
Adım 1: Pydantic modellerini tanımlayın
Önce adres ve kullanıcı bilgileri için Pydantic modellerini tanımlayalım:
from pydantic import BaseModel
from typing import List
# Define the Pydantic model for an address
class Address(BaseModel):
street: str
city: str
state: str
zip_code: str
# Define the Pydantic model for user information
class UserInfo(BaseModel):
name: str
email: str
phone: str
addresses: List[Address]
Bu örnekte:
Addressbir adresin yapısını tanımlayan bir Pydantic modelidir.UserInfo, kullanıcının adı, e-posta adresi ve telefon numarası alanlarına ek olarak birAddressnesneleri listesi içeren bir Pydantic modelidir.
Adım 2: İç içe Pydantic modellerini API çağrılarında kullanın
Sonraki adımda, bu iç içe Pydantic modellerini OpenAI API çağrısında çıktı yapısını zorunlu kılmak için kullanırız:
SYSTEM_PROMPT = "You are a user information extraction assistant."
PROMPT_TEMPLATE = """ Extract the user information from the following text:\n\n{text}"""
# Function to extract user information using OpenAI's chat completions API with structured outputs
def extract_user_info(text):
response = client.beta.chat.completions.parse(
model=MODEL,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": PROMPT_TEMPLATE.format(text=text)},
],
response_format=UserInfo
)
return response.choices[0].message
# Example text containing user information
text = """John DoeEmail: john.doe@example.comPhone: 123-456-7890Addresses:- 123 Main St, Springfield, IL, 62701- 456 Elm St, Shelbyville, IL, 62702"""
# Extract user information and print the results
user_info = extract_user_info(text)
Örnek metin tamamen okunaksız ve ana bilgi parçaları arasında boşluk yok. Model başarılı olacak mı görelim. Yanıtı okunaklı hale getirmek için json kütüphanesini kullanacağız:
import json
data = json.loads(user_info.content)
pretty_response = json.dumps(data, indent=2)
print(pretty_response)
{
"name": "John Doe",
"email": "john.doe@example.com",
"phone": "123-456-7890",
"addresses": [
{
"street": "123 Main St",
"city": "Springfield",
"state": "IL",
"zip_code": "62701"
},
{
"street": "456 Elm St",
"city": "Shelbyville",
"state": "IL",
"zip_code": "62702"
}
]
}
Görüldüğü gibi, model sağladığımız şemaya göre tek bir kullanıcının bilgilerini ve iki ayrı adresini doğru şekilde yakaladı.
Kısacası, Pydantic modellerini iç içe kullanarak hiyerarşik verileri işleyen ve karmaşık çıktılar için belirli yapıları zorunlu kılan gelişmiş şemalar tanımlayabilirsiniz.
Structured Outputs ile İşlev Çağırma
Yeni dil modellerinin yaygın özelliklerinden biri işlev çağırmadır (tool calling olarak da anılır). Bu yetenek, dil modellerini kullanıcı tanımlı işlevlere bağlamanıza olanak tanır ve bu sayede modellere dış dünyaya erişim kazandırır.
Yaygın örnekler şunlardır:
- Gerçek zamanlı verileri alma (ör. hava durumu, hisse senedi fiyatları, spor skorları)
- Hesaplama veya veri analizi yapma
- Veritabanlarını veya API’leri sorgulama
- Görsel veya diğer medya üretimi
- Diller arasında çeviri yapma
- Akıllı ev cihazlarını veya IoT sistemlerini kontrol etme
- Özel iş mantığı veya iş akışları yürütme
Burada işlev çağırmanın nasıl çalıştığına girmeyeceğiz; ancak OpenAI Function Calling eğitimimizi okuyabilirsiniz.
Bilmeniz gereken önemli nokta şu: Structured Outputs sayesinde, OpenAI modellerinde işlev çağırma çok daha kolay hale gelir. Geçmişte, OpenAI modellerine ilettiğiniz işlevler; her işlev parametresini tür ipuçlarıyla ayrıntılandıran, karmaşık JSON şemaları yazmanızı gerektiriyordu. İşte bir örnek:
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Get the current weather",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"format": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The temperature unit to use. Infer this from the users location.",
},
},
"required": ["location", "format"],
},
}
}
Her ne kadar get_current_weather işlevinin iki parametresi olsa da, JSON şeması devasa boyutlara ulaşır ve elle yazması hataya açıktır.
Structured Outputs’ta bu durum, yine Pydantic modelleri kullanılarak çözülür:
from pydantic import BaseModel
from typing import Literal
def get_weather(location: str, unit: str, condition: str):
# Implementation details...
pass
class WeatherData(BaseModel):
location: str
unit: Literal["celsius", "fahrenheit"]
condition: Literal["sunny", "cloudy", "rainy", "snowy"]
Önce işlevin kendisini ve mantığını yazarsınız. Ardından, beklenen giriş parametrelerini belirterek bunu bir Pydantic modeliyle yeniden tanımlarsınız.
Pydantic modelini uyumlu bir JSON şemasına dönüştürmek için de pydantic_function_tool çağrısı yapılır:
>>> import openai
>>> openai.pydantic_function_tool(WeatherData)
{'type': 'function',
'function': {'name': 'WeatherData',
'strict': True,
'parameters': {'properties': {'location': {'title': 'Location',
'type': 'string'},
'unit': {'enum': ['celsius', 'fahrenheit'],
'title': 'Unit',
'type': 'string'},
'condition': {'enum': ['sunny', 'cloudy', 'rainy', 'snowy'],
'title': 'Condition',
'type': 'string'}},
'required': ['location', 'unit', 'condition'],
'title': 'WeatherData',
'type': 'object',
'additionalProperties': False}}}
Bu aracın bir isteğin parçası olarak nasıl kullanılacağı şöyledir:
import openai
client = OpenAI()
tools = [openai.pydantic_function_tool(WeatherData)]
messages = [
{
"role": "system",
"content": "You are a helpful customer support assistant. Use the supplied tools to assist the user.",
},
{
"role": "user",
"content": "What is the weather in Tokyo?",
}
]
response = client.chat.completions.create(
model=MODEL, messages=messages, tools=tools
)
tool_call = response.choices[0].message.tool_calls[0]
>>> tool_call
ChatCompletionMessageToolCall(id='call_QnZZ0DmNN2cxw3bN433JQNIC', function=Function(arguments='{"location":"Tokyo","unit":"celsius","condition":"sunny"}', name='WeatherData'), type='function')
Pydantic modelini Sohbet Tamamlama API’sinin tools parametresine uyumlu JSON biçiminde iletiriz. Ardından, sorgumuza bağlı olarak model aracı çağırıp çağırmamaya karar verir.
Yukarıdaki örnekte sorgumuz “Tokyo’da hava nasıl?” olduğundan, dönen ileti nesnesinin tool_calls alanında bir çağrı görüyoruz.
Unutmayın, model get_weather işlevini çağırmaz; verdiğimiz Pydantic şemasına göre bu işlev için argümanlar üretir:
arguments = json.loads(tool_call.function.arguments)
>>> arguments
{'location': 'Tokyo', 'unit': 'celsius', 'condition': 'sunny'}
Sağlanan argümanlarla işlevi çağırmak bize kalmıştır:
some_result = get_weather(**arguments)
Modelin hem işlev için argüman üretmesini hem de aynı anda çağırmasını istiyorsanız, bir yapay zekâ ajanına ihtiyacınız vardır.
İlgileniyorsanız ayrı bir LangChain Agents eğitimimiz var.
OpenAI Structured Outputs Kullanırken En İyi Uygulamalar
Structured Outputs kullanırken akılda tutulması gereken çeşitli en iyi uygulamalar ve öneriler vardır. Bu bölümde, bunlardan bazılarını özetleyeceğiz.
- Beklenen çıktı yapılarını açık ve tür güvenli bir şekilde tanımladıkları için çıktı şemalarını belirlerken Pydantic modellerini kullanın.
- En doğru sonuçlar için şemaları basit ve amaca özel tutun.
- Verinizi doğru temsil etmek için uygun veri türlerini (
str,int,float,bool,List,Dict) kullanın. - Alanlar için belirli izin verilen değerleri tanımlamak amacıyla enum’larda
Literaltürlerini kullanın. - Model retlerini yönetin. Yeni
.parse()yöntemi kullanıldığında, ileti nesnelerinde bir ret durumunu belirtmek için yeni bir.refusalözniteliği bulunur:
text = """John DoeEmail: john.doe@example.comPhone: 123-456-7890Addresses:- 123 Main St, Springfield, IL, 62701- 456 Elm St, Shelbyville, IL, 62702"""
user_info = extract_user_info(text)
if user_info.refusal:
print(user_info.refusal)
else:
print(user_info.content)
Çıktı:
{"name":"John Doe","email":"john.doe@example.com","phone":"123-456-7890","addresses":[{"street":"123 Main St","city":"Springfield","state":"IL","zip_code":"62701"},{"street":"456 Elm St","city":"Shelbyville","state":"IL","zip_code":"62702"}]}
6. Model çıktı hassasiyetini artırmak için Pydantic modellerinizde her alan için net ve öz açıklamalar sağlayın:
from pydantic import BaseModel, Field
class Person(BaseModel):
name: str = Field(..., description="The person's full name")
age: int = Field(..., description="The person's age in years")
occupation: str = Field(..., description="The person's current job or profession")
Bu uygulamalar, Structured Outputs’tan maksimum verim almanıza önemli katkı sağlayacaktır.
Sonuç
Bu eğitimde, OpenAI API’nin yeni bir özelliği olan Structured Outputs’a nasıl başlanacağını öğrendik. Bu özelliğin, dil modellerini belirttiğimiz biçimde çıktı üretmeye nasıl zorladığını gördük. Bunu işlev çağırma ile birlikte nasıl kullanacağımızı öğrendik ve özellikten en iyi şekilde yararlanmak için bazı en iyi uygulamaları inceledik.
Anlayışınızı derinleştirmek için ilgili bazı kaynaklar:
Structured Outputs SSS
Pydantic modelleri Structured Outputs ile nasıl çalışır?
Pydantic modelleri, istenen çıktı yapısının şemasını tanımlamak için kullanılır ve bu şema, yanıt biçimini zorunlu kılmak üzere OpenAI API’sine iletilir.
Structured Outputs işlev çağırma ile birlikte kullanılabilir mi?
Evet, Structured Outputs işlev çağırma ile birlikte kullanılabilir ve işlev parametrelerini ve beklenen çıktıları tanımlama sürecini basitleştirir.
Structured Outputs kullanmanın faydaları nelerdir?
Faydalar arasında tutarlı yanıt biçimleri, daha az sonradan işleme ihtiyacı, yapay zekâ uygulamalarında artan güvenilirlik ve mevcut sistemlerle daha kolay entegrasyon yer alır.
Structured Outputs kullanmanın herhangi bir sınırlaması var mı?
Güçlü olsa da, Structured Outputs yanıt esnekliğini sınırlayabilir ve çıktılarda istenen ayrıntı düzeyi ile yapı arasında denge kurmak için dikkatli şema tasarımı gerektirebilir.
2 yılı aşkın deneyime sahip bir veri bilimi içerik üreticisiyim ve Medium’da en büyük takipçi kitlelerinden birine sahibim. Yapay zekâ ve makine öğrenimi üzerine, biraz da alaycı bir üslupla yazılmış, ayrıntılı makaleler kaleme almayı seviyorum; çünkü onları biraz daha az sıkıcı hale getirmek için bir şeyler yapmak gerekiyor. 130’un üzerinde makale ve bir de DataCamp kursu ürettim; bir diğeri de hazırlık aşamasında. İçeriklerim 5 milyondan fazla kişi tarafından görüldü; bunların 20 bini Medium ve LinkedIn’de takipçim oldu.

