Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import random | |
| import time | |
| from typing import List, Dict, Any | |
| # Sample responses for the chatbot | |
| RESPONSES = [ | |
| "That's an interesting question! Let me think about it...", | |
| "I understand what you're saying. Here's my perspective...", | |
| "Great point! Have you considered this as well?", | |
| "I'm here to help! What would you like to know more about?", | |
| "That reminds me of something important I'd like to share...", | |
| "Thanks for sharing that with me. Let me provide some insights...", | |
| "I appreciate your question. Here's what I think...", | |
| "Absolutely! Let me elaborate on that topic...", | |
| ] | |
| def generate_response(message: str, history: List[Dict[str, str]]) -> str: | |
| """Generate a response based on the user message and chat history.""" | |
| # Simple logic - in a real app, this would call an AI model | |
| time.sleep(0.5) # Simulate thinking time | |
| # Check for specific keywords to provide more relevant responses | |
| message_lower = message.lower() | |
| if "hello" in message_lower or "hi" in message_lower: | |
| return "Hello! It's great to chat with you today. How can I assist you?" | |
| elif "how are you" in message_lower: | |
| return "I'm doing wonderfully, thank you for asking! I'm here and ready to help you with anything you need." | |
| elif "bye" in message_lower or "goodbye" in message_lower: | |
| return "Goodbye! It was a pleasure chatting with you. Feel free to come back anytime!" | |
| elif "help" in message_lower: | |
| return "I'm here to help! You can ask me questions, share your thoughts, or just have a friendly conversation. What's on your mind?" | |
| elif "thank" in message_lower: | |
| return "You're very welcome! I'm always happy to assist. Is there anything else I can help you with?" | |
| else: | |
| # Return a random response | |
| return random.choice(RESPONSES) | |
| def user_input(user_message: str, history: List[Dict[str, str]]) -> tuple[str, List[Dict[str, str]]]: | |
| """Process user input and add it to the chat history.""" | |
| if not user_message.strip(): | |
| return "", history | |
| # Add user message to history | |
| history.append({"role": "user", "content": user_message}) | |
| return "", history | |
| def bot_response(history: List[Dict[str, str]]) -> List[Dict[str, str]]: | |
| """Generate and add bot response to the chat history.""" | |
| if not history: | |
| return history | |
| last_message = history[-1]["content"] | |
| bot_message = generate_response(last_message, history) | |
| # Add bot message to history | |
| history.append({"role": "assistant", "content": bot_message}) | |
| return history | |
| def stream_response(message: str, history: List[Dict[str, str]]): | |
| """Stream the bot response character by character.""" | |
| if not history: | |
| return | |
| last_message = history[-1]["content"] | |
| full_response = generate_response(last_message, history) | |
| # Add empty bot message to history | |
| history.append({"role": "assistant", "content": ""}) | |
| # Stream the response | |
| for i in range(len(full_response)): | |
| history[-1]["content"] = full_response[:i+1] | |
| yield history | |
| time.sleep(0.02) # Small delay for streaming effect | |
| # Example conversations | |
| EXAMPLE_CONVERSATIONS = [ | |
| ["Hello! How are you today?"], | |
| ["Can you help me with something?"], | |
| ["What's the weather like?"], | |
| ["Tell me an interesting fact"], | |
| ["Thank you for your help!"] | |
| ] | |
| # Apple-style CSS | |
| APPLE_CSS = """ | |
| /* Apple-style design system */ | |
| .gradio-container { | |
| font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Helvetica Neue", Helvetica, Arial, sans-serif !important; | |
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important; | |
| min-height: 100vh; | |
| } | |
| /* Main container styling */ | |
| .main-container { | |
| background: rgba(255, 255, 255, 0.95) !important; | |
| backdrop-filter: blur(20px) !important; | |
| border-radius: 20px !important; | |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1) !important; | |
| border: 1px solid rgba(255, 255, 255, 0.2) !important; | |
| margin: 20px auto !important; | |
| padding: 30px !important; | |
| max-width: 1200px !important; | |
| } | |
| /* Header styling */ | |
| .header-container { | |
| text-align: center; | |
| margin-bottom: 30px; | |
| padding: 20px 0; | |
| } | |
| .header-container h1 { | |
| font-weight: 600 !important; | |
| font-size: 2.5rem !important; | |
| background: linear-gradient(45deg, #007AFF, #5856D6) !important; | |
| -webkit-background-clip: text !important; | |
| -webkit-text-fill-color: transparent !important; | |
| margin-bottom: 10px !important; | |
| } | |
| .header-container p { | |
| color: #8e8e93 !important; | |
| font-size: 1.1rem !important; | |
| font-weight: 400 !important; | |
| } | |
| /* Chatbot styling */ | |
| .chatbot-container { | |
| border-radius: 16px !important; | |
| overflow: hidden !important; | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08) !important; | |
| border: 1px solid rgba(0, 0, 0, 0.05) !important; | |
| } | |
| /* Message bubbles */ | |
| .message.user { | |
| background: linear-gradient(135deg, #007AFF 0%, #5856D6 100%) !important; | |
| color: white !important; | |
| border-radius: 18px !important; | |
| margin-left: auto !important; | |
| max-width: 70% !important; | |
| box-shadow: 0 2px 8px rgba(0, 122, 255, 0.3) !important; | |
| } | |
| .message.assistant { | |
| background: #f2f2f7 !important; | |
| color: #1c1c1e !important; | |
| border-radius: 18px !important; | |
| margin-right: auto !important; | |
| max-width: 70% !important; | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08) !important; | |
| } | |
| /* Input styling */ | |
| .input-container { | |
| background: white !important; | |
| border-radius: 16px !important; | |
| padding: 12px 16px !important; | |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05) !important; | |
| border: 1px solid rgba(0, 0, 0, 0.05) !important; | |
| } | |
| /* Button styling - Apple-like */ | |
| .btn-primary { | |
| background: linear-gradient(135deg, #007AFF 0%, #5856D6 100%) !important; | |
| border: none !important; | |
| border-radius: 12px !important; | |
| font-weight: 600 !important; | |
| font-size: 0.95rem !important; | |
| padding: 12px 24px !important; | |
| transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) !important; | |
| box-shadow: 0 4px 14px rgba(0, 122, 255, 0.3) !important; | |
| } | |
| .btn-primary:hover { | |
| transform: translateY(-2px) !important; | |
| box-shadow: 0 6px 20px rgba(0, 122, 255, 0.4) !important; | |
| } | |
| .btn-secondary { | |
| background: #f2f2f7 !important; | |
| color: #007AFF !important; | |
| border: 1px solid #d1d1d6 !important; | |
| border-radius: 12px !important; | |
| font-weight: 600 !important; | |
| font-size: 0.95rem !important; | |
| padding: 12px 24px !important; | |
| transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) !important; | |
| } | |
| .btn-secondary:hover { | |
| background: #e5e5ea !important; | |
| transform: translateY(-1px) !important; | |
| } | |
| /* Sidebar styling */ | |
| .sidebar-container { | |
| background: rgba(255, 255, 255, 0.8) !important; | |
| backdrop-filter: blur(10px) !important; | |
| border-radius: 16px !important; | |
| padding: 20px !important; | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05) !important; | |
| border: 1px solid rgba(255, 255, 255, 0.3) !important; | |
| } | |
| /* Stats and info styling */ | |
| .stats-container { | |
| background: white !important; | |
| border-radius: 12px !important; | |
| padding: 16px !important; | |
| margin: 10px 0 !important; | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04) !important; | |
| } | |
| /* Examples styling */ | |
| .examples-container { | |
| background: #f8f9fa !important; | |
| border-radius: 12px !important; | |
| padding: 16px !important; | |
| border: 1px solid #e9ecef !important; | |
| } | |
| /* Text input styling */ | |
| input[type="text"], textarea { | |
| background: white !important; | |
| border: 1px solid #e5e5ea !important; | |
| border-radius: 10px !important; | |
| padding: 12px 16px !important; | |
| font-size: 1rem !important; | |
| transition: all 0.3s ease !important; | |
| } | |
| input[type="text"]:focus, textarea:focus { | |
| outline: none !important; | |
| border-color: #007AFF !important; | |
| box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1) !important; | |
| } | |
| /* Smooth transitions */ | |
| * { | |
| transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) !important; | |
| } | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 8px !important; | |
| height: 8px !important; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #f1f1f1 !important; | |
| border-radius: 4px !important; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #c7c7cc !important; | |
| border-radius: 4px !important; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #8e8e93 !important; | |
| } | |
| """ | |
| with gr.Blocks( | |
| title="AI Assistant", | |
| elem_classes=["main-container"] | |
| ) as demo: | |
| # Apple-style header | |
| gr.HTML(""" | |
| <div class="header-container"> | |
| <h1>AI Assistant</h1> | |
| <p>Your intelligent conversation partner</p> | |
| <p style="font-size: 0.9em; color: #8e8e93; margin-top: 10px;"> | |
| Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #007AFF; text-decoration: none;">anycoder</a> | |
| </p> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| # Main chat area | |
| with gr.Column(scale=3, elem_classes=["chatbot-container"]): | |
| chatbot = gr.Chatbot( | |
| label="", | |
| height=550, | |
| buttons=["copy"], | |
| placeholder="Start a conversation...", | |
| avatar_images=( | |
| None, | |
| "https://picsum.photos/seed/ai-assistant/100/100.jpg" | |
| ), | |
| elem_id="chatbot-main" | |
| ) | |
| # Input area with Apple-style design | |
| with gr.Row(elem_classes=["input-container"]): | |
| msg = gr.Textbox( | |
| label="", | |
| placeholder="Type a message...", | |
| lines=1, | |
| max_lines=4, | |
| container=False, | |
| scale=4, | |
| show_label=False | |
| ) | |
| submit_btn = gr.Button( | |
| "Send", | |
| variant="primary", | |
| scale=1, | |
| size="sm", | |
| elem_classes=["btn-primary"] | |
| ) | |
| # Action buttons | |
| with gr.Row(): | |
| clear_btn = gr.Button( | |
| "Clear Chat", | |
| variant="secondary", | |
| scale=1, | |
| size="sm", | |
| elem_classes=["btn-secondary"] | |
| ) | |
| example_btn = gr.Button( | |
| "Random Example", | |
| variant="secondary", | |
| scale=1, | |
| size="sm", | |
| elem_classes=["btn-secondary"] | |
| ) | |
| # Sidebar with Apple-style cards | |
| with gr.Column(scale=1, elem_classes=["sidebar-container"]): | |
| # Quick tips | |
| with gr.Group(elem_classes=["stats-container"]): | |
| gr.Markdown(""" | |
| ### 💬 Quick Tips | |
| • Press Enter to send messages | |
| • Click messages to copy | |
| • Use examples for inspiration | |
| """) | |
| # Message counter | |
| with gr.Group(elem_classes=["stats-container"]): | |
| message_count = gr.Number( | |
| label="Messages", | |
| value=0, | |
| interactive=False, | |
| precision=0 | |
| ) | |
| # Examples in a clean container | |
| with gr.Group(elem_classes=["examples-container"]): | |
| gr.Markdown("### 🎯 Conversation Starters") | |
| gr.Examples( | |
| examples=EXAMPLE_CONVERSATIONS, | |
| inputs=msg, | |
| label="", | |
| examples_per_page=5 | |
| ) | |
| # Event handlers | |
| def update_message_count(history: List[Dict[str, str]]) -> int: | |
| """Update the message count display.""" | |
| return len(history) if history else 0 | |
| # Handle user input and generate streaming response | |
| msg.submit( | |
| user_input, | |
| [msg, chatbot], | |
| [msg, chatbot], | |
| queue=False | |
| ).then( | |
| stream_response, | |
| [msg, chatbot], | |
| chatbot | |
| ).then( | |
| update_message_count, | |
| chatbot, | |
| message_count | |
| ) | |
| submit_btn.click( | |
| user_input, | |
| [msg, chatbot], | |
| [msg, chatbot], | |
| queue=False | |
| ).then( | |
| stream_response, | |
| [msg, chatbot], | |
| chatbot | |
| ).then( | |
| update_message_count, | |
| chatbot, | |
| message_count | |
| ) | |
| # Clear conversation | |
| def clear_conversation(): | |
| """Clear the chat history and reset message count.""" | |
| return [], 0 | |
| clear_btn.click( | |
| clear_conversation, | |
| outputs=[chatbot, message_count] | |
| ) | |
| # Random example | |
| def get_random_example(): | |
| """Get a random example message.""" | |
| return random.choice(EXAMPLE_CONVERSATIONS)[0] | |
| example_btn.click( | |
| get_random_example, | |
| outputs=msg | |
| ) | |
| # Welcome message on load | |
| demo.load( | |
| lambda: [{"role": "assistant", "content": "👋 Hello! I'm your AI assistant. How can I help you today?"}], | |
| outputs=chatbot | |
| ).then( | |
| update_message_count, | |
| chatbot, | |
| message_count | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch( | |
| theme=gr.themes.Soft(), | |
| css=APPLE_CSS, | |
| share=False, | |
| show_error=True, | |
| quiet=False | |
| ) |