Aller au contenu

Optimisation de la latence des agents vocaux : guide étape par étape

Publié
Dernière mise à jour

ÉcouterÉcouter cet article

La réactivité d’un agent vocal dépend du délai total entre le moment où l’utilisateur finit de parler et celui où l’agent commence à répondre. Ce délai provient rarement d’un seul composant lent. Il s’accumule sur plusieurs étapes indépendantes, chacune ajoutant quelques dizaines ou centaines de millisecondes. Le réduire exige de savoir combien de temps prend chaque étape.

L’optimisation de la latence d’un agent vocal consiste à identifier où ce temps se cache et à le récupérer étape par étape.

Cet article complète la présentation conceptuelle de la latence. Cette dernière explique ce qu’est la latence ; celui-ci traite de l’architecture et de la mesure. Vous disposerez ainsi d’un budget de latence mesurable et d’actions concrètes à mettre en œuvre.

En résumé

  • Le délai avant le premier audio couvre l’ensemble du pipeline, et non le seul temps d’inférence d’un modèle.
  • Le délai avant le premier token du LLM et la détection de fin de parole constituent les deux principaux postes.
  • Faire se chevaucher les étapes, plutôt que de les exécuter en série, permet de récupérer l’essentiel du budget.
  • Le streaming, le choix du codec et l’ajustement du buffer du lecteur permettent chacun de gagner des millisecondes mesurables.
  • Mesurez les résultats par région sur votre propre déploiement, en indiquant les valeurs P50 et P95.

Définir le budget de latence d’un agent vocal

Un budget de latence est un objectif global de délai avant le premier audio, réparti entre les étapes du pipeline. Chaque étape reçoit une enveloppe, dont la somme doit rester sous votre objectif. Le définir est la première étape, et c’est aussi là que le travail sur la latence déraille le plus souvent : les ingénieurs peuvent confondre deux métriques qui se ressemblent, mais dont le sens diffère.

La première est la latence d’inférence du modèle : le temps qu’un modèle consacre à générer une sortie. Pour nos modèles Flash, elle est d’environ 75 ms pour des entrées courtes typiques, hors surcoûts réseau et applicatifs. Il s’agit d’une métrique interne, utile pour comparer les modèles entre eux. Ce n’est pas celle vécue par l’utilisateur.

Du point de vue de l’utilisateur, vous vous intéresserez au délai avant le premier audio (TTFA) : le temps écoulé entre la fin de parole de l’utilisateur et le moment où il entend le premier échantillon de la réponse de l’agent. Le TTFA est toujours supérieur à la latence d’inférence d’un modèle isolé, car il additionne l’ensemble du pipeline.

Un agent vocal en cascade est une chaîne de cinq étapes :

  • capture (micro) -> STT -> LLM -> TTS -> lecture

L’audio est capturé par le microphone, transcrit en texte, envoyé à un modèle de langage, puis le texte du modèle est synthétisé en parole, mise en buffer et lue. Chaque étape ajoute de la latence et, à plusieurs d’entre elles, le coût le plus élevé n’est pas celui que vous imaginez.

Voici un exemple pour un agent anglophone dont les serveurs sont raisonnablement proches de l’utilisateur. Les chiffres sont des fourchettes indicatives, non des garanties.

What it covers
Capture + endpointing
Mic capture, VAD/turn-detection delay before the turn is considered finished
STT finalization
Last partial to committed transcript after end-of-speech
Network (client to your server to our API)
Round-trips across the pipeline
LLM time-to-first-token
Prompt processing until the first usable token
TTS time-to-first-audio
First TTS request until first audio chunk leaves the model
Player buffering
Client-side buffer before playback begins
End-to-end TTFA
The total latency of the end-to-end pipeline
P50
Capture + endpointing
120 ms
STT finalization
60 ms
Network (client to your server to our API)
60 ms
LLM time-to-first-token
250 ms
TTS time-to-first-audio
110 ms
Player buffering
80 ms
End-to-end TTFA
~680 ms
P95
Capture + endpointing
280 ms
STT finalization
150 ms
Network (client to your server to our API)
160 ms
LLM time-to-first-token
600 ms
TTS time-to-first-audio
220 ms
Player buffering
150 ms
End-to-end TTFA
~1560 ms

En général, les deux principaux postes de latence sont le délai avant le premier token du LLM et le délai de détection de fin de parole au début de la chaîne. 

Le tableau permet de visualiser le pipeline, mais il laisse entendre que les étapes s’exécutent strictement en série, ce qui n’est pas le cas. Plusieurs des optimisations les plus importantes de la latence d’un agent vocal reposent sur leur chevauchement ; c’est là que se récupère l’essentiel du budget ci-dessous.

Speech to Text : optimiser la latence de transcription et de détection de fin de parole

La transcription est la deuxième étape du pipeline. Son vrai coût ne réside pas dans la transcription elle-même, mais dans la détermination du moment où l’utilisateur a fini de parler. Cette section couvre ces deux aspects afin de vous aider à optimiser la latence de votre agent vocal.

La transcription intervient avant que l’audio n’atteigne le LLM. Scribe v2 Realtime (scribe_v2_realtime) renvoie des transcriptions partielles en environ 150 ms et traite l’audio en chunks ; la transcription se construit donc pendant que l’utilisateur parle encore. Il prend en charge le PCM de 8 kHz à 48 kHz et l’encodage mu-law, ce qui importe pour la section sur les codecs ci-dessous. Les résultats partiels à 150 ms sont peu coûteux.

Le coût de latence le plus important est la détection de fin de parole : le moment où votre système décide que l’utilisateur a réellement terminé son tour de parole.

La détection d’activité vocale (VAD) segmente la parole en fonction des silences, et c’est là que le temps s’accumule. Si vous attendez, par exemple, 700 ms de silence avant de déclarer le tour terminé, vous ajoutez 700 ms à chaque tour, en plus de la transcription elle-même. Ce délai est invisible dans un benchmark de précision de transcription, mais très présent dans une conversation réelle. C’est souvent la latence contrôlable la plus importante de tout le pipeline ; puisqu’elle est contrôlable, c’est un bon point de départ.

La détection de fin de parole implique un compromis entre réactivité et interruption. Un seuil de silence court permet à l’agent de répondre vite, mais risque de couper l’utilisateur au milieu d’une phrase lors d’une pause naturelle. Un seuil long est plus sûr, mais plus lent. En pratique, les trois changements qui optimisent la latence du speech to text sont :

  1. Ajustez finement le seuil de silence : réduisez-le à la plus petite valeur qui ne tronque pas les pauses naturelles de vos utilisateurs, puis mesurez le taux d’interruption en production plutôt que de l’estimer.
  2. Intégrez un événement de contrôle physique : utilisez une validation manuelle lorsque votre application sait, grâce à un autre signal, que le tour est terminé (relâchement du push-to-talk, événement d’interface), au lieu d’attendre le minuteur VAD.
  3. Chevauchez les traitements du LLM : transmettez tôt les résultats partiels en aval. Envoyez les partiels stables au LLM et corrigez-les si la transcription finale diffère : une forme d’exécution spéculative qui masque le délai de détection de fin de parole derrière le traitement du prompt par le LLM.

Pour en savoir plus, Scribe v2 Realtime est décrit en détail sur la page des fonctionnalités de speech to text et sur la page produit realtime speech to text.

La contribution du LLM à la latence

Le modèle de langage est généralement le principal contributeur individuel au TTFA. C’est donc aussi là que le chevauchement apporte le plus à l’optimisation de la latence d’un agent vocal. L’idée clé : l’agent n’a pas besoin de disposer de toute la réponse avant de commencer à parler.

La méthode qui récupère le plus de budget de latence consiste à diffuser les tokens du LLM et à les transmettre au TTS dès leur arrivée, découpés aux limites des phrases ou propositions. Mettez les tokens en buffer jusqu’à une fin de phrase, puis synthétisez cette phrase pendant que la suivante est encore générée :

const SENTENCE_END = /(?<=[.!?])\s+/;

async function* speakLlmStream(tokens: AsyncIterable<string>) {
  let buffer = "";
  for await (const token of tokens) {
    buffer += token;
    const parts = buffer.split(SENTENCE_END);
    buffer = parts.pop() ?? ""; // keep the incomplete fragment
    for (const sentence of parts) {
      if (sentence.trim()) yield* synthesize(sentence.trim());
    }
  }
  if (buffer.trim()) yield* synthesize(buffer.trim());
}

async function* synthesize(text: string) {
  const stream = await elevenlabs.textToSpeech.stream("JBFqnCBsd6RMkjVDRZzb", {
    text,
    modelId: "eleven_flash_v2_5",
    outputFormat: "mp3_44100_128",
  });
  yield* stream;
}

Pour les conversations longues, privilégiez le WebSocket TTS afin qu’une connexion ouverte puisse recevoir le texte progressivement, sans devoir réinitialiser la connexion à chaque phrase. Seul le temps où le modèle génère activement de l’audio est comptabilisé dans votre limite de requêtes simultanées ; un WebSocket ouvert mais inactif est donc presque gratuit.

Text to Speech : streaming et choix de voix

Text to Speech est l’étape où vous pouvez maîtriser la latence avec le plus de précision. Elle repose sur deux principaux leviers : la manière dont vous diffusez l’audio et la voix choisie.

Flash v2.5 (eleven_flash_v2_5) est le modèle à utiliser dans un agent. Il offre environ 75 ms d’inférence pour des entrées courtes, prend en charge 32 langues et accepte jusqu’à 40 000 caractères par requête.

Les 75 ms ne concernent que l’inférence. La ligne TTFA du TTS dans le budget ci-dessus est plus élevée, car elle ajoute l’aller-retour réseau et la planification serveur à l’inférence.

Le streaming est ici le levier le plus important. Si vous demandez l’audio complet et attendez sa réception, l’utilisateur attend que tout le clip soit synthétisé avant d’entendre quoi que ce soit. Avec le streaming, il entend le premier chunk dès sa génération, tandis que le reste arrive alors qu’il écoute déjà. Le streaming n’accélère pas le modèle ; il commence simplement à transmettre l’audio à l’utilisateur pendant que la génération se poursuit.

Le guide pratique du streaming couvre le streaming HTTP, et le guide WebSocket en temps réel couvre la voie WebSocket à privilégier lorsque vous alimentez le TTS avec les tokens d’un LLM.

Initialisez le client une seule fois et réutilisez-le pour tous les appels ci-dessous :

import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient({ apiKey: process.env.ELEVENLABS_API_KEY });

Configurez ensuite un stream et transmettez-le à mesure de son arrivée :

const stream = await elevenlabs.textToSpeech.stream("JBFqnCBsd6RMkjVDRZzb", {
  text: "Your call is connected. How can I help today?",
  modelId: "eleven_flash_v2_5",
  outputFormat: "mp3_44100_128",
});

for await (const chunk of stream) {
  // forward each chunk to your audio sink as it arrives
}

L’autre levier est le choix de la voix, qui a lui aussi un coût de latence. Les voix par défaut, les voix synthétiques et les Instant Voice Clones (IVC) se synthétisent plus vite que les Professional Voice Clones (PVC), car ces derniers impliquent une complexité de modèle supplémentaire qui ajoute un surcoût à chaque génération. Pour un agent soumis à des exigences strictes de latence, la combinaison de Flash avec un IVC ou une voix par défaut offre la latence la plus faible.

Choisir la taille des chunks en streaming

Une fois les tokens envoyés au TTS et l’audio renvoyé, la décision suivante porte sur la taille des segments et sur le volume mis en buffer par le lecteur avant son démarrage.

Les chunks plus petits atteignent le lecteur plus tôt et réduisent la latence avant le premier octet, au prix d’un plus grand nombre de messages et d’un léger surcoût par chunk. Les chunks plus grands sont plus efficaces à transporter, mais font attendre davantage l’utilisateur avant le premier. Pour les agents interactifs, privilégiez les petits chunks au début de l’énoncé : c’est le premier que l’utilisateur attend. Les suivants arrivent alors que l’audio est déjà lu, et leur taille importe moins.

Le lecteur représente une part importante de la latence restante. La plupart des lecteurs audio ne démarrent pas la lecture dès le premier octet. Ils mettent une petite quantité d’audio en buffer afin d’éviter les saccades si le stream ralentit brièvement. Un buffer par défaut de 500 ms est courant et s’ajoute directement à la latence perçue. Le réduire diminue le TTFA, en échange d’un risque légèrement accru de saccades. La valeur appropriée dépend de la gigue réseau entre votre serveur et le client :

  • Sur une connexion stable (lecture côté serveur, client colocalisé), un buffer de 50 à 150 ms est généralement sûr et réduit sensiblement le TTFA.
  • Sur une connexion mobile instable ou interrégionale, un buffer plus important évite des coupures audibles, plus gênantes que la latence qu’il ajoute.

La configuration exacte dépend de votre cas d’usage actif et de vos priorités.

Choix des codecs

La destination de l’audio doit déterminer le codec demandé. Nous renvoyons notamment les formats mp3_44100_128, mp3_22050_32, pcm_16000, pcm_24000 et ulaw_8000. Adapter le format natif du transport élimine une étape de transcodage et contribue à optimiser la latence de l’agent vocal.

Pour la téléphonie et les fournisseurs similaires, utilisez ulaw_8000. Le réseau téléphonique utilise le mu-law à 8 kHz de bout en bout : le demander directement évite une étape de transcodage dans votre pipeline et correspond aux attentes de l’opérateur. Il n’est pas utile de synthétiser un audio de meilleure fidélité que le réseau téléphonique sous-échantillonnera immédiatement ; vous ajouteriez seulement de la latence sans perte audible.

Pour WebRTC et la lecture dans un navigateur, utilisez le PCM (pcm_24000 ou pcm_16000) ou un format MP3. Le PCM n’est pas compressé : le client n’a donc aucune étape de décodage, ce qui supprime une faible latence par chunk et s’avère pratique lorsque vous alimentez directement un pipeline Web Audio. Le MP3 est plus compact sur le réseau, ce qui aide sur les connexions limitées, au prix d’un léger décodage côté client.

Géographie et distances réseau

Toutes les optimisations ci-dessus supposent que les octets ont peu de distance à parcourir. La géographie fixe le plancher de votre budget de latence ; il vaut donc la peine de l’examiner avant tout autre réglage.

Nous traitons les requêtes depuis des clusters en Amérique du Nord, en Europe et en Asie du Sud-Est, et acheminons automatiquement chaque requête vers le cluster le plus proche. L’aller-retour réseau sur Internet est généralement de 20 à 200 ms selon la proximité géographique, et il ne peut être réduit sans changer l’emplacement de votre infrastructure.

Un agent qui semble instantané à San Francisco, à faible distance d’un cluster nord-américain, peut sembler lent à un utilisateur d’Asie du Sud dont le trafic traverse un océan deux fois par tour.

La solution consiste à colocaliser les serveurs de votre application avec vos utilisateurs, et pas seulement avec nous. Si vos utilisateurs sont en Europe, exécutez le backend de votre agent en Europe afin de raccourcir le trajet entre l’utilisateur et votre serveur ; notre routage gérera ensuite le trajet de votre serveur au modèle depuis un cluster proche.

Mesurer vous-même la latence d’un agent vocal

Les chiffres du tableau de budget de latence ci-dessus sont des fourchettes indicatives pour planifier. Les chiffres sur lesquels vous vous engagez doivent provenir d’un script comme celui-ci, exécuté sur votre propre déploiement.

L’instrumentation ci-dessous mesure le TTFA de l’étape TTS isolée, soit le temps entre la requête et le premier chunk audio, sur de nombreux essais, puis indique les percentiles. Exécutez-la depuis la même région que vos serveurs, et non depuis votre machine de développement. Elle suppose le client elevenlabs utilisé plus haut :

const VOICE_ID = "JBFqnCBsd6RMkjVDRZzb";
const TEXT = "Thanks for waiting. I have pulled up your account and I can help with that now.";
const TRIALS = 50;

async function measureTtfa(): Promise<number | null> {
  const start = performance.now();
  const stream = await elevenlabs.textToSpeech.stream(VOICE_ID, {
    text: TEXT,
    modelId: "eleven_flash_v2_5",
    outputFormat: "mp3_44100_128",
  });
  for await (const _chunk of stream) {
    return performance.now() - start; // first chunk -> stop the clock
  }
  return null;
}

function percentile(values: number[], p: number): number {
  const v = [...values].sort((a, b) => a - b);
  const k = (v.length - 1) * (p / 100);
  const lo = Math.floor(k);
  const hi = Math.min(lo + 1, v.length - 1);
  return v[lo] + (v[hi] - v[lo]) * (k - lo);
}

const samples: number[] = [];
for (let i = 0; i < TRIALS; i++) {
  const ttfa = await measureTtfa();
  if (ttfa !== null) samples.push(ttfa);
  await new Promise((r) => setTimeout(r, 300)); // space requests, don't measure your own queueing
}

console.log(`trials: ${samples.length}`);
console.log(`P50:    ${percentile(samples, 50).toFixed(0)} ms`);
console.log(`P95:    ${percentile(samples, 95).toFixed(0)} ms`);

Quelques points à retenir :

  • Indiquez P50 et P95 : privilégiez ces métriques à la moyenne. La moyenne masque la traîne, et c’est elle qui donne l’impression qu’un agent n’est pas fiable. La valeur P95 représente l’expérience d’un tour sur vingt. 
  • Tests par emplacement : exécutez le même script depuis chaque région desservie et conservez les résultats séparément.
  • Espacez les requêtes pour plus de précision : espacez vos requêtes (avec le setTimeout ci-dessus). Si vous les lancez toutes en même temps, vous mesurez votre propre file d’attente plutôt que le service. Lorsque la limite de requêtes simultanées est dépassée, les requêtes sont mises en file selon leur priorité, ce qui ajoute généralement environ 50 ms ; au-delà de la capacité, vous recevez une réponse HTTP 429.
  • Mesurez toute la chaîne de latence : étendez le même modèle de mesure aux autres étapes. Encadrez votre finalisation STT, le premier token de votre LLM et le démarrage de votre lecteur dans les mêmes bornes performance.now(). Vous pourrez ainsi renseigner le tableau de budget complet avec vos propres chiffres et identifier l’étape à traiter en premier.

En appliquant ces conseils, vous pourrez mesurer vous-même la latence d’un agent vocal. Vous disposerez alors d’un ordre clair de priorités à traiter.

Qu’est-ce qui réduit le plus la latence d’un agent vocal ?

Si vous cherchez des actions rapides à prioriser, voici les changements les plus efficaces.

Approximativement par ordre d’impact, vous pouvez réduire la latence de l’agent avec les méthodes suivantes :

  • Lancez le traitement du LLM sur des résultats partiels STT stables afin de masquer le délai de détection de fin de parole.
  • Diffusez les tokens du LLM vers le TTS aux limites des phrases, afin que la synthèse de la première phrase chevauche la génération de la seconde.
  • Diffusez l’audio TTS vers le lecteur et réduisez son buffer à la plus petite valeur tolérée par votre gigue réseau.
  • Utilisez Flash avec une voix par défaut ou un IVC pour le TTS le moins latant, et adaptez le codec au transport (ulaw_8000 pour la téléphonie, PCM ou MP3 pour le navigateur/WebRTC).
  • Colocalisez vos serveurs avec vos utilisateurs et mesurez par région, car les trajets réseau sont réels et inégaux.

Pour des techniques plus spécifiques, consultez le guide pratique pour développeurs sur l’optimisation de la latence. Pour un point de départ complet et exécutable, le quickstart API et le guide pratique du streaming proposent des exemples complets. 

Vous souhaitez accéder plus rapidement à des cascades d’agents affinées ? ElevenAgents met en œuvre ce pipeline avec des optimisations de chevauchement déjà intégrées.

Créez des agents vocaux à faible latence avec ElevenAgents

L’optimisation de la latence d’un agent vocal exige de mesurer chaque étape, puis de les faire se chevaucher afin que les plus lentes s’exécutent pendant qu’un autre traitement est déjà en cours. Vous pouvez construire et ajuster cette cascade manuellement en plusieurs itérations, en vous appuyant sur les méthodes ci-dessus, ou partir d’un pipeline qui intègre déjà des optimisations de latence.

ElevenAgents met en œuvre cette cascade complète, du streaming STT au transfert token par token vers le LLM, puis au TTS Flash, avec des techniques de chevauchement déjà intégrées. Plutôt que de partir de zéro, vous ajusterez les seuils selon les performances qui comptent le plus pour vous.

Commencez avec ElevenAgents pour créer un agent dès aujourd’hui ou contacter l’équipe commerciale pour en savoir plus.

FAQ sur l’optimisation de la latence des agents vocaux 

Articles similaires

Créez avec l'audio IA de la plus haute qualité