Presentiamo Eleven v4Scopri Eleven v4, il nostro modello più espressivo di sempre.

Vai al contenuto

Ottimizzazione della latenza degli agenti vocali: guida passo passo

Pubblicato
Ultimo aggiornamento

AscoltaAscolta questo articolo

La reattività di un agente vocale è determinata dal ritardo totale tra il momento in cui un utente finisce di parlare e quello in cui l'agente inizia a rispondere. Raramente questo ritardo è causato da un singolo componente lento. Si accumula in diverse fasi indipendenti, ognuna delle quali aggiunge alcune decine o centinaia di millisecondi; per ridurlo, devi sapere quanto tempo richiede ogni fase.

Ottimizzare la latenza di un agente vocale significa individuare dove si nasconde questo tempo e recuperarlo fase dopo fase.

Questo articolo integra la panoramica concettuale sulla latenza. Quella pagina spiega cos'è la latenza, mentre questa tratta architettura e misurazione: al termine avrai un budget di latenza con cui confrontarti e una serie di azioni concrete da intraprendere.

In sintesi

  • Il time-to-first-audio rappresenta l'intera pipeline, non il tempo di inferenza di un singolo modello.
  • Il time-to-first-token dell'LLM e l'endpointing sono le due voci principali.
  • Sovrapponendo le fasi, anziché eseguirle in serie, recuperi gran parte del budget.
  • Streaming, scelta del codec e regolazione del buffer del player riducono ciascuno millisecondi misurabili.
  • Misura per regione sulla tua infrastruttura e riporta P50 e P95.

Definire il budget di latenza di un agente vocale

Un budget di latenza è un obiettivo totale di time-to-first-audio stabilito tra le fasi della pipeline, assegnando a ciascuna un margine che, sommato agli altri, deve restare sotto il tuo obiettivo. Definirlo è il primo passo ed è anche il punto in cui il lavoro sulla latenza più spesso va storto, perché gli ingegneri possono confondere due valori simili ma con significati diversi.

Il primo è la latenza di inferenza del modello: il tempo che un modello impiega a generare l'output. Per i nostri modelli Flash è di circa 75 ms per input brevi tipici, esclusi overhead di rete e dell'applicazione. È un valore interno, utile per confrontare un modello con un altro. Non è il valore percepito dall'utente.

Dal punto di vista dell'utente, devi concentrarti sul time-to-first-audio (TTFA): il tempo trascorso da quando l'utente smette di parlare a quando sente il primo campione della risposta dell'agente. Il TTFA è sempre maggiore della latenza di inferenza di qualsiasi singolo modello, perché somma l'intera pipeline.

Un agente vocale a cascata è una catena di cinque fasi:

  • acquisizione (microfono) -> STT -> LLM -> TTS -> riproduzione

L'audio viene acquisito dal microfono, trascritto in testo, inviato a un modello linguistico, quindi il testo del modello viene sintetizzato nuovamente in parlato, che viene memorizzato nel buffer e riprodotto. Ogni fase aggiunge latenza e, in varie fasi, il costo maggiore non è quello che ti aspetteresti.

Ecco un esempio pratico per un agente in lingua inglese, con server ragionevolmente vicini all'utente. I numeri sono intervalli indicativi, non garanzie.

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

In genere, le due voci di latenza più rilevanti sono il time-to-first-token dell'LLM e il ritardo di endpointing all'inizio della catena. 

La tabella è utile per visualizzare la pipeline, ma suggerisce che le fasi vengano eseguite rigorosamente in serie, cosa che non accade. Molte delle più importanti ottimizzazioni della latenza degli agenti vocali derivano dalla loro sovrapposizione, ed è proprio così che si recupera gran parte del budget riportato sotto.

Speech to Text: ottimizzazione della latenza di trascrizione ed endpointing

La trascrizione è la seconda fase della pipeline e il suo costo effettivo non è la trascrizione in sé, ma decidere quando l'utente ha smesso di parlare. Questa sezione tratta entrambi gli aspetti per aiutarti a ottimizzare la latenza dell'agente vocale.

La trascrizione avviene prima di raggiungere l'LLM. Scribe v2 Realtime (scribe_v2_realtime) restituisce trascrizioni parziali in circa 150 ms e trasmette chunk audio in streaming, quindi la trascrizione viene generata mentre l'utente sta ancora parlando. Supporta PCM da 8 kHz a 48 kHz e la codifica mu-law, aspetti rilevanti per la sezione sui codec qui sotto. Le parziali da 150 ms hanno un costo contenuto.

Il costo di latenza maggiore è l'endpointing: il momento in cui il sistema decide che l'utente ha effettivamente concluso il proprio turno.

Rilevamento dell'attività vocale (VAD) segmenta il parlato in base ai silenzi, ed è qui che il tempo si accumula. Se aspetti, ad esempio, 700 ms di silenzio prima di dichiarare concluso il turno, aggiungi 700 ms a ogni turno, oltre al tempo della trascrizione stessa. Questo ritardo è invisibile in un benchmark sull'accuratezza della trascrizione, ma è molto evidente in una conversazione reale. Spesso è la maggiore latenza controllabile dell'intera pipeline e, proprio perché è controllabile, è un buon punto da cui iniziare.

L'endpointing è un compromesso tra reattività e interruzioni. Una soglia di silenzio breve fa rispondere rapidamente l'agente, ma rischia di interrompere l'utente a metà frase durante una pausa naturale. Una soglia lunga è sicura ma lenta. In pratica, le tre modifiche che ottimizzano la latenza nello Speech to Text sono:

  1. Regola con precisione la soglia di silenzio: Riduci la soglia di silenzio al valore minimo che non tronchi le pause naturali degli utenti, poi misura il tasso di interruzioni in produzione anziché fare ipotesi.
  2. Integra un evento di controllo fisico: usa il controllo di commit manuale quando l'applicazione sa, da un altro segnale, che il turno è terminato (il rilascio del push-to-talk o un evento dell'interfaccia utente), anziché attendere il timer VAD.
  3. Sovrapponi l'elaborazione dell'LLM: inoltra presto le trascrizioni parziali nelle fasi successive. Fornisci le parziali stabili all'LLM e correggi se la trascrizione finale differisce: una forma di esecuzione speculativa che nasconde il ritardo di endpointing dietro l'elaborazione del prompt dell'LLM.

Per maggiori informazioni, Scribe v2 Realtime è descritto più nel dettaglio nella pagina sulle funzionalità di Speech to Text e nella pagina del prodotto Speech to Text in tempo reale.

Il contributo dell'LLM alla latenza

Il modello linguistico è di solito il maggiore contributore singolo al TTFA, quindi è anche dove la sovrapposizione offre i vantaggi maggiori nell'ottimizzazione della latenza degli agenti vocali. L'aspetto fondamentale è che l'agente non ha bisogno dell'intera risposta prima di iniziare a parlare.

Il modello che recupera la maggior parte del budget di latenza consiste nel trasmettere in streaming i token dell'LLM e inviarli al TTS man mano che arrivano, suddividendoli ai confini di frasi o proposizioni. La logica è memorizzare i token nel buffer fino alla fine di una frase, quindi sintetizzare quella frase mentre viene ancora generata la successiva:

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;
}

Per le conversazioni di lunga durata, preferisci il WebSocket TTS affinché una connessione aperta possa ricevere testo in modo incrementale senza dover sostenere nuovamente l'inizializzazione della connessione a ogni frase. Solo il tempo in cui il modello sta generando attivamente audio conta ai fini del limite di concorrenza, quindi un WebSocket aperto ma inattivo è quasi gratuito.

Text to Speech: streaming e scelta della voce

Text to Speech è la fase in cui puoi definire la latenza con maggiore precisione. Ha due leve principali: come trasmetti l'audio in streaming e quale voce scegli.

Flash v2.5 (eleven_flash_v2_5) è il modello da usare in un agente. Offre circa 75 ms di inferenza del modello per input brevi, supporta 32 lingue e accetta fino a 40.000 caratteri per richiesta.

Il valore di 75 ms riguarda solo l'inferenza. La voce TTFA del TTS nel budget sopra è maggiore perché, oltre all'inferenza, aggiunge il round-trip di rete e la pianificazione del server.

La leva più importante qui è lo streaming. Se richiedi l'audio completo e lo aspetti, l'utente deve attendere che l'intera clip venga sintetizzata prima di sentire qualcosa. Con lo streaming, l'utente sente il primo chunk non appena viene generato, mentre il resto arriva quando sta già ascoltando. Lo streaming non rende il modello più veloce: inizia semplicemente a inviare l'output all'utente mentre il modello sta ancora generando.

La guida pratica sullo streaming tratta lo streaming HTTP, mentre la guida al WebSocket in tempo reale tratta il percorso WebSocket che ti servirà per inviare token da un LLM.

Inizializza il client una sola volta e riutilizzalo per ogni chiamata seguente:

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

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

Poi configura uno stream e inoltralo man mano che arriva:

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'altra leva è la scelta della voce, che comporta anch'essa un costo di latenza. Le voci predefinite, le voci sintetiche e le Clonazioni Vocali Istantanee (IVC) sintetizzano più rapidamente delle Clonazioni Vocali Professionali (PVC), perché le PVC hanno una complessità aggiuntiva del modello che aumenta l'overhead per ogni generazione. Per un agente con requisiti di latenza rigorosi, Flash combinato con un'IVC o una voce predefinita è l'opzione con la minore latenza.

Scelta della dimensione dei chunk in streaming

Con i token che confluiscono nel TTS e l'audio che torna indietro, la decisione successiva riguarda la dimensione dei segmenti e quanto il player deve memorizzare nel buffer prima di avviarsi.

I chunk più piccoli raggiungono prima il player, riducendo la latenza del primo byte, a fronte di più messaggi e di un overhead leggermente maggiore per chunk. I chunk più grandi sono più efficienti da trasportare, ma fanno attendere più a lungo l'utente per il primo. Per gli agenti interattivi, privilegia chunk più piccoli all'inizio dell'enunciato, perché è il primo chunk quello che l'utente sta aspettando; i successivi arrivano mentre l'audio è già in riproduzione e la loro dimensione conta meno.

Il player rappresenta una quota significativa della latenza rimanente. La maggior parte dei player audio non avvia la riproduzione al primo byte. Memorizza una piccola quantità di audio nel buffer per evitare scatti se lo stream rallenta brevemente. Un buffer predefinito di 500 ms è comune e viene aggiunto direttamente alla latenza percepita. Ridurlo comporta un lieve aumento del rischio di scatti in cambio di un TTFA inferiore; il valore corretto dipende dal jitter di rete tra il server e il client:

  • Su una connessione stabile (riproduzione lato server o client co-localizzato), un buffer da 50 a 150 ms è di solito sicuro e riduce sensibilmente il TTFA.
  • Su una connessione mobile instabile o tra regioni diverse, un buffer più ampio evita interruzioni udibili, peggiori della latenza che comportano.

La configurazione esatta da scegliere dipende dal tuo caso d'uso attivo e da ciò a cui dai priorità.

Scelta dei codec

La destinazione dell'audio dovrebbe determinare il codec da richiedere. Restituiamo formati come mp3_44100_128, mp3_22050_32, pcm_16000, pcm_24000 e ulaw_8000. Far corrispondere il formato nativo del trasporto elimina un passaggio di transcodifica, aiutando a ottimizzare la latenza degli agenti vocali.

Per la telefonia, ad esempio Twilio e provider simili, usa ulaw_8000. La rete telefonica usa mu-law a 8 kHz end-to-end, quindi richiederlo direttamente evita un passaggio di transcodifica nella pipeline e corrisponde a ciò che il gestore si aspetta. Non c'è alcun vantaggio nel sintetizzare audio a fedeltà più elevata che la rete telefonica ridurrà immediatamente di frequenza; aggiungeresti soltanto latenza senza perdere nulla di udibile.

Per WebRTC e la riproduzione nel browser, usa PCM (pcm_24000 o pcm_16000) oppure un formato MP3. Il PCM non è compresso, quindi non richiede una fase di decodifica sul client: elimina una piccola quantità di latenza per chunk ed è pratico quando alimenti direttamente una pipeline Web Audio. L'MP3 è più compatto in transito, utile su connessioni limitate, al costo di una leggera decodifica lato client.

Geografia e distanze di rete

Ogni ottimizzazione descritta sopra presuppone che i byte debbano percorrere una distanza breve. La geografia stabilisce il limite minimo del budget di latenza, quindi vale la pena esaminarla prima di regolare qualsiasi altra cosa.

Forniamo le richieste da cluster in Nord America, Europa e Sud-est asiatico e instradiamo automaticamente ogni richiesta al cluster più vicino. Il round-trip di rete su Internet pubblico è in genere compreso tra 20 e 200 ms, a seconda della vicinanza geografica, e non può essere ridotto senza cambiare dove viene eseguita la tua infrastruttura.

Un agente che sembra immediato a San Francisco, a breve distanza da un cluster nordamericano, può risultare lento per un utente in Asia meridionale, il cui traffico attraversa un oceano due volte per turno.

La soluzione è co-localizzare i server dell'applicazione con gli utenti, non soltanto con noi. Se gli utenti sono in Europa, esegui il backend dell'agente in Europa affinché il tratto tra utente e server sia breve; il nostro instradamento gestirà poi il tratto tra il tuo server e il modello da un cluster vicino.

Misurare autonomamente la latenza degli agenti vocali

I numeri nella tabella del budget di latenza sopra sono intervalli indicativi su cui pianificare. I numeri in base a cui rilasci dovrebbero provenire da uno script come questo, eseguito sulla tua infrastruttura.

La strumentazione seguente misura il TTFA per la sola fase TTS, ovvero il tempo dalla richiesta al primo chunk audio, su numerose prove e riporta i percentili. Eseguila dalla stessa regione in cui operano i server, non dalla macchina di sviluppo. Presuppone il client elevenlabs usato in precedenza:

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`);

Alcuni aspetti da ricordare:

  • Riporta P50 e P95: concentrati su questi valori anziché sulla media. La media nasconde la coda, ed è la coda a far sembrare un agente inaffidabile. P95 rappresenta l'esperienza di un turno su venti. 
  • Sperimentazione basata sulla località: esegui lo stesso script da ogni regione servita e mantieni separati i risultati.
  • Distribuisci le richieste per maggiore accuratezza: distanza le richieste (il setTimeout sopra). Se le invii tutte insieme, misuri l'accodamento generato da te anziché il servizio. Quando viene superato il limite di concorrenza, le richieste vengono messe in coda per priorità, aggiungendo in genere circa 50 ms; oltre la capacità, ricevi HTTP 429.
  • Misura l'intera catena di latenza: estendi lo stesso schema di misurazione alle altre fasi. Inserisci la finalizzazione STT, il primo token dell'LLM e l'avvio del player negli stessi blocchi performance.now(); potrai così compilare la tabella completa del budget con i tuoi numeri e capire quale fase affrontare per prima.

Seguendo questi suggerimenti, potrai misurare autonomamente la latenza degli agenti vocali. Da lì, avrai un percorso chiaro delle priorità da affrontare per prime.

Cosa riduce maggiormente la latenza degli agenti vocali?

Se vuoi alcune azioni rapide su cui concentrarti, queste sono le modifiche con l'impatto maggiore.

All'incirca in ordine di impatto, puoi usare i seguenti metodi per ridurre la latenza dell'agente:

  • Avvia l'elaborazione dell'LLM sulle parziali STT stabili per nascondere il ritardo di endpointing.
  • Trasmetti in streaming i token dell'LLM al TTS ai confini delle frasi, così la sintesi della prima frase si sovrappone alla generazione della seconda.
  • Trasmetti l'audio TTS in streaming al player e riduci il relativo buffer al valore minimo tollerato dal jitter di rete.
  • Usa Flash con una voce predefinita o un'IVC per il TTS con la minore latenza e abbina il codec al trasporto (ulaw_8000 per la telefonia, PCM o MP3 per browser/WebRTC).
  • Co-localizza i server con gli utenti e misura per regione, perché i tratti di rete sono reali e non uguali.

Per tecniche specifiche più approfondite, consulta la guida pratica per sviluppatori sull'ottimizzazione della latenza. Per un punto di partenza completo ed eseguibile, la guida rapida dell'API e la guida pratica sullo streaming includono esempi completi. 

Vuoi accedere più rapidamente a cascate di agenti ottimizzate? ElevenAgents implementa questa pipeline con ottimizzazioni di sovrapposizione già attive.

Crea agenti vocali a bassa latenza con ElevenAgents

L'ottimizzazione della latenza degli agenti vocali richiede di misurare ogni fase e poi sovrapporre le fasi affinché quelle più lente vengano eseguite mentre è già in corso altro lavoro. Puoi creare e regolare manualmente questa cascata in diverse iterazioni, sfruttando i modelli descritti sopra, oppure iniziare da una pipeline che ha già ottimizzazioni di latenza.

ElevenAgents implementa l'intera cascata, dallo STT in streaming al passaggio token per token all'LLM fino al TTS Flash, con tecniche di sovrapposizione già integrate. Anziché partire da zero, regolerai le soglie in base alle prestazioni più importanti per te.

Inizia usando ElevenAgents per creare un agente oggi oppure contatta il team vendite per maggiori informazioni.

Domande frequenti sull'ottimizzazione della latenza degli agenti vocali 

Scritto da

Tadas Petra è Developer Relations Engineer e aiuta gli sviluppatori a creare con la suite di prodotti ElevenLabs. È anche il fondatore di Hungrimind, una piattaforma di formazione per sviluppatori. In passato è stato Lead Developer Advocate in Agora e docente presso Zero To Mastery.

Articoli simili

Crea con l'audio IA della massima qualità