TL;DR: On the Live API with gemini-3.1-flash-live-preview, at low temperature (especially temperature=0.0) the model often finishes speaking its actual response, then keeps emitting 10–40 seconds of near-silent audio as modelTurn parts before turnComplete fires. To the user this is a long dead pause (“the model went dead”). It is stochastic and it disappears at temperature ≥ 0.5. Reproducible in a minimal setup.
Environment
- Model:
gemini-3.1-flash-live-preview response_modalities: ["AUDIO"],thinkingLevel: medium, native audio out (voice Sulafat)google-genaiPython SDK; raw-WebSocket behaviour is identical
Symptom / wire behaviour
On an affected turn:
- The model streams its speech (e.g. ~2s: “That’s ‘eye.’ How do you say ‘hand’?”), bursted faster than real time.
generationCompletefires early.- It keeps sending
serverContent.modelTurnaudio parts that are near-silent comfort noise (~−55 dBFS), totalling 10–40s. turnCompleteonly fires after the full virtual playback of that audio (turnComplete_time ≈ total_generated_audio_seconds), leaving a long silent gap after the real speech ends.- On a minority of affected turns the speech itself truncates mid-sentence (e.g. “Correct! How do you say” → stops), then the tail + delayed
turnComplete.
The tail is billed as output audio tokens (responseTokensDetails: AUDIO), so a ~2s answer can cost the tokens of a ~40s response.
The key finding — temperature dependence
Two-part “confirm + ask next” turn, everything else fixed, interleaved runs:
temperature turns with the tail
----------- -------------------
0.0 ~6–7 of 8 (+ occasional mid-sentence truncation)
0.3 ~3 of 7 (transitional)
0.5 0 of 7 (clean, turnComplete ~2–3s)
0.7 0 of 7 (clean)
1.0 0 of 7 (clean)
Small n per cell and a single bench, but the separation is stark and monotonic. Knee ≈ 0.4–0.5.
Determinism note
At temperature=0.0, identical input produces the byte-identical transcript, yet the tail length varies from ~1s to ~40s across runs. So token generation is deterministic while the tail / turn-completion is not — the non-determinism appears to live in the audio/turn-completion path, not token sampling.
Ruled out (no effect on the tail)
- System-prompt wording — an explicit “don’t pad with silence, end your turn immediately” instruction did nothing.
- Streaming vs not streaming input audio.
clientContentvsrealtimeInputfor the input.- Automatic VAD on vs off.
thinkingLevelminimal vs medium (medium helped somewhat but did not fix it).
Only turn structure (single-act turns tail far less than two-part “statement + question” turns) and temperature move it.
Minimal repro (needs only an API key)
import asyncio, time
from google import genai
from google.genai import types
MODEL = "gemini-3.1-flash-live-preview"
SYS = ("You are a Ukrainian tutor doing vocab recall. The student says a word; "
"confirm it briefly, then ask them the next word. Keep turns short.")
async def one(temp):
client = genai.Client()
cfg = types.LiveConnectConfig(
response_modalities=["AUDIO"], temperature=temp, system_instruction=SYS,
output_audio_transcription=types.AudioTranscriptionConfig(),
thinking_config=types.ThinkingConfig(thinking_level="medium"))
async with client.aio.live.connect(model=MODEL, config=cfg) as s:
await s.send_client_content(
turns=[types.Content(role="user", parts=[types.Part(text="кіт")])],
turn_complete=True)
t0, audio = time.monotonic(), 0
async for m in s.receive():
sc = m.server_content
if sc and sc.model_turn:
for p in (sc.model_turn.parts or []):
if p.inline_data and p.inline_data.data:
audio += len(p.inline_data.data)
if sc and sc.turn_complete:
print(f"temp={temp}: turnComplete after {time.monotonic()-t0:4.1f}s, "
f"{audio/2/24000:4.1f}s audio generated")
return
for t in (0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0):
asyncio.run(one(t))
Expected: several temp=0.0 runs print turnComplete after ~15–40s, ~15–40s audio generated for a ~2s answer; temp=1.0 runs print ~2–3s.
Questions for the team
- Is this a known issue? Is the post-
generationComplete“comfort noise until virtual playback finishes” behaviour intended? - Why is it so strongly temperature-dependent? We’d like
temperature=0for deterministic tool-calling, but it triggers this reliably. - Is there a supported way to suppress the tail at low temperature, or to have
generationCompletebe treated as end-of-turn rather than waiting out the virtual playback?