ProCat Solutions
Arquitectura de voice agent: STT, LLM y TTS en tiempo real
Agente de voz con IA en tiempo real: cadena STT, LLM y TTS en streaming, presupuesto de latencia, jitter buffer, medios SIP/WebRTC y el caso del húngaro.
En los últimos meses hemos montado varios agentes telefónicos con IA, y en todos surgieron las mismas tres preguntas básicas: cuánto tiempo pasa desde que quien llama termina la frase hasta que oye la respuesta, qué ocurre si interrumpe, y cómo se defiende el sistema con el húngaro. En este artículo describimos a qué arquitectura llegamos nosotros y dónde están las trampas.
El pipeline: streaming en todas partes
La configuración clásica tiene tres escalones: reconocimiento de voz (STT), modelo de lenguaje (LLM), síntesis de voz (TTS). Si los ejecutamos uno tras otro, en modo bloqueante, el tiempo de respuesta se va fácilmente por encima de los 3-5 segundos, algo inasumible por teléfono. Por eso usamos los tres escalones en modo streaming:
- el STT entrega transcripciones parciales (partial) a medida que llega el audio, sin esperar al final de la frase;
- el LLM emite token a token, y en el primer signo de puntuación que cierra una frase ya pasamos el texto al siguiente paso;
- el TTS sintetiza por fragmentos de frase, y el primer chunk de audio sale cuando el modelo todavía está generando la continuación.
El conjunto es una tubería asíncrona en la que cada tramo tiene su propia cola y su propia señal de cancelación. En Node.js esto sale de forma natural: streams, iteradores asíncronos, AbortController.
Endpointing, detección de turno y el presupuesto de latencia
La mayor parte de la latencia no está en los modelos, sino en la decisión: ¿cuándo ha terminado la frase quien llama? Un umbral de silencio fijo (por ejemplo, 700 ms) es simple, pero falla de dos maneras: en una pausa corta interrumpe a quien habla, y con un umbral largo el sistema parece lento.
Nosotros usamos un enfoque combinado: VAD (voice activity detection) sobre el audio en bruto, la propia señal de end-of-speech del STT, y una heurística lingüística sencilla que estima a partir de la transcripción parcial si la frase está sintácticamente cerrada. En húngaro esto es más difícil que en inglés, porque el orden de las palabras es más libre, pero las partículas interrogativas y los sufijos ayudan mucho. Una máquina de estados pondera las tres señales, y el umbral es adaptativo: si quien llama habla despacio, con pausas, el sistema se vuelve más paciente.
Con el endpointing resuelto, viene el presupuesto. Para la experiencia, lo que cuenta es el tiempo que pasa entre la última sílaba de quien llama y el primer sonido que oye de vuelta. Nosotros lo repartimos más o menos así, con órdenes de magnitud orientativos:
- decisión de endpointing: 200-400 ms
- cierre del STT: 100-300 ms
- primer token del LLM: 300-600 ms
- primer chunk de audio del TTS: 150-300 ms
- red y jitter buffer: 100-200 ms
En total ronda el segundo o segundo y medio, lo que ya resulta natural. Medimos cada tramo por separado (con spans, por llamada), porque si solo vemos la suma final no sabemos dónde se ha estropeado. Un truco que funciona bien es la reacción de relleno: si el primer token del LLM se retrasa, ya puede salir una confirmación breve y dependiente del contexto (“De acuerdo, lo compruebo.”), que gana tiempo y evita que el sistema parezca mudo a quien llama.
Medios: SIP, WebRTC, RTP y el jitter buffer
La parte telefónica es la menos vistosa y, aun así, la que más trabajo da. Desde la PSTN llega RTP por un trunk SIP, normalmente G.711 (8 kHz, alaw/ulaw) o, con suerte, Opus. Desde el navegador llega WebRTC, Opus a 48 kHz. Los modelos de STT, en cambio, esperan casi siempre PCM a 16 kHz, y el TTS suele entregar 24 kHz. Por eso en la capa de medios hay resampling en todas las direcciones, y conviene resolverlo en un único sitio, con un contrato de formato inequívoco; si no, el audio se vuelve “chillón” o va a media velocidad.
Los paquetes RTP no llegan a intervalos regulares, así que en el lado entrante usamos un jitter buffer (rango de 20-60 ms, adaptativo). En el lado saliente hace falta pacing: el TTS produce audio más rápido de lo que la línea lo transporta, así que lo enviamos en tramas de 20 ms, a ritmo de reloj, no según va llegando. Si no lo hacemos, el jitter buffer del otro extremo descarta los paquetes.
Manejo de errores, barge-in, fallbacks
Quien llama interrumpe: eso es el barge-in. En ese momento hay que detener de inmediato la reproducción del TTS, vaciar el búfer de salida, cancelar la generación del LLM y tratar la nueva entrada del usuario como un turno nuevo. Lo difícil es gestionar la respuesta dejada a medias: en el historial de la conversación guardamos lo que de verdad se dijo, no el texto generado completo.
Timeouts en cada llamada externa: si el proveedor de STT no responde dentro de un plazo, cambiamos a un proveedor secundario, y en el LLM caemos a un modelo más pequeño. La lógica de reintento solo se permite en pasos idempotentes; un TTS ya reproducido a medias no se repite. Si todo falla, el agente pide disculpas con un archivo de audio pregrabado y promete devolver la llamada: es peor que el funcionamiento normal, pero mucho mejor que el silencio.
Particularidades del húngaro
El húngaro es una lengua aglutinante, así que los modelos de STT son más inseguros con las formas de palabra poco frecuentes que en inglés. Lo que hemos observado:
- el reconocimiento de nombres propios y términos técnicos (nombres de calles, códigos de producto) mejora si damos al STT un glosario o un prompt hint;
- los números, las fechas y las horas no se pueden dejar en bruto al TTS: en lugar de “2024. 12. 10.” lo pasamos como “kétezer-huszonnégy december tizedike”, con la declinación incluida (“tizedikén”, “háromkor”);
- los números de teléfono y los identificadores los hacemos leer agrupados, con pausas, y después los confirmamos preguntando;
- entre las voces de TTS en húngaro hay mucha dispersión en la entonación; conviene comparar varios proveedores con el mismo conjunto de frases.
La lección más importante: un agente de voz no es un LLM más dos API, sino un sistema de medios en tiempo real en el que el LLM es solo un tramo. La latencia, la capacidad de interrupción y la normalización lingüística exigen al menos tanto trabajo de ingeniería como el prompt.