Este repositorio contiene un cliente de referencia, también conocido como biblioteca de muestras para conectarse a la API de tiempo real de Openi. Esta biblioteca está en beta y no debe tratarse como una implementación final. Puede usarlo para prototipos fácilmente de aplicaciones de conversación.
La forma más fácil de jugar con la API de inmediato es usar la consola en tiempo real , utiliza el cliente de referencia para ofrecer un inspector API totalmente funcional con ejemplos de visualización de voz y más.
Esta biblioteca está construida para ser utilizada tanto en el servidor (Node.js) como en el navegador (React, Vue), tanto en JavaScript como en Basas de código TypeScript. Mientras esté en Beta, para instalar la biblioteca, deberá npm install directamente desde el repositorio de 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?` } ] ) ; Puede usar este cliente directamente desde el navegador en EG React o Vue aplicaciones. No recomendamos esto, sus claves API están en riesgo si se conecta a OpenAI directamente desde el navegador. Para instanciar al cliente en un entorno de navegador, use:
import { RealtimeClient } from '@openai/realtime-api-beta' ;
const client = new RealtimeClient ( {
apiKey : process . env . OPENAI_API_KEY ,
dangerouslyAllowAPIKeyInBrowser : true ,
} ) ;Si está ejecutando su propio servidor de retransmisión, por ejemplo, con la consola en tiempo real, puede conectarse a la URL del servidor de retransmisión de así decirlo:
const client = new RealtimeClient ( { url : RELAY_SERVER_URL } ) ; En esta biblioteca, hay tres primitivas para interactuar con la API de tiempo real. Recomendamos comenzar con RealtimeClient , pero los usuarios más avanzados pueden estar más cómodos trabajando más cerca del metal.
RealtimeClientconversation.updated personalizada. Updated, conversation.item.appended , conversation.item.completed , conversation.interrupted y realtime.eventRealtimeAPIclient.realtimeserver.{event_name} y client.{event_name} , respectivamenteRealtimeConversationclient.conversationEl cliente viene empaquetado con algunas utilidades básicas que facilitan la creación de aplicaciones en tiempo real rápidamente.
Enviar mensajes al servidor desde el usuario es fácil.
client . sendUserMessageContent ( [ { type : 'input_text' , text : `How are you?` } ] ) ;
// or (empty audio)
client . sendUserMessageContent ( [
{ type : 'input_audio' , audio : new Int16Array ( 0 ) } ,
] ) ; Para enviar audio de transmisión, use el método .appendInputAudio() . Si está en el modo turn_detection: 'disabled' , entonces debe usar .createResponse() para decirle al modelo que responda.
// 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 ( ) ; Trabajar con herramientas es fácil. Simplemente llame .addTool() y configure una devolución de llamada como el segundo parámetro. La devolución de llamada se ejecutará con los parámetros para la herramienta, y el resultado se enviará automáticamente al modelo.
// 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 ;
} ,
) ; El método .addTool() ejecuta automáticamente un controlador de herramientas y desencadena una respuesta al finalizar el controlador. A veces es posible que no desee eso, por ejemplo: usar herramientas para generar un esquema que usa para otros fines.
En este caso, podemos usar el elemento tools con updateSession . En este caso, debe especificar type: 'function' , que no es necesaria para .addTool() .
Nota: Las herramientas agregadas con .addTool() no se anularán al actualizar sesiones manualmente de esta manera, pero cada cambio updateSession() anulará los cambios anteriores updateSession() . Las herramientas agregadas a través de .addTool() se persisten y se agregan a cualquier cosa establecida manualmente aquí.
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' ] ,
} ,
} ,
] ,
} ) ;Luego, para manejar llamadas de función ...
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
}
} ) ; Es posible que desee interrumpir el modelo manualmente, especialmente en el modo turn_detection: 'disabled' . Para hacer esto, podemos usar:
// 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 ) ; Este método hará que el modelo cese de inmediato la generación, pero también truncará el elemento que se reproduce eliminando todo el audio después de sampleCount y bordeando la respuesta del texto. Al usar este método, puede interrumpir el modelo y evitar que "recordara" cualquier cosa que haya generado que esté por delante de dónde está el estado del usuario.
Si necesita más control manual y desea enviar eventos de cliente personalizados de acuerdo con la referencia de la API de eventos de cliente real, puede usar client.realtime.send() así:
// 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' ) ; Con RealtimeClient hemos reducido la sobrecarga del evento de los eventos del servidor a cinco eventos principales que son más críticos para el flujo de control de su aplicación. Estos eventos no forman parte de la especificación API en sí, pero envuelve la lógica para facilitar el desarrollo de aplicaciones.
// 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' */
} ) ; Si desea más control sobre el desarrollo de su aplicación, puede usar el evento realtime.event y elegir solo para responder a los eventos del servidor . La documentación completa para estos eventos está disponible en la referencia de la API de eventos del servidor real en tiempo real.
// 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 ) ;
}
} ) ; Deberá asegurarse de tener un archivo .env con OPENAI_API_KEY= set para ejecutar pruebas. A partir de ahí, ejecutar la suite de prueba es fácil.
$ npm testPara ejecutar pruebas con registros de depuración (registrará eventos enviados y recibidos de WebSocket), use:
$ npm test -- --debugGracias por visitar la API de tiempo real. Me encantaría saber de ti. Un agradecimiento especial al equipo de API en tiempo real por hacer todo esto posible.