import os import gradio as gr from groq import Groq # 1. Setup API Client api_key = os.environ.get("GROQ_API_KEY") client = Groq(api_key=api_key) # 2. UI Styling custom_css = """ /* Standard Layout */ .gradio-container { max-width: 100% !important; height: 95vh !important; margin: 0 !important; padding: 10px 20px !important; } #chatbot-window { height: 70vh !important; border-radius: 12px; border: 1px solid #e0e0e0; background: white; } /* --- MOBILE RESPONSIVE LOGIC --- */ @media (max-width: 768px) { .gradio-container { padding: 5px !important; height: auto !important; } #chatbot-window { height: 60vh !important; } .sidebar-panel { min-width: 100% !important; margin-top: 20px; } h1 { font-size: 1.5rem !important; } } /* Dark Mode Overrides */ .dark #chatbot-window { background: #1a1a1a !important; border-color: #444 !important; } #system-prompt-container textarea, .scroll-input textarea { height: 45px !important; max-height: 45px !important; overflow-y: auto !important; resize: none !important; } #settings-btn { width: 44px !important; height: 44px !important; min-width: 44px !important; border-radius: 8px !important; background: #f0f0f0 !important; border: 1px solid #ddd !important; display: flex !important; align-items: center !important; justify-content: center !important; font-size: 20px !important; cursor: pointer !important; } .sidebar-panel { background-color: #f9f9f9; padding: 15px !important; border-radius: 12px; border: 1px solid #ddd; min-width: 300px !important; } .dark .sidebar-panel { background-color: #2d2d2d !important; border-color: #444 !important; } """ # 3. Secure Chat Logic def chat_with_groq(message, history, model, temperature, system_prompt): cleaned_messages = [{"role": "system", "content": system_prompt}] for msg in history: cleaned_messages.append({"role": msg["role"], "content": msg["content"]}) cleaned_messages.append({"role": "user", "content": message}) try: response = client.chat.completions.create( model=model, messages=cleaned_messages, temperature=temperature, stream=True ) partial_message = "" for chunk in response: if chunk.choices[0].delta.content: partial_message += chunk.choices[0].delta.content yield partial_message except Exception as e: yield f"⚠️ API Error: {str(e)}" def toggle_dark_mode(current_is_dark): new_state = not current_is_dark new_label = "☀️ Light Mode" if new_state else "🌙 Dark Mode" return new_label, new_state toggle_dark_js = """() => { document.body.classList.toggle('dark'); }""" # 4. Interface Setup with gr.Blocks() as demo: sidebar_state = gr.State(False) dark_state = gr.State(False) # Header Section with gr.Row(): with gr.Column(scale=20): gr.Markdown("# 🤖 SageBot | *Developed by Hassan Naseer*") with gr.Column(scale=1, min_width=50): settings_btn = gr.Button("⚙️", elem_id="settings-btn") with gr.Row(): # Main Chat Area with gr.Column(scale=4) as chat_col: chatbot = gr.Chatbot(elem_id="chatbot-window") with gr.Row(): msg_input = gr.Textbox( placeholder="Ask me anything...", container=False, scale=9, elem_classes="scroll-input" ) submit_btn = gr.Button("Send", variant="primary", scale=1, min_width=80) # Sidebar Area with gr.Column(scale=1, visible=False, elem_classes="sidebar-panel") as sidebar_col: dark_btn = gr.Button("🌙 Dark Mode", variant="secondary") model_choice = gr.Dropdown( choices=["llama-3.3-70b-versatile", "llama-3.1-8b-instant"], value="llama-3.3-70b-versatile", label="Select Model" ) temp = gr.Slider(0.0, 1.0, 0.7, label="Temperature") sys_msg = gr.Textbox( value="You are a professional assistant.", label="System Prompt", lines=1, elem_id="system-prompt-container" ) # Re-added Support Section with full SVG Icons gr.HTML("""
""") # --- Events --- settings_btn.click(lambda s: (gr.update(visible=not s), not s), [sidebar_state], [sidebar_col, sidebar_state]) dark_btn.click(toggle_dark_mode, [dark_state], [dark_btn, dark_state], js=toggle_dark_js) def user_turn(msg, hist): if not msg: return "", hist hist.append({"role": "user", "content": msg}) return "", hist def bot_turn(hist, m, t, s): user_msg = hist[-1]["content"] gen = chat_with_groq(user_msg, hist[:-1], m, t, s) hist.append({"role": "assistant", "content": ""}) for chunk in gen: hist[-1]["content"] = chunk yield hist msg_input.submit(user_turn, [msg_input, chatbot], [msg_input, chatbot], queue=False).then( bot_turn, [chatbot, model_choice, temp, sys_msg], chatbot ) submit_btn.click(user_turn, [msg_input, chatbot], [msg_input, chatbot], queue=False).then( bot_turn, [chatbot, model_choice, temp, sys_msg], chatbot ) if __name__ == "__main__": demo.launch(css=custom_css)