Spaces:
Running
Running
| import gradio as gr | |
| from huggingface_hub import InferenceClient | |
| # --------------------------- | |
| # L U A U T H E M E (S I M P L E) | |
| # --------------------------- | |
| custom_css = """ | |
| /* GLOBAL PAGE BACKGROUND + FONT */ | |
| body, .gradio-container { | |
| background: radial-gradient(circle at top left, #1f2a3c 0%, #050812 40%, #050812 100%) !important; | |
| color: #f8feff !important; | |
| font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", sans-serif; | |
| } | |
| /* MAKE CONTENT WIDE AND CENTERED */ | |
| .gradio-container .app { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| } | |
| /* SCROLLBAR */ | |
| ::-webkit-scrollbar { | |
| width: 10px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: rgba(255,255,255,0.05); | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #00f7ff; | |
| border-radius: 10px; | |
| } | |
| /* TITLE */ | |
| #title { | |
| font-size: 40px; | |
| font-weight: 900; | |
| text-align: center; | |
| margin-top: 10px; | |
| margin-bottom: 6px; | |
| color: #00f7ff; | |
| } | |
| /* SUBTITLE */ | |
| #subtitle { | |
| font-size: 16px; | |
| text-align: center; | |
| color: #c5eaff; | |
| opacity: 0.9; | |
| margin-bottom: 18px; | |
| } | |
| /* CHATBOT CONTAINER: | |
| - BIG HEIGHT | |
| - EASY TO SEE */ | |
| .gr-chatbot { | |
| border-radius: 20px !important; | |
| box-shadow: 0 0 25px rgba(0,255,255,0.3), 0 0 40px rgba(0,0,0,0.8) !important; | |
| background: rgba(3, 16, 40, 0.95) !important; | |
| border: 1px solid rgba(0,247,255,0.35) !important; | |
| overflow: hidden !important; | |
| height: 70vh !important; /* LARGE CHAT WINDOW */ | |
| min-height: 500px !important; | |
| } | |
| /* CHAT INNER AREA */ | |
| .gr-chatbot > div { | |
| background: linear-gradient(145deg, #050810, #060c18) !important; | |
| } | |
| /* MESSAGE TEXT: BIGGER FONT, GOOD LINE SPACING */ | |
| .message.user, .message.bot { | |
| border-radius: 14px !important; | |
| padding: 10px 12px !important; | |
| margin: 6px 0 !important; | |
| max-width: 92%; | |
| line-height: 1.6; | |
| font-size: 16px; | |
| border: 1px solid transparent; | |
| } | |
| /* USER MESSAGES */ | |
| .message.user { | |
| background: rgba(0, 160, 255, 0.35) !important; | |
| border-color: rgba(0,200,255,0.7); | |
| } | |
| /* BOT MESSAGES */ | |
| .message.bot { | |
| background: rgba(0, 220, 150, 0.28) !important; | |
| border-color: rgba(0,255,153,0.6); | |
| } | |
| /* INPUT AREA: BIG, CLEAR, EASY TO CLICK */ | |
| textarea, .gr-textbox textarea { | |
| border-radius: 16px !important; | |
| background: rgba(15, 30, 50, 0.9) !important; | |
| color: #f7feff !important; | |
| border: 1px solid rgba(0,247,255,0.45) !important; | |
| resize: none !important; | |
| font-size: 16px; | |
| padding: 10px 12px !important; | |
| } | |
| textarea::placeholder { | |
| color: rgba(200, 240, 255, 0.8); | |
| } | |
| /* CONTROL PANEL UNDER CHAT */ | |
| #controls-panel { | |
| margin-top: 16px; | |
| padding: 16px; | |
| border-radius: 16px; | |
| background: rgba(0,0,0,0.4); | |
| border: 1px solid rgba(0,247,255,0.4); | |
| } | |
| /* LABELS: CLEAR AND READABLE */ | |
| label, .gr-slider label, .gr-textbox label { | |
| font-weight: 700 !important; | |
| letter-spacing: 0.05em; | |
| text-transform: uppercase; | |
| font-size: 12px; | |
| color: #88f6ff !important; | |
| } | |
| /* DESCRIPTIVE TEXT */ | |
| .control-help { | |
| font-size: 13px; | |
| color: #c9f3ff; | |
| opacity: 0.9; | |
| margin-top: 4px; | |
| margin-bottom: 10px; | |
| } | |
| /* BUTTONS: CLEAR BUT NOT FLASHY */ | |
| button { | |
| border-radius: 999px !important; | |
| font-weight: 700 !important; | |
| letter-spacing: 0.04em; | |
| text-transform: uppercase; | |
| border: 1px solid rgba(0,247,255,0.7) !important; | |
| background: #00bcd4 !important; | |
| color: #021318 !important; | |
| font-size: 14px !important; | |
| padding: 8px 16px !important; | |
| } | |
| /* FOOTER */ | |
| #footer { | |
| text-align: center; | |
| color: #7bc5ff; | |
| font-size: 12px; | |
| margin-top: 10px; | |
| opacity: 0.85; | |
| } | |
| #footer a { | |
| color: #00f7ff; | |
| text-decoration: none; | |
| } | |
| #footer a:hover { | |
| text-decoration: underline; | |
| } | |
| """ | |
| # --------------------------- | |
| # L U A U B O T L O G I C | |
| # --------------------------- | |
| def respond( | |
| message, | |
| history: list[dict[str, str]], | |
| system_message, | |
| max_tokens, | |
| temperature, | |
| top_p, | |
| hf_token: gr.OAuthToken, | |
| ): | |
| merged_system_message = ( | |
| "You are Luau, a friendly, clear AI assistant. " | |
| "You explain things simply so anyone can understand. " | |
| "Use short paragraphs and avoid complex jargon unless the user asks. " | |
| f"Extra instructions: {system_message}" | |
| ) | |
| client = InferenceClient( | |
| token=hf_token.token, | |
| model="openai/gpt-oss-20b" | |
| ) | |
| messages = [{"role": "system", "content": merged_system_message}] | |
| messages.extend(history) | |
| messages.append({"role": "user", "content": message}) | |
| response = "" | |
| for msg in client.chat_completion( | |
| messages=messages, | |
| max_tokens=max_tokens, | |
| stream=True, | |
| temperature=temperature, | |
| top_p=top_p, | |
| ): | |
| choices = getattr(msg, "choices", []) | |
| token = "" | |
| if choices and choices[0].delta and choices[0].delta.get("content"): | |
| token = choices[0].delta["content"] | |
| response += token | |
| yield response | |
| # --------------------------- | |
| # U I | |
| # --------------------------- | |
| chatbot = gr.ChatInterface( | |
| fn=respond, | |
| type="messages", | |
| title="Luau β Simple AI Chat", | |
| css=custom_css, | |
| additional_inputs=[ | |
| gr.Textbox( | |
| value="You are Luau, a friendly AI. Explain things simply.", | |
| label="System Message (optional)", | |
| lines=2, | |
| ), | |
| gr.Slider( | |
| minimum=64, | |
| maximum=4096, | |
| value=1024, | |
| step=64, | |
| label="Max Tokens (answer length)", | |
| ), | |
| gr.Slider( | |
| minimum=0.1, | |
| maximum=2.0, | |
| value=1.0, | |
| step=0.1, | |
| label="Temperature (creativity)", | |
| ), | |
| gr.Slider( | |
| minimum=0.1, | |
| maximum=1.0, | |
| value=0.9, | |
| step=0.05, | |
| label="Top-p (sampling)", | |
| ), | |
| ], | |
| ) | |
| with gr.Blocks(css=custom_css) as demo: | |
| gr.HTML("<div id='title'>Luau</div>") | |
| gr.HTML("<div id='subtitle'>A clear, easy-to-use AI chat assistant.</div>") | |
| chatbot.render() | |
| with gr.Row(elem_id="controls-panel"): | |
| with gr.Column(): | |
| gr.Markdown("### Controls (optional)") | |
| gr.Markdown( | |
| "<div class='control-help'>" | |
| "<b>System Message</b> β Extra instructions for Luau (you can leave this as it is).<br>" | |
| "<b>Max Tokens</b> β How long the answer can be (higher = longer).<br>" | |
| "<b>Temperature</b> β Higher is more creative, lower is more strict.<br>" | |
| "<b>Top-p</b> β Another way to control randomness; 0.9 is usually fine.<br>" | |
| "</div>", | |
| elem_classes=["control-help"], | |
| ) | |
| gr.HTML( | |
| "<div id='footer'>Powered by <a href='https://huggingface.co' target='_blank'>Hugging Face</a></div>" | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |