Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| from huggingface_hub import InferenceClient | |
| import os | |
| from typing import Generator, List, Dict, Any, Optional | |
| # Default model configurations | |
| DEFAULT_MODEL = "meta-llama/Llama-3.2-11B-Vision-Instruct" | |
| DEFAULT_SYSTEM_MESSAGE = "You are a helpful, harmless, and honest AI assistant." | |
| # Available models from Hugging Face | |
| AVAILABLE_MODELS = [ | |
| "meta-llama/Llama-3.2-11B-Vision-Instruct", | |
| "meta-llama/Llama-3.2-3B-Instruct", | |
| "meta-llama/Llama-3.1-8B-Instruct", | |
| "mistralai/Mistral-7B-Instruct-v0.3", | |
| "HuggingFaceH4/zephyr-7b-beta", | |
| "microsoft/Phi-3-mini-4k-instruct", | |
| "google/gemma-2-2b-it", | |
| "Qwen/Qwen2.5-7B-Instruct", | |
| ] | |
| def get_inference_client(token: Optional[str] = None) -> InferenceClient: | |
| """Create an InferenceClient with optional token.""" | |
| return InferenceClient(token=token or os.getenv("HF_TOKEN")) | |
| def format_messages( | |
| message: str, | |
| history: List[Dict[str, str]], | |
| system_message: str, | |
| image: Optional[Any] = None | |
| ) -> List[Dict[str, Any]]: | |
| """Format messages for the chat API.""" | |
| messages = [] | |
| # Add system message if present | |
| if system_message: | |
| messages.append({"role": "system", "content": system_message}) | |
| # Add conversation history | |
| for msg in history: | |
| messages.append({"role": msg["role"], "content": msg["content"]}) | |
| # Add current message with image if multimodal | |
| if image is not None: | |
| # For multimodal, content is a list | |
| content = [] | |
| if image is not None: | |
| content.append({"type": "image", "url": image}) | |
| content.append({"type": "text", "text": message}) | |
| messages.append({"role": "user", "content": content}) | |
| else: | |
| messages.append({"role": "user", "content": message}) | |
| return messages | |
| def chat_response( | |
| message: str, | |
| history: List[Dict[str, str]], | |
| model: str, | |
| system_message: str, | |
| temperature: float, | |
| max_tokens: int, | |
| top_p: float, | |
| token: str, | |
| image: Optional[Any] = None, | |
| ) -> Generator[str, None, None]: | |
| """ | |
| Generate streaming chat response from Hugging Face model. | |
| """ | |
| try: | |
| client = get_inference_client(token if token else None) | |
| # Format messages | |
| messages = format_messages(message, history, system_message, image) | |
| # Stream the response | |
| stream = client.chat.completions.create( | |
| model=model, | |
| messages=messages, | |
| temperature=temperature, | |
| max_tokens=max_tokens, | |
| top_p=top_p, | |
| stream=True, | |
| ) | |
| partial_message = "" | |
| for chunk in stream: | |
| if chunk.choices and chunk.choices[0].delta.content: | |
| partial_message += chunk.choices[0].delta.content | |
| yield partial_message | |
| except Exception as e: | |
| error_msg = f"Error: {str(e)}" | |
| if "401" in str(e): | |
| error_msg = "Authentication Error: Please provide a valid Hugging Face token." | |
| elif "404" in str(e): | |
| error_msg = f"Model '{model}' not found or not available." | |
| elif "429" in str(e): | |
| error_msg = "Rate limit exceeded. Please try again later." | |
| yield error_msg | |
| def clear_chat(): | |
| """Clear the chat history.""" | |
| return None | |
| def get_model_info(model: str) -> str: | |
| """Get information about the selected model.""" | |
| info = { | |
| "meta-llama/Llama-3.2-11B-Vision-Instruct": | |
| "Multimodal model supporting both text and images. Great for vision tasks.", | |
| "meta-llama/Llama-3.2-3B-Instruct": | |
| "Efficient small model good for quick responses and simpler tasks.", | |
| "meta-llama/Llama-3.1-8B-Instruct": | |
| "Balanced performance and quality. Good general-purpose assistant.", | |
| "mistralai/Mistral-7B-Instruct-v0.3": | |
| "Strong performance on reasoning and coding tasks.", | |
| "HuggingFaceH4/zephyr-7b-beta": | |
| "Fine-tuned for helpful and engaging conversations.", | |
| "microsoft/Phi-3-mini-4k-instruct": | |
| "Compact model with strong reasoning capabilities.", | |
| "google/gemma-2-2b-it": | |
| "Lightweight model from Google, good for everyday tasks.", | |
| "Qwen/Qwen2.5-7B-Instruct": | |
| "Strong multilingual capabilities and long context understanding.", | |
| } | |
| return info.get(model, "No information available.") | |
| def toggle_multimodal(multimodal: bool) -> Dict[str, Any]: | |
| """Toggle multimodal input visibility.""" | |
| return { | |
| "visible": multimodal, | |
| "value": None | |
| } | |
| # Custom theme for modern appearance | |
| custom_theme = gr.themes.Soft( | |
| primary_hue="indigo", | |
| secondary_hue="blue", | |
| neutral_hue="slate", | |
| font=gr.themes.GoogleFont("Inter"), | |
| text_size="md", | |
| spacing_size="md", | |
| radius_size="lg" | |
| ).set( | |
| button_primary_background_fill="*primary_600", | |
| button_primary_background_fill_hover="*primary_700", | |
| button_secondary_background_fill="*neutral_100", | |
| button_secondary_background_fill_hover="*neutral_200", | |
| block_title_text_weight="600", | |
| block_label_text_weight="500", | |
| ) | |
| # CSS for additional styling | |
| custom_css = """ | |
| .gradio-container { | |
| max-width: 1400px !important; | |
| } | |
| .chatbot-container { | |
| min-height: 500px; | |
| } | |
| .settings-accordion { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| } | |
| .built-with { | |
| text-align: center; | |
| padding: 10px; | |
| margin-top: 20px; | |
| color: #6b7280; | |
| font-size: 0.875rem; | |
| } | |
| .built-with a { | |
| color: #4f46e5; | |
| text-decoration: none; | |
| font-weight: 500; | |
| } | |
| .built-with a:hover { | |
| text-decoration: underline; | |
| } | |
| """ | |
| with gr.Blocks(theme=custom_theme, css=custom_css) as demo: | |
| # Header | |
| gr.Markdown(""" | |
| # 🤖 Hugging Face Chat Interface | |
| Chat with state-of-the-art language models from the Hugging Face Hub. | |
| Supports both text-only and multimodal (text + image) conversations. | |
| """) | |
| # Built with anycoder link | |
| gr.Markdown(""" | |
| <div class="built-with"> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">Built with anycoder</a> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| # Main chat area | |
| with gr.Column(scale=3): | |
| chatbot = gr.Chatbot( | |
| label="Conversation", | |
| height=500, | |
| type="messages", | |
| show_copy_button=True, | |
| avatar_images=( | |
| "https://cdn-icons-png.flaticon.com/512/1077/1077114.png", # user | |
| "https://cdn-icons-png.flaticon.com/512/4712/4712035.png", # assistant | |
| ), | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=10): | |
| msg_input = gr.MultimodalTextbox( | |
| label="Message", | |
| placeholder="Type your message here...", | |
| show_label=False, | |
| sources=["upload", "clipboard"], | |
| file_count="single", | |
| file_types=["image"], | |
| submit_btn=True, | |
| stop_btn=True, | |
| ) | |
| with gr.Column(scale=1, min_width=80): | |
| clear_btn = gr.ClearButton( | |
| components=[chatbot, msg_input], | |
| value="🗑️", | |
| size="lg", | |
| ) | |
| # Settings sidebar | |
| with gr.Column(scale=1, min_width=300): | |
| with gr.Accordion("⚙️ Model Settings", open=True): | |
| model_dropdown = gr.Dropdown( | |
| choices=AVAILABLE_MODELS, | |
| value=DEFAULT_MODEL, | |
| label="Model", | |
| info="Select a Hugging Face model" | |
| ) | |
| model_info = gr.Textbox( | |
| value=get_model_info(DEFAULT_MODEL), | |
| label="Model Info", | |
| interactive=False, | |
| lines=3, | |
| ) | |
| hf_token = gr.Textbox( | |
| label="Hugging Face Token", | |
| placeholder="hf_... (optional)", | |
| type="password", | |
| info="Required for some models. Get yours at huggingface.co/settings/tokens", | |
| ) | |
| system_msg = gr.Textbox( | |
| label="System Message", | |
| value=DEFAULT_SYSTEM_MESSAGE, | |
| lines=3, | |
| info="Instructions for the AI's behavior", | |
| ) | |
| with gr.Accordion("🔧 Generation Parameters", open=False): | |
| temperature = gr.Slider( | |
| minimum=0.0, | |
| maximum=2.0, | |
| value=0.7, | |
| step=0.1, | |
| label="Temperature", | |
| info="Higher = more creative, lower = more focused", | |
| ) | |
| max_tokens = gr.Slider( | |
| minimum=50, | |
| maximum=4096, | |
| value=1024, | |
| step=64, | |
| label="Max Tokens", | |
| info="Maximum response length", | |
| ) | |
| top_p = gr.Slider( | |
| minimum=0.0, | |
| maximum=1.0, | |
| value=0.9, | |
| step=0.05, | |
| label="Top-p (Nucleus Sampling)", | |
| info="Controls diversity of outputs", | |
| ) | |
| with gr.Accordion("ℹ️ About", open=False): | |
| gr.Markdown(""" | |
| ### How to use: | |
| 1. **Select a model** from the dropdown | |
| 2. **Type your message** in the chat box | |
| 3. **Upload images** (for multimodal models) using the paperclip icon | |
| 4. **Adjust parameters** to control the response style | |
| ### Tips: | |
| - Use **temperature** to control creativity | |
| - **Vision models** (like Llama 3.2 11B) support image understanding | |
| - Add a **Hugging Face token** for better rate limits | |
| ### Privacy: | |
| Messages are sent to Hugging Face's inference API. | |
| Your token is only used for authentication and never stored. | |
| """) | |
| # Event handlers | |
| def user_message_handler(message: Dict[str, Any], history: List[Dict[str, str]]): | |
| """Handle user message submission.""" | |
| text = message.get("text", "") | |
| files = message.get("files", []) | |
| image = files[0] if files else None | |
| # Add user message to history | |
| history = history + [{"role": "user", "content": text}] | |
| return "", history, image | |
| def bot_response_handler( | |
| history: List[Dict[str, str]], | |
| model: str, | |
| system_msg: str, | |
| temperature: float, | |
| max_tokens: int, | |
| top_p: float, | |
| token: str, | |
| image: Any, | |
| ): | |
| """Generate bot response.""" | |
| if not history: | |
| return history | |
| # Get the last user message | |
| last_message = "" | |
| for msg in reversed(history): | |
| if msg["role"] == "user": | |
| last_message = msg["content"] | |
| break | |
| if not last_message: | |
| return history | |
| # Generate response | |
| full_response = "" | |
| for partial in chat_response( | |
| message=last_message, | |
| history=history[:-1], # Exclude the last user message we just added | |
| model=model, | |
| system_message=system_msg, | |
| temperature=temperature, | |
| max_tokens=max_tokens, | |
| top_p=top_p, | |
| token=token, | |
| image=image, | |
| ): | |
| full_response = partial | |
| # Update the last assistant message or add new one | |
| if history and history[-1]["role"] == "assistant": | |
| history[-1]["content"] = full_response | |
| else: | |
| history = history + [{"role": "assistant", "content": full_response}] | |
| yield history | |
| # Update model info when model changes | |
| model_dropdown.change( | |
| fn=get_model_info, | |
| inputs=model_dropdown, | |
| outputs=model_info, | |
| api_visibility="private", | |
| ) | |
| # Chat submission | |
| msg_input.submit( | |
| fn=user_message_handler, | |
| inputs=[msg_input, chatbot], | |
| outputs=[msg_input, chatbot, gr.State()], | |
| queue=False, | |
| ).then( | |
| fn=bot_response_handler, | |
| inputs=[ | |
| chatbot, | |
| model_dropdown, | |
| system_msg, | |
| temperature, | |
| max_tokens, | |
| top_p, | |
| hf_token, | |
| gr.State(), | |
| ], | |
| outputs=chatbot, | |
| api_visibility="public", | |
| ) | |
| # Example conversations | |
| gr.Examples( | |
| examples=[ | |
| [{"text": "Explain quantum computing in simple terms", "files": []}], | |
| [{"text": "Write a Python function to calculate fibonacci numbers", "files": []}], | |
| [{"text": "What can you see in this image?", "files": ["https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"]}], | |
| [{"text": "Help me brainstorm ideas for a science fiction story", "files": []}], | |
| ], | |
| inputs=msg_input, | |
| label="Example Prompts (click to try)", | |
| ) | |
| # Launch with Gradio 6 syntax - all parameters in launch() | |
| demo.launch( | |
| theme=custom_theme, | |
| css=custom_css, | |
| footer_links=[ | |
| {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}, | |
| "gradio", | |
| "api", | |
| ], | |
| show_error=True, | |
| pwa=True, | |
| favicon_path="https://huggingface.co/front/assets/huggingface_logo-noborder.svg", | |
| ) |