OpenAI Realtime Console está pensada como inspector y referencia de API interactiva para OpenAI Realtime API. Viene con dos bibliotecas de utilidades, openai/openai-realtime-api-beta, que actúa como cliente de referencia (para navegador y Node.js) y /src/lib/wavtools
, que permite una gestión sencilla del audio en el navegador.
Este es un proyecto de React creado usando create-react-app
que se incluye a través de Webpack. Instálelo extrayendo el contenido de este paquete y usando;
$ npm i
Inicie su servidor con:
$ npm start
Debería estar disponible a través de localhost:3000
.
La consola requiere una clave API de OpenAI ( clave de usuario o clave de proyecto ) que tenga acceso a la API en tiempo real. Al inicio se le pedirá que lo ingrese. Se guardará a través de localStorage
y se puede cambiar en cualquier momento desde la interfaz de usuario.
Para iniciar una sesión necesitarás conectarte . Esto requerirá acceso al micrófono. Luego podrá elegir entre los modos de conversación manual (Pulsar para hablar) y vad (Detección de actividad de voz) y alternar entre ellos en cualquier momento.
Hay dos funciones habilitadas;
get_weather
: Pregunte por el clima en cualquier lugar y el modelo hará todo lo posible para identificar la ubicación, mostrarla en un mapa y obtener el clima para esa ubicación. Tenga en cuenta que no tiene acceso a la ubicación y que las coordenadas se "adivinan" a partir de los datos de entrenamiento del modelo, por lo que la precisión puede no ser perfecta.set_memory
: Puede pedirle al modelo que recuerde información por usted y la almacenará en un blob JSON a la izquierda.Puede interrumpir libremente el modelo en cualquier momento en el modo pulsar para hablar o VAD.
Si desea crear una implementación más sólida y jugar con el cliente de referencia utilizando su propio servidor, hemos incluido un servidor de retransmisión Node.js.
$ npm run relay
Se iniciará automáticamente en localhost:8081
.
Deberá crear un archivo .env
con la siguiente configuración:
OPENAI_API_KEY=YOUR_API_KEY
REACT_APP_LOCAL_RELAY_SERVER_URL=http://localhost:8081
Deberá reiniciar tanto su aplicación React como su servidor de retransmisión para el .env.
los cambios entren en vigor. La URL del servidor local se carga a través de ConsolePage.tsx
. Para dejar de usar el servidor de retransmisión en cualquier momento, simplemente elimine la variable de entorno o configúrela como una cadena vacía.
/**
* Running a local relay server will allow you to hide your API key
* and run custom logic on the server
*
* Set the local relay server address to:
* REACT_APP_LOCAL_RELAY_SERVER_URL=http://localhost:8081
*
* This will also require you to set OPENAI_API_KEY= in a `.env` file
* You can run it with `npm run relay`, in parallel with `npm start`
*/
const LOCAL_RELAY_SERVER_URL : string =
process . env . REACT_APP_LOCAL_RELAY_SERVER_URL || '' ;
Este servidor es sólo una simple retransmisión de mensajes , pero puede ampliarse a:
instructions
) directamente en el servidorTendrás que implementar estas características tú mismo.
El cliente de referencia y la documentación más recientes están disponibles en GitHub en openai/openai-realtime-api-beta.
Puede utilizar este cliente usted mismo en cualquier proyecto React (front-end) o Node.js. Para obtener la documentación completa, consulte el repositorio de GitHub, pero puede utilizar la guía aquí como guía para comenzar.
import { RealtimeClient } from '/src/lib/realtime-api-beta/index.js' ;
const client = new RealtimeClient ( { apiKey : process . env . OPENAI_API_KEY } ) ;
// Can set parameters ahead of connecting
client . updateSession ( { instructions : 'You are a great, upbeat friend.' } ) ;
client . updateSession ( { voice : 'alloy' } ) ;
client . updateSession ( { turn_detection : 'server_vad' } ) ;
client . updateSession ( { input_audio_transcription : { model : 'whisper-1' } } ) ;
// Set up event handling
client . on ( 'conversation.updated' , ( { item , delta } ) => {
const items = client . conversation . getItems ( ) ; // can use this to render all items
/* includes all changes to conversations, delta may be populated */
} ) ;
// Connect to Realtime API
await client . connect ( ) ;
// Send an item and triggers a generation
client . sendUserMessageContent ( [ { type : 'text' , text : `How are you?` } ] ) ;
Para enviar audio en streaming, utilice el método .appendInputAudio()
. Si estás en turn_detection: 'disabled'
, entonces necesitas usar .generate()
para indicarle 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 establezca una devolución de llamada como segundo parámetro. La devolución de llamada se ejecutará con los parámetros de 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 ;
}
) ;
Es posible que desees interrumpir manualmente el modelo, 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 deje de generarse inmediatamente, pero también truncará el elemento que se está reproduciendo eliminando todo el audio después de sampleCount
y borrando la respuesta de texto. Al utilizar este método, puede interrumpir el modelo y evitar que "recuerde" cualquier cosa que haya generado y que esté por delante del estado del usuario.
Hay cinco eventos de cliente principales para el flujo de control de aplicaciones en RealtimeClient
. Tenga en cuenta que esto es solo una descripción general del uso del cliente, la especificación completa de eventos de la API en tiempo real es considerablemente mayor. Si necesita más control, consulte el repositorio de GitHub: openai/openai-realtime-api-beta.
// 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' */
} ) ;
Wavtools contiene una gestión sencilla de las transmisiones de audio PCM16 en el navegador, tanto para grabación como para reproducción.
import { WavRecorder } from '/src/lib/wavtools/index.js' ;
const wavRecorder = new WavRecorder ( { sampleRate : 24000 } ) ;
wavRecorder . getStatus ( ) ; // "ended"
// request permissions, connect microphone
await wavRecorder . begin ( ) ;
wavRecorder . getStatus ( ) ; // "paused"
// Start recording
// This callback will be triggered in chunks of 8192 samples by default
// { mono, raw } are Int16Array (PCM16) mono & full channel data
await wavRecorder . record ( ( data ) => {
const { mono , raw } = data ;
} ) ;
wavRecorder . getStatus ( ) ; // "recording"
// Stop recording
await wavRecorder . pause ( ) ;
wavRecorder . getStatus ( ) ; // "paused"
// outputs "audio/wav" audio file
const audio = await wavRecorder . save ( ) ;
// clears current audio buffer and starts recording
await wavRecorder . clear ( ) ;
await wavRecorder . record ( ) ;
// get data for visualization
const frequencyData = wavRecorder . getFrequencies ( ) ;
// Stop recording, disconnects microphone, output file
await wavRecorder . pause ( ) ;
const finalAudio = await wavRecorder . end ( ) ;
// Listen for device change; e.g. if somebody disconnects a microphone
// deviceList is array of MediaDeviceInfo[] + `default` property
wavRecorder . listenForDeviceChange ( ( deviceList ) => { } ) ;
import { WavStreamPlayer } from '/src/lib/wavtools/index.js' ;
const wavStreamPlayer = new WavStreamPlayer ( { sampleRate : 24000 } ) ;
// Connect to audio output
await wavStreamPlayer . connect ( ) ;
// Create 1s of empty PCM16 audio
const audio = new Int16Array ( 24000 ) ;
// Queue 3s of audio, will start playing immediately
wavStreamPlayer . add16BitPCM ( audio , 'my-track' ) ;
wavStreamPlayer . add16BitPCM ( audio , 'my-track' ) ;
wavStreamPlayer . add16BitPCM ( audio , 'my-track' ) ;
// get data for visualization
const frequencyData = wavStreamPlayer . getFrequencies ( ) ;
// Interrupt the audio (halt playback) at any time
// To restart, need to call .add16BitPCM() again
const trackOffset = await wavStreamPlayer . interrupt ( ) ;
trackOffset . trackId ; // "my-track"
trackOffset . offset ; // sample number
trackOffset . currentTime ; // time in track
Gracias por visitar Realtime Console. Esperamos que te diviertas con la API en tiempo real. Un agradecimiento especial a todo el equipo de Realtime API por hacer esto posible. No dude en comunicarse, hacer preguntas o enviar comentarios creando un problema en el repositorio. ¡También puedes comunicarte con nosotros y contarnos lo que piensas directamente!