Spaces:
Running on Zero
Running on Zero
| """NeuroBait UI — hybrid: a standard AI-chat experience (``gr.ChatInterface``, | |
| DeepSeek/Perplexity-ish) carrying NeuroBait's identity. | |
| gradio-only (no torch/spaces) so the UI can be built and smoke-tested without the | |
| model stack. Theme + CSS are applied at ``launch()`` because Gradio 6 moved | |
| ``theme``/``css``/``js`` off the Blocks/ChatInterface constructor — see the | |
| deprecation warning we hit in the Space logs. | |
| Dark-only, earthy, calm sage-teal accent (gentler / more sensory-safe for ADHD | |
| than vivid green). The palette is set straight on ``:root`` and mapped onto | |
| Gradio's core CSS vars unconditionally, so the app is dark with no dependence on | |
| JS or HF's ``?__theme``. | |
| """ | |
| from __future__ import annotations | |
| import gradio as gr | |
| MOODS = ["Calm", "Tired", "Anxious", "Focused"] | |
| THEME = gr.themes.Soft(primary_hue="teal", neutral_hue="slate") | |
| TITLE = "🧠 NeuroBait" | |
| DESCRIPTION = ( | |
| "A warm space and a gentle boost for your everyday — NeuroBait works *with* " | |
| "your dopamine, not against your willpower. Your brain isn't broken; it's " | |
| "wired for a different kind of focus." | |
| ) | |
| PLACEHOLDER = ( | |
| "### 🧠 NeuroBait\n" | |
| "Tell me what's on your mind — no need to be tidy, just honest.\n\n" | |
| "*No red pen · no urgency · no streaks.*" | |
| ) | |
| EXAMPLES = [ | |
| ["There's something I've been meaning to get to, and it keeps slipping by.", "Calm"], | |
| ["My space feels a bit cluttered today.", "Tired"], | |
| ["My mind feels a little foggy right now.", "Anxious"], | |
| ] | |
| CSS = """ | |
| /* Earthy, always-dark palette on :root (no .dark dependency), with a calm muted | |
| sage-teal accent instead of vivid green. */ | |
| :root { | |
| --forest: #6fb6a2; | |
| --sage: #5da894; | |
| --mint: #20362f; | |
| --cream: #1d2128; | |
| --linen: #15181d; | |
| --sand: #2e333b; | |
| --stone: #aeb6bf; | |
| --charcoal: #eef1f4; | |
| --radius: 10px; | |
| --brand-grad: linear-gradient(135deg, #5da894, #4f9582); | |
| } | |
| /* map Gradio core theme vars onto our dark palette so built-in components render | |
| dark even when Gradio's own .dark class is off */ | |
| body, .gradio-container, gradio-app, .dark { | |
| --body-background-fill: var(--linen); | |
| --background-fill-primary: var(--cream); | |
| --background-fill-secondary: var(--linen); | |
| --block-background-fill: var(--cream); | |
| --block-label-background-fill: var(--cream); | |
| --block-border-color: var(--sand); | |
| --border-color-primary: var(--sand); | |
| --body-text-color: var(--charcoal); | |
| --body-text-color-subdued: var(--stone); | |
| --input-background-fill: var(--cream); | |
| --input-border-color: var(--sand); | |
| --button-secondary-background-fill: var(--cream); | |
| --button-secondary-text-color: var(--charcoal); | |
| } | |
| body, .gradio-container { | |
| background: var(--linen) !important; | |
| color: var(--charcoal) !important; | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji" !important; | |
| } | |
| /* keep the conversation in a comfortable centered column like a modern chat app */ | |
| .gradio-container { max-width: 960px !important; margin: 0 auto !important; } | |
| h1 { letter-spacing: -0.5px; font-weight: 800; } | |
| /* user bubble gets the brand accent, assistant stays flat/quiet */ | |
| .message.user, [data-testid="user"] { | |
| background: var(--brand-grad) !important; color: #fff !important; border: none !important; | |
| } | |
| .message.bot, [data-testid="bot"] { | |
| background: var(--cream) !important; border: 1px solid var(--sand) !important; color: var(--charcoal) !important; | |
| } | |
| /* rounded, calm input + primary button */ | |
| textarea, input[type="text"] { | |
| border-radius: var(--radius) !important; background: var(--cream) !important; | |
| border: 1px solid var(--sand) !important; color: var(--charcoal) !important; | |
| } | |
| button.primary, .submit-button, [variant="primary"] { | |
| background: var(--brand-grad) !important; border: none !important; color: #fff !important; | |
| } | |
| """ | |
| def message_text(content) -> str: | |
| if isinstance(content, str): | |
| return content.strip() | |
| if isinstance(content, list): | |
| parts = [] | |
| for item in content: | |
| if isinstance(item, dict): | |
| text = item.get("text") | |
| if isinstance(text, str): | |
| parts.append(text) | |
| return " ".join(part.strip() for part in parts if part.strip()).strip() | |
| return "" | |
| def build_demo(respond_fn): | |
| """Build the NeuroBait chat. ``respond_fn`` signature (streaming generator ok): | |
| respond_fn(message: str, history: list[dict], mood: str) -> str | generator[str] | |
| """ | |
| mood = gr.Radio(MOODS, value="Calm", label="🌳 How are you feeling?") | |
| chatbot = gr.Chatbot( | |
| height=560, | |
| show_label=False, | |
| placeholder=PLACEHOLDER, | |
| avatar_images=(None, None), | |
| ) | |
| return gr.ChatInterface( | |
| fn=respond_fn, | |
| chatbot=chatbot, | |
| additional_inputs=[mood], | |
| additional_inputs_accordion=gr.Accordion("🌳 How are you feeling?", open=True), | |
| title=TITLE, | |
| description=DESCRIPTION, | |
| examples=EXAMPLES, | |
| cache_examples=False, | |
| save_history=True, | |
| fill_height=True, | |
| autoscroll=True, | |
| ) | |