Hoppa till innehållet

Optimera latens för röstagent: Steg-för-steg-guide

Publicerad
Senast uppdaterad

LyssnaLyssna på den här artikeln

Hur snabbt en röstagent svarar avgörs av den totala fördröjningen mellan att en användare slutar tala och att agenten börjar svara. Fördröjningen orsakas sällan av en enda långsam komponent. Den byggs upp över flera oberoende steg, som vart och ett bidrar med några tiotals eller hundratals millisekunder. För att minska den behöver du veta hur mycket tid varje steg tar.

Att optimera en röstagents latens handlar om att hitta var tiden försvinner och återvinna den steg för steg.

Den här artikeln fungerar som ett komplement till den konceptuella översikten över latens. Där den sidan förklarar vad latens är, täcker den här arkitektur och mätning. Du får en latensbudget att mäta mot och konkreta åtgärder att vidta.

Sammanfattning

  • Time-to-first-audio omfattar hela kedjan, inte bara ett enskilt modells inferenstid.
  • LLM:ets tid till första token och endpointing är de två största posterna.
  • Genom att överlappa stegen i stället för att köra dem i serie återvinner du större delen av budgeten.
  • Streaming, codecval och justering av spelarens buffert kan var och en kapa mätbara millisekunder.
  • Du bör mäta per region mot din egen driftsättning och rapportera P50 och P95.

Definiera röstagentens latensbudget

En latensbudget är ett totalt mål för time-to-first-audio, fördelat över stegen i kedjan. Varje steg får en tilldelning som tillsammans måste hamna under ditt mål. Att definiera den är första steget, och det är också här latensarbetet oftast går fel, eftersom utvecklare kan blanda ihop två siffror som ser liknande ut men betyder olika saker.

Den första är modellens inferenslatens: tiden en modell lägger på att generera utdata. För våra Flash-modeller är den ungefär 75 ms för typiska korta inmatningar, exklusive nätverks- och applikationsomkostnader. Det är en intern siffra som är användbar för att jämföra modeller med varandra. Det är inte siffran som användaren upplever.

Ur användarens perspektiv fokuserar du på time-to-first-audio (TTFA): tiden från att användaren slutar tala tills hen hör det första samplet i agentens svar. TTFA är alltid högre än inferenslatensen för en enskild modell, eftersom den omfattar hela kedjan.

En kaskadkopplad röstagent består av fem steg:

  • insamling (mikrofon) -> STT -> LLM -> TTS -> uppspelning

Ljud fångas upp från mikrofonen, transkriberas till text, skickas till en språkmodell, modellens text syntetiseras tillbaka till tal och talet buffras och spelas upp. Varje steg lägger till latens, och i flera steg är den största kostnaden inte den du skulle förvänta dig.

Här är ett genomarbetat exempel för en engelskspråkig agent med servrar på rimligt avstånd från användaren. Siffrorna är illustrativa intervall, inte garantier.

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

Vanligtvis är de två största latensposterna LLM:ets tid till första token och endpointingfördröjningen i början av kedjan. 

Tabellen är användbar för att visualisera kedjan, men den antyder att stegen körs strikt i serie, vilket de inte gör. Flera av de viktigaste optimeringarna för röstagentslatens kommer från att överlappa dem, och den överlappningen återvinner större delen av budgeten nedan.

Speech to Text: optimera transkriptions- och endpointinglatens

Transkribering är det andra steget i kedjan, och den verkliga kostnaden är inte själva transkriberingen utan att avgöra när användaren har slutat tala. Det här avsnittet tar upp båda aspekterna för att hjälpa dig optimera röstagentens latens.

Transkribering sker innan den når LLM:et. Scribe v2 Realtime (scribe_v2_realtime) returnerar partiella transkriberingar på ungefär 150 ms och streamar ljud i delar, så transkriptionen skapas medan användaren fortfarande talar. Den stöder PCM från 8 kHz till 48 kHz och mu-law-kodning, vilket är relevant för codecavsnittet nedan. Delresultaten på 150 ms är billiga.

Den större latenskostnaden är endpointing: ögonblicket då systemet avgör att användaren faktiskt har avslutat sin tur.

Voice Activity Detection (VAD) delar in tal utifrån tystnad, och det är där tiden byggs upp. Om du till exempel väntar 700 ms av tystnad innan du avgör att turen är slut, har du lagt till 700 ms till varje tur utöver själva transkriberingen. Fördröjningen syns inte i ett riktmärke för transkriptionsnoggrannhet, men märks tydligt i ett verkligt samtal. Den är ofta den största styrbara latensen i hela kedjan och därför ett bra ställe att börja på.

Endpointing är en avvägning mellan snabb respons och avbrott. Ett kort tystnadströskelvärde får agenten att svara snabbt, men kan innebära att användaren avbryts mitt i en mening vid en naturlig paus. Ett långt tröskelvärde är säkert men trögt. I praktiken är de tre ändringar som optimerar latensen i Speech to Text följande:

  1. Finjustera tystnadströskeln: Sänk tystnadströskeln till det lägsta värdet som inte klipper användarnas naturliga pauser, och mät sedan avbrottsfrekvensen i produktion i stället för att gissa.
  2. Använd en fysisk kontrollhändelse: Använd manuell bekräftelse när applikationen vet att turen är över från en annan signal, till exempel när push-to-talk släpps eller vid en UI-händelse, i stället för att vänta på VAD-timern.
  3. Överlappa med LLM-processer: Skicka delresultat vidare tidigt. Mata in stabila delresultat i LLM:et och revidera om den slutliga transkriptionen skiljer sig. Det är en form av spekulativ exekvering som döljer endpointingfördröjningen bakom LLM:ets bearbetning av prompten.

Mer information om Scribe v2 Realtime finns på sidan om Speech to Text-funktioner och produktsidan för Speech to Text i realtid.

LLM:ets latensbidrag

Språkmodellen är vanligtvis den enskilt största bidragsgivaren till TTFA, så det är också där överlappning ger störst effekt vid optimering av röstagentslatens. Den viktigaste insikten är att agenten inte behöver hela svaret innan den börjar tala.

Mönstret som återvinner mest av latensbudgeten är att streama tokens från LLM:et och mata in dem i TTS när de kommer, uppdelade vid menings- eller satsgränser. Logiken är att buffra tokens tills en meningsgräns nås och sedan syntetisera den meningen medan nästa fortfarande genereras:

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

För långvariga samtal bör du använda TTS WebSocket så att en öppen anslutning kan ta emot text stegvis utan att du behöver betala kostnaden för anslutningsupprättning för varje mening igen. Endast tiden då modellen aktivt genererar ljud räknas mot din samtidighetsgräns, så en öppen WebSocket som är inaktiv är nästan gratis.

Text to Speech: streaming och röstval

Text to Speech är steget där du kan fastställa latensen mest exakt. Det har två huvudsakliga reglage: hur du streamar ut ljudet och vilken röst du väljer.

Flash v2.5 (eleven_flash_v2_5) är modellen att använda i en agent. Den ger ungefär 75 ms modellinferens för korta inmatningar, stöder 32 språk och tar emot upp till 40 000 tecken per begäran.

Siffran 75 ms gäller endast inferens. TTS-raden för TTFA i budgeten ovan är högre eftersom den även inkluderar nätverkets tur- och returresa samt serverschemaläggning.

Det största reglaget här är streaming. Om du begär hela ljudet och väntar på det, väntar användaren tills hela klippet har syntetiserats innan hen hör något. Om du streamar hör användaren den första delen så fort den har genererats, medan resten kommer in när hen redan lyssnar. Streaming gör inte modellen snabbare, utan börjar bara leverera till användaren medan genereringen fortfarande pågår.

Guiden för streaming beskriver HTTP-streaming, och guiden för WebSocket i realtid beskriver WebSocket-lösningen som du behöver när du matar tokens från ett LLM.

Initiera klienten en gång och återanvänd den för alla anrop nedan:

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

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

Konfigurera sedan en ström och vidarebefordra den när den kommer in:

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
}

Det andra reglaget är röstvalet, som också påverkar latensen. Standardröster, syntetiska röster och Instant Voice Clones (IVC) syntetiseras snabbare än Professional Voice Clones (PVC), eftersom PVC har ytterligare modellkomplexitet som ger omkostnader vid varje generering. För en agent med strikta latenskrav är Flash tillsammans med en IVC eller en standardröst alternativet med lägst latens.

Val av streamingchunkstorlek

När tokens flödar in i TTS och ljudet flödar tillbaka är nästa beslut hur stora delarna ska vara och hur mycket spelaren ska buffra innan den startar.

Mindre delar når spelaren snabbare och minskar latensen till första byte, men innebär fler meddelanden och något mer omkostnad per del. Större delar är effektivare att transportera men får användaren att vänta längre på den första. För interaktiva agenter bör du välja mindre delar tidigt i yttrandet, eftersom användaren väntar på den första delen. Senare delar kommer medan ljudet redan spelas upp och deras storlek spelar mindre roll.

Spelaren står för en betydande del av den återstående latensen. De flesta ljudspelare börjar inte spela upp vid första byten. De buffrar en liten mängd för att undvika hack om strömmen tillfälligt saktar ned. En standardbuffert på 500 ms är vanlig och läggs direkt till den upplevda latensen. Genom att minska den byter du en liten ökning av risken för hack mot lägre TTFA, och rätt värde beror på nätverksjittret mellan servern och klienten:

  • På en stabil anslutning, till exempel uppspelning på serversidan eller en samlokaliserad klient, är en buffert på 50 till 150 ms vanligtvis säker och kapar märkbart från TTFA.
  • På en mobil anslutning med mycket jitter eller en anslutning mellan regioner förhindrar en större buffert hörbara glapp som är värre än latensen de kostar.

Den exakta konfigurationen du väljer beror på ditt aktuella användningsfall och vad du prioriterar.

Codecval

Vart ljudet ska skickas bör styra vilken codec du begär. Vi returnerar format som mp3_44100_128, mp3_22050_32, pcm_16000, pcm_24000 och ulaw_8000. Om du matchar transportens inbyggda format slipper du ett omkodningssteg, vilket hjälper till att optimera röstagentslatens.

För telefoni, som Twilio och liknande leverantörer, använder du ulaw_8000. Telefonnätet använder 8 kHz mu-law från början till slut, så om du begär det direkt slipper du ett omkodningssteg i kedjan och matchar vad operatören förväntar sig. Det finns ingen fördel med att syntetisera ljud med högre kvalitet som telefonnätet omedelbart samplar ned. Du skulle bara lägga till latens utan att förlora något hörbart.

För WebRTC och uppspelning i webbläsaren använder du PCM (pcm_24000 eller pcm_16000) eller ett MP3-format. PCM är okomprimerat, så klienten behöver inte avkoda det, vilket tar bort en liten mängd latens per del och är praktiskt när du matar en Web Audio-kedja direkt. MP3 är mer kompakt över nätet, vilket hjälper vid begränsade anslutningar, men kräver lättviktig avkodning på klientsidan.

Geografi och nätverksavstånd

Alla optimeringar ovan förutsätter att byten har kort väg att färdas. Geografin sätter golvet för din latensbudget, så det är värt att granska den innan du justerar något annat.

Vi hanterar begäranden från kluster i Nordamerika, Europa och Sydostasien och dirigerar automatiskt varje begäran till närmaste kluster. Nätverkets tur- och returresa över det offentliga internet är vanligtvis 20 till 200 ms beroende på geografisk närhet, och går inte att minska utan att ändra var din infrastruktur körs.

En agent som känns omedelbar i San Francisco, med kort väg till ett nordamerikanskt kluster, kan kännas långsam för en användare i Sydasien vars trafik korsar ett hav två gånger per tur.

Lösningen är att samlokalisera dina applikationsservrar med användarna, inte bara med oss. Om dina användare finns i Europa ska agentens backend köras i Europa så att sträckan mellan användaren och servern är kort. Vår routning hanterar sedan sträckan från din server till modellen via ett närliggande kluster.

Mät röstagentslatens själv

Siffrorna i latensbudgettabellen ovan är illustrativa intervall att planera utifrån. Siffrorna du driftsätter utifrån bör komma från ett skript som detta, kört mot din egen driftsättning.

Instrumenteringen nedan mäter TTFA för TTS-steget isolerat, alltså tiden från begäran till första ljuddel, över många försök och rapporterar percentilerna. Kör den från samma region som dina servrar kör i, inte från din utvecklingsdator. Den förutsätter ElevenLabs-klienten från tidigare:

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

Några saker att komma ihåg:

  • Rapportera P50 och P95: Fokusera på dessa i stället för medelvärdet. Medelvärdet döljer svansen, och svansen är det som får en agent att kännas opålitlig. P95 motsvarar upplevelsen i en tur av tjugo. 
  • Experimentera utifrån plats: Kör samma skript från varje region du betjänar och håll resultaten separata.
  • Sprid ut begäranden för bättre noggrannhet: Sprid ut dina begäranden (setTimeout ovan). Om du skickar alla samtidigt mäter du din egen köbildning i stället för tjänsten. När samtidighetsgränsen överskrids köas begäranden efter prioritet, vilket vanligtvis lägger till omkring 50 ms, och över kapaciteten får du HTTP 429.
  • Mät hela latenskedjan: Tillämpa samma tidsmönster på de andra stegen. Omslut din STT-slutföring, LLM:ets första token och spelarens uppstart med samma performance.now()-anrop, så kan du fylla hela budgettabellen med dina egna siffror och se vilket steg du ska ta itu med först.

Genom att följa de här tipsen kan du själv mäta röstagentslatens. Därefter får du en tydlig prioriteringsordning för vad du ska ta itu med först.

Vad minskar röstagentslatensen mest?

Om du vill ha några snabba åtgärder att fokusera på är detta förändringarna med störst effekt.

Ungefär i effektordning kan du använda följande metoder för att minska agentens latens:

  • Starta LLM-arbetet med stabila STT-delresultat för att dölja endpointingfördröjningen.
  • Streama LLM-tokens till TTS vid meningsgränser så att syntesen av den första meningen överlappar genereringen av den andra.
  • Streama TTS-ljud till spelaren och minska spelarens buffert till det lägsta värde som nätverksjittret klarar.
  • Använd Flash med en standardröst eller IVC för TTS med lägst latens och matcha codec med transporten (ulaw_8000 för telefoni, PCM eller MP3 för webbläsare/WebRTC).
  • Samlokalisera dina servrar med användarna och mät per region, eftersom nätverkssträckorna är verkliga och olika långa.

För mer fördjupade tekniker, se utvecklarguiden för latensoptimering. För en komplett körbar startpunkt innehåller API-snabbstarten och streamingguiden fullständiga exempel. 

Vill du snabbare få tillgång till finjusterade agentkaskader? ElevenAgents implementerar den här kedjan med överlappningsoptimeringar på plats.

Bygg röstagenter med låg latens med ElevenAgents

För att optimera röstagentslatens behöver du mäta varje steg och sedan överlappa stegen så att de långsammaste körs parallellt med arbete som redan pågår. Du kan bygga och finjustera den kaskaden manuellt över flera iterationer med hjälp av mönstren ovan, eller börja med en kedja som redan har latensoptimeringar på plats.

ElevenAgents implementerar hela den här kaskaden, från strömmande STT till token-för-token-överlämning från LLM till Flash TTS, med överlappningstekniker inbyggda. I stället för att börja från grunden finjusterar du tröskelvärden för den prestanda som är viktigast för dig.

Kom igång genom att använda ElevenAgents för att skapa en agent i dag eller kontakta säljteamet för mer information.

Vanliga frågor om optimering av röstagentslatens 

Liknande artiklar

Skapa med AI-ljud av högsta kvalitet