Kurs
Yeni tanıtılan OpenAI Realtime API uygulamalarımıza hızlı, düşük gecikmeli ve çok modlu deneyimler entegre etmemizi sağlar. Bu API ile kullanıcılar ile büyük dil modelleri (LLM'ler) arasında kesintisiz konuşmadan konuşmaya etkileşimler oluşturabiliriz.
Bu API, ses odaklı deneyimler için birden fazla modele duyulan ihtiyacı ortadan kaldırır; çünkü tek bir entegre API içinde eksiksiz bir çözüm sunar. Sadece gecikmeyi azaltmayı hedeflemekle kalmaz, aynı zamanda konuşmaların duygusal nüanslarını ve doğal akışını da korur.
Bu yazıda, OpenAI Realtime API'yi kullanarak sesle kontrol edilen yapay zeka asistanları oluşturmayı öğreneceğiz. Node.js ile kalıcı WebSocket bağlantıları oluşturacağız ve bunun terminal içinde API ile iletişim kurmak için nasıl kullanılabileceğini göreceğiz. Ayrıca, bu API'nin yeteneklerinden yararlanan bir React uygulamasını dağıtma konusunda sizi yönlendireceğim.
OpenAI Realtime API için API Anahtarı Oluşturma
OpenAI Realtime API'yi kullanmak için önce bir API anahtarı oluşturmamız gerekir. Bunun için API anahtarı sayfasına gidin. Bunun için bir hesap gerektiğini unutmayın. Sayfanın üst kısmında “Create new secret key” düğmesine tıklayın.

Bir açılır pencere açılacaktır. Varsayılan seçenekleri kullanıp “Create secret key”e tıklayabiliriz.

Anahtar oluşturulduğunda kopyalama fırsatımız olur. Pencereyi kapatmadan önce mutlaka kopyalayın; çünkü anahtar yalnızca bu anda gösterilir.

Anahtar kaybolursa her zaman silebilir ve yenisini oluşturabiliriz.
Anahtarı saklamak için .env adlı bir dosya oluşturup anahtarı aşağıdaki formatla kaydetmenizi öneririz:
OPENAI_API_KEY=<paste_they_key_here>
Bu dosyayı, API'ye bağlanmak için yazı boyunca kullanacağız.
Realtime API için Maliyet Hususları
Devam etmeden önce, Realtime API'nin ücretsiz olmadığını ve kullanmak için hesabımıza kredi eklememiz gerektiğini unutmayın. Kredileri profilimizde yer alan faturalama sayfasından ekleyebiliriz.
Maliyeti anlamanız için, bu yazı üzerinde çalışırken API ile denemeler yapmamın bana ne kadara mal olduğuna dair genel bir görünüm:

Toplamda yaklaşık beş dolar harcadım. Bu büyük bir tutar değil, ancak OpenAI'nin sunduğu diğer API'lara göre oldukça daha pahalı. Bu yazı üzerinde çalışırken bunu aklınızda bulundurun.
Maliyetin çoğu (ilk çubuk), bu yazının sonunda incelediğimiz React konsol uygulamasıyla oynamama karşılık geliyor. Geri kalan, yaklaşık yarım dolar, WebSocket'leri kullanarak API'yi kullanmanın bana maliyeti oldu. Dolayısıyla, bu yazıyı bir dolardan daha az bir maliyetle takip etmek mümkün.
API fiyatlandırması hakkında daha fazla detay için fiyatlandırma sayfalarındaki “Realtime API” bölümüne göz atın.
Yapay Zeka Uygulamaları Geliştirin
Realtime API'yi WebSocket'lerle Kullanma
OpenAI API'nin diğer bileşenlerinin aksine, Realtime API WebSocket'leri kullanır. WebSocket, istemci ile sunucu arasında çift yönlü bir iletişim kanalı kuran bir iletişim protokolüdür. HTTP'nin geleneksel istek-yanıt modelinden farklı olarak, WebSocket'ler sürekli, gerçek zamanlı etkileşimleri destekler. Bu da WebSocket'leri, sesli sohbet gibi gerçek zamanlı uygulamalar için özellikle uygun kılar.
Bu yazı, WebSocket'lerin nasıl çalıştığını kapsayacak ve Realtime API ile etkileşime dair birkaç örnek içerecektir.
Node.js kullanacağız, bu nedenle bilgisayarımızda kurulu olduğundan emin olmalıyız. Değilse, Node.js'i resmi web sitesinden indirebilir ve kurabiliriz.
Betik başlatma
.env dosyasını oluşturduğumuz klasörü oluşturmanızı öneririz. Bu klasör içinde, betiği başlatmak için şu komutu çalıştırın:
npm init -y && touch index.js
Bu komut tamamlandıktan sonra klasör içinde şu dosyalar olmalı:

Bağımlılıkların kurulması
İki paketi kurarak başlayın:
ws: Bu, API ile etkileşim kurmak için gereken ana paket olan WebSocket paketidir.dotenv: API anahtarını.envdosyasından yükleyen yardımcı bir pakettir.
Bunları şu komutla kurun:
npm install ws dotenv
Realtime API'ye bağlanma
Realtime API ile bir bağlantı başlatmak için, API URL'sini ve bağlantı için gereken bilgileri içeren başlıkları geçirerek yeni bir WebSocket nesnesi oluştururuz:
// Import the web socket library
const WebSocket = require("ws");
// Load the .env file into memory so the code has access to the key
const dotenv = require("dotenv");
dotenv.config();
function main() {
// Connect to the API
const url = "wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2024-10-01";
const ws = new WebSocket(url, {
headers: {
"Authorization": "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Beta": "realtime=v1",
},
});
}
main();
Bağlantı açıldığında bir eylem ayarlama
Yukarıdaki kod, API'ye web socket bağlantısını oluşturur ancak henüz onunla bir şey yapmaz.
WebSocket'ler, bazı olaylar gerçekleştiğinde yürütülecek eylemler tanımlamamıza olanak tanır. Bağlantı kurulduğunda yürütmek istediğimiz kodu belirtmek için open olayını kullanabiliriz.
Bir olay dinleyicisi eklemenin genel söz dizimi şöyledir:
ws.on(<event>, <function>);
<event> kısmını olayın adını içeren bir dizeyle, <function> kısmını ise olay gerçekleştiğinde yürütülecek bir işleve değiştiririz.
Bağlantı hazır olduğunda metin göstermek için şöyle yapabiliriz:
// Add inside the main() function of index.js after creating ws
async function handleOpen() {
console.log("Connection is opened");
}
ws.on("open", handleOpen);
Bu kodu çalıştırmak için şu komutu kullanırız:
node index.js
API anahtarı doğru ayarlandıysa, terminalde “Connection is open” mesajını görürüz. Betik, bağlantı hâlâ açık olduğu için çalışmaya devam eder; bu yüzden elle durdurmamız gerekir.
Mesaj alındığında bir eylem ayarlama
WebSocket'leri kullanırken yanıt verebileceğimiz bir diğer olay message olayıdır. Bu, sunucudan her mesaj alındığında tetiklenir. Alınan her mesajı gösteren bir işlev ekleyelim:
// Add inside the main() function of index.js
async function handleMessage(messageStr) {
const message = JSON.parse(messageStr);
console.log(message);
}
ws.on("message", handleMessage);
Betik şimdi çalıştırıldığında, oturum başlatıldığında API'nin gönderdiği session.created olayını da göstermelidir.
Diğer WebSocket olayları
Yukarıda, open ve message olaylarına olay dinleyicileri eklemeyi öğrendik. WebSocket'ler, örneklerimizde kullanmayacağımız iki ek olayı daha destekler.
close olayı, soket kapatıldığında bir geri çağrı eklemek için kullanılabilir:
async function handleClose() {
console.log(“Socket closed”);
}
ws.on(“close”, handleClose);
error olayı, bir hata olduğunda bir geri çağrı eklemek için kullanılır:
async function handleError(error) {
console.log(“Error”, error);
}
ws.on(“error”, handleError);
Realtime API ile iletişim kurma
WebSocket'lerle çalışmak, olay güdümlü bir şekilde programlama yapmamızı gerektirir. Mesajlar iletişim kanalında ileri geri gönderilir ve bu mesajların ne zaman iletileceğini veya alınacağını kontrol edemeyiz.
İletişimi başlatan kod, handleOpen() içine eklenmelidir. O Aksi halde, bu kod web socket iletişim kanalı oluşturulmadan önce yürütülebileceğinden bir hata oluşur.
Mesajları işleyen kod için de aynı durum geçerlidir. Tüm mantık handleMessage() işlevine gitmelidir.
Gelecek örneklerde, başlangıç noktası olarak aşağıdaki kodu kullanacağız. Değişikliklerin çoğu handleOpen() ve handleMessage()'ı güncellemeyi içerir.
// Import the web socket library
const WebSocket = require("ws");
// Load the .env file into memory so the code has access to the key
const dotenv = require("dotenv");
dotenv.config();
function main() {
// Connect to the API
const url = "wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2024-10-01";
const ws = new WebSocket(url, {
headers: {
"Authorization": "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Beta": "realtime=v1",
},
});
async function handleOpen() {
console.log("Connection is opened");
}
ws.on("open", handleOpen);
async function handleMessage(messageStr) {
const message = JSON.parse(messageStr);
console.log(message);
}
ws.on("message", handleMessage);
}
main();
Realtime API'yi metin göndermek ve almak için kullanma
Realtime API ile iletişim, olaylar kullanılarak gerçekleşir. OpenAI gerçek zamanlı dokümantasyon API'si desteklenen olayları listeler. Bir konuşmayı başlatmak için conversation.item.create olayını kullanırız. Olaylar, alanları belgelerde açıklanan JSON nesneleri olarak temsil edilir.
İşte conversation.item.create olayına bir örnek; “Bir web socket'in ne olduğunu bir cümlede açıkla” istemini gönderiyor:
const createConversationEvent = {
type: "conversation.item.create",
item: {
type: "message",
role: "user",
content: [
{
type: "input_text",
text: "Explain in one sentence what a web socket is"
}
]
}
};
Bu olay, metinsel bir konuşma başlatmak istediğimizi API'ye bildirir. Bu, content alanında, tür olarak "input_text" kullanılarak ve bir metin istemi sağlanarak belirtilir.
ws.send() yöntemini mesaj göndermek için kullanırız. Web socket paketi argüman olarak bir dize beklediğinden, JSON olayımızı JSON.stringify() işleviyle bir dizeye dönüştürmemiz gerekir. Bunları birleştirince, yukarıdaki olayı şöyle gönderebiliriz:
ws.send(JSON.stringify(createConversationEvent));
Bu, konuşmayı başlatacaktır; ancak API'nin bize otomatik olarak yanıt göndermesini tetiklemeyecektir. Bir yanıtı tetiklemek için response.create olayı göndeririz. İşte bir örnek:
const createResponseEvent = {
type: "response.create",
response: {
modalities: ["text"],
instructions: "Please assist the user.",
}
}
ws.send(JSON.stringify(createResponseEvent));
Bu olay, modalities yanıt parametresini kullanarak metinsel bir yanıt talep eder. Talimatlar en önemli kısımdır; modelden ne yapmasını istediğimizi açıklar; bu durumda, kullanıcıya yardımcı olmasını isteyen genel bir istem.
handleOpen() işlevinde bu iki olayı göndeririz; böylece bağlantı kurulur kurulmaz bir konuşma başlatılır. Bu örnekteki handleOpen() işlevinin tam uygulaması şöyledir:
async function handleOpen() {
// Define what happens when the connection is opened
// Create and send an event to initiate a conversation
const createConversationEvent = {
type: "conversation.item.create",
item: {
type: "message",
role: "user",
content: [
{
type: "input_text",
text: "Explain in one sentence what a web socket is"
}
]
}
};
// Create and send an event to initiate a response
ws.send(JSON.stringify(createConversationEvent));
const createResponseEvent = {
type: "response.create",
response: {
modalities: ["text"],
instructions: "Please assist the user.",
}
}
ws.send(JSON.stringify(createResponseEvent));
}
Gelen mesajlarla ilgili olarak, bu örnek için not etmeye değer üç tür olay vardır: response.text.delta, response.text.done ve response.done olayları:
-
response.text.deltaolayları yanıtıdeltaalanında parçalara bölünmüş şekilde içerir. Bunlar, gerçek zamanlı bir deneyim sunmak istediğimizde önemlidir; çünkü yanıtı parça parça anında akıtmamıza olanak tanır. -
response.text.doneolayı metinsel yanıtın sonunu işaret eder ve tam yanıtıtextalanında içerir. -
response.doneolayı yanıtın sonunu işaret eder.
Betiklerin bu olaylara nasıl tepki vermesini istediğimizi handleMessage() işlevinde bir switch deyimiyle belirtebiliriz:
async function handleMessage(messageStr) {
const message = JSON.parse(messageStr);
// Define what happens when a message is received
switch(message.type) {
case "response.text.delta":
// We got a new text chunk, print it
process.stdout.write(message.delta);
break;
case "response.text.done":
// The text is complete, print a new line
process.stdout.write("\n");
break;
case "response.done":
// Response complete, close the socket
ws.close();
break;
}
}
Bu örnekte, yanıtın parçalarını alır almaz konsola yazdırmak için response.text.delta olayını kullanıyoruz. Yanıt tamamlandığında response.text.done olayı tetiklenir ve çıktının bittiğini göstermek için yeni bir satır yazdırırız. Son olarak, response.done olayını aldığımızda web socket'i kapatırız.
Bu örneği çalıştırmak için bu işlevleri yukarıdaki şablon koda yapıştırıp şu komutla çalıştırın:
node index.js
Bu, terminalde “Explain in one sentence what a web socket is” istemine bir yanıt üretecektir; ChatGPT kullanmaya benzer.
Metin örneğinin tam kodu burada mevcuttur.
Realtime API'yi ses göndermek ve almak için kullanma
Önceki örnek, metin verilerini nasıl ele aldığımızı gösterdi. Ancak Realtime API'nin asıl ilgi çekici yanı, gerçek zamanlı yanıt veren bir sesli asistan oluşturmaktır.
Ses verilerini işlemek, metin verilerine göre biraz daha karmaşıktır. Konunun odağından sapmamak için sesle ilgili bazı ayrıntıları atlayacağız.
Önce iki paket kuruyoruz:
npm install node-record-lpcm16 speaker
node-record-lpcm16, mikrofondan ses kaydeder; böylece sesli istem gönderebiliriz.speaker, yapay zekâ ses yanıtını çalmak için kullanılır.
Ayrıca SoX (Sound eXchange) kurulmalıdır; bu, mikrofonla arayüz oluşturmak ve ses kaydetmek için node kütüphanesinin kullandığı bir komut satırı yardımcı programıdır. macOS'ta brew install sox veya Linux'ta sudo apt install sox kullanın.
Bu paketler kurulduktan sonra, bunları içe aktarır ve kullanıcının sesli istemlerini kaydeden startRecording() işlevini ekleriz. Ana konumuzdan fazla uzaklaştıracağı için işlevi ayrıntılı açıklamayacağız.
index.js dosyasına, ortamı yükledikten sonra aşağıdaki kodu ekleyin:
// Add to index.js before the main() function
// Import the web socket library
const WebSocket = require("ws");
// Load the .env file into memory so the code has access to the key
const dotenv = require("dotenv");
dotenv.config();
const Speaker = require("speaker");
const record = require("node-record-lpcm16");
// Function to start recording audio
function startRecording() {
return new Promise((resolve, reject) => {
console.log("Speak to send a message to the assistant. Press Enter when done.");
// Create a buffer to hold the audio data
const audioData = [];
// Start recording in PCM16 format
const recordingStream = record.record({
sampleRate: 16000, // 16kHz sample rate (standard for speech recognition)
threshold: 0, // Start recording immediately
verbose: false,
recordProgram: "sox", // Specify the program
});
// Capture audio data
recordingStream.stream().on("data", (chunk) => {
audioData.push(chunk); // Store the audio chunks
});
// Handle errors in the recording stream
recordingStream.stream().on("error", (err) => {
console.error("Error in recording stream:", err);
reject(err);
});
// Set up standard input to listen for the Enter key press
process.stdin.resume(); // Start listening to stdin
process.stdin.on("data", () => {
console.log("Recording stopped.");
recordingStream.stop(); // Correctly stop the recording stream
process.stdin.pause(); // Stop listening to stdin
// Convert audio data to a single Buffer
const audioBuffer = Buffer.concat(audioData);
// Convert the Buffer to Base64
const base64Audio = audioBuffer.toString("base64");
resolve(base64Audio); // Resolve the promise with Base64 audio
});
});
};
startRecording() işlevi, mikrofondan ses kaydeder ve “Enter” tuşuna basılmasını bekler.
Sonraki adımda, yapay zekânın yanıtını çalmak için kullanılan Speaker()'ı başlatarak main() işlevini güncelliyoruz:
// Add to the main() function after ws is initialized
const speaker = new Speaker({
channels: 1, // Mono or Stereo
bitDepth: 16, // PCM16 (16-bit audio)
sampleRate: 24000, // Common sample rate (44.1kHz)
});
Bunu hallettikten sonra, sesi işlemek için handleOpen() ve handleMessage()'ı uygulayabiliriz.
handleOpen() işlevinde, yalnızca kullanıcının sesli istemini kaydetmek için startRecording() işlevini çağırmamız gerekir. Olayları da biraz güncellememiz gerekiyor:
createConversationEvent'in içeriğini"input_text"yerine"input_audio"türünü kullanacak şekilde güncelleyin vetextalanınıaudio: base64AudioDataile değiştirin.-
createResponseEvent'te yanıt kipine"audio"ekleyin.
Güncellenmiş handleOpen() işlevi şöyle:
async function handleOpen() {
// Define what happens when the connection is opened
const base64AudioData = await startRecording();
const createConversationEvent = {
type: "conversation.item.create",
item: {
type: "message",
role: "user",
content: [
{
type: "input_audio",
audio: base64AudioData,
},
],
},
};
ws.send(JSON.stringify(createConversationEvent));
const createResponseEvent = {
type: "response.create",
response: {
modalities: ["text", "audio"],
instructions: "Please assist the user.",
},
};
ws.send(JSON.stringify(createResponseEvent));
}
handleMessage() işlevini uygulamak için, ses arabelleğini güncellemek ve yeni ses deltalarını çalmak üzere "response.audio.delta" olayını değiştiririz:
case "response.audio.delta":
// We got a new audio chunk
const base64AudioChunk = message.delta;
const audioBuffer = Buffer.from(base64AudioChunk, "base64");
speaker.write(audioBuffer);
break;
"response.text.done" olayını switch deyiminden kaldırır ve "response.done" olayını, hoparlörü durduracak şekilde güncelleriz:
case "response.audio.done":
speaker.end();
ws.close();
break;
Son durumda handleMessage() işlevi şöyle görünür:
function handleMessage(messageStr) {
const message = JSON.parse(messageStr);
// Define what happens when a message is received
switch (message.type) {
case "response.audio.delta":
// We got a new audio chunk
const base64AudioChunk = message.delta;
const audioBuffer = Buffer.from(base64AudioChunk, "base64");
speaker.write(audioBuffer);
break;
case "response.audio.done":
speaker.end();
ws.close();
break;
}
}
Bu örneği çalıştırmak için, bu değişiklikleri şablon koda uygulayın ve şu komutla çalıştırın:
node index.js
Mikrofon kayda başlayacaktır. İsteğimizi söyleyip “Enter”a basarak gönderebiliriz. Ardından yapay zekânın yanıtı hoparlörlerden çalınır (mikrofonun kapalı olmadığından ve hoparlörlerin sesinin açık olduğundan emin olun).
Ses örneğinin tam kodu burada mevcuttur.
Fonksiyon çağırma
OpenAI API'nin güzel özelliklerinden biri fonksiyon çağrıları gerçekleştirme yeteneğidir. Asistana fonksiyonlar ekleyebiliriz ve bu fonksiyonlardan birinin yanıtı üretmede faydalı olacağını tespit ederse, belirli bir fonksiyonun çağrılmasını talep eden bir olay gönderir.
OpenAI dokümantasyonu, bir fonksiyon çağrısının yaşam döngüsünü açıklayan aşağıdaki diyagramı sağlar:

Kaynak: OpenAI
Diyagramdan gördüğümüz üzere, istemcinin LLM'in çağırabileceği fonksiyonların tanımlarını sağlaması gerekir. Ayrıca, fonksiyon yürütmesi istemci tarafında gerçekleşir; yapay zekâ, çağrılacak fonksiyonu ve argümanlarını talep eden bir olay gönderir. Sonrasında sonucu geri göndermek bizim sorumluluğumuzdadır.
Asistanımızı iki sayıyı toplayan bir fonksiyonla güçlendirelim. Bu örneği, yukarıdaki ses örneğini genişleterek oluşturacağız.
Kullanılabilir fonksiyonları belirtmek için LLM'e bir araç listesi (tools) sağlamalıyız. Her araç, fonksiyonla ilgili bilgileri belirten bir JSON nesnesidir. Toplama fonksiyonu için bir aracı şöyle tanımlayabiliriz:
const sumTool = {
type: "function",
name: "calculate_sum",
description: "Use this function when asked to add numbers together, for example when asked 'What's 4 + 6'?.",
parameters: {
type: "object",
properties: {
"a": { "type": "number" },
"b": { "type": "number" }
},
required: ["a", "b"]
}
}
Nesne yapısını açıklayalım:
type, bir fonksiyon tanımladığımızı belirtir.name, fonksiyonu tanımlamak için kullanılır. LLM, hangi fonksiyonu çağrılmasını istediğini bize belirtmek için bunu kullanır.description, LLM'in bu fonksiyonu ne zaman kullanması gerektiğini belirtir.parameters, fonksiyonun argümanlarını belirtmek için kullanılır. Bu durumda,avebadlı iki sayıdır.
Bir sonraki adım, fonksiyonu kodumuzda tanımlamaktır. Bir fonksiyon çağrısı olayına yanıt verirken uygun fonksiyonu çağırmayı kolaylaştırmak için calculate_sum anahtarına sahip bir sözlük kullanacağız:
const functions = {
calculate_sum: (args) => args.a + args.b,
}
API, fonksiyon argümanlarını yukarıdaki parametersta tanımlanan yapıyla aynı sözlük olarak sağlar. Bu durumda, örneğin 3 ile 5'i toplamak için sözlük {"a": 3, "b": 5} olurdu.
sumTool ve functions sabitleri, içe aktarmalardan sonra ve main() işlevinden önce index.js'in üst kısmına eklenebilir.
Sonraki adımda, LLM'e sumTools'un kullanılabilir olduğunu bildirmek için response.create olayını güncelliyoruz. Bu, response'a tools ve tool_choice alanlarını ekleyerek yapılır:
const createResponseEvent = {
type: "response.create",
response: {
modalities: ["text", "audio"],
instructions: "Please assist the user.",
tools: [sumTool], // New
tool_choice: "auto", // New
},
};
LLM bir fonksiyonu çağırmak istediğine karar verdiğinde, response.function_call_arguments.done olayını yayacaktır. Buna şu şekilde yanıt vermemiz gerekir:
- Fonksiyon bilgisini almak ve fonksiyonu çağırmak.
- Fonksiyon çağrısının sonucunu göndermek.
- Bir yanıt talep etmek.
Bunu, hanldeMessage() işlevinin içindeki switch deyimine aşağıdaki durumu ekleyerek ele alırız:
case "response.function_call_arguments.done":
console.log(Using function ${message.name} with arguments ${message.arguments});
// 1. Get the function information and call the function
const function_name = message.name;
const function_arguments = JSON.parse(message.arguments);
const result = functions[function_name](function_arguments);
// 2. Send the result of the function call
const functionOutputEvent = {
type: "conversation.item.create",
item: {
type: "function_call_output",
role: "system",
output: ${result},
}
};
ws.send(JSON.stringify(functionOutputEvent));
// 3. Request a response
ws.send(JSON.stringify({type: "response.create"}));
break;
Şimdi betiği çalıştırır ve iki sayının toplamını istersek, model fonksiyonu çağırmalı ve sonucu sağlamalıdır.
Bu fonksiyon nispeten basittir; ancak fonksiyon istemci tarafından yürütüldüğü için her şey olabilir. Bir sonraki bölümde, daha karmaşık iki fonksiyon örneği göreceğiz.
Bu örneğin tam kodu burada mevcuttur.
OpenAI Realtime API Kullanan Demo Uygulaması
OpenAI ekibi, Realtime API'yi sergilemek için bir React demo uygulaması sağlar. Burada, nasıl kurulacağını öğrenecek ve nasıl çalıştığını keşfedeceğiz. Daha karmaşık bir uygulama inşa etmek için harika bir başlangıç noktasıdır.
Uygulama kurulumu
Çalıştırmak için React bilgisi gerekmez. Ancak, değiştirmek veya genişletmek için React'e aşina olmanız gerekir.
Uygulamaları bu depoda barındırılıyor. Kurmak için, şu klonlama işlemini aşağıdaki Git komutuyla başlatın:
git clone org-14957082@github.com:openai/openai-realtime-console.git
Alternatif olarak, GitHub arayüzünden manuel olarak da indirebiliriz.
Uygulamayı kurmak için şu NPM (node paket yöneticisi) komutunu kullanırız:
npm install
Kurulum tamamlandıktan sonra, projenin kök klasöründe .env adlı bir dosya oluşturun ve aşağıdaki içeriği yapıştırın:
OPENAI_API_KEY=<openai_api_key>
REACT_APP_LOCAL_RELAY_SERVER_URL=http://localhost:8081
<openai_api_key> kısmını OpenAI API anahtarınızla değiştirin.
Uygulama artık çalıştırılmaya hazır olmalıdır. İki bölümden oluşur:
- Uygulamanın web kullanıcı arayüzünden oluşan bir React ön yüzü.
- Ön yüz ile OpenAI API arasında aracı olarak kullanılan bir aktarıcı (relay) sunucusu.

Ön yüz ile OpenAI API arasında bir aktarıcı sunucu uygulanmasının birincil amacı, API anahtarını güvenle depolamaktır. Bu anahtar olmadan API ile etkileşim mümkün değildir.
Ancak, anahtar ön yüzde depolansaydı, herhangi bir kullanıcı tarafından erişilebilir olurdu. Bu nedenle çözüm, anahtarı güvenle depolayan ve API ile ön yüz arasında veri alışverişini kolaylaştıran bir sunucu kurmayı içerir. Bu özel senaryoda güvenlik endişeleri minimumdur; çünkü uygulama yalnızca yerel olarak çalıştırılacaktır.
Uygulamayı başlatmak için hem aktarıcı sunucuyu hem de ön yüzü başlatmak gerekir. Aktarıcı sunucuyu başlatmak için şu komutu kullanın:
npm run relay
React ön yüzünü başlatmak için şu komutu kullanın:
npm start
Yükleme tamamlandıktan sonra, tarayıcıda uygulamanın çalıştığı bir sekme açılacaktır.

Uygulamayı kullanma
Uygulamayı kullanmaya başlamadan önce, bilgisayarın sessizde olmadığından emin olun ve uygulamaya mikrofon erişimi izni verin.
“connect” düğmesine tıklayarak başlıyoruz. Bu, Realtime API'ye bir “Hello” mesajı gönderecek ve bir karşılama alacağız.

Bağlantı kurulduktan sonra, ortada yapay zekâ asistanıyla konuşmamıza olanak tanıyan yeni bir düğme görünecektir.

Kullanmak için, düğmeyi bırakmadan basılı tutup konuşun. Mesaj, düğme bırakıldığında gönderilir.
Uygulamada, herhangi bir düğmeye basmamızın gerekmediği bir VAD (voice activity detection) modu da vardır. Bu modda, uygulama sürekli dinler ve asistanla aktif bir sohbet gerçekleştirmemizi sağlar. Kullanmak için “vad” düğmesine basın ve konuşun.

Fonksiyonlar
Öğrendiğimiz üzere, Realtime API yapay zekânın belirli fonksiyonları yerine getirmesini sağlayan bir özellik sunar. Bu demoda, belirli bir konumdaki hava durumunu sormaya yönelik bir fonksiyon ve asistanı kişiselleştirmek için hafıza öğeleri eklemeye yönelik başka bir fonksiyon sergilenir.
Bu fonksiyonları, “Yarın New York'ta hava nasıl?” gibi sorular sorarak ve “En sevdiğim renk mavi.” gibi tercihleri belirterek deneyimleyin. Asistan bu sorulara sözlü yanıtlar verecek ve bilgiler uygulamanın sağ tarafında da gösterilecektir.

Bazen hava durumu raporu istediğimde, yanıt o anda erişilemediğini belirtti. Ancak bilgiler sağ tarafta tutarlı şekilde gösterildi. Bir demo uygulaması olduğundan, tam işlevli bir ürün olmayı amaçlamaz; daha ziyade API'nin yeteneklerini sergilemeyi hedefler.
İstemciyi anlama
Bu bölümü takip etmek için React hakkında üst düzey bir anlayış gerekir; çünkü uygulamanın bazı uygulama ayrıntılarını ele alacağız.
ConsolePage.tsx dosyasına bakacağız. Uygulama mantığının çoğu burada tanımlanmıştır. Demo uygulaması, Node.js komut satırı uygulaması örneklerimizde yaptığımız gibi ham WebSocket'leri kullanmaz. API ile etkileşimi kolaylaştıran bir gerçek zamanlı istemci inşa ettiler. Dosyanın başında içe aktarılan şey budur:
import { RealtimeClient } from '@openai/realtime-api-beta';
API ile entegrasyon şu useEffect() çağrısında tanımlanmıştır. Bu useEffect() içindeki kod, konsol sayfası ilk kez render edildiğinde çalıştırılır. Node.js betiğimize benzer şekilde, API olaylarına nasıl yanıt verileceğini ana hatlarıyla belirtir. Birincil fark, RealtimeClient sarmalayıcısını kullanmasıdır.
Araçları tanımlama
RealtimeClient.addTool() işlevi, araçları tanımlamak için kullanılır. İki parametre alır:
- Araç tanımı JSON nesnesi.
- Yürütülecek fonksiyon.
Bu yaklaşım, araçların entegrasyonunu basitleştirir; çünkü istemci zaten olayları ele almak ve fonksiyon çağrılarını otomatikleştirmek üzere donatılmıştır. Hafıza aracı burada, hava durumu aracının tanımı ise burada tanımlanmıştır.
Örneğin, daha önce tanımlanan toplama aracını eklemek için şunu yapabiliriz:
client.addTool(
{
name: "calculate_sum",
description: "Use this function when asked to add numbers together, for example when asked 'What's 4 + 6'?.",
parameters: {
type: "object",
properties: {
"a": { "type": "number" },
"b": { "type": "number" }
},
required: ["a", "b"]
}
},
(a: number, b: number): number => a + b
);
Uygulamanın TypeScript kullandığını ve bu nedenle fonksiyon tanımında türlerin belirtilmesinin gerektiğini unutmayın.
Olayları dinleme
Bir olayı dinlemek için RealtimeClient.on() işlevi kullanılır. İki parametre kabul eder:
- Olayın adı.
- Yürütülecek geri çağrı işlevi.
Bu yaklaşım, daha önce kullandığımız WebSocket.on() işlevine benzer; ancak farklı bir olay kümesini uygular. GitHub sayfalarında desteklenen olayların listesi bulunur.
Bu özel örnekte şu olaylar kullanılır:
realtime.eventolayı burada tüm olayların bir günlüğünü tutmak için kullanılır.errorolayı burada hataları hata ayıklama amacıyla konsola basitçe kaydeder.conversation.interruptedolayı burada konuşma kesildiğinde istekleri iptal etmek için kullanılır.- Son olarak,
conversation.updatedolayı burada, API'den yeni parçalar geldiğinde ses akışına yeni ses eklemek için kullanılır.
Sonuç
Bu eğitimde, OpenAI Realtime API'yi ve gerçek zamanlı iletişim için WebSocket'leri nasıl kullandığını inceledik. API ile etkileşim kurmak için bir Node.js ortamının kurulumu, metin ve ses mesajları gönderme/alma ve gelişmiş işlevsellik için fonksiyon çağırmayı uygulama konularını ele aldık.
Ayrıca, temel bir sesli asistan uygulamasının nasıl dağıtılacağını gösteren OpenAI demo React uygulamasını da keşfettik.
En güncel OpenAI geliştirici araçları hakkında daha fazla bilgi edinmek için şu eğitimleri öneririm:

