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("""

AI Assistant

Your intelligent conversation partner

Built with anycoder

""") 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 )