diff --git a/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/.gitattributes b/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/.gitattributes new file mode 100644 index 0000000..a6344aa --- /dev/null +++ b/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/.gitattributes @@ -0,0 +1,35 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text diff --git a/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/README.md b/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/README.md new file mode 100644 index 0000000..faccc29 --- /dev/null +++ b/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/README.md @@ -0,0 +1,13 @@ +--- +title: Voice Enabled Multi Model AI Assistant +emoji: 💻 +colorFrom: gray +colorTo: gray +sdk: gradio +sdk_version: 5.49.0 +app_file: Voice_Enabled_Multi_Model_AI_Assistant.py +pinned: false +license: apache-2.0 +--- + +Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference diff --git a/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/Voice_Enabled_Multi_Model_AI_Assistant.py b/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/Voice_Enabled_Multi_Model_AI_Assistant.py new file mode 100644 index 0000000..202577d --- /dev/null +++ b/week2/community-contributions/Voice_Enabled_Multi_Model_AI_Assistant/Voice_Enabled_Multi_Model_AI_Assistant.py @@ -0,0 +1,620 @@ +import os +import gradio as gr +from openai import OpenAI +import anthropic +import google.generativeai as genai +from dotenv import load_dotenv + +# Load environment variables +load_dotenv() +OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") +anthropic_api_key = os.getenv('ANTHROPIC_API_KEY') +google_api_key = os.getenv('GOOGLE_API_KEY') + +# Verify API keys are loaded +if not OPENAI_API_KEY: + raise ValueError("OPENAI_API_KEY not found in environment variables") +if not anthropic_api_key: + raise ValueError("ANTHROPIC_API_KEY not found in environment variables") +if not google_api_key: + raise ValueError("GOOGLE_API_KEY not found in environment variables") + +# Initialize clients +openai_client = OpenAI(api_key=OPENAI_API_KEY) +genai.configure(api_key=google_api_key) +claude_client = anthropic.Anthropic(api_key=anthropic_api_key) + +# System prompt - Universal and comprehensive +SYSTEM_PROMPT = """You are a highly capable and versatile AI assistant designed to help with any type of question or task. + +Your capabilities span across all domains including but not limited to: +- Programming, software development, and technology +- Science, mathematics, and engineering +- Arts, literature, and creative writing +- History, philosophy, and social sciences +- Business, finance, and economics +- Health, wellness, and lifestyle advice +- Education and learning support +- Problem-solving and critical thinking +- General knowledge and trivia +- Casual conversation and entertainment + +Guidelines: +- Provide accurate, helpful, and comprehensive responses +- Adapt your tone and style to match the context of the question +- Use examples and explanations when helpful +- Be creative when asked for creative content +- Be precise and factual when asked for information +- Ask clarifying questions if the request is ambiguous +- Admit when you're uncertain and provide the best possible guidance +- Be conversational, friendly, and supportive + +You can help with anything from technical coding problems to creative storytelling, from academic research to casual chat. There are no topic restrictions - feel free to engage with any subject matter the user brings up.""" + +# Model configurations +model_configs = { + "GPT-4o": {"provider": "openai", "model": "gpt-4o"}, + "GPT-4o-mini": {"provider": "openai", "model": "gpt-4o-mini"}, + "GPT-3.5-turbo": {"provider": "openai", "model": "gpt-3.5-turbo"}, + "Claude Sonnet 4": {"provider": "anthropic", "model": "claude-sonnet-4-20250514"}, + "Gemini 2.0 Flash": {"provider": "google", "model": "gemini-2.0-flash-exp"}, +} + +def chat_streaming(message, history, model_name, temperature): + """Main chat function with streaming support""" + + config = model_configs[model_name] + provider = config["provider"] + model = config["model"] + + # Convert messages format history to API format + messages = [] + for msg in history: + if msg["role"] == "user": + messages.append({"role": "user", "content": msg["content"]}) + elif msg["role"] == "assistant": + messages.append({"role": "assistant", "content": msg["content"]}) + messages.append({"role": "user", "content": message}) + + # Stream based on provider + if provider == "openai": + stream = openai_client.chat.completions.create( + model=model, + messages=[{"role": "system", "content": SYSTEM_PROMPT}] + messages, + temperature=temperature, + stream=True + ) + + response = "" + for chunk in stream: + if chunk.choices[0].delta.content: + response += chunk.choices[0].delta.content + yield response + + elif provider == "anthropic": + response = "" + with claude_client.messages.stream( + model=model, + max_tokens=2000, + temperature=temperature, + system=SYSTEM_PROMPT, + messages=messages, + ) as stream: + for text in stream.text_stream: + response += text + yield response + + elif provider == "google": + gemini = genai.GenerativeModel( + model_name=model, + system_instruction=SYSTEM_PROMPT, + ) + + # Convert history for Gemini + gemini_history = [] + for msg in history: + if msg["role"] == "user": + gemini_history.append({"role": "user", "parts": [msg["content"]]}) + elif msg["role"] == "assistant": + gemini_history.append({"role": "model", "parts": [msg["content"]]}) + + chat = gemini.start_chat(history=gemini_history) + + stream = chat.send_message( + message, + stream=True, + generation_config=genai.types.GenerationConfig(temperature=temperature) + ) + + response = "" + for chunk in stream: + response += chunk.text + yield response + +def handle_audio_input(audio): + """Transcribe audio input using Whisper""" + if audio is None: + return "" + + try: + audio_file = open(audio, "rb") + transcript = openai_client.audio.transcriptions.create( + model="whisper-1", + file=audio_file + ) + return transcript.text + except Exception as e: + return f"Error transcribing audio: {str(e)}" + +def text_to_speech(text): + """Convert text response to speech""" + try: + response = openai_client.audio.speech.create( + model="tts-1", + voice="nova", + input=text[:4096] # Limit to prevent errors + ) + + audio_path = "response.mp3" + response.stream_to_file(audio_path) + return audio_path + except Exception as e: + print(f"TTS Error: {str(e)}") + return None + +# Custom CSS for modern, attractive UI +custom_css = """ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); + +.gradio-container { + font-family: 'Inter', sans-serif !important; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; +} + +:root .dark { + --background-fill-primary: #f0f0f0; + --body-background-fill: var(--background-fill-primary); + --block-background-fill: white !important; + --block-title-background-fill: #dfe7ff; + --block-title-text-color:#6366f1; + --body-text-color: black; + --button-secondary-text-color:black; + --input-background-fill:white; + + --block-label-background-fill:#dfe7ff; + --block-label-text-color:#6366f1; + + --block-border-color:#eaeaea; + --input-border-color: #eaeaea; + --border-color-primary:#eaeaea; + + --color-accent-soft: #dfe7ff; + --border-color-accent-subdued: #98a6cf; + + --checkbox-background-color: #eaeaea; + --checkbox-border-color: #eaeaea; + --background-fill-secondary:#eaeaea; +} + +.main { + background: white; + border-radius: 20px; + box-shadow: 0 20px 60px rgba(0,0,0,0.3); + padding: 0 !important; + overflow: hidden; +} + +.contain { + padding: 2rem !important; +} + +/* Header Styling */ +.header-section { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + padding: 2.5rem 2rem; + border-radius: 20px 20px 0 0; + margin: -2rem 0rem 2rem 0rem; + color: white; + box-shadow: 0 4px 20px rgba(102, 126, 234, 0.4); +} + +.header-section h1 { + font-size: 2.5rem !important; + font-weight: 700 !important; + margin: 0 0 0.5rem 0 !important; + color: white !important; + text-shadow: 2px 2px 4px rgba(0,0,0,0.2); +} + +.header-section p { + font-size: 1.1rem !important; + margin: 0.5rem 0 !important; + color: rgba(255,255,255,0.95) !important; + font-weight: 400; +} + +.feature-badge { + display: inline-block; + background: rgba(255,255,255,0.2); + padding: 0.4rem 1rem; + border-radius: 20px; + margin: 0.3rem; + font-size: 0.9rem; + backdrop-filter: blur(10px); + border: 1px solid rgba(255,255,255,0.3); +} + +/* Sidebar Styling */ +.control-panel { + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + padding: 1.5rem; + border-radius: 15px; + box-shadow: 0 4px 15px rgba(0,0,0,0.1); + height: 100%; +} + +.control-panel label { + font-weight: 600 !important; + font-size: 0.95rem !important; +} + +/* Dropdown Styling */ +.dropdown-container select { + background: white !important; + border: 2px solid #e2e8f0 !important; + border-radius: 10px !important; + padding: 0.75rem !important; + font-weight: 500 !important; + transition: all 0.3s ease !important; +} + +.dropdown-container select:hover { + border-color: #667eea !important; + box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important; +} + +/* Slider Styling */ +input[type="range"] { + accent-color: #667eea !important; +} + +/* Button Styling */ +.primary-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + border: none !important; + color: white !important; + font-weight: 600 !important; + padding: 0.75rem 2rem !important; + border-radius: 10px !important; + box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4) !important; + transition: all 0.3s ease !important; +} + +.primary-btn:hover { + transform: translateY(-2px) !important; + box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6) !important; +} + +.secondary-btn { + background: #e2e8f0 !important; + border: none !important; + color: #2d3748 !important; + font-weight: 600 !important; + padding: 0.75rem 1.5rem !important; + border-radius: 10px !important; + transition: all 0.3s ease !important; +} + +.secondary-btn:hover { + background: #cbd5e0 !important; + transform: translateY(-2px) !important; +} + +/* Chatbot Styling */ +.chatbot-container { + background: white; + border-radius: 15px; + border: 2px solid #e2e8f0; + box-shadow: 0 4px 20px rgba(0,0,0,0.08); + overflow: hidden; +} + +/* Input Box Styling */ +.message-input textarea { + border: 2px solid #e2e8f0 !important; + border-radius: 12px !important; + padding: 1rem !important; + font-size: 1rem !important; + transition: all 0.3s ease !important; +} + +.message-input textarea:focus { + border-color: #667eea !important; + box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important; +} + +/* Input Row Centering */ +.input-row { + display: flex !important; + justify-content: center !important; + align-items: center !important; + gap: 1rem !important; +} + +.input-row > * { + flex-shrink: 0 !important; +} + +/* Audio Components */ +.audio-component { + background: #f7fafc; + border: 2px dashed #cbd5e0; + border-radius: 12px; + padding: 1rem; + transition: all 0.3s ease; +} + +.audio-component:hover { + border-color: #667eea; + background: #edf2f7; +} + +/* Checkbox Styling */ +.checkbox-label { + display: flex; + align-items: center; + gap: 0.5rem; + font-weight: 500; + color: #2d3748; +} + +/* Tips Section */ +.tips-section { + background: linear-gradient(135deg, #f7fafc 0%, #edf2f7 100%); + padding: 1.5rem; + border-radius: 15px; + margin-top: 2rem; + border-left: 4px solid #667eea; +} + +.tips-section h3 { + color: #667eea !important; + font-weight: 600 !important; + margin-bottom: 1rem !important; +} + +.tips-section ul { + list-style: none; + padding: 0; +} + +.tips-section li { + padding: 0.5rem 0; + color: #4a5568 !important; + font-size: 0.95rem; +} + +.tips-section li:before { + content: "→ "; + color: #667eea; + font-weight: bold; + margin-right: 0.5rem; +} + +/* Force black color for strong/bold text */ +.tips-section strong { + color: #1a202c !important; +} + +.prose * { + color: inherit !important; +} + +.prose strong { + color: #1a202c !important; + font-weight: 600 !important; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .header-section h1 { + font-size: 1.8rem !important; + } + + .contain { + padding: 1rem !important; + } +} + +.fillable{ + max-width:95% !important; +} +#component-5{ + flex-grow:1.1 !important; +} +.bubble-wrap.svelte-gjtrl6 { + background:none !important; +} +.bot.svelte-1csv61q.message { + background-color: white !important; + border: 1px solid #f3f3f3; +} +.options.svelte-y6qw75> li:hover{ + background:white ; +} +.options.svelte-y6qw75> .selected{ + background:white ; +} + +""" + +# Build Gradio Interface +with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo: + + # Header + with gr.Row(elem_classes="header-section"): + with gr.Column(): + gr.HTML(""" +
Your intelligent companion for any question - from coding to creativity, science to storytelling!
+