For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navigation principale
25 mars 2026 Audio

Comment Perplexity a rendu la recherche vocale accessible à des millions de personnes grâce à la Realtime API

Les enseignements tirés de la création de l’agent vocal de Perplexity Computer avec la Realtime API.

Auteurs: Paul Fryzel (Perplexity), Charu Jaiswal (OpenAI)

Comment Perplexity a rendu la recherche vocale accessible à des millions de personnes grâce à la Realtime API

Chez Perplexity, nous tenons à créer des produits particulièrement agréables à utiliser. Pour Perplexity Comet, notre navigateur agentique, et Perplexity Computer, notre puissant assistant numérique polyvalent, cela passait en grande partie par la possibilité de tout faire à la voix. Pouvoir simplement dire ce que l’on veut, déléguer la tâche et la voir s’exécuter procure une satisfaction unique. Nous croyons beaucoup aux interfaces vocales, car elles donnent aux interactions un petit côté magique.

Nous avons utilisé Realtime-1.5 en production pour apporter cette magie aux millions de sessions vocales que Perplexity gère chaque mois. Voir les usages de la voix se développer dans l’interface de Computer a été aussi passionnant qu’instructif. Voici quelques-uns des enseignements surprenants que nous en avons tirés jusqu’ici. Nous vous encourageons à essayer Realtime-1.5 et à partager vous aussi vos découvertes avec nous.

1. Définissez votre stratégie de gestion du contexte

Les contenus longs, notamment les podcasts denses de plusieurs heures, ont été l’un de nos tests les plus révélateurs pour la gestion du contexte. Nous voulions permettre aux utilisateurs d’interroger les transcriptions de podcasts à la voix : ils devaient pouvoir poser directement une question sur ce qui se disait à un moment précis, deux heures et demie après le début, et obtenir une réponse cohérente.

La transcription entière ne tient pas dans le contexte. Nous avons d’abord essayé de l’envoyer par gros blocs. Nous avons vite constaté qu’en cas d’échec, ces mises à jour volumineuses obéissaient à une logique de tout ou rien. Si vous tentez d’envoyer une mise à jour de 10 000 tokens dans une fenêtre qui ne peut plus en accueillir que 5 000, le modèle perd tout l’historique précédent. Les gros blocs étaient donc bien plus risqués : une seule mise à jour trop volumineuse pouvait effacer tout un pan du contexte, au lieu de laisser le système oublier progressivement.

Nous avons donc changé d’approche. Au lieu d’envoyer de grosses mises à jour, nous avons commencé à tout découper en blocs bien plus petits, de 2 000 tokens, puis à les transmettre progressivement. Cela entraîne un surcoût de traitement, mais le comportement est beaucoup plus stable. Lorsqu’une troncature se produit, elle ne retire qu’une petite partie de l’historique au lieu de tout effacer.

Nous avons également découvert une autre subtilité : tous les éléments de contexte ne doivent pas être transmis au modèle de la même manière. Lorsque vous utilisez conversation.item.create pour mettre à jour le contexte, un élément item.type: "message" peut avoir l’un des trois rôles suivants : system, user et assistant. Ces rôles indiquent au modèle le type de message qu’il reçoit. Le rôle system sert à fournir des instructions et à orienter le comportement, user correspond aux entrées de l’utilisateur final et assistant aux sorties générées par le modèle.

Lorsque nous nous trompions dans ce choix, l’interaction devenait étrange. Si trop de contexte arrivait avec le rôle user, le modèle se comportait comme si l’utilisateur énonçait chaque bloc de texte, y compris les extraits de pages web et les commentaires, au lieu de simplement poser une question fondée sur ces contenus. Si trop de contexte arrivait avec le rôle system, l’inverse se produisait. Le modèle ne distinguait plus ce qu’il « savait » par lui-même, ce qui lui avait été fourni comme contexte et ce que l’utilisateur lui demandait à cet instant.

La navigation web en est un bon exemple. Lorsqu’une personne fait défiler une page, nous transmettons continuellement au modèle ce qui s’affiche à l’écran. Si tout cela lui est présenté comme une entrée utilisateur, le modèle commence à se comporter comme si l’utilisateur avait lu chaque paragraphe à voix haute. Ce n’est pas ainsi que l’interaction doit fonctionner. Nous voulons donner l’impression que le système suit la page en arrière-plan, puis répond naturellement lorsque l’utilisateur pose une question. Au final, l’enjeu tenait moins au volume brut de contexte qu’à la bonne interprétation du rôle des messages dans la conversation.

2. Standardisez l’audio dans les différentes interfaces du produit

Perplexity propose plusieurs interfaces, comme Ask, Comet et Computer. Chacune repose sur une pile technologique différente côté client. Swift, TypeScript, Rust et C++ peuvent tous produire des tampons audio natifs différents. Lorsque nous laissions chaque client envoyer son propre format audio brut ou natif à la Realtime API, cela entraînait des écarts de performances.

Nous avons fini par créer un SDK en Rust pour masquer ces différences propres à chaque plateforme et garantir que tous les clients envoient à l’API un flux audio conforme aux mêmes spécifications. En pratique, cela impliquait de traiter le signal audio avant même qu’il n’atteigne le serveur : rééchantillonnage en mono à 48 kHz, conformément à la fréquence privilégiée par le codec Opus et à la fréquence interne de WebRTC, passage par WebRTC APM pour l’annulation d’écho, le contrôle automatique du gain, la réduction du bruit et le filtrage passe-haut, puis encodage pour le transport. Le SDK nous a permis de centraliser la standardisation des constantes audio, le rééchantillonnage et la configuration de toute la chaîne de traitement, au lieu de le faire séparément pour chaque client.

3. Adaptez les réglages aux conditions réelles

Il est important de régler la détection d’activité vocale (VAD) dans l’environnement réel des utilisateurs. Cela signifie la calibrer en tenant compte des microphones utilisés, du volume des haut-parleurs et du bruit de fond. L’un de nos scénarios de test internes se déroulait dans un bar bruyant de San Francisco, car cela nous semblait représentatif d’un véritable moment de découverte du produit. Une personne demande : « Tu as essayé la nouvelle application Perplexity ? » Son ami sort son téléphone et, si la fonction vocale échoue, nous venons de perdre deux utilisateurs. Quand elle fonctionne, la réaction ressemble plutôt à « p**ain, c’est dingue ». Ce scénario nous a imposé une contrainte utile. Ce qui fonctionne dans des conditions idéales échoue souvent dans la réalité. Mieux vaut commencer par régler le système pour les environnements difficiles.

Bien gérer les pauses a été l’un des aspects les plus difficiles de l’expérience vocale. Les gens s’arrêtent naturellement pour réfléchir, afficher quelque chose à l’écran ou se préparer à lire à voix haute. Le modèle peut facilement interpréter cette pause comme la fin du tour de parole et intervenir trop tôt. Nous l’avons constaté, par exemple, lorsqu’une personne demandait de l’aide pour une démonstration mathématique. Elle s’interrompait pour retrouver la formule, et le modèle intervenait avant qu’elle ait terminé sa question. C’est ce qui nous a amenés à créer le verrouillage de la parole. Nous avons inversé l’approche classique de l’appui pour parler, où la voix est désactivée par défaut et où l’utilisateur doit appuyer pour s’exprimer. Par défaut, l’interaction reste ouverte, sans action particulière, mais lorsque l’utilisateur souhaite garder la parole un instant, il peut la verrouiller et conserver son tour. Nous y voyons aussi plus qu’une fonctionnalité ponctuelle. À mesure que les interfaces vocales s’intègrent à des workflows plus complexes, nous pensons qu’une variante de ce mode d’interaction deviendra la norme.

4. Limitez-vous aux outils essentiels et restez dans la distribution d’entraînement du modèle

Limitez l’ensemble d’outils aux quelques-uns qui comptent le plus, soit moins de dix dans notre cas. Nous nous sommes concentrés sur un petit noyau couvrant les actions les plus utiles. Ce compromis était pertinent et devrait devenir plus favorable à mesure que les nouvelles versions du modèle s’améliorent.

Nous avons ajouté à notre prompt système des instructions explicites sur le moment et la manière d’appeler chaque outil. Nous avons veillé à ce que les schémas des outils comme leurs sorties restent dans la distribution d’entraînement du modèle. En pratique, cela revenait à formater les sorties comme des données d’outils structurées ordinaires, plutôt que comme des répliques de l’assistant. Nous renvoyions du JSON structuré avec des champs clairement séparés, comme response_text pour le texte à prononcer à l’utilisateur et des indicateurs tels que require_repeat_verbatim pour le comportement, au lieu de mêler contenu à prononcer et instructions intégrées. Cela a stabilisé l’utilisation des outils et maintenu un mode d’interaction plus proche de ce que le modèle avait probablement rencontré pendant l’entraînement.

// 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 prêt

Realtime-1.5 marque un tournant pour le secteur. Il reste bien sûr des progrès à faire dans la gestion des contextes longs, d’un plus grand nombre d’outils et des tâches qui sollicitent fortement les capacités intellectuelles du modèle. Mais nous nous attendons à ce que les modèles s’améliorent. Chez Perplexity, nous réfléchissons dès aujourd’hui à la manière de construire pour cet avenir. Nous voulons rendre les systèmes actuels utilisables tout en nous préparant à la prochaine génération de modèles Realtime et aux nouvelles expériences vocales qu’ils rendront possibles.