siyah1 commited on
Commit
d516471
·
verified ·
1 Parent(s): b297a73

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +279 -45
app.py CHANGED
@@ -1,39 +1,148 @@
1
  import gradio as gr
2
  from geminisearch import webSearch
 
 
 
 
 
 
3
 
4
- # Concise example questions for MCP interface
5
- mcp_examples = [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  "What are the latest AI technology developments?",
7
  "What's happening in global news today?",
8
  "What's the current cryptocurrency market status?"
9
  ]
10
 
11
- # Custom CSS for better styling
12
  custom_css = """
13
  .gradio-container {
14
  max-width: 1200px !important;
15
  margin: auto !important;
 
 
 
 
 
 
 
 
 
 
16
  }
17
 
18
  .chatbot {
19
  border-radius: 15px !important;
20
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important;
 
21
  }
22
 
23
- .input-container {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  border-radius: 25px !important;
25
  border: 2px solid #e1e5e9 !important;
 
26
  }
27
 
28
- .input-container:focus-within {
29
- border-color: #4285f4 !important;
30
- box-shadow: 0 0 0 3px rgba(66, 133, 244, 0.1) !important;
31
  }
32
 
33
  h1 {
34
  text-align: center !important;
35
- color: #1a73e8 !important;
36
- font-weight: 600 !important;
 
 
 
 
 
 
 
 
 
37
  margin-bottom: 2rem !important;
38
  }
39
 
@@ -47,54 +156,179 @@ h1 {
47
  color: white !important;
48
  border: none !important;
49
  transition: all 0.3s ease !important;
 
50
  }
51
 
52
  .example:hover {
53
  transform: translateY(-2px) !important;
54
- box-shadow: 0 8px 25px rgba(0,0,0,0.2) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  }
56
  """
57
 
58
- # Create the enhanced interface
59
- app = gr.ChatInterface(
60
- webSearch,
61
- chatbot=gr.Chatbot(
62
- height=500,
63
- show_label=False,
64
- container=True,
65
- bubble_full_width=False,
66
- render_markdown=True
67
- ),
68
- type="messages",
69
- textbox=gr.Textbox(
70
- placeholder="🔍 Ask me anything about current events, news, or real-time information...",
71
- container=False,
72
- scale=7,
73
- show_label=False,
74
- lines=1,
75
- max_lines=3
76
- ),
77
- title="✨ Quasar LLM Web Chat",
78
- description="Quasar LLM powered interface for real-time web search and intelligent responses.",
79
  theme=gr.themes.Soft(
80
  primary_hue="blue",
81
  secondary_hue="slate",
82
  neutral_hue="slate",
83
  font=gr.themes.GoogleFont("Inter")
84
  ),
85
- examples=mcp_examples,
86
- cache_examples=False,
87
  css=custom_css,
88
- analytics_enabled=False,
89
- show_progress="minimal"
90
- )
91
-
92
- # Additional configuration
93
- app.queue(
94
- default_concurrency_limit=20,
95
- max_size=50
96
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
 
98
  if __name__ == "__main__":
99
  app.launch(
100
  mcp_server=True,
@@ -102,6 +336,6 @@ if __name__ == "__main__":
102
  inbrowser=True,
103
  show_error=True,
104
  quiet=False,
105
- favicon_path=None,
106
- ssl_verify=False
107
  )
 
1
  import gradio as gr
2
  from geminisearch import webSearch
3
+ import speech_recognition as sr
4
+ import pyttsx3
5
+ import threading
6
+ import io
7
+ import wave
8
+ import numpy as np
9
 
10
+ class QuasarAudioChat:
11
+ def __init__(self):
12
+ self.tts_engine = pyttsx3.init()
13
+ self.tts_engine.setProperty('rate', 150)
14
+ self.tts_engine.setProperty('volume', 0.9)
15
+ self.recognizer = sr.Recognizer()
16
+ self.is_listening = False
17
+
18
+ def speech_to_text(self, audio_data):
19
+ """Convert speech to text"""
20
+ try:
21
+ if audio_data is None:
22
+ return "No audio received"
23
+
24
+ # Convert audio to the format expected by speech_recognition
25
+ with sr.AudioFile(io.BytesIO(audio_data)) as source:
26
+ audio = self.recognizer.record(source)
27
+ text = self.recognizer.recognize_google(audio)
28
+ return text
29
+ except sr.UnknownValueError:
30
+ return "Could not understand audio"
31
+ except sr.RequestError as e:
32
+ return f"Speech recognition error: {e}"
33
+
34
+ def text_to_speech(self, text):
35
+ """Convert text to speech"""
36
+ try:
37
+ # Remove markdown and special characters for cleaner speech
38
+ clean_text = text.replace('*', '').replace('#', '').replace('`', '')
39
+ self.tts_engine.say(clean_text)
40
+ self.tts_engine.runAndWait()
41
+ except Exception as e:
42
+ print(f"TTS Error: {e}")
43
+
44
+ def process_audio_message(self, audio, chat_history):
45
+ """Process audio input and return response"""
46
+ if audio is None:
47
+ return chat_history, "Please provide audio input"
48
+
49
+ # Convert audio to text
50
+ user_text = self.speech_to_text(audio)
51
+
52
+ if "error" in user_text.lower() or "could not" in user_text.lower():
53
+ chat_history.append({"role": "user", "content": "[Audio Error]"})
54
+ chat_history.append({"role": "assistant", "content": user_text})
55
+ return chat_history, user_text
56
+
57
+ # Add user message to chat
58
+ chat_history.append({"role": "user", "content": f"🎤 {user_text}"})
59
+
60
+ # Get response from webSearch
61
+ try:
62
+ response = webSearch(user_text)
63
+ chat_history.append({"role": "assistant", "content": response})
64
+
65
+ # Convert response to speech in background thread
66
+ threading.Thread(target=self.text_to_speech, args=(response,), daemon=True).start()
67
+
68
+ return chat_history, response
69
+ except Exception as e:
70
+ error_msg = f"Search error: {str(e)}"
71
+ chat_history.append({"role": "assistant", "content": error_msg})
72
+ return chat_history, error_msg
73
+
74
+ # Initialize audio chat
75
+ audio_chat = QuasarAudioChat()
76
+
77
+ # Predefined questions for Quasar LLM
78
+ quasar_examples = [
79
  "What are the latest AI technology developments?",
80
  "What's happening in global news today?",
81
  "What's the current cryptocurrency market status?"
82
  ]
83
 
84
+ # Enhanced CSS with audio-focused styling
85
  custom_css = """
86
  .gradio-container {
87
  max-width: 1200px !important;
88
  margin: auto !important;
89
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
90
+ min-height: 100vh !important;
91
+ }
92
+
93
+ .main-container {
94
+ background: rgba(255, 255, 255, 0.95) !important;
95
+ border-radius: 20px !important;
96
+ padding: 2rem !important;
97
+ margin: 1rem !important;
98
+ box-shadow: 0 20px 40px rgba(0,0,0,0.1) !important;
99
  }
100
 
101
  .chatbot {
102
  border-radius: 15px !important;
103
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1) !important;
104
+ border: 2px solid #e1e5e9 !important;
105
  }
106
 
107
+ .audio-input {
108
+ border-radius: 50px !important;
109
+ background: linear-gradient(135deg, #ff6b6b, #ffd93d) !important;
110
+ border: none !important;
111
+ color: white !important;
112
+ font-weight: bold !important;
113
+ box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3) !important;
114
+ transition: all 0.3s ease !important;
115
+ }
116
+
117
+ .audio-input:hover {
118
+ transform: translateY(-2px) !important;
119
+ box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4) !important;
120
+ }
121
+
122
+ .text-input {
123
  border-radius: 25px !important;
124
  border: 2px solid #e1e5e9 !important;
125
+ background: rgba(255, 255, 255, 0.9) !important;
126
  }
127
 
128
+ .text-input:focus-within {
129
+ border-color: #667eea !important;
130
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
131
  }
132
 
133
  h1 {
134
  text-align: center !important;
135
+ background: linear-gradient(135deg, #667eea, #764ba2) !important;
136
+ -webkit-background-clip: text !important;
137
+ -webkit-text-fill-color: transparent !important;
138
+ font-weight: 700 !important;
139
+ font-size: 2.5rem !important;
140
+ margin-bottom: 1rem !important;
141
+ }
142
+
143
+ .description {
144
+ text-align: center !important;
145
+ color: #666 !important;
146
  margin-bottom: 2rem !important;
147
  }
148
 
 
156
  color: white !important;
157
  border: none !important;
158
  transition: all 0.3s ease !important;
159
+ font-weight: 500 !important;
160
  }
161
 
162
  .example:hover {
163
  transform: translateY(-2px) !important;
164
+ box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3) !important;
165
+ }
166
+
167
+ .audio-controls {
168
+ display: flex !important;
169
+ justify-content: center !important;
170
+ gap: 1rem !important;
171
+ margin: 1rem 0 !important;
172
+ }
173
+
174
+ .status-indicator {
175
+ padding: 0.5rem 1rem !important;
176
+ border-radius: 20px !important;
177
+ background: #e8f4f8 !important;
178
+ color: #1976d2 !important;
179
+ font-weight: 500 !important;
180
+ text-align: center !important;
181
  }
182
  """
183
 
184
+ # Create the Quasar LLM interface with audio capabilities
185
+ with gr.Blocks(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  theme=gr.themes.Soft(
187
  primary_hue="blue",
188
  secondary_hue="slate",
189
  neutral_hue="slate",
190
  font=gr.themes.GoogleFont("Inter")
191
  ),
 
 
192
  css=custom_css,
193
+ title="Quasar LLM Audio Chat"
194
+ ) as app:
195
+
196
+ gr.HTML("""
197
+ <div style="text-align: center; margin-bottom: 2rem;">
198
+ <h1>✨ Quasar LLM Audio Chat</h1>
199
+ <p class="description">
200
+ 🎤 Real-time voice-powered web search with intelligent responses<br>
201
+ Speak your questions or type them - get instant answers with audio feedback!
202
+ </p>
203
+ </div>
204
+ """)
205
+
206
+ with gr.Row():
207
+ with gr.Column(scale=1):
208
+ # Chat interface
209
+ chatbot = gr.Chatbot(
210
+ value=[],
211
+ height=400,
212
+ show_label=False,
213
+ container=True,
214
+ bubble_full_width=False,
215
+ render_markdown=True,
216
+ type="messages"
217
+ )
218
+
219
+ # Audio input section
220
+ with gr.Row():
221
+ with gr.Column(scale=3):
222
+ audio_input = gr.Audio(
223
+ sources=["microphone"],
224
+ type="numpy",
225
+ label="🎤 Voice Input",
226
+ show_label=True,
227
+ container=True,
228
+ elem_classes=["audio-input"]
229
+ )
230
+
231
+ with gr.Column(scale=1):
232
+ audio_submit = gr.Button(
233
+ "🎤 Send Voice",
234
+ variant="primary",
235
+ size="lg",
236
+ elem_classes=["audio-input"]
237
+ )
238
+
239
+ # Text input as backup
240
+ with gr.Row():
241
+ text_input = gr.Textbox(
242
+ placeholder="💬 Or type your message here...",
243
+ container=False,
244
+ scale=7,
245
+ show_label=False,
246
+ lines=1,
247
+ max_lines=3,
248
+ elem_classes=["text-input"]
249
+ )
250
+ text_submit = gr.Button("Send", variant="secondary")
251
+
252
+ # Status indicator
253
+ status = gr.Textbox(
254
+ value="Ready for voice or text input",
255
+ label="Status",
256
+ interactive=False,
257
+ elem_classes=["status-indicator"]
258
+ )
259
+
260
+ # Example questions
261
+ gr.Examples(
262
+ examples=quasar_examples,
263
+ inputs=[text_input],
264
+ label="✨ Try these questions:",
265
+ elem_classes=["examples"]
266
+ )
267
+
268
+ # Audio processing function
269
+ def process_audio(audio, history):
270
+ if audio is None:
271
+ return history, "Please record some audio first"
272
+
273
+ try:
274
+ # Convert numpy array to audio format for speech recognition
275
+ sample_rate, audio_data = audio
276
+
277
+ # Convert to WAV format
278
+ wav_buffer = io.BytesIO()
279
+ with wave.open(wav_buffer, 'wb') as wav_file:
280
+ wav_file.setnchannels(1)
281
+ wav_file.setsampwidth(2)
282
+ wav_file.setframerate(sample_rate)
283
+ wav_file.writeframes((audio_data * 32767).astype(np.int16).tobytes())
284
+
285
+ wav_buffer.seek(0)
286
+ return audio_chat.process_audio_message(wav_buffer.read(), history)
287
+ except Exception as e:
288
+ error_msg = f"Audio processing error: {str(e)}"
289
+ history.append({"role": "assistant", "content": error_msg})
290
+ return history, error_msg
291
+
292
+ # Text processing function
293
+ def process_text(text, history):
294
+ if not text.strip():
295
+ return history, "", "Please enter a message"
296
+
297
+ history.append({"role": "user", "content": text})
298
+
299
+ try:
300
+ response = webSearch(text)
301
+ history.append({"role": "assistant", "content": response})
302
+
303
+ # Convert response to speech
304
+ threading.Thread(target=audio_chat.text_to_speech, args=(response,), daemon=True).start()
305
+
306
+ return history, "", f"Processed: {text[:50]}..."
307
+ except Exception as e:
308
+ error_msg = f"Search error: {str(e)}"
309
+ history.append({"role": "assistant", "content": error_msg})
310
+ return history, "", error_msg
311
+
312
+ # Event handlers
313
+ audio_submit.click(
314
+ process_audio,
315
+ inputs=[audio_input, chatbot],
316
+ outputs=[chatbot, status]
317
+ )
318
+
319
+ text_submit.click(
320
+ process_text,
321
+ inputs=[text_input, chatbot],
322
+ outputs=[chatbot, text_input, status]
323
+ )
324
+
325
+ text_input.submit(
326
+ process_text,
327
+ inputs=[text_input, chatbot],
328
+ outputs=[chatbot, text_input, status]
329
+ )
330
 
331
+ # Launch configuration
332
  if __name__ == "__main__":
333
  app.launch(
334
  mcp_server=True,
 
336
  inbrowser=True,
337
  show_error=True,
338
  quiet=False,
339
+ server_name="0.0.0.0",
340
+ server_port=7860
341
  )