En Perplexity, nos importa mucho crear productos que sean un placer de usar. Para Perplexity Comet, nuestro navegador con agentes, y Perplexity Computer, nuestro potente trabajador digital de propósito general, una parte importante de ese objetivo era permitir que se usaran por completo mediante la voz. Hay algo especialmente satisfactorio en poder decir lo que quieres, delegar la tarea y ver cómo avanza. Apostamos por la voz como interfaz porque hace que la interacción se sienta un poco más cercana a la magia.
Usamos Realtime-1.5 en producción para llevar esa magia a los millones de sesiones de voz que Perplexity gestiona cada mes. Ver cómo crece el uso de la voz a través de la interfaz de Computer ha sido increíblemente emocionante y nos ha enseñado mucho. Compartiremos algunas de las cosas sorprendentes que hemos aprendido hasta ahora. Te invitamos a probar Realtime-1.5 y a compartir también con nosotros lo que aprendas.
1. Define tu estrategia de gestión del contexto
El contenido extenso, en especial los podcasts de varias horas con mucha información, fue una de nuestras pruebas más claras de gestión del contexto. Queríamos que las transcripciones de los podcasts se pudieran consultar mediante la voz para que un usuario pudiera empezar a interactuar, preguntar qué ocurría en un momento específico a las dos horas y media y obtener una respuesta coherente.
La transcripción completa no cabe en el contexto. Nuestro primer intento fue enviarla en fragmentos grandes. Pronto descubrimos que las actualizaciones grandes fallan de una manera radical: es todo o nada. Si intentas enviar una actualización de 10 000 tokens a una ventana en la que solo caben 5000 tokens más, el modelo perderá todo el historial anterior. Esto hacía que los fragmentos grandes fueran mucho más riesgosos, porque una sola actualización demasiado grande podía borrar un bloque entero de contexto, en lugar de permitir que el sistema olvidara información de manera más gradual.
Así que cambiamos el enfoque. En lugar de enviar actualizaciones grandes, empezamos a dividir todo en fragmentos mucho más pequeños, de 2000 tokens, y a incorporarlos de manera incremental. Esto implica una mayor sobrecarga, pero el comportamiento es mucho más estable. Cuando se produce un truncamiento, se recorta un poco del historial en lugar de borrarlo todo.
Otro detalle sutil que aprendimos fue que no todo el contexto debe ingresar al modelo de la misma manera. Al usar conversation.item.create para actualizar el contexto, item.type: "message" tiene tres roles: system, user y assistant. Estos roles le indican al modelo qué tipo de mensaje está recibiendo. system se usa para dar instrucciones y orientar el comportamiento, user para la entrada del usuario final y assistant para la salida generada por el modelo.
Cuando nos equivocábamos en esto, la interacción empezaba a sentirse extraña. Si se incorporaba demasiado contexto como user, el modelo se comportaba como si el usuario estuviera narrando cada bloque de texto, incluidos los fragmentos de páginas web y los comentarios, en lugar de simplemente hacer una pregunta basada en ese material. Si se incorporaba demasiado como system, ocurría lo contrario. El modelo dejaba de distinguir entre lo que “sabía” por sí mismo, lo que se le había proporcionado como contexto y lo que el usuario realmente estaba preguntando en ese momento.
Un buen ejemplo son los flujos de navegación. A medida que alguien se desplaza por una página, actualizamos continuamente el modelo con lo que aparece en pantalla. Si todo eso se presenta como entrada del usuario, el modelo empieza a actuar como si el usuario hubiera dicho cada párrafo en voz alta. Ese no es el modelo mental adecuado. Queremos que el sistema dé la sensación de estar al tanto de la página en segundo plano y que luego responda con naturalidad cuando el usuario pregunte algo. Al final, esto dependía menos del volumen total de contexto y más de representar correctamente la semántica de la conversación.
2. Estandariza el audio en las distintas interfaces del producto
Perplexity tiene varias interfaces de producto, como Ask, Comet y Computer. Cada una se basa en un conjunto distinto de tecnologías del lado del cliente. Swift, TypeScript, Rust y C++ pueden producir distintos búferes de audio nativos. Cuando permitimos que cada cliente enviara su propio formato de audio sin procesar o nativo a la Realtime API, se generaron inconsistencias en el rendimiento.
Finalmente, creamos un SDK en Rust para abstraer esas diferencias entre plataformas y asegurarnos de que todos los clientes enviaran audio a la API conforme al mismo contrato. En la práctica, eso implicaba procesar la forma de onda antes de que llegara al servidor: remuestrearla a 48 kHz en mono, de acuerdo con la preferencia del códec Opus y la frecuencia interna de WebRTC; pasarla por WebRTC APM para aplicar cancelación de eco, control automático de ganancia, reducción de ruido y filtrado pasaaltos; y luego codificarla para su transporte. El SDK nos permitió centralizar la estandarización de las constantes de audio, el remuestreo y la configuración de todo el flujo de procesamiento, en lugar de hacerlo cliente por cliente.
3. Ajusta el sistema para entornos con condiciones poco ideales
Es importante ajustar la VAD en el entorno en el que viven los usuarios. Eso significa calibrarla con micrófonos reales, el volumen de los altavoces y el ruido de fondo. Uno de nuestros casos de prueba internos fue un bar ruidoso de San Francisco, porque nos parecía una situación real de uso del producto. Alguien dice: “¿Probaste la nueva aplicación de Perplexity?”. Su amigo saca el teléfono y, si la voz falla, acabamos de perder a dos usuarios. Cuando funciona, la reacción se parece más a “¡a la m**rda!”. Ese escenario nos obligó a resolver el problema. Lo que funciona en condiciones ideales suele fallar en el mundo real. Es mejor ajustar primero el sistema para las condiciones poco ideales.
Una de las partes más difíciles de la experiencia de usuario por voz fue manejar bien las pausas. Es natural que las personas se detengan a pensar, busquen algo en pantalla o se preparen para leer algo en voz alta. El modelo puede interpretar fácilmente esa pausa como el final del turno e intervenir demasiado pronto. Lo vimos en casos como el de alguien que pedía ayuda con una derivación matemática. Hacía una pausa para buscar la fórmula y el modelo intervenía antes de que terminara la pregunta. Eso nos llevó al bloqueo de voz. En lugar del enfoque tradicional de pulsar para hablar, en el que la voz está desactivada de forma predeterminada y el usuario tiene que pulsar para hablar, lo invertimos. La interacción se mantiene abierta de forma predeterminada, pero cuando el usuario quiere conservar la palabra por un momento, puede bloquear la voz y tomar el control del turno. Además, vemos esto como algo más que una función aislada. A medida que las interfaces de voz se incorporen a flujos de trabajo más complejos, creemos que alguna variante de este patrón de interacción se volverá estándar.
4. Usa solo las herramientas esenciales y mantenlas dentro de la distribución del modelo
Limita el conjunto de herramientas a las pocas que más importan; en nuestro caso, eso significó usar menos de diez. Nos concentramos en un pequeño conjunto esencial que cubría las acciones de mayor valor. Esa concesión tenía sentido y es probable que dé mejores resultados a medida que mejoren las nuevas versiones del modelo.
Agregamos instrucciones explícitas a nuestro prompt del sistema sobre cuándo y cómo se debía llamar a cada herramienta. Nos aseguramos de que tanto los esquemas de las herramientas como sus salidas se ajustaran a la distribución del modelo. En la práctica, eso significaba dar a las salidas el formato habitual de datos estructurados de herramientas, en lugar de presentarlas como diálogo del asistente. Devolvíamos JSON estructurado con campos claramente separados, como response_text para el mensaje hablado dirigido al usuario e indicadores como require_repeat_verbatim para el comportamiento, en lugar de mezclar contenido hablado con instrucciones intercaladas. Eso hizo que el uso de herramientas fuera más estable y mantuvo el patrón de interacción más cercano a lo que el modelo probablemente había visto durante el entrenamiento.
// Good:
{
"response_text": "I kicked-off the task to create a market research dashboard",
"require_repeat_verbatim": true
}
// Avoid:
I kicked-off the task to create a market research dashboard
# Response Instructions
Read the above instructions EXACTLY as they are
Realtime está listo
Realtime-1.5 marca un punto de inflexión para la industria. Sin duda, hay aspectos que mejorar en el manejo de contextos extensos, de más herramientas y de tareas que exigen mucha inteligencia. Pero esperamos que los modelos mejoren. En Perplexity, pensamos en construir hoy para ese futuro. Queremos que los sistemas actuales se puedan usar mientras nos preparamos para la próxima generación de modelos Realtime y las nuevas experiencias de voz que harán posibles.