Spaces:
Running
Running
| import gradio as gr | |
| from huggingface_hub import InferenceClient | |
| import os | |
| HF_TOKEN = os.getenv("HF_TOKEN") | |
| # Allowed subjects keywords + common Chemistry, Physics, Maths, Biology terms | |
| ALLOWED_KEYWORDS = [ | |
| "biology", "physics", "chemistry", "math", "mathematics", | |
| "acid", "base", "neutralization", "molecule", "atom", "cell", | |
| "force", "energy", "gravity", "equation", "algebra", "calculus", "integral", "derivative" | |
| ] | |
| def respond(message, history: list[dict[str, str]]): | |
| # Check if message contains allowed topics/keywords | |
| if not any(keyword in message.lower() for keyword in ALLOWED_KEYWORDS): | |
| yield "β Sorry, I only know about Biology, Physics, Chemistry, and Maths. Please ask me about them." | |
| return | |
| # Allowed topic β send to GPT model | |
| client = InferenceClient(token=HF_TOKEN, model="openai/gpt-oss-20b") | |
| messages = [ | |
| {"role": "system", "content": "You are a friendly chatbot. You only answer questions about Biology, Physics, Chemistry, and Maths. For anything else, politely reply that you can't answer it."} | |
| ] | |
| messages.extend(history) | |
| messages.append({"role": "user", "content": message}) | |
| response = "" | |
| for msg in client.chat_completion( | |
| messages, | |
| max_tokens=512, | |
| stream=True, | |
| temperature=0.7, | |
| top_p=0.95 | |
| ): | |
| if msg.choices and msg.choices[0].delta.content: | |
| response += msg.choices[0].delta.content | |
| yield response | |
| # π Modern CSS + Footer Hide + Compact Layout | |
| custom_css = """ | |
| .gradio-container { | |
| background: linear-gradient(to bottom right, #7E498B, #f5f5f5); | |
| font-family: 'Segoe UI', sans-serif; | |
| height: 100vh; | |
| padding: 20px; | |
| } | |
| /* Chat box styling */ | |
| .svelte-1ipelgc, .svelte-1f354aw { | |
| border-radius: 20px !important; | |
| background: white !important; | |
| padding: 12px !important; | |
| box-shadow: 0px 6px 25px rgba(0,0,0,0.12) !important; | |
| max-width: 700px !important; | |
| margin: 0 auto !important; | |
| } | |
| /* User bubble */ | |
| .user.svelte-1ipelgc { | |
| background: linear-gradient(135deg, #7E498B, #9b59b6) !important; | |
| color: white !important; | |
| border-radius: 20px 20px 0 20px !important; | |
| padding: 12px 16px !important; | |
| max-width: 80% !important; | |
| animation: fadeIn 0.3s ease-in; | |
| } | |
| /* Bot bubble */ | |
| .bot.svelte-1ipelgc { | |
| background: #f1f1f1 !important; | |
| color: #333 !important; | |
| border-radius: 20px 20px 20px 0 !important; | |
| padding: 12px 16px !important; | |
| max-width: 80% !important; | |
| box-shadow: 0px 2px 8px rgba(0,0,0,0.05) !important; | |
| animation: fadeIn 0.3s ease-in; | |
| } | |
| /* Input box */ | |
| textarea { | |
| border-radius: 30px !important; | |
| padding: 14px 18px !important; | |
| border: 1px solid #ddd !important; | |
| outline: none !important; | |
| font-size: 16px !important; | |
| resize: none !important; | |
| } | |
| /* Send button */ | |
| button { | |
| border-radius: 30px !important; | |
| background: linear-gradient(135deg, #7E498B, #9b59b6) !important; | |
| color: white !important; | |
| font-weight: bold !important; | |
| transition: 0.3s; | |
| } | |
| button:hover { | |
| background: #632f73 !important; | |
| } | |
| /* Animations */ | |
| @keyframes fadeIn { | |
| from {opacity: 0; transform: translateY(10px);} | |
| to {opacity: 1; transform: translateY(0);} | |
| } | |
| /* π Hide Gradio Footer */ | |
| footer, .svelte-1yycg3h, .builder-bar, .wrap.svelte-1ipelgc { | |
| display: none !important; | |
| visibility: hidden !important; | |
| } | |
| """ | |
| with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo: | |
| gr.ChatInterface(respond, type="messages") | |
| if __name__ == "__main__": | |
| demo.launch(share=True) | |