Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,9 +2,10 @@ import gradio as gr
|
|
| 2 |
from datetime import datetime
|
| 3 |
from huggingface_hub import InferenceClient
|
| 4 |
import os
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
|
|
|
| 8 |
cycle_ai_prompt = """
|
| 9 |
Cycle-Aware Wellness AI Coach (Strict Enforcement Version)
|
| 10 |
==========================================================
|
|
@@ -44,78 +45,96 @@ Final Boundary Rule:
|
|
| 44 |
--------------------
|
| 45 |
Strictly decline all unrelated questions. Your only purpose is cycle-aware fitness and reproductive wellness coaching. Do not give general medical, tech, cooking, legal, or life advice.
|
| 46 |
"""
|
| 47 |
-
#
|
| 48 |
-
user_profile = {
|
| 49 |
-
|
|
|
|
| 50 |
def calculate_cycle_phase(start_date, end_date):
|
| 51 |
today = datetime.today().date()
|
| 52 |
start = datetime.strptime(start_date, "%Y-%m-%d").date()
|
| 53 |
end = datetime.strptime(end_date, "%Y-%m-%d").date()
|
| 54 |
-
cycle_length = 28
|
| 55 |
days_since_start = (today - start).days
|
| 56 |
if days_since_start < 0:
|
| 57 |
return ":warning: Your entered period start date is in the future."
|
| 58 |
day_in_cycle = days_since_start % cycle_length
|
| 59 |
-
|
|
|
|
| 60 |
return "Menstrual phase :drop_of_blood:"
|
| 61 |
elif day_in_cycle <= 13:
|
| 62 |
return "Follicular phase :seedling:"
|
| 63 |
elif day_in_cycle <= 16:
|
| 64 |
return "Ovulation phase :dizzy:"
|
| 65 |
-
elif day_in_cycle <= 28:
|
| 66 |
-
return "Luteal phase :full_moon:"
|
| 67 |
else:
|
| 68 |
-
return "
|
| 69 |
-
# Save
|
| 70 |
-
def save_user_profile(name, age, level, period_start, period_end
|
| 71 |
-
user_profile
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
|
|
|
|
|
|
| 76 |
phase = calculate_cycle_phase(period_start, period_end)
|
| 77 |
-
welcome = f":wave:
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
# Respond to user input
|
| 81 |
def respond(message, history):
|
| 82 |
if not isinstance(history, list):
|
| 83 |
history = []
|
| 84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
messages.append({"role": "user", "content": message})
|
| 86 |
-
|
| 87 |
try:
|
| 88 |
-
|
|
|
|
| 89 |
except Exception as e:
|
| 90 |
-
|
| 91 |
-
history.append(
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
# UI
|
| 95 |
with gr.Blocks() as app:
|
| 96 |
-
gr.Markdown("# 🩷 Menstrual Cycle Chatbot")
|
| 97 |
with gr.Row():
|
| 98 |
with gr.Column(scale=1):
|
| 99 |
-
gr.Markdown("### :woman_standing: Your
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
profile_output = gr.Markdown()
|
| 107 |
with gr.Column(scale=2):
|
| 108 |
-
chatbot = gr.Chatbot(label="Cycle Chat"
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
fn=save_user_profile,
|
| 113 |
-
inputs=[
|
| 114 |
-
outputs=
|
| 115 |
)
|
| 116 |
-
|
| 117 |
fn=respond,
|
| 118 |
-
inputs=[
|
| 119 |
-
outputs=[chatbot,
|
| 120 |
)
|
| 121 |
app.launch()
|
|
|
|
| 2 |
from datetime import datetime
|
| 3 |
from huggingface_hub import InferenceClient
|
| 4 |
import os
|
| 5 |
+
# Set your Hugging Face token and model
|
| 6 |
+
os.environ["HF_TOKEN"] = "your_huggingface_token_here"
|
| 7 |
+
client = InferenceClient("google/gemma-2b-it")
|
| 8 |
+
# System prompt for the assistant
|
| 9 |
cycle_ai_prompt = """
|
| 10 |
Cycle-Aware Wellness AI Coach (Strict Enforcement Version)
|
| 11 |
==========================================================
|
|
|
|
| 45 |
--------------------
|
| 46 |
Strictly decline all unrelated questions. Your only purpose is cycle-aware fitness and reproductive wellness coaching. Do not give general medical, tech, cooking, legal, or life advice.
|
| 47 |
"""
|
| 48 |
+
# Global variables to persist across chats
|
| 49 |
+
user_profile = {}
|
| 50 |
+
chat_history = []
|
| 51 |
+
# Calculate cycle phase
|
| 52 |
def calculate_cycle_phase(start_date, end_date):
|
| 53 |
today = datetime.today().date()
|
| 54 |
start = datetime.strptime(start_date, "%Y-%m-%d").date()
|
| 55 |
end = datetime.strptime(end_date, "%Y-%m-%d").date()
|
| 56 |
+
cycle_length = 28 # Average cycle
|
| 57 |
days_since_start = (today - start).days
|
| 58 |
if days_since_start < 0:
|
| 59 |
return ":warning: Your entered period start date is in the future."
|
| 60 |
day_in_cycle = days_since_start % cycle_length
|
| 61 |
+
period_length = (end - start).days
|
| 62 |
+
if day_in_cycle <= period_length:
|
| 63 |
return "Menstrual phase :drop_of_blood:"
|
| 64 |
elif day_in_cycle <= 13:
|
| 65 |
return "Follicular phase :seedling:"
|
| 66 |
elif day_in_cycle <= 16:
|
| 67 |
return "Ovulation phase :dizzy:"
|
|
|
|
|
|
|
| 68 |
else:
|
| 69 |
+
return "Luteal phase :full_moon:"
|
| 70 |
+
# Save user info
|
| 71 |
+
def save_user_profile(name, age, level, period_start, period_end):
|
| 72 |
+
user_profile.update({
|
| 73 |
+
"name": name,
|
| 74 |
+
"age": age,
|
| 75 |
+
"level": level,
|
| 76 |
+
"period_start": period_start,
|
| 77 |
+
"period_end": period_end
|
| 78 |
+
})
|
| 79 |
phase = calculate_cycle_phase(period_start, period_end)
|
| 80 |
+
welcome = f":wave: Hi {name}! Based on your last period, you're currently in the **{phase}**.\n\nHow can I support your wellness today?"
|
| 81 |
+
return welcome
|
| 82 |
+
# Main chatbot function
|
|
|
|
| 83 |
def respond(message, history):
|
| 84 |
if not isinstance(history, list):
|
| 85 |
history = []
|
| 86 |
+
# Build conversation with system + chat history
|
| 87 |
+
messages = [{"role": "system", "content": cycle_ai_prompt}]
|
| 88 |
+
# Append user profile to context as assistant message
|
| 89 |
+
if user_profile:
|
| 90 |
+
profile_intro = (
|
| 91 |
+
f"User Info:\n"
|
| 92 |
+
f"- Name: {user_profile.get('name')}\n"
|
| 93 |
+
f"- Age: {user_profile.get('age')}\n"
|
| 94 |
+
f"- Experience Level: {user_profile.get('level')}\n"
|
| 95 |
+
f"- Period Start: {user_profile.get('period_start')}\n"
|
| 96 |
+
f"- Period End: {user_profile.get('period_end')}\n"
|
| 97 |
+
f"- Current Phase: {calculate_cycle_phase(user_profile.get('period_start'), user_profile.get('period_end'))}"
|
| 98 |
+
)
|
| 99 |
+
messages.append({"role": "assistant", "content": profile_intro})
|
| 100 |
+
for turn in history:
|
| 101 |
+
if isinstance(turn, list) and len(turn) == 2:
|
| 102 |
+
messages.append({"role": "user", "content": turn[0]})
|
| 103 |
+
messages.append({"role": "assistant", "content": turn[1]})
|
| 104 |
messages.append({"role": "user", "content": message})
|
| 105 |
+
# Get response from model
|
| 106 |
try:
|
| 107 |
+
response = client.chat_completion(messages=messages, max_tokens=500, temperature=0.5)
|
| 108 |
+
assistant_reply = response["choices"][0]["message"]["content"].strip()
|
| 109 |
except Exception as e:
|
| 110 |
+
assistant_reply = f":warning: Something went wrong: {e}"
|
| 111 |
+
history.append((message, assistant_reply))
|
| 112 |
+
return history, ""
|
| 113 |
+
# Gradio UI
|
|
|
|
| 114 |
with gr.Blocks() as app:
|
| 115 |
+
gr.Markdown("# 🩷 Menstrual Cycle & Wellness Chatbot")
|
| 116 |
with gr.Row():
|
| 117 |
with gr.Column(scale=1):
|
| 118 |
+
gr.Markdown("### :woman_standing: Your Profile")
|
| 119 |
+
name = gr.Textbox(label="Name")
|
| 120 |
+
age = gr.Textbox(label="Age")
|
| 121 |
+
level = gr.Dropdown(["Beginner", "Intermediate", "Expert"], label="Experience Level")
|
| 122 |
+
period_start = gr.Textbox(label="Period Start Date (YYYY-MM-DD)")
|
| 123 |
+
period_end = gr.Textbox(label="Period End Date (YYYY-MM-DD)")
|
| 124 |
+
save_btn = gr.Button("Save Profile")
|
| 125 |
profile_output = gr.Markdown()
|
| 126 |
with gr.Column(scale=2):
|
| 127 |
+
chatbot = gr.Chatbot(label="Cycle Chat").style(height=400)
|
| 128 |
+
user_msg = gr.Textbox(placeholder="Ask about your workouts, cycle, birth control, etc…")
|
| 129 |
+
send_btn = gr.Button("Send")
|
| 130 |
+
save_btn.click(
|
| 131 |
fn=save_user_profile,
|
| 132 |
+
inputs=[name, age, level, period_start, period_end],
|
| 133 |
+
outputs=profile_output
|
| 134 |
)
|
| 135 |
+
send_btn.click(
|
| 136 |
fn=respond,
|
| 137 |
+
inputs=[user_msg, chatbot],
|
| 138 |
+
outputs=[chatbot, user_msg]
|
| 139 |
)
|
| 140 |
app.launch()
|