Spaces:
Runtime error
Runtime error
| import os | |
| import re | |
| import gradio as gr | |
| import numpy as np | |
| import colorsys | |
| from huggingface_hub import InferenceClient | |
| from sentence_transformers import SentenceTransformer | |
| from sklearn.metrics.pairwise import cosine_similarity | |
| # ---------------------------- | |
| # Hugging Face API Client | |
| # ---------------------------- | |
| token = os.getenv("naiyya") | |
| client = InferenceClient( | |
| "Qwen/Qwen2.5-7B-Instruct", | |
| token=token | |
| ) | |
| # ---------------------------- | |
| # Load Embedding Model | |
| # ---------------------------- | |
| embedding_model = SentenceTransformer( | |
| "sentence-transformers/all-MiniLM-L6-v2" | |
| ) | |
| # ---------------------------- | |
| # Load Knowledge Base | |
| # ---------------------------- | |
| chunks = [] | |
| chunk_embeddings = None | |
| try: | |
| if os.path.exists("knowledge.txt"): | |
| with open("knowledge.txt", "r", encoding="utf-8") as file: | |
| knowledge_base = file.read() | |
| chunks = [ | |
| chunk.strip() | |
| for chunk in knowledge_base.split("\n\n") | |
| if chunk.strip() | |
| ] | |
| if chunks: | |
| print(f"Loaded {len(chunks)} knowledge chunks.") | |
| chunk_embeddings = embedding_model.encode(chunks) | |
| else: | |
| print("knowledge.txt exists, but no chunks were found.") | |
| else: | |
| print("Warning: knowledge.txt missing. Starting in pure chat mode.") | |
| except Exception as e: | |
| print("Knowledge base initialization error:", e) | |
| chunks = [] | |
| chunk_embeddings = None | |
| # ---------------------------- | |
| # Clean Model Response | |
| # ---------------------------- | |
| def clean_response_text(content): | |
| if content is None: | |
| return "" | |
| if isinstance(content, list): | |
| text_parts = [] | |
| for item in content: | |
| if isinstance(item, dict): | |
| if "text" in item: | |
| text_parts.append(str(item["text"])) | |
| elif "content" in item: | |
| text_parts.append(str(item["content"])) | |
| else: | |
| text_parts.append(str(item)) | |
| else: | |
| text_parts.append(str(item)) | |
| text = "\n".join(text_parts) | |
| elif isinstance(content, dict): | |
| if "text" in content: | |
| text = str(content["text"]) | |
| elif "content" in content: | |
| text = str(content["content"]) | |
| else: | |
| text = str(content) | |
| else: | |
| text = str(content) | |
| # Remove weird markdown/table/code characters | |
| text = text.replace("```", "") | |
| text = text.replace("`", "") | |
| text = text.replace("|", "") | |
| text = text.replace("โ", "") | |
| text = text.replace("โ", "") | |
| text = text.replace("โ", "") | |
| text = text.replace(">", "") | |
| cleaned_lines = [] | |
| for line in text.splitlines(): | |
| line = line.strip() | |
| if not line: | |
| continue | |
| cleaned_lines.append(line) | |
| text = "\n".join(cleaned_lines) | |
| # Clean extra spaces and extra line breaks | |
| text = re.sub(r"\n{3,}", "\n\n", text) | |
| text = re.sub(r"[ \t]+", " ", text) | |
| return text.strip() | |
| # ---------------------------- | |
| # RAG Semantic Search Function | |
| # ---------------------------- | |
| def retrieve_context(query, top_k=3): | |
| if not chunks or chunk_embeddings is None: | |
| return "" | |
| query_embedding = embedding_model.encode([query]) | |
| scores = cosine_similarity( | |
| query_embedding, | |
| chunk_embeddings | |
| )[0] | |
| top_indices = scores.argsort()[-top_k:][::-1] | |
| relevant_chunks = [ | |
| chunks[i] | |
| for i in top_indices | |
| ] | |
| return "\n\n".join(relevant_chunks) | |
| # ---------------------------- | |
| # Chat Function | |
| # ---------------------------- | |
| def respond(message, history): | |
| if history is None: | |
| history = [] | |
| if not message or not message.strip(): | |
| return "", history | |
| context = retrieve_context(message) | |
| system_prompt = f""" | |
| You are GlowGuide, an empathetic, non-judgmental AI Health and Emotional Well-being Assistant. | |
| KNOWLEDGE BASE: | |
| {context} | |
| Your goal is to support the user's emotional well-being, confidence, healthy habits, and daily decision-making. | |
| You can help with: | |
| - Stress, anxiety, overwhelm, and emotional check-ins | |
| - Social pressure, peer pressure, family expectations, school stress, work stress, and boundaries | |
| - Coping strategies such as journaling, grounding, breathing, reframing, and mindfulness | |
| - Healthy food ideas, balanced meals, high-protein meals, and healthier sweet snack options | |
| - General wellness habits like sleep, movement, hydration, and routine-building | |
| STRICT RULES: | |
| 1. EMOTIONAL SUPPORT | |
| - Identify the user's feelings. | |
| - Validate them warmly. | |
| - Avoid sounding robotic or clinical. | |
| 2. SOCIAL PRESSURE | |
| - Help users handle peer pressure, family pressure, school stress, work stress, social media comparison, or body-image pressure. | |
| - Give practical scripts for setting boundaries when helpful. | |
| 3. FOOD, FITNESS, AND WEIGHT-RELATED SUPPORT | |
| - Give balanced, realistic food suggestions. | |
| - If the user asks for something sweet but healthy, suggest options like Greek yogurt bowls, fruit with nut butter, protein smoothies, dark chocolate with fruit, cottage cheese with fruit, or homemade protein snacks. | |
| - If the user asks for high-protein meals, suggest simple meals with lean protein, carbs, and healthy fats. | |
| - Do not promote crash dieting, starvation, extreme restriction, guilt around food, or unsafe weight loss. | |
| - Do not diagnose eating disorders or give medical nutrition plans. | |
| - Encourage balance, energy, strength, and feeling good rather than shame or perfection. | |
| 4. ACTIONABLE SOLUTIONS | |
| - Give 2-4 practical suggestions. | |
| - Make advice easy to try today. | |
| - Keep responses concise and useful. | |
| 5. SAFETY | |
| - You are not a doctor, therapist, dietitian, or emergency service. | |
| - If the user mentions self-harm, suicide, severe distress, or immediate danger, encourage them to contact emergency services, a crisis hotline, or a trusted adult immediately. | |
| 6. RESPONSE FORMAT | |
| - Begin with one warm validating sentence. | |
| - Use normal plain text only. | |
| - Use simple dash bullets if needed. | |
| - Do not use vertical bars. | |
| - Do not use the | character. | |
| - Do not use blockquotes. | |
| - Do not use code blocks. | |
| - Do not use Markdown tables. | |
| - Do not add decorative lines before or after the response. | |
| - Do not output JSON, Python lists, dictionaries, brackets, or raw object formatting. | |
| - Keep language simple, supportive, and encouraging. | |
| """ | |
| messages = [ | |
| { | |
| "role": "system", | |
| "content": system_prompt | |
| } | |
| ] | |
| for turn in history: | |
| if isinstance(turn, dict): | |
| role = turn.get("role") | |
| content = clean_response_text(turn.get("content")) | |
| if role in ["user", "assistant"] and content: | |
| messages.append({ | |
| "role": role, | |
| "content": content | |
| }) | |
| messages.append({ | |
| "role": "user", | |
| "content": message | |
| }) | |
| try: | |
| response = client.chat.completions.create( | |
| model="Qwen/Qwen2.5-7B-Instruct", | |
| messages=messages, | |
| max_tokens=350, | |
| temperature=0.7, | |
| stream=False | |
| ) | |
| raw_content = response.choices[0].message.content | |
| reply = clean_response_text(raw_content) | |
| # Final extra cleanup | |
| reply = reply.replace("|", "") | |
| reply = reply.replace("โ", "") | |
| reply = reply.replace("โ", "") | |
| reply = reply.replace("โ", "") | |
| reply = reply.replace("```", "") | |
| reply = reply.replace("`", "") | |
| reply = reply.strip() | |
| except Exception as e: | |
| reply = f"Error communicating with AI: {str(e)}" | |
| history.append({ | |
| "role": "user", | |
| "content": message | |
| }) | |
| history.append({ | |
| "role": "assistant", | |
| "content": reply | |
| }) | |
| return "", history | |
| # ---------------------------- | |
| # Helper Functions for Tabs | |
| # ---------------------------- | |
| def save_journal(entry, mood): | |
| if not entry or not entry.strip(): | |
| return "Write something first, even just one sentence ๐" | |
| if not mood: | |
| mood = "Not selected" | |
| return f""" | |
| ### Journal Saved Reflection ๐ | |
| **Mood:** {mood} | |
| **Your reflection:** {entry} | |
| **Gentle reminder:** You took a moment to check in with yourself, and that matters. | |
| """ | |
| def grounding_response(choice): | |
| if choice == "5-4-3-2-1 Grounding": | |
| return """ | |
| ### 5-4-3-2-1 Grounding Exercise ๐ฟ | |
| Name: | |
| - 5 things you can see | |
| - 4 things you can feel | |
| - 3 things you can hear | |
| - 2 things you can smell | |
| - 1 thing you can taste | |
| Take one slow breath after each step. | |
| """ | |
| if choice == "Box Breathing": | |
| return """ | |
| ### Box Breathing ๐ฌ๏ธ | |
| Try this for 1 minute: | |
| - Breathe in for 4 seconds | |
| - Hold for 4 seconds | |
| - Breathe out for 4 seconds | |
| - Hold for 4 seconds | |
| Repeat until your body feels a little calmer. | |
| """ | |
| return """ | |
| ### Quick Reset โจ | |
| Try this: | |
| - Put both feet on the floor | |
| - Relax your shoulders | |
| - Take 3 slow breaths | |
| - Say: โI am safe in this moment.โ | |
| """ | |
| def fuel_response(goal): | |
| if goal == "Sweet but Healthy": | |
| return """ | |
| ### Sweet but Healthy Ideas ๐ | |
| - Greek yogurt with berries and honey | |
| - Apple slices with peanut butter | |
| - Protein smoothie with banana and milk | |
| - Cottage cheese with pineapple | |
| - Dark chocolate with strawberries | |
| - Rice cake with peanut butter and banana | |
| Try to choose something that gives you energy and makes you feel good. | |
| """ | |
| if goal == "High Protein Meal": | |
| return """ | |
| ### High-Protein Meal Ideas ๐ช | |
| - Chicken, rice, and avocado bowl | |
| - Turkey wrap with fruit on the side | |
| - Eggs with toast and berries | |
| - Greek yogurt bowl with granola and fruit | |
| - Tuna sandwich with a side salad | |
| - Tofu or chicken stir-fry with rice | |
| A balanced plate usually has protein, carbs, fats, and fiber. | |
| """ | |
| if goal == "Quick Snack": | |
| return """ | |
| ### Quick Balanced Snacks โก | |
| - String cheese with fruit | |
| - Greek yogurt cup | |
| - Protein bar | |
| - Peanut butter toast | |
| - Cottage cheese with fruit | |
| - Trail mix | |
| - Turkey roll-ups | |
| Pick something easy, satisfying, and realistic. | |
| """ | |
| return """ | |
| ### Balanced Wellness Tip ๐ฑ | |
| Focus on food that gives you energy, helps you feel full, and supports your day. Balance matters more than perfection. | |
| """ | |
| # ---------------------------- | |
| # Custom CSS | |
| # ---------------------------- | |
| custom_css = """ | |
| :root { | |
| color-scheme: light !important; | |
| } | |
| body, .gradio-container, .contain, .main { | |
| background: linear-gradient(135deg, #F4ECFF 0%, #EEF5FF 50%, #FFF0F4 100%) !important; | |
| font-family: Arial, Helvetica, sans-serif !important; | |
| color: #4A3E65 !important; | |
| } | |
| footer { | |
| display: none !important; | |
| } | |
| .gradio-container { | |
| max-width: 1100px !important; | |
| margin: auto !important; | |
| } | |
| .app-header { | |
| text-align: center; | |
| padding: 22px 10px 26px 10px; | |
| } | |
| .app-header h1 { | |
| color: #8E7AB5 !important; | |
| font-size: 42px !important; | |
| font-weight: 800 !important; | |
| margin-bottom: 4px !important; | |
| letter-spacing: -1px; | |
| } | |
| .app-header p { | |
| color: #9F8DCA !important; | |
| font-size: 18px !important; | |
| font-weight: 600 !important; | |
| } | |
| .glow-card { | |
| background: rgba(255, 255, 255, 0.96) !important; | |
| border-radius: 28px !important; | |
| border: 1px solid #EFE7FF !important; | |
| padding: 24px !important; | |
| box-shadow: 0px 12px 35px rgba(154, 126, 185, 0.13) !important; | |
| margin-bottom: 24px !important; | |
| } | |
| .card-title { | |
| color: #4E3B67 !important; | |
| font-weight: 800 !important; | |
| font-size: 22px !important; | |
| margin-bottom: 6px !important; | |
| } | |
| .card-subtitle { | |
| color: #7A6C99 !important; | |
| font-size: 16px !important; | |
| font-weight: 600 !important; | |
| margin-bottom: 18px !important; | |
| } | |
| /* Better global text */ | |
| label, | |
| span, | |
| p, | |
| h1, | |
| h2, | |
| h3, | |
| h4, | |
| li, | |
| div { | |
| font-family: Arial, Helvetica, sans-serif !important; | |
| } | |
| label, | |
| .label-wrap, | |
| .block-info, | |
| .form label, | |
| .wrap label { | |
| color: #4E3B67 !important; | |
| font-weight: 700 !important; | |
| font-size: 16px !important; | |
| } | |
| .markdown, | |
| .markdown *, | |
| .prose, | |
| .prose * { | |
| color: #4A3E65 !important; | |
| font-family: Arial, Helvetica, sans-serif !important; | |
| } | |
| .tab-nav button, | |
| .tabitem, | |
| [role="tab"] { | |
| color: #5F4B7A !important; | |
| font-weight: 800 !important; | |
| font-size: 15px !important; | |
| } | |
| .mood-btn { | |
| background: #FFF0F5 !important; | |
| border: 1px solid #FFDDE8 !important; | |
| border-radius: 18px !important; | |
| padding: 14px 16px !important; | |
| color: #7A5C86 !important; | |
| font-weight: 800 !important; | |
| font-size: 16px !important; | |
| } | |
| .mood-btn:hover { | |
| transform: translateY(-3px); | |
| background: #FFE5EF !important; | |
| box-shadow: 0px 6px 14px rgba(255, 182, 193, 0.35) !important; | |
| } | |
| fieldset, | |
| fieldset *, | |
| .radio-group *, | |
| .checkbox-group *, | |
| select, | |
| option { | |
| color: #4A3E65 !important; | |
| font-family: Arial, Helvetica, sans-serif !important; | |
| font-weight: 600 !important; | |
| } | |
| input, | |
| textarea, | |
| select { | |
| background: #FFFFFF !important; | |
| color: #4A3E65 !important; | |
| border-radius: 16px !important; | |
| border: 1px solid #D8CDEA !important; | |
| font-family: Arial, Helvetica, sans-serif !important; | |
| font-size: 16px !important; | |
| } | |
| textarea::placeholder, | |
| input::placeholder { | |
| color: #7A6C99 !important; | |
| opacity: 1 !important; | |
| } | |
| button { | |
| font-family: Arial, Helvetica, sans-serif !important; | |
| font-weight: 700 !important; | |
| } | |
| /* Chatbot readability & Pink Panel Adjustments */ | |
| #glow-chatbot { | |
| background: #FFF0F5 !important; /* This sets the main chat container background pink */ | |
| color: #4A3E65 !important; | |
| border-radius: 24px !important; | |
| border: 1px solid #FFD6E8 !important; | |
| padding: 12px !important; | |
| } | |
| #glow-chatbot .message, | |
| #glow-chatbot *, | |
| #glow-chatbot .prose, | |
| #glow-chatbot .prose *, | |
| #glow-chatbot p, | |
| #glow-chatbot span, | |
| #glow-chatbot div { | |
| color: #4A3E65 !important; | |
| font-weight: 500 !important; | |
| font-family: Arial, Helvetica, sans-serif !important; | |
| } | |
| /* Individual message boxes are transparent so the panel's pink shines through */ | |
| #glow-chatbot [data-testid="user"], | |
| #glow-chatbot [data-testid="bot"], | |
| #glow-chatbot [data-testid="assistant"], | |
| #glow-chatbot .message { | |
| background: transparent !important; | |
| border: none !important; | |
| box-shadow: none !important; | |
| } | |
| /* Slightly darken user messages or distinct rows for minimal text readability separation */ | |
| #glow-chatbot .user { | |
| background: rgba(255, 255, 255, 0.4) !important; | |
| border-radius: 14px !important; | |
| padding: 8px 12px !important; | |
| } | |
| #glow-chatbot blockquote, | |
| #glow-chatbot pre, | |
| #glow-chatbot code, | |
| #glow-chatbot .prose blockquote, | |
| #glow-chatbot .message blockquote { | |
| border-left: none !important; | |
| border-right: none !important; | |
| border: none !important; | |
| background: transparent !important; | |
| padding-left: 0 !important; | |
| margin-left: 0 !important; | |
| box-shadow: none !important; | |
| } | |
| #glow-chatbot button { | |
| color: #F9FAFB !important; | |
| } | |
| /* Dock cards */ | |
| .dock-card { | |
| background: #F7FBFF !important; | |
| border: 1px solid #DDEEFF !important; | |
| border-radius: 22px !important; | |
| padding: 22px !important; | |
| text-align: center !important; | |
| color: #5F4B7A !important; | |
| box-shadow: 0px 6px 18px rgba(160, 180, 220, 0.12) !important; | |
| } | |
| .dock-card h3 { | |
| color: #4E3B67 !important; | |
| font-size: 18px !important; | |
| font-weight: 800 !important; | |
| margin-bottom: 8px !important; | |
| } | |
| .dock-card p { | |
| color: #7B6E93 !important; | |
| font-size: 14px !important; | |
| margin: 6px 0 !important; | |
| } | |
| .footer-text { | |
| text-align: center; | |
| color: #7A6C99 !important; | |
| font-size: 16px !important; | |
| margin-top: 18px !important; | |
| font-weight: 700 !important; | |
| } | |
| """ | |
| # ---------------------------- | |
| # Gradio App With Tabs | |
| # ---------------------------- | |
| with gr.Blocks( | |
| title="GlowGuide", | |
| theme=gr.themes.Soft( | |
| primary_hue="purple", | |
| secondary_hue="pink", | |
| neutral_hue="slate" | |
| ) | |
| ) as demo: | |
| gr.HTML(""" | |
| <div class="app-header"> | |
| <h1>โจ GlowGuide โจ</h1> | |
| <p>Your light. Your pace. You matter. ๐</p> | |
| </div> | |
| """) | |
| with gr.Tabs(): | |
| # Chat Tab | |
| with gr.Tab("๐ฌ Chat"): | |
| with gr.Column(elem_classes=["glow-card"]): | |
| gr.HTML(""" | |
| <p class="card-title">Daily Check-in Moodboard โจ</p> | |
| <p class="card-subtitle">How are you feeling today?</p> | |
| """) | |
| with gr.Row(): | |
| gr.Button("โ๏ธ Calm", elem_classes=["mood-btn"]) | |
| gr.Button("๐ธ Happy", elem_classes=["mood-btn"]) | |
| gr.Button("โ๏ธ Okay", elem_classes=["mood-btn"]) | |
| gr.Button("๐ง๏ธ Anxious", elem_classes=["mood-btn"]) | |
| gr.Button("โ๏ธ Overwhelmed", elem_classes=["mood-btn"]) | |
| gr.HTML(""" | |
| <p style="text-align:center; font-size:14px; color:#A396C7; margin-top:10px;"> | |
| ๐ All feelings are valid here. | |
| </p> | |
| """) | |
| with gr.Column(elem_classes=["glow-card"]): | |
| chatbot = gr.Chatbot( | |
| height=350, | |
| show_label=False, | |
| render_markdown=False, | |
| elem_id="glow-chatbot" | |
| ) | |
| with gr.Row(): | |
| msg_input = gr.Textbox( | |
| placeholder="What's on your mind?", | |
| show_label=False, | |
| scale=9 | |
| ) | |
| submit_btn = gr.Button("โก๏ธ", scale=1) | |
| msg_input.submit( | |
| fn=respond, | |
| inputs=[msg_input, chatbot], | |
| outputs=[msg_input, chatbot] | |
| ) | |
| submit_btn.click( | |
| fn=respond, | |
| inputs=[msg_input, chatbot], | |
| outputs=[msg_input, chatbot] | |
| ) | |
| # Journal Tab | |
| with gr.Tab("๐ Journal"): | |
| with gr.Column(elem_classes=["glow-card"]): | |
| gr.HTML(""" | |
| <p class="card-title">๐ Personalized Journal</p> | |
| <p class="card-subtitle">Write. Reflect. Heal.</p> | |
| """) | |
| mood_dropdown = gr.Dropdown( | |
| choices=["Calm", "Happy", "Okay", "Anxious", "Overwhelmed"], | |
| label="How are you feeling?" | |
| ) | |
| journal_entry = gr.Textbox( | |
| label="Journal Entry", | |
| placeholder="Today I feel...", | |
| lines=8 | |
| ) | |
| journal_btn = gr.Button("Save Reflection ๐") | |
| journal_output = gr.Markdown() | |
| journal_btn.click( | |
| fn=save_journal, | |
| inputs=[journal_entry, mood_dropdown], | |
| outputs=journal_output | |
| ) | |
| # Grounding Tab | |
| with gr.Tab("๐ฎ Grounding"): | |
| with gr.Column(elem_classes=["glow-card"]): | |
| gr.HTML(""" | |
| <p class="card-title">๐ฎ Grounding Games</p> | |
| <p class="card-subtitle">Play. Breathe. Reset.</p> | |
| """) | |
| grounding_choice = gr.Radio( | |
| choices=[ | |
| "5-4-3-2-1 Grounding", | |
| "Box Breathing", | |
| "Quick Reset" | |
| ], | |
| label="Choose a calming exercise" | |
| ) | |
| grounding_btn = gr.Button("Start Exercise ๐ฟ") | |
| grounding_output = gr.Markdown() | |
| grounding_btn.click( | |
| fn=grounding_response, | |
| inputs=grounding_choice, | |
| outputs=grounding_output | |
| ) | |
| # Healthy Fuel Tab | |
| with gr.Tab("๐ Healthy Fuel"): | |
| with gr.Column(elem_classes=["glow-card"]): | |
| gr.HTML(""" | |
| <p class="card-title">๐ Healthy Fuel Ideas</p> | |
| <p class="card-subtitle">Sweet. Protein. Balanced.</p> | |
| """) | |
| fuel_choice = gr.Radio( | |
| choices=[ | |
| "Sweet but Healthy", | |
| "High Protein Meal", | |
| "Quick Snack", | |
| "Balanced Wellness Tip" | |
| ], | |
| label="What are you looking for?" | |
| ) | |
| fuel_btn = gr.Button("Get Ideas ๐ฝ๏ธ") | |
| fuel_output = gr.Markdown() | |
| fuel_btn.click( | |
| fn=fuel_response, | |
| inputs=fuel_choice, | |
| outputs=fuel_output | |
| ) | |
| with gr.Tab("Relaxing Games "): | |
| with gr.Column(elem_classes=["glow-card"]): | |
| # The Zen headers you want to keep | |
| gr.HTML(""" | |
| <p class="card-title">Zen Draws</p> | |
| <p class="card-subtitle">Draw. Enjoy. Relax</p> | |
| """) | |
| # Single-page coloring canvas completely updated for Gradio 6+ | |
| draw_pad = gr.ImageEditor( | |
| sources=None, # Clean blank drawing canvas | |
| canvas_size=(800, 600), # Full-page canvas space | |
| type="numpy", | |
| label="Coloring Page", | |
| # Fixed: Removed the incompatible 'sizes' and 'colors' lists | |
| brush=gr.Brush( | |
| default_size=10, | |
| default_color="#ff0000" | |
| ) | |
| ) | |
| # Resources Tab | |
| with gr.Tab("๐จ Resources"): | |
| with gr.Column(elem_classes=["glow-card"]): | |
| gr.HTML(""" | |
| <p class="card-title">๐จ Support Resources</p> | |
| <p class="card-subtitle">You deserve support, especially when things feel heavy.</p> | |
| """) | |
| gr.Markdown(""" | |
| ### Immediate Help | |
| If you are in immediate danger, call emergency services right away. | |
| ### United States | |
| - 988 Suicide & Crisis Lifeline | |
| - Call or text 988 | |
| ### Other Support Options | |
| - Talk to a trusted adult | |
| - Reach out to a school counselor | |
| - Contact a mental health professional | |
| - Message a trusted friend or family member | |
| ### Reminder | |
| GlowGuide is an AI assistant, not a therapist, doctor, dietitian, or emergency service. | |
| """) | |
| gr.HTML(""" | |
| <p class="footer-text"> | |
| ๐ You are stronger than you think. Take it one step at a time. โจ | |
| </p> | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch(css=custom_css) |