Spaces:
Runtime error
Runtime error
import os | |
from dotenv import load_dotenv | |
import google.generativeai as genai | |
import google.ai.generativelanguage as glm | |
from PIL import Image | |
import gradio as gr | |
import numpy as np | |
import io | |
import speech_recognition as sr | |
import edge_tts | |
import asyncio | |
import pygame | |
import threading | |
from deep_translator import GoogleTranslator | |
import cv2 | |
from gradio.themes import Base | |
# Load environment variables from .env file | |
load_dotenv() | |
API_KEY = os.getenv("API_KEY") | |
if API_KEY is None: | |
gr.Chatbot("API Key is not set. Please set the API key in the .env file.") | |
else: | |
genai.configure(api_key=API_KEY) | |
# GIF paths | |
GIF_LISTENING = "listening.gif" | |
GIF_THINKING = "Thinking1.gif" | |
GIF_SPEAKING = "speaking.gif" | |
GIF_NEUTRAL = "Neutral.gif" | |
custom_theme = gr.themes.Default( | |
primary_hue="indigo", | |
secondary_hue="blue", | |
neutral_hue="gray", | |
font=("Helvetica", "sans-serif") | |
) | |
# Available voices and languages for TTS | |
VOICES = { | |
"English": {"Female": "en-US-JennyNeural", "Male": "en-US-GuyNeural"}, | |
"Hindi": {"Female": "hi-IN-SwaraNeural", "Male": "hi-IN-MadhurNeural"}, | |
"Spanish": {"Female": "es-ES-ElviraNeural", "Male": "es-ES-AlvaroNeural"}, | |
"French": {"Female": "fr-FR-DeniseNeural", "Male": "fr-FR-HenriNeural"}, | |
"German": {"Female": "de-DE-KatjaNeural", "Male": "de-DE-ConradNeural"}, | |
"Japanese": {"Female": "ja-JP-NanamiNeural", "Male": "ja-JP-KeitaNeural"}, | |
"Telugu": {"Female": "te-IN-ShrutiNeural", "Male": "te-IN-MohanNeural"}, | |
"Mandarin Chinese": {"Female": "zh-CN-XiaoxiaoNeural", "Male": "zh-CN-YunyangNeural"}, | |
"Arabic": {"Female": "ar-EG-SalmaNeural", "Male": "ar-EG-HamedNeural"}, | |
"Russian": {"Female": "ru-RU-DariyaNeural", "Male": "ru-RU-NikitaNeural"}, | |
"Portuguese": {"Female": "pt-BR-FranciscaNeural", "Male": "pt-BR-AntonioNeural"}, | |
"Italian": {"Female": "it-IT-ElsaNeural", "Male": "it-IT-IsmaeleNeural"}, | |
"Korean": {"Female": "ko-KR-SunHyeNeural", "Male": "ko-KR-InJoonNeural"}, | |
"Dutch": {"Female": "nl-NL-ColetteNeural", "Male": "nl-NL-FennNeural"}, | |
"Swedish": {"Female": "sv-SE-HilleviNeural", "Male": "sv-SE-MattiasNeural"}, | |
"Polish": {"Female": "pl-PL-AgnieszkaNeural", "Male": "pl-PL-MarekNeural"}, | |
"Turkish": {"Female": "tr-TR-EmelNeural", "Male": "tr-TR-AhmetNeural"}, | |
"Indonesian": {"Female": "id-ID-GadisNeural", "Male": "id-ID-ArdiNeural"}, | |
"Thai": {"Female": "th-TH-AcharaNeural", "Male": "th-TH-PremwutNeural"}, | |
"Vietnamese": {"Female": "vi-VN-HoaiMyNeural", "Male": "vi-VN-NamMinhNeural"}, | |
"Greek": {"Female": "el-GR-AthinaNeural", "Male": "el-GR-NestorasNeural"}, | |
"Hebrew": {"Female": "he-IL-HilaNeural", "Male": "he-IL-AvriNeural"}, | |
"Hungarian": {"Female": "hu-HU-NoemiNeural", "Male": "hu-HU-TamasNeural"}, | |
"Romanian": {"Female": "ro-RO-AlinaNeural", "Male": "ro-RO-EmilNeural"}, | |
"Czech": {"Female": "cs-CZ-VlastaNeural", "Male": "cs-CZ-AntoninNeural"}, | |
"Finnish": {"Female": "fi-FI-SelmaNeural", "Male": "fi-FI-HarriNeural"}, | |
"Danish": {"Female": "da-DK-ChristelNeural", "Male": "da-DK-JeppeNeural"}, | |
"Norwegian": {"Female": "nb-NO-IselinNeural", "Male": "nb-NO-FinnNeural"}, | |
"Slovak": {"Female": "sk-SK-ViktoriaNeural", "Male": "sk-SK-LukasNeural"}, | |
"Bulgarian": {"Female": "bg-BG-KalinaNeural", "Male": "bg-BG-BorislavNeural"}, | |
# Add more languages and voices as needed | |
} | |
LANGUAGE_CODES = { | |
"English": "en", "Hindi": "hi", "Spanish": "es", | |
"French": "fr", "German": "de", "Japanese": "ja", | |
"Telugu": "te", "Mandarin Chinese": "zh-CN", "Arabic": "ar", | |
"Russian": "ru", "Portuguese": "pt-BR", "Italian": "it", | |
"Korean": "ko", "Dutch": "nl", "Swedish": "sv", | |
"Polish": "pl", "Turkish": "tr", "Indonesian": "id", | |
"Thai": "th", "Vietnamese": "vi", | |
"Greek": "el", | |
"Hebrew": "he", | |
"Hungarian": "hu", | |
"Romanian": "ro", | |
"Czech": "cs", | |
"Finnish": "fi", | |
"Danish": "da", | |
"Norwegian": "nb", | |
"Slovak": "sk", | |
"Bulgarian": "bg", | |
# Add more language codes as needed | |
} | |
conversation_history = [] | |
def text_chat(text, max_output_tokens): | |
global conversation_history | |
model = genai.GenerativeModel(model_name="gemini-1.5-flash") | |
response = model.generate_content( | |
glm.Content( | |
parts=[ | |
glm.Part(text=text), | |
], | |
), | |
generation_config = { | |
"temperature" : 0.7, | |
"max_output_tokens" : max_output_tokens, | |
} , | |
stream=True | |
) | |
response.resolve() | |
conversation_history.append(("You", text)) | |
conversation_history.append(("Assistant", response.text)) | |
return conversation_history | |
def image_analysis(image, prompt, input_language, output_language, voice_input=None): | |
input_language = input_language or "English" | |
output_language = output_language or "English" | |
if voice_input: | |
# Convert voice input to text using the selected input language | |
recognizer = sr.Recognizer() | |
with sr.AudioFile(voice_input) as source: | |
audio = recognizer.record(source) | |
prompt = recognizer.recognize_google(audio, language=LANGUAGE_CODES[input_language]) | |
if input_language != "English": | |
prompt = GoogleTranslator(source=LANGUAGE_CODES[input_language], target='en').translate(prompt) | |
if isinstance(image, np.ndarray): | |
pil_image = Image.fromarray(image) | |
elif isinstance(image, Image.Image): | |
pil_image = image | |
else: | |
bytes_data = image | |
if 'pil_image' in locals(): | |
img_byte_arr = io.BytesIO() | |
pil_image.save(img_byte_arr, format='JPEG') | |
bytes_data = img_byte_arr.getvalue() | |
model = genai.GenerativeModel(model_name="gemini-1.5-flash") | |
response = model.generate_content( | |
glm.Content( | |
parts=[glm.Part(text=prompt), glm.Part(inline_data=glm.Blob(mime_type='image/jpeg', data=bytes_data))], | |
), | |
generation_config = { | |
"temperature" : 0.7, | |
"max_output_tokens" : 100, | |
} , | |
) | |
response.resolve() | |
if output_language != "English": | |
response_text = GoogleTranslator(source='en', target=LANGUAGE_CODES[output_language]).translate(response.text) | |
else: | |
response_text = response.text | |
return response_text # Return only the text response | |
class VoiceInteraction: | |
def __init__(self): | |
self.is_running = False | |
self.recognizer = sr.Recognizer() | |
self.model = genai.GenerativeModel(model_name="gemini-1.5-flash") | |
self.conversation = [] | |
self.current_state = None | |
self.current_image = None | |
self.input_language = "English" | |
self.output_language = "English" | |
self.voice = VOICES["English"]["Female"] | |
# Adjust the recognizer's settings for better sensitivity | |
self.recognizer.energy_threshold = 300 # Lower energy threshold for detecting speech | |
self.recognizer.dynamic_energy_threshold = True # Dynamically adjust for ambient noise | |
self.recognizer.pause_threshold = 0.5 | |
async def text_to_speech_and_play(self, text): | |
self.current_state = "Speaking" | |
communicate = edge_tts.Communicate(text, self.voice) | |
audio_path = "output.mp3" | |
await communicate.save(audio_path) | |
pygame.mixer.init() | |
pygame.mixer.music.load(audio_path) | |
pygame.mixer.music.play() | |
while pygame.mixer.music.get_busy(): | |
pygame.time.Clock().tick(10) | |
pygame.mixer.quit() | |
def listen_and_respond(self): | |
with sr.Microphone() as source: | |
self.recognizer.adjust_for_ambient_noise(source, duration=1) | |
while self.is_running: | |
try: | |
self.current_state = "Listening" | |
audio = self.recognizer.listen(source, timeout=3, phrase_time_limit=10) | |
text = self.recognizer.recognize_google(audio, language=LANGUAGE_CODES[self.input_language]) | |
if self.input_language != "English": | |
text = GoogleTranslator(source=LANGUAGE_CODES[self.input_language], target='en').translate(text) | |
self.conversation.append(("You", text)) | |
self.current_state = "Thinking" | |
if self.current_image: | |
response = image_analysis(self.current_image, text) | |
else: | |
response = self.model.generate_content( | |
glm.Content(parts=[glm.Part(text=text + "Give the Response in only plain text and without any Markdown Formatting ")]), | |
generation_config = { | |
"temperature" : 0.7, | |
"max_output_tokens" : 500, | |
} , | |
) | |
response.resolve() | |
response = response.text | |
if self.output_language != "English": | |
response = GoogleTranslator(source='en', target=LANGUAGE_CODES[self.output_language]).translate(response) | |
self.conversation.append(("Assistant", response)) | |
# Update the conversation output after each cycle | |
gr.update(value=self.conversation) | |
asyncio.run(self.text_to_speech_and_play(response)) | |
except sr.WaitTimeoutError: | |
continue | |
except sr.UnknownValueError: | |
gr.Markdown("Could not understand audio") | |
except sr.RequestError as e: | |
print(f"Error: {str(e)}") | |
def start(self): | |
self.is_running = True | |
self.thread = threading.Thread(target=self.listen_and_respond) | |
self.thread.start() | |
def stop(self): | |
self.is_running = False | |
if hasattr(self, 'thread'): | |
self.thread.join() | |
def set_current_image(self, image): | |
self.current_image = image | |
def set_languages_and_voice(self, input_language, output_language, voice_gender): | |
self.input_language = input_language | |
self.output_language = output_language | |
self.voice = VOICES[output_language][voice_gender] | |
voice_interaction = VoiceInteraction() | |
def start_voice_interaction(): | |
voice_interaction.start() | |
return "Voice interaction started. Speak now!", voice_interaction.conversation | |
def stop_voice_interaction(): | |
voice_interaction.stop() | |
return "Voice interaction stopped.", voice_interaction.conversation | |
def update_conversation(): | |
return voice_interaction.conversation | |
def get_current_gif(): | |
state = voice_interaction.current_state | |
if state == "Listening": | |
return GIF_LISTENING | |
elif state == "Thinking": | |
return GIF_THINKING | |
elif state == "Speaking": | |
return GIF_SPEAKING | |
else: | |
return GIF_NEUTRAL | |
def analyze_and_speak(image, prompt, input_language, output_language, voice_input=None): | |
response_text = image_analysis(image, prompt, input_language, output_language, voice_input) | |
# Generate audio response | |
voice = VOICES[output_language]["Female"] | |
communicate = edge_tts.Communicate(response_text, voice) | |
audio_path = "image_analysis_response.mp3" | |
asyncio.run(communicate.save(audio_path)) | |
return response_text, audio_path | |
def set_image_for_voice(image): | |
voice_interaction.set_current_image(image) | |
return "Image set for voice interaction. You can now ask questions about it." | |
def set_languages_and_voice(input_language, output_language, voice_gender): | |
voice_interaction.set_languages_and_voice(input_language, output_language, voice_gender) | |
return f"Input language set to {input_language}, output language set to {output_language} with {voice_gender} voice" | |
with gr.Blocks(theme=gr.themes.Soft()) as demo: | |
gr.Markdown("# π Conerstional Image Recognition Chatbot") | |
gr.Markdown("## Developed by AI INTENTS ") | |
with gr.Tab("π Home"): | |
gr.Markdown(""" | |
## Welcome to the Conversational Image Recognition Chatbot! | |
This application offers three main features: | |
1. **π¬ Text Chat**: Engage in a text-based conversation with our AI assistant. | |
2. **πΌοΈ Image Analysis**: Upload or capture images for AI-powered analysis and description. | |
3. **ποΈ Voice Interaction**: Have a voice conversation with our AI, with support for multiple languages. | |
Choose a tab above to get started! | |
### How to use: | |
- In Text Chat, simply type your message and click 'Send'. | |
- For Image Analysis, upload an image or use your webcam, then type or speak your question about the image. | |
- In Voice Interaction, click 'Start' and begin speaking. The AI will respond audibly. | |
Enjoy exploring the capabilities of our AI-powered chatbot! | |
""") | |
with gr.Tab("π¬ Text Chat"): | |
with gr.Row(): | |
with gr.Column(scale=4): | |
text_input = gr.Textbox(label="Your message", placeholder="Type your message here...") | |
max_tokens_slider = gr.Slider(minimum=100, maximum=1000, value=500, step=50, label="Max Output Tokens") | |
with gr.Column(scale=1): | |
text_button = gr.Button("Send", variant="primary") | |
text_output = gr.Chatbot(height=400, elem_id="text-chat-output") | |
text_button.click(text_chat, inputs=[text_input, max_tokens_slider], outputs=text_output) | |
with gr.Tab("πΌοΈ Image Analysis"): | |
with gr.Row(): | |
with gr.Column(scale=1): | |
with gr.Row(): | |
image_input = gr.Image(label="Upload Image", type="pil") | |
webcam_button = gr.Button("Capture from Webcam") | |
with gr.Column(scale=1): | |
image_prompt = gr.Textbox(label="Prompt", placeholder="Ask about the image...") | |
input_language_dropdown = gr.Dropdown(choices=list(VOICES.keys()), label="Input Language", value="English") | |
output_language_dropdown = gr.Dropdown(choices=list(VOICES.keys()), label="Output Language", value="English") | |
image_prompt_voice = gr.Audio(label="Prompt via Voice", sources=["microphone"], type="filepath") | |
image_prompt_audio = gr.Audio(label="Upload Audio File", sources=["upload"], type="filepath") | |
image_button = gr.Button("Analyze", variant="primary") | |
image_output = gr.Markdown(label="Analysis Result", elem_id="image-analysis-output") | |
audio_output = gr.Audio(label="Audio Response", elem_id="image-analysis-audio-output") | |
def capture_image_from_webcam(): | |
cap = cv2.VideoCapture(0) | |
ret, frame = cap.read() | |
cap.release() | |
return Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) | |
webcam_button.click(capture_image_from_webcam, outputs=image_input) | |
image_button.click( | |
analyze_and_speak, | |
inputs=[image_input, image_prompt, input_language_dropdown, output_language_dropdown], | |
outputs=[image_output, audio_output] | |
) | |
# Add events for voice and audio file inputs | |
image_prompt_voice.change( | |
image_analysis, | |
inputs=[image_input, image_prompt_voice, input_language_dropdown, output_language_dropdown, image_prompt_voice], | |
outputs=[image_output, audio_output] | |
) | |
image_prompt_audio.change( | |
image_analysis, | |
inputs=[image_input, image_prompt_audio, input_language_dropdown, output_language_dropdown, image_prompt_audio], | |
outputs=[image_output, audio_output] | |
) | |
image_button.click(image_analysis, inputs=[image_input, image_prompt], outputs=image_output) | |
image_prompt_voice.change(lambda x: image_analysis(image_input.value, x), inputs=image_prompt_voice, outputs=image_output) | |
with gr.Tab("ποΈ Voice Interaction"): | |
with gr.Row(): | |
start_button = gr.Button("Start Voice Interaction", variant="primary") | |
stop_button = gr.Button("Stop Voice Interaction", variant="secondary") | |
with gr.Row(): | |
input_language_dropdown = gr.Dropdown(choices=list(VOICES.keys()), label="Input Language", value="English") | |
output_language_dropdown = gr.Dropdown(choices=list(VOICES.keys()), label="Output Language", value="English") | |
voice_gender_dropdown = gr.Dropdown(choices=["Female", "Male"], label="Voice Gender", value="Female") | |
set_language_button = gr.Button("Set Languages and Voice") | |
sensitivity_slider = gr.Slider(minimum=100, maximum=1000, value=300, step=50, label="Microphone Sensitivity") | |
with gr.Row(): | |
with gr.Column(scale=1): | |
gif_output = gr.Image(label="Status", visible=True, elem_id="voice-interaction-gif") | |
status_output = gr.Markdown(label="Status", elem_id="voice-interaction-status") | |
with gr.Column(scale=1): | |
conversation_output = gr.Chatbot(label="Conversation", height=400, elem_id="voice-interaction-output") | |
demo.load(update_conversation, inputs=[], outputs=[conversation_output], every=1) | |
start_button.click(start_voice_interaction, inputs=[], outputs=[status_output, conversation_output]) | |
stop_button.click(stop_voice_interaction, inputs=[], outputs=[status_output, conversation_output]) | |
set_language_button.click(set_languages_and_voice, | |
inputs=[input_language_dropdown, output_language_dropdown, voice_gender_dropdown], | |
outputs=status_output) | |
demo.load(get_current_gif, inputs=[], outputs=gif_output, every=1) | |
def update_sensitivity(value): | |
voice_interaction.recognizer.energy_threshold = value | |
return f"Microphone sensitivity set to {value}" | |
sensitivity_slider.change(update_sensitivity, inputs=[sensitivity_slider], outputs=[status_output]) | |
gr.Markdown("## Developed by AI INTENTS ") | |
demo.launch(share=True) | |