Lektion 3 von 5·11 Min Lesezeit

LLM + Voice Pipeline

Die Verbindung von LLMs mit Voice Output ist das Herzstück jedes Voice Agents. Die Herausforderung: Wie schafft man eine Pipeline, die natürlich klingt, schnell reagiert und skaliert? Hier lernen Sie die Architektur und Optimierung der LLM-to-Voice-Pipeline.

LLMs mit Voice Output verbinden

Die Pipeline im Detail

Audio Input ──→ ASR ──→ Text ──→ LLM ──→ Response Text ──→ TTS ──→ Audio Output
   (Nutzer)   (STT)           (Brain)                    (Voice)    (Nutzer)

Naive Implementation (langsam)

// SCHLECHT: Sequentiell — wartet auf komplette LLM-Antwort
const transcript = await elevenlabs.speechToText(audioInput)
const llmResponse = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: transcript }],
})
const audio = await elevenlabs.textToSpeech.convert(voiceId, {
  text: llmResponse.choices[0].message.content,
})
// Gesamtlatenz: 2.000–4.000 ms

Optimierte Implementation (schnell)

// GUT: Streaming — LLM-Tokens direkt an TTS weiterleiten
const transcript = await elevenlabs.speechToText(audioInput)

// LLM Streaming starten
const stream = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: transcript }],
  stream: true,
})

// TTS WebSocket öffnen
const ttsWs = new WebSocket(
  `wss://api.elevenlabs.io/v1/text-to-speech/${voiceId}/stream-input`
)

let buffer = ''
for await (const chunk of stream) {
  const token = chunk.choices[0]?.delta?.content || ''
  buffer += token

  // Satz-Erkennung: Bei Satzende an TTS senden
  if (buffer.match(/[.!?]\s/)) {
    ttsWs.send(JSON.stringify({ text: buffer }))
    buffer = ''
  }
}
// Gesamtlatenz: 500–1.000 ms bis zum ersten Audio

Latenz-Optimierung

Das Latenz-Budget

PhaseZielOptimierung
ASR< 300 msStreaming STT, Voice Activity Detection
LLM TTFT< 500 msModellwahl, Prompt-Caching
TTS< 300 msTurbo-Modell, Streaming
Netzwerk< 100 msRegionale Endpoints, WebSocket
Gesamt< 1.200 msEnd-to-End-Optimierung

Optimierungsstrategien im Detail

1. LLM-Latenz reduzieren:

  • Kleineres Modell: GPT-4o-mini statt GPT-4o (2× schneller)
  • Prompt-Caching: System-Prompt cachen (50 % schneller bei OpenAI)
  • Kürzere Prompts: Jeder Token zählt bei der Latenz
  • Streaming: Tokens sofort weiterleiten, nicht auf Completion warten

2. ASR-Latenz reduzieren:

  • Voice Activity Detection (VAD): Nur bei Sprache transkribieren
  • Streaming STT: Interim-Results nutzen für schnellere Reaktion
  • Endpointing: Erkennen, wann der Nutzer fertig ist

3. TTS-Latenz reduzieren:

  • Turbo-Modell: eleven_turbo_v2_5 statt multilingual_v2
  • Streaming Output: Erste Audio-Bytes sofort abspielen
  • Chunking: Text satzweise an TTS senden

4. Netzwerk-Latenz reduzieren:

  • WebSocket statt REST: Permanente Verbindung, kein Handshake-Overhead
  • Regionale Deployment: Server nahe am Nutzer
  • Connection Pooling: Verbindungen wiederverwenden

Streaming TTS

Sentence-Level Streaming

Die effektivste Strategie: LLM-Output in Sätze aufteilen und jeden Satz sofort an TTS senden:

LLM Token 1: "Ich"
LLM Token 2: "kann"
LLM Token 3: "Ihnen"
LLM Token 4: "helfen."  ← Satzende erkannt!
→ Satz an TTS senden: "Ich kann Ihnen helfen."
→ Audio wird generiert während LLM den nächsten Satz produziert

Satz-Erkennung

function detectSentenceEnd(buffer: string): boolean {
  // Einfache Heuristik
  return /[.!?]\s/.test(buffer) || buffer.length > 200
}

// Erweitert: Auch Komma-Pausen für natürlicheres Sprechen
function detectPausePoint(buffer: string): boolean {
  return /[.!?,;:]\s/.test(buffer) || buffer.length > 150
}

Context-Aware Voice Modulation

Dynamische Stimmanpassung

Der Voice Agent passt seine Stimme an den Kontext an:

KontextVoice Settings
Begrüßungstability: 0.6, style: 0.4 (freundlich, warm)
Technische Erklärungstability: 0.8, style: 0.1 (klar, sachlich)
Entschuldigungstability: 0.7, style: 0.3 (empathisch)
Verabschiedungstability: 0.5, style: 0.5 (warm, persönlich)

Implementation

function getVoiceSettings(context: ConversationContext) {
  if (context.intent === 'complaint') {
    return { stability: 0.7, similarity_boost: 0.8, style: 0.3 }
  }
  if (context.intent === 'technical_support') {
    return { stability: 0.8, similarity_boost: 0.8, style: 0.1 }
  }
  // Default: freundlich und natürlich
  return { stability: 0.5, similarity_boost: 0.75, style: 0.3 }
}

Geschwindigkeitsanpassung

  • Komplexe Info: Langsamer sprechen (prosody rate: 0.9)
  • Bestätigungen: Normales Tempo (rate: 1.0)
  • Zusammenfassungen: Leicht schneller (rate: 1.1)
  • Dringende Nachrichten: Etwas schneller (rate: 1.15)

Praxis-Tipp: Die wichtigste Optimierung ist Sentence-Level Streaming. Ohne Streaming wartet der Nutzer 2–4 Sekunden auf eine Antwort — mit Streaming hört er die ersten Worte nach 500–800 ms. Das ist der Unterschied zwischen "fühlt sich wie ein Roboter an" und "fühlt sich wie ein Gespräch an".