r
hi
✅ 1
t
Thanks for reaching out, Aaryan. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Hi — great to hear from you. How can I help today? • Do you have a question about LiveKit setup, rooms, SDKs, or an error you’re seeing? • If you’re troubleshooting, please share the project ID, room ID, SDK/language, and a brief description of the issue., with interactive elements
r
so I use deepgram for STT now it sends interim, so currently the gap between 2 interims is 1s, so overall on call, just STT itself takes 1.5s or so. anything we can do to optimize this?
t
Thanks — I’m responding to your question about Deepgram interim results and the ~1.5s STT latency. Quick troubleshooting checklist and actions you can try to reduce latency: • Confirm you’re using Deepgram in streaming mode (not batch). Streaming should emit partials frequently—typically 100–250ms, not 1s. • Ensure
enable_partials=True
(or equivalent) so interim transcripts are emitted immediately. • Use a low-latency model (e.g.,
deepgram/nova-3
or
nova-2
) and, if applicable, the LiveKit Deepgram inference integration via WebRTC for sub-250ms STT. • Reduce audio frame/chunk size (use ~20ms frames like WebRTC). Larger chunks cause buffering and longer gaps between partials. • Verify you’re not batching or buffering audio client-side or server-side before sending to Deepgram—push frames as soon as captured. • Check network/transport: packetization, jitter, or a non-persistent connection can add ~100s ms. Use persistent streaming (WebSocket/WebRTC) rather than repeated HTTP requests. • If you’re doing language detection or using a multi-model setup, try specifying the language explicitly (if known) to avoid extra processing delays. • Profile where time is spent: measure time from capture → send → Deepgram partial received → display. That narrows whether delay is audio framing, network, Deepgram config, or post-processing. If you’d like, tell me: • Which Deepgram model and API (WebSocket, WebRTC, REST) you’re using, • Your audio frame/chunk size and sample rate, • Whether you’re using LiveKit’s Deepgram inference plugin or sending audio separately. With that I can give targeted changes or small config snippets. Sources: Sequential Pipeline Architecture for Voice Agents | LiveKit | Voice Agent Architecture: STT, LLM, and TTS Pipelines Explained | LiveKit | Build Your First AI Voice Agent in Python: Complete Tutorial | LiveKit | Build Your First AI Voice Agent in Python: Complete Tutorial | LiveKit | Deepgram STT | LiveKit Documentation, with interactive elements
r
• nova-2-general; API: WebSocket streaming via LiveKit's plugin. • 8k Hz, channels 1, min_endpointing_delay 0.5, max_endpointing_delay 3s, endpointing_ms: 25ms • LiveKit's official Deepgram plugin
t
Thanks — I’m responding to your setup:
nova-2-general
over WebSocket via LiveKit’s Deepgram plugin, 8 kHz mono, and endpointing settings you listed. Targeted suggestions to reduce the ~1.5s interim gap: • Use a higher sample rate if possible. 8 kHz is low and can increase processing latency and partial quality; 16 kHz or 48 kHz reduces model buffering and improves partial emission. • Reduce audio frame/chunk size to ~20ms frames before sending into the stream. Ensure you’re not aggregating multiple frames into larger chunks on client or plugin. • Confirm plugin is configured to stream audio continuously (no internal batching). Send frames immediately as captured. • Set
enable_partials=True
in the plugin config (if not already). • Lower endpointing delay thresholds: ◦
min_endpointing_delay
at 0.5s may cause the system to wait — try reducing to 0.25s or 0.0s while keeping
endpointing_ms
small (25ms is fine). ◦ Keep
max_endpointing_delay
only as high as needed (3s is fine for end-of-speech, but it shouldn’t affect interim frequency). • Verify the WebSocket is a persistent low-latency connection (no reconnects or buffering). Watch for jitter/packet loss in the network. • Ensure you are not doing heavy post-processing before emitting partials to the UI (e.g., filtering or expensive transforms). • If language is known, set it explicitly to avoid extra model overhead. Quick diagnostic checks to pinpoint the bottleneck: 1. Measure time from audio capture → send → Deepgram partial received → UI display. 2. Temporarily switch to 16 kHz and small frames; see if interim gap drops toward 200–300ms. 3. Log whether partials arrive at Deepgram earlier but are delayed by the plugin or app. If you want, I can suggest exact plugin config snippets or show how to measure timestamps for the capture→send→receive path — which would you prefer? , with interactive elements
r
and what about LLM how to reduce its TTFT - I use gemini-2.5-flash from vertex AI prompt lengths (constant system prompt) ranges from 50k to 70k and user prompt of 2k - just text based LLM input output, with STT and TTS
t
Thanks — I’m responding to your question about reducing TTFT for Gemini‑2.5‑flash given very large prompts (50–70k system + ~2k user), alongside STT/TTS. Key points and targeted actions you can take: • Prompt size is the dominant factor. Gemini must encode the whole context before generating, so 50–70k tokens will significantly increase TTFT. The single most effective step is to reduce active prompt length. • Reduce prompt size via: ◦ Summarization/compression of the system prompt (keep essential rules only). ◦ Split responsibilities: move static instructions to external tools or orchestrator logic instead of embedding them verbatim. ◦ Use retrieval (RAG): store the large corpus externally and retrieve only relevant passages per request. • Context window management: ◦ Keep only recent, relevant conversation in the live prompt; summarize or archive older conversation into short summaries or embeddings. ◦ Trim or chunk the system prompt dynamically based on user intent. • Precompute and cache: ◦ Precompute embeddings or preprocessed context for static portions of the system prompt. ◦ Cache outputs for repeated queries or deterministic instructions. • Parallelism & streaming: ◦ Enable streaming so partial tokens appear as soon as generation starts (improves perceived latency). ◦ Consider preemptive generation: start LLM work on partial STT transcripts when safe to do so. ◦ Use asynchronous pipelines: start TTS synthesis as tokens stream out rather than waiting for full response. • Model and infra choices: ◦ If you can’t reduce prompt size, consider using a faster/lighter model for quick replies and reserve gemini-2.5‑flash for heavy reasoning. ◦ Host LLM calls in the same region as your app to minimize network RTT to Vertex AI. • Instrumentation to find the real bottleneck: ◦ Measure timestamps for: STT final partial → LLM request sent → LLM first token received (TTFT) → TTS start. ◦ If most time is LLM encoding, focus on prompt reduction. If network/Vertex queuing is the issue, try regional placement or parallel requests. If you’d like, I can: • Suggest a concrete RAG workflow or prompt summarization pattern tailored to your system prompt, • Provide example streaming/preemptive generation flow for LiveKit + Vertex, • Or help design timestamp checks to pinpoint encoding vs. network vs. queuing delays. Which of those would help most next? Sources: examples/voice_agents | livekit/livekit_composite | DeepWiki | Agent speech and audio | LiveKit Documentation | examples/bank-ivr | livekit/livekit_composite | DeepWiki | Understand and Improve Agent Latency | LiveKit | Google Gemini LLM | LiveKit Documentation, with interactive elements
r
I use explicit caching, that is to save costs but prompt caching u said, so is it the same or different?
t
Good question — they’re related but different. • Explicit caching (what you already use) is application-level: you store precomputed outputs (e.g., pre-rendered TTS audio or full LLM responses) and reuse them to save cost and latency. You control it entirely. • Prompt caching is model/provider-level: the LLM or Vertex AI may cache intermediate work (embeddings or compiled prompt state) for identical prompts so subsequent requests cost less and run faster. You don’t control it directly from LiveKit. Practical takeaways: • Keep explicit caching for repeated phrases and TTS—continue doing that. • To help provider-side prompt caching, keep the system prompt stable (avoid tiny per-request changes) and move variable parts into small dynamic segments or retrieval calls (RAG). • Use embeddings/cached retrieval for large static corpora instead of inserting the full 50–70k prompt each time. Would you like: • a short pattern example showing how to split stable system instructions from dynamic context, or • a sample flow for using RAG + cached embeddings with your current Vertex AI setup? Sources: Audio customization | LiveKit Documentation | Google Gemini LLM | LiveKit Documentation | Gemini Live API plugin | LiveKit Documentation, with interactive elements