พื้นที่เก็บข้อมูลนี้มีไลบรารีไคลเอนต์อ้างอิง AKA สำหรับการเชื่อมต่อกับ API เรียลไทม์ของ OpenAI ห้องสมุดนี้อยู่ในเบต้าและไม่ควรถือว่าเป็นการดำเนินการขั้นสุดท้าย คุณสามารถใช้มันเพื่อสร้างแอพการสนทนาต้นแบบได้อย่างง่ายดาย
วิธีที่ง่ายที่สุดในการเล่นกับ API ทันที คือการใช้ คอนโซลเรียลไทม์ มันใช้ไคลเอนต์อ้างอิงเพื่อส่งมอบผู้ตรวจการ API ที่ใช้งานได้อย่างสมบูรณ์พร้อมตัวอย่างของการสร้างภาพด้วยเสียงและอื่น ๆ
ไลบรารีนี้ถูกสร้างขึ้นเพื่อใช้ทั้งฝั่งเซิร์ฟเวอร์ (node.js) และในเบราว์เซอร์ (react, vue) ทั้งใน JavaScript และ typescript codebases ในขณะที่อยู่ในเบต้าเพื่อติดตั้งไลบรารีคุณจะต้อง npm install โดยตรงจากที่เก็บ GitHub
$ npm i openai/openai-realtime-api-beta --save import { RealtimeClient } from '@openai/realtime-api-beta' ;
const client = new RealtimeClient ( { apiKey : process . env . OPENAI_API_KEY } ) ;
// Can set parameters ahead of connecting, either separately or all at once
client . updateSession ( { instructions : 'You are a great, upbeat friend.' } ) ;
client . updateSession ( { voice : 'alloy' } ) ;
client . updateSession ( {
turn_detection : { type : 'none' } , // or 'server_vad'
input_audio_transcription : { model : 'whisper-1' } ,
} ) ;
// Set up event handling
client . on ( 'conversation.updated' , ( event ) => {
const { item , delta } = event ;
const items = client . conversation . getItems ( ) ;
/**
* item is the current item being updated
* delta can be null or populated
* you can fetch a full list of items at any time
*/
} ) ;
// Connect to Realtime API
await client . connect ( ) ;
// Send a item and triggers a generation
client . sendUserMessageContent ( [ { type : 'input_text' , text : `How are you?` } ] ) ; คุณสามารถใช้ไคลเอนต์นี้ได้โดยตรงจากเบราว์เซอร์ในแอพ EG React หรือ Vue เราไม่แนะนำสิ่งนี้คีย์ API ของคุณมีความเสี่ยงหากคุณเชื่อมต่อกับ OpenAI โดยตรงจากเบราว์เซอร์ ในการสร้างอินสแตนซ์ลูกค้าในสภาพแวดล้อมของเบราว์เซอร์ให้ใช้:
import { RealtimeClient } from '@openai/realtime-api-beta' ;
const client = new RealtimeClient ( {
apiKey : process . env . OPENAI_API_KEY ,
dangerouslyAllowAPIKeyInBrowser : true ,
} ) ;หากคุณใช้งานเซิร์ฟเวอร์รีเลย์ของคุณเองเช่นกับคอนโซลเรียลไทม์คุณสามารถเชื่อมต่อกับ URL ของเซิร์ฟเวอร์รีเลย์ได้เช่น:
const client = new RealtimeClient ( { url : RELAY_SERVER_URL } ) ; ในห้องสมุดนี้มีสามดั้งเดิมสำหรับการเชื่อมต่อกับ API เรียลไทม์ เราขอแนะนำให้เริ่มต้นด้วย RealtimeClient แต่ผู้ใช้ขั้นสูงอาจจะสะดวกสบายมากขึ้นในการทำงานใกล้กับโลหะ
RealtimeClientconversation.updated ที่กำหนดเอง updated, conversation.item.appended , conversation.item.completed , conversation.interrupted และ realtime.event EventsRealtimeAPIclient.realtimeserver.{event_name} และ client.{event_name} ตามลำดับRealtimeConversationclient.conversationไคลเอนต์มาพร้อมกับยูทิลิตี้พื้นฐานบางอย่างที่ทำให้ง่ายต่อการสร้างแอพเรียลไทม์อย่างรวดเร็ว
การส่งข้อความไปยังเซิร์ฟเวอร์จากผู้ใช้เป็นเรื่องง่าย
client . sendUserMessageContent ( [ { type : 'input_text' , text : `How are you?` } ] ) ;
// or (empty audio)
client . sendUserMessageContent ( [
{ type : 'input_audio' , audio : new Int16Array ( 0 ) } ,
] ) ; ในการส่งสตรีมมิ่งเสียงให้ใช้เมธอด .appendInputAudio() หากคุณอยู่ใน turn_detection: 'disabled' คุณต้องใช้ .createResponse() เพื่อบอกให้โมเดลตอบสนอง
// Send user audio, must be Int16Array or ArrayBuffer
// Default audio format is pcm16 with sample rate of 24,000 Hz
// This populates 1s of noise in 0.1s chunks
for ( let i = 0 ; i < 10 ; i ++ ) {
const data = new Int16Array ( 2400 ) ;
for ( let n = 0 ; n < 2400 ; n ++ ) {
const value = Math . floor ( ( Math . random ( ) * 2 - 1 ) * 0x8000 ) ;
data [ n ] = value ;
}
client . appendInputAudio ( data ) ;
}
// Pending audio is committed and model is asked to generate
client . createResponse ( ) ; การทำงานกับเครื่องมือเป็นเรื่องง่าย เพียงโทร .addTool() และตั้งค่าการโทรกลับเป็นพารามิเตอร์ที่สอง การเรียกกลับจะถูกเรียกใช้งานด้วยพารามิเตอร์สำหรับเครื่องมือและผลลัพธ์จะถูกส่งกลับไปยังโมเดลโดยอัตโนมัติ
// We can add tools as well, with callbacks specified
client . addTool (
{
name : 'get_weather' ,
description :
'Retrieves the weather for a given lat, lng coordinate pair. Specify a label for the location.' ,
parameters : {
type : 'object' ,
properties : {
lat : {
type : 'number' ,
description : 'Latitude' ,
} ,
lng : {
type : 'number' ,
description : 'Longitude' ,
} ,
location : {
type : 'string' ,
description : 'Name of the location' ,
} ,
} ,
required : [ 'lat' , 'lng' , 'location' ] ,
} ,
} ,
async ( { lat , lng , location } ) => {
const result = await fetch (
`https://api.open-meteo.com/v1/forecast?latitude= ${ lat } &longitude= ${ lng } ¤t=temperature_2m,wind_speed_10m` ,
) ;
const json = await result . json ( ) ;
return json ;
} ,
) ; วิธี. .addTool() จะเรียกใช้ตัวจัดการเครื่องมือโดยอัตโนมัติและทริกเกอร์การตอบสนองในการดำเนินการของตัวจัดการโดยอัตโนมัติ บางครั้งคุณอาจไม่ต้องการเช่น: การใช้เครื่องมือในการสร้างสคีมาที่คุณใช้เพื่อวัตถุประสงค์อื่น
ในกรณีนี้เราสามารถใช้รายการ tools ด้วย updateSession ในกรณีนี้คุณ ต้อง ระบุ type: 'function' ซึ่งไม่จำเป็นสำหรับ .addTool()
หมายเหตุ: เครื่องมือที่เพิ่มด้วย .addTool() จะ ไม่ ถูกแทนที่เมื่ออัปเดตเซสชันด้วยตนเองเช่นนี้ แต่ updateSession() การเปลี่ยนแปลงจะแทนที่ updateSession() การเปลี่ยนแปลง เครื่องมือที่เพิ่มผ่าน .addTool() จะคงอยู่และต่อท้ายกับสิ่งที่ตั้งไว้ด้วยตนเองที่นี่
client . updateSession ( {
tools : [
{
type : 'function' ,
name : 'get_weather' ,
description :
'Retrieves the weather for a given lat, lng coordinate pair. Specify a label for the location.' ,
parameters : {
type : 'object' ,
properties : {
lat : {
type : 'number' ,
description : 'Latitude' ,
} ,
lng : {
type : 'number' ,
description : 'Longitude' ,
} ,
location : {
type : 'string' ,
description : 'Name of the location' ,
} ,
} ,
required : [ 'lat' , 'lng' , 'location' ] ,
} ,
} ,
] ,
} ) ;จากนั้นเพื่อจัดการการเรียกใช้ฟังก์ชัน ...
client . on ( 'conversation.updated' , ( { item , delta } ) => {
if ( item . type === 'function_call' ) {
// do something
if ( delta . arguments ) {
// populating the arguments
}
}
} ) ;
client . on ( 'conversation.item.completed' , ( { item } ) => {
if ( item . type === 'function_call' ) {
// your function call is complete, execute some custom code
}
} ) ; คุณอาจต้องการขัดจังหวะโมเดลด้วยตนเองโดยเฉพาะอย่างยิ่งใน turn_detection: 'disabled' ในการทำเช่นนี้เราสามารถใช้:
// id is the id of the item currently being generated
// sampleCount is the number of audio samples that have been heard by the listener
client . cancelResponse ( id , sampleCount ) ; วิธีนี้จะทำให้โมเดลหยุดการสร้างทันที แต่ยังตัดทอนรายการที่เล่นโดยการลบเสียงทั้งหมดหลังจาก sampleCount และล้างการตอบกลับข้อความ ด้วยการใช้วิธีนี้คุณสามารถขัดจังหวะโมเดลและป้องกันไม่ให้ "จดจำ" อะไรก็ได้ที่สร้างขึ้นมาก่อนที่สถานะของผู้ใช้จะอยู่ที่ไหน
หากคุณต้องการการควบคุมด้วยตนเองมากขึ้นและต้องการส่งเหตุการณ์ไคลเอนต์ที่กำหนดเองตามการอ้างอิงเหตุการณ์ไคลเอนต์เรียลไทม์คุณสามารถใช้ client.realtime.send() เช่น:
// manually send a function call output
client . realtime . send ( 'conversation.item.create' , {
item : {
type : 'function_call_output' ,
call_id : 'my-call-id' ,
output : '{function_succeeded:true}' ,
} ,
} ) ;
client . realtime . send ( 'response.create' ) ; ด้วย RealtimeClient เราได้ลดเหตุการณ์ค่าใช้จ่ายจากเหตุการณ์เซิร์ฟเวอร์เป็น ห้า เหตุการณ์หลักที่สำคัญที่สุดสำหรับโฟลว์การควบคุมแอปพลิเคชันของคุณ เหตุการณ์เหล่านี้ ไม่ได้ เป็นส่วนหนึ่งของข้อกำหนด API แต่ห่อตรรกะเพื่อให้การพัฒนาแอปพลิเคชันง่ายขึ้น
// errors like connection failures
client . on ( 'error' , ( event ) => {
// do thing
} ) ;
// in VAD mode, the user starts speaking
// we can use this to stop audio playback of a previous response if necessary
client . on ( 'conversation.interrupted' , ( ) => {
/* do something */
} ) ;
// includes all changes to conversations
// delta may be populated
client . on ( 'conversation.updated' , ( { item , delta } ) => {
// get all items, e.g. if you need to update a chat window
const items = client . conversation . getItems ( ) ;
switch ( item . type ) {
case 'message' :
// system, user, or assistant message (item.role)
break ;
case 'function_call' :
// always a function call from the model
break ;
case 'function_call_output' :
// always a response from the user / application
break ;
}
if ( delta ) {
// Only one of the following will be populated for any given event
// delta.audio = Int16Array, audio added
// delta.transcript = string, transcript added
// delta.arguments = string, function arguments added
}
} ) ;
// only triggered after item added to conversation
client . on ( 'conversation.item.appended' , ( { item } ) => {
/* item status can be 'in_progress' or 'completed' */
} ) ;
// only triggered after item completed in conversation
// will always be triggered after conversation.item.appended
client . on ( 'conversation.item.completed' , ( { item } ) => {
/* item status will always be 'completed' */
} ) ; หากคุณต้องการควบคุมการพัฒนาแอปพลิเคชันของคุณมากขึ้นคุณสามารถใช้เหตุการณ์ realtime.event และเลือกเฉพาะเพื่อตอบสนองต่อเหตุการณ์ เซิร์ฟเวอร์ เอกสารฉบับเต็มสำหรับกิจกรรมเหล่านี้มีอยู่ในการอ้างอิงเหตุการณ์ API ของเซิร์ฟเวอร์เรียลไทม์
// all events, can use for logging, debugging, or manual event handling
client . on ( 'realtime.event' , ( { time , source , event } ) => {
// time is an ISO timestamp
// source is 'client' or 'server'
// event is the raw event payload (json)
if ( source === 'server' ) {
doSomething ( event ) ;
}
} ) ; คุณจะต้องตรวจสอบให้แน่ใจว่าคุณมีไฟล์ .env พร้อม OPENAI_API_KEY= ตั้งค่าเพื่อเรียกใช้การทดสอบ จากนั้นการเรียกใช้ชุดทดสอบเป็นเรื่องง่าย
$ npm testในการเรียกใช้การทดสอบด้วยบันทึกการดีบัก (จะบันทึกเหตุการณ์ที่ส่งไปและรับจาก WebSocket) ใช้:
$ npm test -- --debugขอบคุณสำหรับการตรวจสอบ API เรียลไทม์ ชอบที่จะได้ยินจากคุณ ขอขอบคุณเป็นพิเศษสำหรับทีม API เรียลไทม์ที่ทำให้สิ่งนี้เป็นไปได้ทั้งหมด