Crea un asistente de voz de IA con Twilio Voice, la API de Realtime de OpenAI y Node.js
Time to read:
Crea un asistente de voz de IA con Twilio Voice, la API de Realtime de OpenAI y Node.js
Estamos muy entusiasmados con nuestros amigos de OpenAI que lanzaron su API de Realtime. La API abre las capacidades de voz a voz (S2S) para su modelo multimodal GPT en tiempo real, que admite la entrada y salida directa de audio, lo que evita traducir de un texto a otro con un paso de voz a texto (SST) o de texto a voz (TTS).
¿Qué significa eso para ti? Los modelos S2S mejoran la latencia: la API de Realtime de OpenAI hace posible tener conversaciones fluidas que se sienten como un diálogo humano real... y estoy seguro de que estarás de acuerdo. Es por eso que estamos encantados de proporcionar esta integración de lanzamiento en colaboración con OpenAI.
En este tutorial, te mostraré cómo crear un asistente de voz de IA mediante Twilio Voice y la API de OpenAI Realtime, con tecnología Node.js. Una vez que crees la herramienta, podrás hablar con tu asistente de la misma manera que lo harías con un ser humano y pedirle datos (¡o chistes!). Juntos, configuraremos un servidor de Twilio Media Stream para recibir audio de una llamada telefónica, procesarlo mediante la API de OpenAI Realtime y devolver la respuesta de la IA a Twilio para mantener el flujo de la conversación.
Ajusten sus cinturones y, ¡empecemos!
Requisitos previos
Para seguir los pasos de este tutorial, primero necesitarás lo siguiente:
- Node.js 18 y versiones posteriores (yo utilicé
18.20.4para este tutorial; puedes descargarlo desde aquí) - Una cuenta de Twilio. Si aún no tienes una, puedes registrarte aquí para obtener una prueba gratuita.
- Un número de teléfono de Twilio con capacidades de voz. Estas son las instrucciones para comprar un número de teléfono.
- Una cuenta de OpenAI y una clave de API de OpenAI. Puedes registrarte aquí.
- Acceso a la API de OpenAI Realtime. Haz clic aquí para obtener más información.
- (Opcional) ngrok u otra solución de tunelización para exponer tu servidor local a Internet para realizar pruebas. Descarga ngrok aquí.
- Un teléfono celular o línea fija que pueda realizar llamadas telefónicas salientes.
Con eso, ¡puedes comenzar a crear!
Configura el proyecto de Node de voz a voz con la API de Realtime
En los siguientes pasos, te guiaré a través de la configuración de tu proyecto, la instalación de las dependencias y la escritura del código que necesitarás para establecer conexiones proxy de websocket entre Twilio y OpenAI.
Como alternativa, puedes encontrar nuestro repositorio aquí. También tenemos una versión en video de este tutorial que puedes encontrar aquí:
Muy bien, ¡empecemos de verdad!
Paso 1: Inicialice el proyecto
En primer lugar, configura un nuevo proyecto de Node.js:
Paso 2: Instalación de dependencias
A continuación, instala las dependencias necesarias para el proyecto. Utilizaremos la estructura web Fastify y necesitaremos soporte de websocket. También almacenaremos nuestra variable de entorno sensible en un archivo .env.
Paso 3: Crea los archivos del proyecto
Crearemos un archivo denominado index.js para nuestro código principal. También tendremos ese archivo .env para almacenar variables de entorno. Aquí puedes encontrar más información sobre esta estrategia.
En este caso, solo necesitarás tu clave de API de OpenAI en .env: verifica que tenga acceso a la API de Realtime.
Paso 3.1: Crea el archivo .env
Primero, cree el archivo .env:
Luego, en tu editor de textos favorito, agrega tu OPENAI_API_KEY en la primera línea:
Paso 3.2: Crea el archivo index.js
A continuación, crea un nuevo archivo con el nombre index.js en el directorio de tu proyecto:
Paso 4: Escribe el código del servidor
Excelente: ahora estamos listos para ir al tutorial. Dividiré el código index.js en varios pasos y ofreceré explicaciones para cada parte, pero no dudes en cambiar a la app Code Exchange o al repositorio si deseas avanzar más rápido.
Paso 4.1: Importa las dependencias, carga nuestra variable de entorno e inicializa Fastify
Aquí no hay nada fuera de lo común: comenzamos con la importación de los módulos requeridos, la configuración de la resolución de ruta y la carga de las variables de entorno desde nuestro archivo .env.
Pega el siguiente código en tu index.js:
Paso 4.2: Define algunas constantes
A continuación, definimos las constantes para el mensaje del sistema (SYSTEM_MESSAGE), la voz (VOICE) y el puerto (PORT) del servidor. También elegiremos los eventos de OpenAI para iniciar sesión en la consola.
Esto es lo que debes pegar a continuación en tu archivo:
Aquí, SYSTEM_MESSAGE establece el tono y el comportamiento de la IA durante la conversación, que finalmente pasaremos como instructions a OpenAI. Al personalizar este mensaje, puedes controlar la personalidad y el estilo de interacción de la IA. En algunas secciones, verás cómo lo pasamos a OpenAI para influir en nuestra conversación. Para obtener más detalles sobre la indicación, consulta la Guía de indicaciones de Realtime de OpenAI.
La constante VOICE controla cómo sonará la IA. Puedes elegir una voz desde aquí.
La constante TEMPERATURE controla cuán aleatorias serán las respuestas del LLM (entre más alto sea el valor, más aleatorias serán).
La constante PORT controla qué puerto abrirá tu aplicación. Analizaremos esto con más detalle en la sección ngrok a continuación.
Por último, LOG_EVENT_TYPES se refiere a los tipos de eventos de OpenAI que mostraremos en la línea de comandos. Puedes encontrar toda la lista en la documentación de la API de Realtime de OpenAI.
Paso 4.3: Define dos rutas
Bien, vayamos ahora al corazón del código. Definimos una ruta raíz (principalmente una verificación de estado…) y una ruta para manejar las llamadas entrantes. /incoming-call generará TwiML, el lenguaje de marcado de Twilio, para indicar a Twilio cómo manejar la llamada, ofreceré más información en un segundo.
Pega esto en index.js después de establecer la lista constante de LOG_EVENT_TYPES:
Al igual que con todo TwiML, comenzamos con la versión XML y abrimos una etiqueta <Response>. Luego, le pedimos a Twilio que le diga un breve mensaje a la persona que llama —¡diviértete con esta función!—, que haga una pausa de 2 segundos y luego le pida a la persona que llama que comience a hablar.
El verbo <Connect> funciona junto con el sustantivo <Stream> para abrir una transmisión bidireccional mediante Media Streams de Twilio. Aquí es donde ocurre la magia de la demostración. En el siguiente paso, te mostraré cómo utilizaremos el audio proxy entre dos websockets.
Paso 4.4: Define las conexiones de WebSocket
Ahora debemos configurar la ruta de WebSocket para la transmisión de los medios (la ruta que le damos a Twilio en la sección anterior) y configurar websockets con Twilio y OpenAI. Este código es un poco largo, pero explicaré lo que está sucediendo justo después del bloque de código.
Pega este código siguiente, que es donde se definen las rutas:
Como puedes ver, primero configuramos una ruta de WebSocket (/media-stream) para manejar la transmisión de medios entre Twilio y OpenAI. Esta es la ruta que mencionamos en nuestro TwiML, anteriormente. Las siguientes dos áreas requieren una explicación adicional.
Configura la sesión y conversación de la API de OpenAI Realtime
A continuación, definimos nuestra configuración de sesión con OpenAI. Esta configuración se envía al WebSocket de OpenAI como un objeto JSON después de que se abre la conexión, después de una ligera demora.
Luego, utilizamos la función sendSessionUpdate() para definir cómo interactúa y responde la IA. Puedes obtener más información sobre las opciones que elegí en la documentación de la API de OpenAI Realtime.
La función sendSessionUpdate también configura los atributos de la sesión de OpenAI:
type: aquí le decimos a OpenAI que estamos utilizando Realtime.model: estamos utilizando el modelo spt-realtime.audio.input.turn_detection: habilita la detección de actividad de voz (VAD) del lado del servidor con server_vad.audio.input.format.type/audio.output.format.type: especifica los formatos de audio, que cambiamos aaudio/pcmudebido a los requisitos de Twilio.- audio.output.voice: el modelo VOICE que establecimos anteriormente.
instructions: influye en la interacción de la IA medianteSYSTEM_MESSAGE.output_modalities: habilita la comunicación de audio.
Proxy entre los WebSockets de Twilio y OpenAI
Las siguientes líneas indican datos de audio proxy (mediante el formato de G.711 u-law compatible con Twilio) entre las conexiones de WebSocket de Twilio Media Stream y la API de OpenAI Realtime. Cuando se inicia la llamada, aquí es donde se procesa la voz de la persona que llama y se vuelve a transmitir el audio generado por la IA.
Este es un recorrido detallado de cómo estamos representando OpenAI Realtime y Twilio:
- Evento
start: captura la identificación única del flujo (streamSid). - Evento
media: procesa y reenvía cargas útiles de datos de audio de la llamada en curso a OpenAI. response.output_audio.delta: maneja los datos de audio generados por la IA desde OpenAI, los vuelve a codificar y los envía a Twilio.- Evento
closede WebSocket de Twilio: maneja la desconexión del cliente y cierra los flujos.
Paso 4.5: Prepara el servidor
Por último, iniciamos el servidor Fastify y lo llevamos a casa (mediante el puerto que pasamos o definimos). Pega esto debajo de lo que tienes y ¡estamos listos para lanzarlo!
Ejecuta el servidor
Sal del archivo nuevamente.
Puedes ejecutar el servidor web con el siguiente comando:
Si el servidor se inicia correctamente, deberás ver el mensaje Server is listening on port 5050 (El servidor está escuchando en el puerto 5050) (o el puerto que hayas especificado) en tu terminal.
Termina tu configuración
¡Ahora es el momento de dar instrucciones a Twilio y terminar el cableado! Cubriremos el uso del proxy inverso ngrok para hacer público tu servidor.
Paso 5: Expón tu servidor a Twilio mediante ngrok
Ahora, debes utilizar ngrok o un servicio similar (o un servidor privado virtual, etc.) para exponer tu servidor local a la Internet pública. Twilio requiere una URL pública para enviar solicitudes a tu servidor y recibir instrucciones tuyas.
Descarga e instala ngrok si aún lo necesitas, luego ejecuta el siguiente comando. Si cambiaste el puerto por uno distinto de 5050, asegúrate de actualizarlo aquí:
Esto te dará una URL pública (p. ej., https://abc123.ngrok.io) que puedes utilizar para hacer pruebas. El mío se ve así:
Paso 6: Configura Twilio
Estamos tan cerca, ¿puedes sentirlo?
Ve a Twilio Console y selecciona tu número habilitado para voz.
En Voice & Fax, configura el webhook A CALL COMES IN (CUANDO ENTRA UNA LLAMADA) en tu URL de ngrok (en la línea Forwarding, ( https://ad745c4093d9.ngrok.app en mi captura de pantalla) añadiendo /incoming-call. Por ejemplo, en mi caso, https://ad745c4093d9.ngrok.app/incoming-call.
Guarda tus cambios: ¡estás en el paso final!
¡Prueba tu configuración!
Asegúrate de que tu sesión de ngrok aún se esté ejecutando y que tu servidor esté activo. Si es así, el momento ha llegado: ahora puedes hacer una llamada a tu número de Twilio con un teléfono celular o una línea fija.
El servidor debe hacerse cargo de la llamada (proporcionando tu TwiML a Twilio) y luego conectar mediante proxy los WebSockets de la API de OpenAI Realtime y de Twilio juntos. Comienza a hablar: ahora deberás oír el mensaje del sistema basado en IA y podrás interactuar con él.
Problemas comunes y solución de problemas
Si tu configuración no funciona (pero tu servidor se está ejecutando), hay algunos puntos que debes verificar primero:
- ¿Está funcionando ngrok? ¿La URL está correctamente configurada en la sección Voice Configuration (Configuración de voz) -> A Call Comes In (Cuando entra una llamada)?
- ¿Hubo un error con Twilio, posiblemente en tu TwiML? Puedes depurar los errores de Twilio de distintas maneras: hay más información en este artículo.
- ¿Tu código llama correctamente a OpenAI? Consulta más información en su documentación.
Conclusión
¿Acaso no es increíble? Has creado con éxito un asistente de voz de IA mediante Twilio Voice y la API de OpenAI Realtime. Esta configuración permite aplicaciones de voz interactivas, dinámicas y de baja latencia que pueden responder a los comentarios del usuario casi en tiempo real, y genera una voz a la que puedes llamar de manera confiable, cuando lo necesites.
Estamos ansiosos por ver lo que vas a crear.
Paso siguiente:
- Consulta la documentación de Twilio y los documentos de la API de OpenAI Realtime para obtener funciones más avanzadas.
- Consulta la documentación de OpenAI sobre los conceptos.
Paul Kamp es el editor técnico en jefe del blog de Twilio. Puedes comunicarte con él, o posiblemente con su asistente de IA, en pkamp [arroba] twilio.com.
Dominik Kundel trabaja en Experiencia del Desarrollador en OpenAI.
Publicaciones relacionadas
Recursos relacionados
Twilio Docs
Desde API hasta SDK y aplicaciones de muestra
Documentación de referencia de API, SDK, bibliotecas auxiliares, inicios rápidos y tutoriales para su idioma y plataforma.
Centro de Recursos
Los últimos libros electrónicos, informes de la industria y seminarios web
Aprenda de los expertos en participación del cliente para mejorar su propia comunicación.
Ahoy
Centro de la comunidad de desarrolladores de Twilio
Mejores prácticas, ejemplos de códigos e inspiración para crear comunicaciones y experiencias de participación digital.