Spaces:
Paused
Paused
| import gradio as gr | |
| import os | |
| import spaces | |
| from groq import Groq | |
| # Initialize the Groq client via Hugging Face Secrets | |
| api_key = os.environ.get("GROQ_API_KEY") | |
| if not api_key: | |
| raise ValueError("GROQ_API_KEY environment variable not found. Please add it as a Secret in your Space Settings.") | |
| client = Groq(api_key=api_key) | |
| # Custom CSS for modern styling | |
| custom_css = """ | |
| .gradio-container { background-color: #0b0f19; font-family: 'Inter', sans-serif; } | |
| #title-header { text-align: center; margin-bottom: 20px; } | |
| #title-header h1 { color: #38bdf8; font-weight: 800; font-size: 2.2rem; } | |
| .sidebar-panel { background: #111827 !important; border: 1px solid #1f2937 !important; border-radius: 12px !important; } | |
| .chat-window { border: 1px solid #1f2937 !important; border-radius: 12px !important; background: #111827 !important; } | |
| """ | |
| def chat_stream(message, history, model, system_prompt, temperature, max_tokens): | |
| """ | |
| Handles streaming responses using the standard tuple-based chat history format. | |
| history layout: [[user_msg1, bot_msg1], [user_msg2, bot_msg2], ...] | |
| """ | |
| if not message.strip(): | |
| yield history | |
| return | |
| # 1. Initialize message list with system prompt for Groq API | |
| api_messages = [{"role": "system", "content": system_prompt}] | |
| # 2. Append existing conversation history seamlessly | |
| for user_msg, bot_msg in history: | |
| if user_msg: | |
| api_messages.append({"role": "user", "content": user_msg}) | |
| if bot_msg: | |
| api_messages.append({"role": "assistant", "content": bot_msg}) | |
| # 3. Append the newest user message to the API list | |
| api_messages.append({"role": "user", "content": message}) | |
| # 4. Update the Gradio UI history with an empty slot for the bot's upcoming message | |
| history.append([message, ""]) | |
| yield history | |
| # 5. Stream from Groq | |
| try: | |
| stream = client.chat.completions.create( | |
| model=model, | |
| messages=api_messages, | |
| temperature=temperature, | |
| max_tokens=max_tokens, | |
| stream=True, | |
| ) | |
| partial_response = "" | |
| for chunk in stream: | |
| if chunk.choices[0].delta.content: | |
| partial_response += chunk.choices[0].delta.content | |
| # Update the very last bot message slot in history | |
| history[-1][1] = partial_response | |
| yield history | |
| except Exception as e: | |
| history[-1][1] = f"⚠️ Error connecting to Groq: {str(e)}" | |
| yield history | |
| # Build the layout manually | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 🚀 Personal AI ChatBot", elem_id="title-header") | |
| gr.Markdown("A fully customizable, hyper-fast LLM workspace.") | |
| with gr.Row(): | |
| # --- LEFT COLUMN: CONTROL PANEL --- | |
| with gr.Column(scale=1, elem_classes="sidebar-panel"): | |
| gr.Markdown("### ⚙️ Engine Configurations") | |
| model_select = gr.Dropdown( | |
| choices=["llama-3.3-70b-versatile", "llama-3.1-8b-instant"], | |
| value="llama-3.3-70b-versatile", | |
| label="Select AI Model" | |
| ) | |
| system_input = gr.Textbox( | |
| value="You are a helpful, brilliant, and concise AI assistant.", | |
| label="System Prompt / AI Persona", | |
| lines=3, | |
| placeholder="Ex: Act as a cynical senior developer..." | |
| ) | |
| gr.Markdown("---") | |
| gr.Markdown("### 🧠 Hyperparameters") | |
| temp_slider = gr.Slider( | |
| minimum=0.0, maximum=2.0, value=0.7, step=0.1, | |
| label="Temperature", info="Higher = more creative, Lower = more factual" | |
| ) | |
| tokens_slider = gr.Slider( | |
| minimum=128, maximum=4096, value=1024, step=128, | |
| label="Max Output Tokens" | |
| ) | |
| gr.Markdown("---") | |
| gr.Markdown("**Status:** 🟢 Connected via ZeroGPU to Groq") | |
| # --- RIGHT COLUMN: CHAT INTERFACE --- | |
| with gr.Column(scale=3): | |
| # Removed the `type="messages"` keyword argument entirely to prevent the TypeError | |
| chatbot = gr.Chatbot(elem_classes="chat-window") | |
| msg_input = gr.Textbox( | |
| placeholder="Type your message here and press Enter...", | |
| show_label=False, | |
| container=False | |
| ) | |
| clear_btn = gr.Button("🗑️ Clear Conversation") | |
| # Native component wiring | |
| msg_input.submit( | |
| fn=chat_stream, | |
| inputs=[msg_input, chatbot, model_select, system_input, temp_slider, tokens_slider], | |
| outputs=[chatbot] | |
| ).then( | |
| fn=lambda: "", | |
| inputs=None, | |
| outputs=[msg_input] | |
| ) | |
| # Clear chat utility logic | |
| clear_btn.click(fn=lambda: [], inputs=None, outputs=[chatbot]) | |
| if __name__ == "__main__": | |
| demo.launch(css=custom_css, theme=gr.themes.Soft()) |