saadpie commited on
Commit
91a7eef
·
verified ·
1 Parent(s): 478d03a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -50
app.py CHANGED
@@ -5,18 +5,18 @@ from google import genai
5
 
6
  app = Quart(__name__)
7
 
8
- # Force v1beta version (Required for the 'live' preview models)
9
  client = genai.Client(http_options={'api_version': 'v1beta'})
10
 
11
- # The exact key from your available_models list; models/gemini-2.5-flash-native-audio-preview-12-2025
12
  MODEL = "models/gemini-2.5-flash-native-audio-preview-12-2025"
13
 
14
  VOICE_MODES = {
15
- 'Zephyr': 'Zephyr', # Default / Balanced
16
- 'Puck': 'Puck', # Energetic / Bright
17
- 'Charon': 'Charon', # Deep / Calm
18
- 'Kore': 'Kore', # Soft / Warm
19
- 'Fenrir': 'Fenrir' # Formal / Sharp
20
  }
21
 
22
  @app.route('/')
@@ -24,25 +24,12 @@ async def index():
24
  return {
25
  "status": "online",
26
  "service": "ASH-BAND Live Neural Link",
27
- "endpoint": "/stream",
28
- "supported_voices": list(VOICE_MODES.keys())
29
  }
30
 
31
- @app.route('/models')
32
- async def list_models():
33
- """Use this to see exactly which models your key has access to if it fails."""
34
- try:
35
- models = client.models.list()
36
- return {"available_models": [m.name for m in models]}
37
- except Exception as e:
38
- return {"error": str(e)}
39
-
40
  @app.websocket('/stream')
41
  async def ws_stream():
42
- """
43
- WebSocket endpoint for the Termux client.
44
- Connect via: wss://<hf-space-url>/stream?voice=Zephyr
45
- """
46
  requested_voice = websocket.args.get("voice", "Zephyr")
47
  voice_name = VOICE_MODES.get(requested_voice, "Zephyr")
48
 
@@ -56,8 +43,7 @@ async def ws_stream():
56
  "tools": [{"google_search": {}}],
57
  "system_instruction": (
58
  "You are ASH-BAND, a high-fidelity AI wearable companion. "
59
- "Speak in a professional, concise, and helpful tone. "
60
- "Keep responses brief to minimize latency. Your responses are spoken aloud."
61
  )
62
  }
63
 
@@ -72,45 +58,34 @@ async def ws_stream():
72
  while True:
73
  data = await websocket.receive()
74
  if isinstance(data, bytes):
 
75
  await session.send(
76
  input={"data": data, "mime_type": "audio/pcm;rate=16000"}
77
  )
78
- except asyncio.CancelledError:
79
- pass
 
80
  except Exception as e:
81
- print(f"Error reading from client: {e}")
82
 
83
  async def gemini_to_client():
84
  try:
85
  async for message in session.receive():
86
- server_content = message.server_content
87
- if server_content:
88
- if server_content.interrupted:
89
- print("AI Interrupted.")
90
-
91
- model_turn = server_content.model_turn
92
- if model_turn:
93
- for part in model_turn.parts:
94
- if part.inline_data and part.inline_data.data:
95
- await websocket.send(part.inline_data.data)
96
- except asyncio.CancelledError:
97
- pass
98
  except Exception as e:
99
- print(f"Error receiving from Gemini: {e}")
100
 
101
- task1 = asyncio.create_task(client_to_gemini())
102
- task2 = asyncio.create_task(gemini_to_client())
103
-
104
- await asyncio.wait(
105
- [task1, task2],
106
- return_when=asyncio.FIRST_COMPLETED,
107
- )
108
-
109
- task1.cancel()
110
- task2.cancel()
111
 
112
  except Exception as e:
113
  print(f"Connection failed: {e}")
 
 
114
 
115
  if __name__ == "__main__":
116
  app.run(host="0.0.0.0", port=7860)
 
5
 
6
  app = Quart(__name__)
7
 
8
+ # Force v1beta version (Required for Native Audio and Live features)
9
  client = genai.Client(http_options={'api_version': 'v1beta'})
10
 
11
+ # Using the Native Audio preview model you identified
12
  MODEL = "models/gemini-2.5-flash-native-audio-preview-12-2025"
13
 
14
  VOICE_MODES = {
15
+ 'Zephyr': 'Zephyr',
16
+ 'Puck': 'Puck',
17
+ 'Charon': 'Charon',
18
+ 'Kore': 'Kore',
19
+ 'Fenrir': 'Fenrir'
20
  }
21
 
22
  @app.route('/')
 
24
  return {
25
  "status": "online",
26
  "service": "ASH-BAND Live Neural Link",
27
+ "model": MODEL,
28
+ "endpoint": "/stream"
29
  }
30
 
 
 
 
 
 
 
 
 
 
31
  @app.websocket('/stream')
32
  async def ws_stream():
 
 
 
 
33
  requested_voice = websocket.args.get("voice", "Zephyr")
34
  voice_name = VOICE_MODES.get(requested_voice, "Zephyr")
35
 
 
43
  "tools": [{"google_search": {}}],
44
  "system_instruction": (
45
  "You are ASH-BAND, a high-fidelity AI wearable companion. "
46
+ "Speak concisely and professionally. Your responses are spoken aloud."
 
47
  )
48
  }
49
 
 
58
  while True:
59
  data = await websocket.receive()
60
  if isinstance(data, bytes):
61
+ # Handle microphone audio
62
  await session.send(
63
  input={"data": data, "mime_type": "audio/pcm;rate=16000"}
64
  )
65
+ elif isinstance(data, str):
66
+ # Handle 'echo' text commands from Termux
67
+ await session.send(input=data)
68
  except Exception as e:
69
+ print(f"Client -> Gemini Error: {e}")
70
 
71
  async def gemini_to_client():
72
  try:
73
  async for message in session.receive():
74
+ if message.server_content and message.server_content.model_turn:
75
+ for part in message.server_content.model_turn.parts:
76
+ if part.inline_data and part.inline_data.data:
77
+ # Send back raw 24kHz PCM audio
78
+ await websocket.send(part.inline_data.data)
 
 
 
 
 
 
 
79
  except Exception as e:
80
+ print(f"Gemini -> Client Error: {e}")
81
 
82
+ # Run both tasks and wait for them to finish or error out
83
+ await asyncio.gather(client_to_gemini(), gemini_to_client())
 
 
 
 
 
 
 
 
84
 
85
  except Exception as e:
86
  print(f"Connection failed: {e}")
87
+ finally:
88
+ print("Session closed.")
89
 
90
  if __name__ == "__main__":
91
  app.run(host="0.0.0.0", port=7860)