3v324v23 commited on
Commit
ed2a840
·
1 Parent(s): 34529d9

Persist live session receive loop by wrapping session.receive iterator in a while True loop to support multi-turn dialogues

Browse files
Files changed (1) hide show
  1. backend/main.py +32 -25
backend/main.py CHANGED
@@ -323,36 +323,43 @@ async def websocket_live_endpoint(websocket: WebSocket):
323
  ws_log("Client WebSocket disconnected (WebSocketDisconnect).")
324
  except Exception as e:
325
  ws_log(f"[WebSocket Proxy Client -> Gemini] Error: {e}")
 
 
326
 
327
  async def send_to_client():
328
  try:
329
- async for response in session.receive():
330
- server_content = response.server_content
331
- if server_content is not None:
332
- model_turn = server_content.model_turn
333
- if model_turn is not None:
334
- for part in model_turn.parts:
335
- if part.inline_data is not None:
336
- # Stream PCM audio output back to client as Base64
337
- audio_b64 = base64.b64encode(part.inline_data.data).decode('utf-8')
338
- await websocket.send_json({
339
- "type": "audio",
340
- "data": audio_b64
341
- })
342
- elif part.text is not None:
343
- # Stream text transcription back to client
344
- ws_log(f"Streaming text chunk from Gemini: {part.text}")
345
- await websocket.send_json({
346
- "type": "text",
347
- "data": part.text
348
- })
349
-
350
- # Handle turn completion (model finished speaking)
351
- if server_content.turn_complete:
352
- ws_log("Gemini sent turn_complete.")
353
- await websocket.send_json({"type": "turn_complete"})
 
 
 
354
  except Exception as e:
355
  ws_log(f"[WebSocket Proxy Gemini -> Client] Error: {e}")
 
 
356
 
357
  # Run both tasks concurrently and terminate when the first one finishes
358
  done, pending = await asyncio.wait(
 
323
  ws_log("Client WebSocket disconnected (WebSocketDisconnect).")
324
  except Exception as e:
325
  ws_log(f"[WebSocket Proxy Client -> Gemini] Error: {e}")
326
+ finally:
327
+ ws_log("receive_from_client loop exited.")
328
 
329
  async def send_to_client():
330
  try:
331
+ while True:
332
+ async for response in session.receive():
333
+ server_content = response.server_content
334
+ if server_content is not None:
335
+ model_turn = server_content.model_turn
336
+ if model_turn is not None:
337
+ for part in model_turn.parts:
338
+ if part.inline_data is not None:
339
+ # Stream PCM audio output back to client as Base64
340
+ audio_b64 = base64.b64encode(part.inline_data.data).decode('utf-8')
341
+ await websocket.send_json({
342
+ "type": "audio",
343
+ "data": audio_b64
344
+ })
345
+ elif part.text is not None:
346
+ # Stream text transcription back to client
347
+ ws_log(f"Streaming text chunk from Gemini: {part.text}")
348
+ await websocket.send_json({
349
+ "type": "text",
350
+ "data": part.text
351
+ })
352
+
353
+ # Handle turn completion (model finished speaking)
354
+ if server_content.turn_complete:
355
+ ws_log("Gemini sent turn_complete.")
356
+ await websocket.send_json({"type": "turn_complete"})
357
+ # Avoid tight loop if iterator finishes instantly
358
+ await asyncio.sleep(0.1)
359
  except Exception as e:
360
  ws_log(f"[WebSocket Proxy Gemini -> Client] Error: {e}")
361
+ finally:
362
+ ws_log("send_to_client loop exited.")
363
 
364
  # Run both tasks concurrently and terminate when the first one finishes
365
  done, pending = await asyncio.wait(