SandyGudisa commited on
Commit
eafef62
Β·
verified Β·
1 Parent(s): 3713acb

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +406 -0
app.py ADDED
@@ -0,0 +1,406 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ import google.generativeai as genai
4
+ import google.ai.generativelanguage as glm
5
+ from PIL import Image
6
+ import gradio as gr
7
+ import numpy as np
8
+ import io
9
+ import speech_recognition as sr
10
+ import edge_tts
11
+ import asyncio
12
+ import pygame
13
+ import threading
14
+ from deep_translator import GoogleTranslator
15
+ import cv2
16
+ from gradio.themes import Base
17
+
18
+ # Load environment variables from .env file
19
+ load_dotenv()
20
+ API_KEY = os.getenv("API_KEY")
21
+
22
+ if API_KEY is None:
23
+ gr.Chatbot("API Key is not set. Please set the API key in the .env file.")
24
+ else:
25
+ genai.configure(api_key=API_KEY)
26
+
27
+ # GIF paths
28
+ GIF_LISTENING = "Images/listening.gif"
29
+ GIF_THINKING = "Images/Thinking1.gif"
30
+ GIF_SPEAKING = "Images/speaking.gif"
31
+ GIF_NEUTRAL = "Images/Neutral.gif"
32
+
33
+ custom_theme = gr.themes.Default(
34
+ primary_hue="indigo",
35
+ secondary_hue="blue",
36
+ neutral_hue="gray",
37
+ font=("Helvetica", "sans-serif")
38
+ )
39
+ # Available voices and languages for TTS
40
+ VOICES = {
41
+ "English": {"Female": "en-US-JennyNeural", "Male": "en-US-GuyNeural"},
42
+ "Hindi": {"Female": "hi-IN-SwaraNeural", "Male": "hi-IN-MadhurNeural"},
43
+ "Spanish": {"Female": "es-ES-ElviraNeural", "Male": "es-ES-AlvaroNeural"},
44
+ "French": {"Female": "fr-FR-DeniseNeural", "Male": "fr-FR-HenriNeural"},
45
+ "German": {"Female": "de-DE-KatjaNeural", "Male": "de-DE-ConradNeural"},
46
+ "Japanese": {"Female": "ja-JP-NanamiNeural", "Male": "ja-JP-KeitaNeural"},
47
+ "Telugu": {"Female": "te-IN-ShrutiNeural", "Male": "te-IN-MohanNeural"},
48
+ "Mandarin Chinese": {"Female": "zh-CN-XiaoxiaoNeural", "Male": "zh-CN-YunyangNeural"},
49
+ "Arabic": {"Female": "ar-EG-SalmaNeural", "Male": "ar-EG-HamedNeural"},
50
+ "Russian": {"Female": "ru-RU-DariyaNeural", "Male": "ru-RU-NikitaNeural"},
51
+ "Portuguese": {"Female": "pt-BR-FranciscaNeural", "Male": "pt-BR-AntonioNeural"},
52
+ "Italian": {"Female": "it-IT-ElsaNeural", "Male": "it-IT-IsmaeleNeural"},
53
+ "Korean": {"Female": "ko-KR-SunHyeNeural", "Male": "ko-KR-InJoonNeural"},
54
+ "Dutch": {"Female": "nl-NL-ColetteNeural", "Male": "nl-NL-FennNeural"},
55
+ "Swedish": {"Female": "sv-SE-HilleviNeural", "Male": "sv-SE-MattiasNeural"},
56
+ "Polish": {"Female": "pl-PL-AgnieszkaNeural", "Male": "pl-PL-MarekNeural"},
57
+ "Turkish": {"Female": "tr-TR-EmelNeural", "Male": "tr-TR-AhmetNeural"},
58
+ "Indonesian": {"Female": "id-ID-GadisNeural", "Male": "id-ID-ArdiNeural"},
59
+ "Thai": {"Female": "th-TH-AcharaNeural", "Male": "th-TH-PremwutNeural"},
60
+ "Vietnamese": {"Female": "vi-VN-HoaiMyNeural", "Male": "vi-VN-NamMinhNeural"},
61
+ "Greek": {"Female": "el-GR-AthinaNeural", "Male": "el-GR-NestorasNeural"},
62
+ "Hebrew": {"Female": "he-IL-HilaNeural", "Male": "he-IL-AvriNeural"},
63
+ "Hungarian": {"Female": "hu-HU-NoemiNeural", "Male": "hu-HU-TamasNeural"},
64
+ "Romanian": {"Female": "ro-RO-AlinaNeural", "Male": "ro-RO-EmilNeural"},
65
+ "Czech": {"Female": "cs-CZ-VlastaNeural", "Male": "cs-CZ-AntoninNeural"},
66
+ "Finnish": {"Female": "fi-FI-SelmaNeural", "Male": "fi-FI-HarriNeural"},
67
+ "Danish": {"Female": "da-DK-ChristelNeural", "Male": "da-DK-JeppeNeural"},
68
+ "Norwegian": {"Female": "nb-NO-IselinNeural", "Male": "nb-NO-FinnNeural"},
69
+ "Slovak": {"Female": "sk-SK-ViktoriaNeural", "Male": "sk-SK-LukasNeural"},
70
+ "Bulgarian": {"Female": "bg-BG-KalinaNeural", "Male": "bg-BG-BorislavNeural"},
71
+ # Add more languages and voices as needed
72
+ }
73
+
74
+ LANGUAGE_CODES = {
75
+ "English": "en", "Hindi": "hi", "Spanish": "es",
76
+ "French": "fr", "German": "de", "Japanese": "ja",
77
+ "Telugu": "te", "Mandarin Chinese": "zh-CN", "Arabic": "ar",
78
+ "Russian": "ru", "Portuguese": "pt-BR", "Italian": "it",
79
+ "Korean": "ko", "Dutch": "nl", "Swedish": "sv",
80
+ "Polish": "pl", "Turkish": "tr", "Indonesian": "id",
81
+ "Thai": "th", "Vietnamese": "vi",
82
+ "Greek": "el",
83
+ "Hebrew": "he",
84
+ "Hungarian": "hu",
85
+ "Romanian": "ro",
86
+ "Czech": "cs",
87
+ "Finnish": "fi",
88
+ "Danish": "da",
89
+ "Norwegian": "nb",
90
+ "Slovak": "sk",
91
+ "Bulgarian": "bg",
92
+ # Add more language codes as needed
93
+ }
94
+
95
+ conversation_history = []
96
+
97
+ def text_chat(text, max_output_tokens):
98
+ global conversation_history
99
+ model = genai.GenerativeModel(model_name="gemini-1.5-flash")
100
+
101
+ response = model.generate_content(
102
+ glm.Content(
103
+ parts=[
104
+ glm.Part(text=text),
105
+ ],
106
+ ),
107
+ generation_config = {
108
+ "temperature" : 0.7,
109
+ "max_output_tokens" : max_output_tokens,
110
+ } ,
111
+ stream=True
112
+ )
113
+ response.resolve()
114
+ conversation_history.append(("You", text))
115
+ conversation_history.append(("Assistant", response.text))
116
+ return conversation_history
117
+ def image_analysis(image, prompt, input_language, output_language, voice_input=None):
118
+ input_language = input_language or "English"
119
+ output_language = output_language or "English"
120
+
121
+ if voice_input:
122
+ # Convert voice input to text using the selected input language
123
+ recognizer = sr.Recognizer()
124
+ with sr.AudioFile(voice_input) as source:
125
+ audio = recognizer.record(source)
126
+ prompt = recognizer.recognize_google(audio, language=LANGUAGE_CODES[input_language])
127
+
128
+ if input_language != "English":
129
+ prompt = GoogleTranslator(source=LANGUAGE_CODES[input_language], target='en').translate(prompt)
130
+
131
+ if isinstance(image, np.ndarray):
132
+ pil_image = Image.fromarray(image)
133
+ elif isinstance(image, Image.Image):
134
+ pil_image = image
135
+ else:
136
+ bytes_data = image
137
+
138
+ if 'pil_image' in locals():
139
+ img_byte_arr = io.BytesIO()
140
+ pil_image.save(img_byte_arr, format='JPEG')
141
+ bytes_data = img_byte_arr.getvalue()
142
+
143
+ model = genai.GenerativeModel(model_name="gemini-1.5-flash")
144
+
145
+ response = model.generate_content(
146
+ glm.Content(
147
+ parts=[glm.Part(text=prompt), glm.Part(inline_data=glm.Blob(mime_type='image/jpeg', data=bytes_data))],
148
+ ),
149
+ generation_config = {
150
+ "temperature" : 0.7,
151
+ "max_output_tokens" : 100,
152
+ } ,
153
+ )
154
+
155
+ response.resolve()
156
+
157
+ if output_language != "English":
158
+ response_text = GoogleTranslator(source='en', target=LANGUAGE_CODES[output_language]).translate(response.text)
159
+ else:
160
+ response_text = response.text
161
+
162
+ return response_text # Return only the text response
163
+ class VoiceInteraction:
164
+ def __init__(self):
165
+ self.is_running = False
166
+ self.recognizer = sr.Recognizer()
167
+ self.model = genai.GenerativeModel(model_name="gemini-1.5-flash")
168
+ self.conversation = []
169
+ self.current_state = None
170
+ self.current_image = None
171
+ self.input_language = "English"
172
+ self.output_language = "English"
173
+ self.voice = VOICES["English"]["Female"]
174
+
175
+ # Adjust the recognizer's settings for better sensitivity
176
+ self.recognizer.energy_threshold = 300 # Lower energy threshold for detecting speech
177
+ self.recognizer.dynamic_energy_threshold = True # Dynamically adjust for ambient noise
178
+ self.recognizer.pause_threshold = 0.5
179
+
180
+ async def text_to_speech_and_play(self, text):
181
+ self.current_state = "Speaking"
182
+ communicate = edge_tts.Communicate(text, self.voice)
183
+ audio_path = "output.mp3"
184
+ await communicate.save(audio_path)
185
+
186
+ pygame.mixer.init()
187
+ pygame.mixer.music.load(audio_path)
188
+ pygame.mixer.music.play()
189
+ while pygame.mixer.music.get_busy():
190
+ pygame.time.Clock().tick(10)
191
+ pygame.mixer.quit()
192
+
193
+ def listen_and_respond(self):
194
+ with sr.Microphone() as source:
195
+ self.recognizer.adjust_for_ambient_noise(source, duration=1)
196
+
197
+ while self.is_running:
198
+ try:
199
+ self.current_state = "Listening"
200
+ audio = self.recognizer.listen(source, timeout=3, phrase_time_limit=10)
201
+ text = self.recognizer.recognize_google(audio, language=LANGUAGE_CODES[self.input_language])
202
+
203
+ if self.input_language != "English":
204
+ text = GoogleTranslator(source=LANGUAGE_CODES[self.input_language], target='en').translate(text)
205
+
206
+ self.conversation.append(("You", text))
207
+
208
+ self.current_state = "Thinking"
209
+ if self.current_image:
210
+ response = image_analysis(self.current_image, text)
211
+ else:
212
+ response = self.model.generate_content(
213
+ glm.Content(parts=[glm.Part(text=text + "Give the Response in only plain text and without any Markdown Formatting ")]),
214
+ generation_config = {
215
+ "temperature" : 0.7,
216
+ "max_output_tokens" : 500,
217
+ } ,
218
+ )
219
+ response.resolve()
220
+ response = response.text
221
+
222
+ if self.output_language != "English":
223
+ response = GoogleTranslator(source='en', target=LANGUAGE_CODES[self.output_language]).translate(response)
224
+
225
+ self.conversation.append(("Assistant", response))
226
+
227
+ # Update the conversation output after each cycle
228
+ gr.update(value=self.conversation)
229
+
230
+ asyncio.run(self.text_to_speech_and_play(response))
231
+ except sr.WaitTimeoutError:
232
+ continue
233
+ except sr.UnknownValueError:
234
+ gr.Markdown("Could not understand audio")
235
+ except sr.RequestError as e:
236
+ print(f"Error: {str(e)}")
237
+
238
+ def start(self):
239
+ self.is_running = True
240
+ self.thread = threading.Thread(target=self.listen_and_respond)
241
+ self.thread.start()
242
+
243
+ def stop(self):
244
+ self.is_running = False
245
+ if hasattr(self, 'thread'):
246
+ self.thread.join()
247
+
248
+ def set_current_image(self, image):
249
+ self.current_image = image
250
+
251
+ def set_languages_and_voice(self, input_language, output_language, voice_gender):
252
+ self.input_language = input_language
253
+ self.output_language = output_language
254
+ self.voice = VOICES[output_language][voice_gender]
255
+
256
+ voice_interaction = VoiceInteraction()
257
+
258
+ def start_voice_interaction():
259
+ voice_interaction.start()
260
+ return "Voice interaction started. Speak now!", voice_interaction.conversation
261
+
262
+ def stop_voice_interaction():
263
+ voice_interaction.stop()
264
+ return "Voice interaction stopped.", voice_interaction.conversation
265
+
266
+ def update_conversation():
267
+ return voice_interaction.conversation
268
+
269
+ def get_current_gif():
270
+ state = voice_interaction.current_state
271
+ if state == "Listening":
272
+ return GIF_LISTENING
273
+ elif state == "Thinking":
274
+ return GIF_THINKING
275
+ elif state == "Speaking":
276
+ return GIF_SPEAKING
277
+ else:
278
+ return GIF_NEUTRAL
279
+ def analyze_and_speak(image, prompt, input_language, output_language, voice_input=None):
280
+ response_text = image_analysis(image, prompt, input_language, output_language, voice_input)
281
+
282
+ # Generate audio response
283
+ voice = VOICES[output_language]["Female"]
284
+ communicate = edge_tts.Communicate(response_text, voice)
285
+ audio_path = "image_analysis_response.mp3"
286
+ asyncio.run(communicate.save(audio_path))
287
+
288
+ return response_text, audio_path
289
+ def set_image_for_voice(image):
290
+ voice_interaction.set_current_image(image)
291
+ return "Image set for voice interaction. You can now ask questions about it."
292
+
293
+ def set_languages_and_voice(input_language, output_language, voice_gender):
294
+ voice_interaction.set_languages_and_voice(input_language, output_language, voice_gender)
295
+ return f"Input language set to {input_language}, output language set to {output_language} with {voice_gender} voice"
296
+
297
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
298
+ gr.Markdown("# 🌐 Conerstional Image Recognition Chatbot")
299
+ gr.Markdown("## Developed by AI INTENTS ")
300
+ with gr.Tab("🏠 Home"):
301
+ gr.Markdown("""
302
+ ## Welcome to the Conversational Image Recognition Chatbot!
303
+
304
+ This application offers three main features:
305
+
306
+ 1. **πŸ’¬ Text Chat**: Engage in a text-based conversation with our AI assistant.
307
+ 2. **πŸ–ΌοΈ Image Analysis**: Upload or capture images for AI-powered analysis and description.
308
+ 3. **πŸŽ™οΈ Voice Interaction**: Have a voice conversation with our AI, with support for multiple languages.
309
+
310
+ Choose a tab above to get started!
311
+
312
+ ### How to use:
313
+ - In Text Chat, simply type your message and click 'Send'.
314
+ - For Image Analysis, upload an image or use your webcam, then type or speak your question about the image.
315
+ - In Voice Interaction, click 'Start' and begin speaking. The AI will respond audibly.
316
+
317
+ Enjoy exploring the capabilities of our AI-powered chatbot!
318
+ """)
319
+ with gr.Tab("πŸ’¬ Text Chat"):
320
+ with gr.Row():
321
+ with gr.Column(scale=4):
322
+ text_input = gr.Textbox(label="Your message", placeholder="Type your message here...")
323
+ max_tokens_slider = gr.Slider(minimum=100, maximum=1000, value=500, step=50, label="Max Output Tokens")
324
+ with gr.Column(scale=1):
325
+ text_button = gr.Button("Send", variant="primary")
326
+ text_output = gr.Chatbot(height=400, elem_id="text-chat-output")
327
+ text_button.click(text_chat, inputs=[text_input, max_tokens_slider], outputs=text_output)
328
+ with gr.Tab("πŸ–ΌοΈ Image Analysis"):
329
+ with gr.Row():
330
+ with gr.Column(scale=1):
331
+ with gr.Row():
332
+ image_input = gr.Image(label="Upload Image", type="pil")
333
+ webcam_button = gr.Button("Capture from Webcam")
334
+ with gr.Column(scale=1):
335
+ image_prompt = gr.Textbox(label="Prompt", placeholder="Ask about the image...")
336
+ input_language_dropdown = gr.Dropdown(choices=list(VOICES.keys()), label="Input Language", value="English")
337
+ output_language_dropdown = gr.Dropdown(choices=list(VOICES.keys()), label="Output Language", value="English")
338
+ image_prompt_voice = gr.Audio(label="Prompt via Voice", sources=["microphone"], type="filepath")
339
+ image_prompt_audio = gr.Audio(label="Upload Audio File", sources=["upload"], type="filepath")
340
+ image_button = gr.Button("Analyze", variant="primary")
341
+ image_output = gr.Markdown(label="Analysis Result", elem_id="image-analysis-output")
342
+ audio_output = gr.Audio(label="Audio Response", elem_id="image-analysis-audio-output")
343
+
344
+ def capture_image_from_webcam():
345
+ cap = cv2.VideoCapture(0)
346
+ ret, frame = cap.read()
347
+ cap.release()
348
+ return Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
349
+
350
+ webcam_button.click(capture_image_from_webcam, outputs=image_input)
351
+ image_button.click(
352
+ analyze_and_speak,
353
+ inputs=[image_input, image_prompt, input_language_dropdown, output_language_dropdown],
354
+ outputs=[image_output, audio_output]
355
+ )
356
+
357
+ # Add events for voice and audio file inputs
358
+ image_prompt_voice.change(
359
+ image_analysis,
360
+ inputs=[image_input, image_prompt_voice, input_language_dropdown, output_language_dropdown, image_prompt_voice],
361
+ outputs=[image_output, audio_output]
362
+ )
363
+
364
+ image_prompt_audio.change(
365
+ image_analysis,
366
+ inputs=[image_input, image_prompt_audio, input_language_dropdown, output_language_dropdown, image_prompt_audio],
367
+ outputs=[image_output, audio_output]
368
+ )
369
+ image_button.click(image_analysis, inputs=[image_input, image_prompt], outputs=image_output)
370
+ image_prompt_voice.change(lambda x: image_analysis(image_input.value, x), inputs=image_prompt_voice, outputs=image_output)
371
+ with gr.Tab("πŸŽ™οΈ Voice Interaction"):
372
+ with gr.Row():
373
+ start_button = gr.Button("Start Voice Interaction", variant="primary")
374
+ stop_button = gr.Button("Stop Voice Interaction", variant="secondary")
375
+ with gr.Row():
376
+ input_language_dropdown = gr.Dropdown(choices=list(VOICES.keys()), label="Input Language", value="English")
377
+ output_language_dropdown = gr.Dropdown(choices=list(VOICES.keys()), label="Output Language", value="English")
378
+ voice_gender_dropdown = gr.Dropdown(choices=["Female", "Male"], label="Voice Gender", value="Female")
379
+ set_language_button = gr.Button("Set Languages and Voice")
380
+ sensitivity_slider = gr.Slider(minimum=100, maximum=1000, value=300, step=50, label="Microphone Sensitivity")
381
+ with gr.Row():
382
+ with gr.Column(scale=1):
383
+ gif_output = gr.Image(label="Status", visible=True, elem_id="voice-interaction-gif")
384
+ status_output = gr.Markdown(label="Status", elem_id="voice-interaction-status")
385
+ with gr.Column(scale=1):
386
+ conversation_output = gr.Chatbot(label="Conversation", height=400, elem_id="voice-interaction-output")
387
+ demo.load(update_conversation, inputs=[], outputs=[conversation_output], every=1)
388
+
389
+ start_button.click(start_voice_interaction, inputs=[], outputs=[status_output, conversation_output])
390
+ stop_button.click(stop_voice_interaction, inputs=[], outputs=[status_output, conversation_output])
391
+ set_language_button.click(set_languages_and_voice,
392
+ inputs=[input_language_dropdown, output_language_dropdown, voice_gender_dropdown],
393
+ outputs=status_output)
394
+
395
+ demo.load(get_current_gif, inputs=[], outputs=gif_output, every=1)
396
+
397
+ def update_sensitivity(value):
398
+ voice_interaction.recognizer.energy_threshold = value
399
+ return f"Microphone sensitivity set to {value}"
400
+
401
+ sensitivity_slider.change(update_sensitivity, inputs=[sensitivity_slider], outputs=[status_output])
402
+ gr.Markdown("## Developed by AI INTENTS ")
403
+
404
+ demo.launch(share=False)
405
+
406
+