Spaces:
Sleeping
Sleeping
import gradio as gr | |
import pandas as pd | |
import datetime | |
import json | |
import os | |
from typing import Dict, List, Tuple | |
import plotly.graph_objects as go | |
import plotly.express as px | |
from dataclasses import dataclass, asdict | |
import google.generativeai as genai | |
# Data structure for health records | |
class HealthRecord: | |
date: str | |
morning_mood: int | |
morning_energy: int | |
morning_sleep_quality: int | |
afternoon_water_intake: int | |
afternoon_physical_activity: int | |
afternoon_stress_level: int | |
evening_meal_quality: int | |
evening_screen_time: int | |
evening_gratitude: int | |
daily_score: float | |
ai_recommendation: str | |
class AIDoctor: | |
def __init__(self): | |
self.data_file = "health_data.json" | |
self.setup_gemini() | |
self.load_data() | |
def setup_gemini(self): | |
"""Setup Google Gemini AI""" | |
# Get API key from environment variable or Hugging Face Secrets | |
api_key = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY") | |
if api_key: | |
genai.configure(api_key=api_key) | |
self.model = genai.GenerativeModel('gemini-pro') | |
self.gemini_available = True | |
else: | |
self.gemini_available = False | |
print("β οΈ Gemini API key not found. Using fallback recommendations.") | |
def load_data(self): | |
"""Load existing health data""" | |
if os.path.exists(self.data_file): | |
try: | |
with open(self.data_file, 'r') as f: | |
data = json.load(f) | |
self.records = [HealthRecord(**record) for record in data] | |
except: | |
self.records = [] | |
else: | |
self.records = [] | |
def save_data(self): | |
"""Save health data to file""" | |
try: | |
with open(self.data_file, 'w') as f: | |
json.dump([asdict(record) for record in self.records], f, indent=2) | |
except: | |
pass | |
def calculate_daily_score(self, morning_data: Dict, afternoon_data: Dict, evening_data: Dict) -> float: | |
"""Calculate daily health score (0-100)""" | |
# Morning score (30% weight) | |
morning_score = ( | |
morning_data['mood'] * 0.4 + | |
morning_data['energy'] * 0.4 + | |
morning_data['sleep_quality'] * 0.2 | |
) * 10 | |
# Afternoon score (40% weight) | |
afternoon_score = ( | |
min(morning_data['water_intake'] / 8, 1) * 40 + # 8 glasses target | |
min(afternoon_data['physical_activity'] / 60, 1) * 40 + # 60 min target | |
(10 - afternoon_data['stress_level']) * 2 # Lower stress is better | |
) | |
# Evening score (30% weight) | |
evening_score = ( | |
evening_data['meal_quality'] * 8 + | |
max(0, (8 - evening_data['screen_time'])) * 2 + # Less than 8 hours | |
evening_data['gratitude'] * 10 | |
) | |
# Weighted total | |
total_score = (morning_score * 0.3 + afternoon_score * 0.4 + evening_score * 0.3) | |
return min(100, max(0, total_score)) | |
def generate_ai_recommendation(self, score: float, morning_data: Dict, afternoon_data: Dict, evening_data: Dict) -> str: | |
"""Generate AI doctor recommendations using Gemini""" | |
if self.gemini_available: | |
try: | |
# Create detailed health context for Gemini | |
health_context = f""" | |
You are an AI Health Doctor analyzing a patient's daily health data. Provide personalized, actionable health recommendations. | |
PATIENT DAILY HEALTH DATA: | |
- Overall Health Score: {score:.1f}/100 | |
Morning Metrics: | |
- Mood: {morning_data['mood']}/10 | |
- Energy Level: {morning_data['energy']}/10 | |
- Sleep Quality: {morning_data['sleep_quality']}/10 | |
Afternoon Metrics: | |
- Water Intake: {morning_data['water_intake']} glasses (target: 8) | |
- Physical Activity: {afternoon_data['physical_activity']} minutes (target: 60) | |
- Stress Level: {afternoon_data['stress_level']}/10 (lower is better) | |
Evening Metrics: | |
- Meal Quality: {evening_data['meal_quality']}/10 | |
- Screen Time: {evening_data['screen_time']} hours | |
- Gratitude Practice: {evening_data['gratitude']}/10 | |
INSTRUCTIONS: | |
1. Analyze the overall health pattern | |
2. Identify 2-3 key areas for improvement | |
3. Provide specific, actionable recommendations | |
4. Use encouraging, doctor-like tone | |
5. Include emojis for better engagement | |
6. Keep response under 300 words | |
7. Focus on the lowest-scoring metrics | |
Format: Start with overall assessment, then provide specific recommendations for improvement areas. | |
""" | |
# Get historical context if available | |
if len(self.records) >= 3: | |
recent_scores = [r.daily_score for r in self.records[-3:]] | |
trend = "improving" if recent_scores[-1] > recent_scores[0] else "declining" if recent_scores[-1] < recent_scores[0] else "stable" | |
health_context += f"\n\nRecent 3-day trend: {trend} (scores: {recent_scores})" | |
# Generate response with Gemini | |
response = self.model.generate_content(health_context) | |
return response.text | |
except Exception as e: | |
print(f"Gemini API error: {e}") | |
return self.fallback_recommendations(score, morning_data, afternoon_data, evening_data) | |
else: | |
return self.fallback_recommendations(score, morning_data, afternoon_data, evening_data) | |
def fallback_recommendations(self, score: float, morning_data: Dict, afternoon_data: Dict, evening_data: Dict) -> str: | |
"""Fallback recommendations when Gemini is not available""" | |
recommendations = [] | |
# Score-based general advice | |
if score >= 85: | |
recommendations.append("π Excellent health habits! You're doing amazing!") | |
elif score >= 70: | |
recommendations.append("π Good health practices! Small improvements can make you even better.") | |
elif score >= 50: | |
recommendations.append("β οΈ Moderate health status. Focus on key areas for improvement.") | |
else: | |
recommendations.append("π¨ Your health needs attention. Let's work on fundamental habits.") | |
# Specific recommendations | |
if morning_data['sleep_quality'] < 6: | |
recommendations.append("π€ Sleep Quality: Aim for 7-9 hours of sleep. Create a bedtime routine.") | |
if morning_data['mood'] < 6: | |
recommendations.append("π Mood: Try 10 minutes of meditation or journaling in the morning.") | |
if morning_data['energy'] < 6: | |
recommendations.append("β‘ Energy: Consider a protein-rich breakfast and light morning exercise.") | |
if morning_data['water_intake'] < 6: | |
recommendations.append("π§ Hydration: Aim for 8 glasses of water daily. Set hourly reminders.") | |
if afternoon_data['physical_activity'] < 30: | |
recommendations.append("π Activity: Try to get at least 30 minutes of physical activity daily.") | |
if afternoon_data['stress_level'] > 7: | |
recommendations.append("π§ Stress: Practice deep breathing or take short breaks throughout the day.") | |
if evening_data['meal_quality'] < 6: | |
recommendations.append("π₯ Nutrition: Focus on whole foods, vegetables, and balanced meals.") | |
if evening_data['screen_time'] > 6: | |
recommendations.append("π± Screen Time: Reduce screen time before bed for better sleep quality.") | |
return " | ".join(recommendations) | |
def morning_checkin(self, mood: int, energy: int, sleep_quality: int, water_goal: int) -> str: | |
"""Process morning check-in""" | |
today = datetime.date.today().isoformat() | |
# Store morning data temporarily | |
self.temp_morning = { | |
'mood': mood, | |
'energy': energy, | |
'sleep_quality': sleep_quality, | |
'water_intake': water_goal | |
} | |
return f"β Morning check-in completed!\n\nMood: {mood}/10\nEnergy: {energy}/10\nSleep Quality: {sleep_quality}/10\nWater Goal: {water_goal} glasses\n\nπ Complete your afternoon check-in next!" | |
def afternoon_checkin(self, water_consumed: int, physical_activity: int, stress_level: int) -> str: | |
"""Process afternoon check-in""" | |
if not hasattr(self, 'temp_morning'): | |
return "β Please complete your morning check-in first!" | |
self.temp_afternoon = { | |
'physical_activity': physical_activity, | |
'stress_level': stress_level | |
} | |
# Update water intake | |
self.temp_morning['water_intake'] = water_consumed | |
return f"β Afternoon check-in completed!\n\nWater Consumed: {water_consumed} glasses\nPhysical Activity: {physical_activity} minutes\nStress Level: {stress_level}/10\n\nπ Complete your evening check-in to get your daily score!" | |
def evening_checkin(self, meal_quality: int, screen_time: int, gratitude: int) -> Tuple[str, str, object]: | |
"""Process evening check-in and generate daily report""" | |
if not hasattr(self, 'temp_morning') or not hasattr(self, 'temp_afternoon'): | |
return "β Please complete morning and afternoon check-ins first!", "", None | |
evening_data = { | |
'meal_quality': meal_quality, | |
'screen_time': screen_time, | |
'gratitude': gratitude | |
} | |
# Calculate daily score | |
score = self.calculate_daily_score(self.temp_morning, self.temp_afternoon, evening_data) | |
# Generate AI recommendation | |
recommendation = self.generate_ai_recommendation(score, self.temp_morning, self.temp_afternoon, evening_data) | |
# Create health record | |
today = datetime.date.today().isoformat() | |
record = HealthRecord( | |
date=today, | |
morning_mood=self.temp_morning['mood'], | |
morning_energy=self.temp_morning['energy'], | |
morning_sleep_quality=self.temp_morning['sleep_quality'], | |
afternoon_water_intake=self.temp_morning['water_intake'], | |
afternoon_physical_activity=self.temp_afternoon['physical_activity'], | |
afternoon_stress_level=self.temp_afternoon['stress_level'], | |
evening_meal_quality=evening_data['meal_quality'], | |
evening_screen_time=evening_data['screen_time'], | |
evening_gratitude=evening_data['gratitude'], | |
daily_score=score, | |
ai_recommendation=recommendation | |
) | |
# Save record | |
self.records = [r for r in self.records if r.date != today] # Remove today's old record | |
self.records.append(record) | |
self.save_data() | |
# Generate report | |
report = f""" | |
# π₯ Daily Health Report - {today} | |
## π Your Health Score: {score:.1f}/100 | |
### π Morning Metrics: | |
- Mood: {self.temp_morning['mood']}/10 | |
- Energy: {self.temp_morning['energy']}/10 | |
- Sleep Quality: {self.temp_morning['sleep_quality']}/10 | |
### π Afternoon Metrics: | |
- Water Intake: {self.temp_morning['water_intake']} glasses | |
- Physical Activity: {self.temp_afternoon['physical_activity']} minutes | |
- Stress Level: {self.temp_afternoon['stress_level']}/10 | |
### π Evening Metrics: | |
- Meal Quality: {evening_data['meal_quality']}/10 | |
- Screen Time: {evening_data['screen_time']} hours | |
- Gratitude Practice: {gratitude}/10 | |
## π€ AI Doctor Recommendations: | |
{recommendation} | |
--- | |
*Keep up the great work! Consistency is key to better health.* π | |
""" | |
# Create progress chart | |
chart = self.create_progress_chart() | |
# Clear temporary data | |
delattr(self, 'temp_morning') | |
delattr(self, 'temp_afternoon') | |
return f"β Evening check-in completed!", report, chart | |
def create_progress_chart(self): | |
"""Create progress visualization""" | |
if len(self.records) < 2: | |
return None | |
df = pd.DataFrame([asdict(record) for record in self.records[-7:]]) # Last 7 days | |
fig = go.Figure() | |
fig.add_trace(go.Scatter( | |
x=df['date'], | |
y=df['daily_score'], | |
mode='lines+markers', | |
name='Daily Health Score', | |
line=dict(color='#2E86AB', width=3), | |
marker=dict(size=8) | |
)) | |
fig.update_layout( | |
title='π Your 7-Day Health Progress', | |
xaxis_title='Date', | |
yaxis_title='Health Score', | |
yaxis=dict(range=[0, 100]), | |
template='plotly_white', | |
height=400 | |
) | |
return fig | |
def get_weekly_summary(self) -> str: | |
"""Generate weekly health summary""" | |
if len(self.records) < 7: | |
return "π Complete 7 days of check-ins to see your weekly summary!" | |
recent_records = self.records[-7:] | |
avg_score = sum(r.daily_score for r in recent_records) / len(recent_records) | |
# Find trends | |
scores = [r.daily_score for r in recent_records] | |
trend = "π Improving" if scores[-1] > scores[0] else "π Declining" if scores[-1] < scores[0] else "β‘οΈ Stable" | |
best_day = max(recent_records, key=lambda x: x.daily_score) | |
summary = f""" | |
# π Weekly Health Summary | |
## π― Average Score: {avg_score:.1f}/100 | |
## π Trend: {trend} | |
## π Best Day: {best_day.date} (Score: {best_day.daily_score:.1f}) | |
### Key Insights: | |
- Best performing area: {"Sleep" if sum(r.morning_sleep_quality for r in recent_records) > 42 else "Physical Activity" if sum(r.afternoon_physical_activity for r in recent_records) > 210 else "Nutrition"} | |
- Focus area: {"Sleep routine" if sum(r.morning_sleep_quality for r in recent_records) < 35 else "Exercise" if sum(r.afternoon_physical_activity for r in recent_records) < 140 else "Stress management"} | |
*Keep building those healthy habits! πͺ* | |
""" | |
return summary | |
# Initialize AI Doctor | |
ai_doctor = AIDoctor() | |
# Create Gradio Interface | |
with gr.Blocks(title="π₯ AI Doctor - Daily Health Checkup", theme=gr.themes.Soft()) as app: | |
gr.Markdown(""" | |
# π₯ AI Doctor - Your Personal Health Assistant | |
Complete 3 daily check-ins to track your health and get **AI-powered recommendations from Google Gemini**! π€β¨ | |
**π± How it works:** | |
1. **Morning Check-in** - Rate your mood, energy, and sleep | |
2. **Afternoon Check-in** - Log water, activity, and stress | |
3. **Evening Check-in** - Rate meals, screen time, and gratitude | |
Get your daily health score and personalized AI recommendations! | |
> π **Setup**: Add your `GEMINI_API_KEY` in Hugging Face Secrets for enhanced AI recommendations! | |
""") | |
# API Key status indicator | |
if ai_doctor.gemini_available: | |
gr.Markdown("β **Gemini AI Active** - Enhanced recommendations enabled!") | |
else: | |
gr.Markdown("β οΈ **Gemini AI Inactive** - Add GEMINI_API_KEY for enhanced recommendations (using fallback mode)") | |
with gr.Tabs(): | |
# Morning Check-in Tab | |
with gr.TabItem("π Morning Check-in"): | |
gr.Markdown("### Start your day with a quick health check!") | |
with gr.Row(): | |
mood_slider = gr.Slider(1, 10, value=7, label="π How's your mood? (1=Terrible, 10=Amazing)") | |
energy_slider = gr.Slider(1, 10, value=7, label="β‘ Energy level? (1=Exhausted, 10=Energetic)") | |
with gr.Row(): | |
sleep_slider = gr.Slider(1, 10, value=7, label="π€ Sleep quality? (1=Terrible, 10=Perfect)") | |
water_goal = gr.Slider(4, 12, value=8, label="π§ Water goal today? (glasses)") | |
morning_btn = gr.Button("Complete Morning Check-in β ", variant="primary") | |
morning_output = gr.Textbox(label="Morning Status", lines=6) | |
morning_btn.click( | |
ai_doctor.morning_checkin, | |
inputs=[mood_slider, energy_slider, sleep_slider, water_goal], | |
outputs=morning_output | |
) | |
# Afternoon Check-in Tab | |
with gr.TabItem("π Afternoon Check-in"): | |
gr.Markdown("### Midday health update!") | |
with gr.Row(): | |
water_consumed = gr.Slider(0, 15, value=4, label="π§ Water consumed so far? (glasses)") | |
activity_minutes = gr.Slider(0, 180, value=30, label="π Physical activity? (minutes)") | |
stress_slider = gr.Slider(1, 10, value=5, label="π° Stress level? (1=Zen, 10=Overwhelmed)") | |
afternoon_btn = gr.Button("Complete Afternoon Check-in β ", variant="primary") | |
afternoon_output = gr.Textbox(label="Afternoon Status", lines=6) | |
afternoon_btn.click( | |
ai_doctor.afternoon_checkin, | |
inputs=[water_consumed, activity_minutes, stress_slider], | |
outputs=afternoon_output | |
) | |
# Evening Check-in Tab | |
with gr.TabItem("π Evening Check-in"): | |
gr.Markdown("### End your day and get your health score!") | |
with gr.Row(): | |
meal_quality = gr.Slider(1, 10, value=7, label="π₯ Meal quality today? (1=Junk, 10=Nutritious)") | |
screen_time = gr.Slider(0, 12, value=4, label="π± Screen time? (hours)") | |
gratitude_slider = gr.Slider(1, 10, value=7, label="π Gratitude practice? (1=None, 10=Very mindful)") | |
evening_btn = gr.Button("Complete Evening Check-in & Get Score! π―", variant="primary") | |
with gr.Row(): | |
evening_status = gr.Textbox(label="Evening Status") | |
daily_report = gr.Markdown(label="π Daily Health Report") | |
progress_chart = gr.Plot(label="π Progress Chart") | |
evening_btn.click( | |
ai_doctor.evening_checkin, | |
inputs=[meal_quality, screen_time, gratitude_slider], | |
outputs=[evening_status, daily_report, progress_chart] | |
) | |
# Progress Tab | |
with gr.TabItem("π Weekly Summary"): | |
gr.Markdown("### Your health journey overview") | |
summary_btn = gr.Button("Generate Weekly Summary π ", variant="secondary") | |
weekly_summary = gr.Markdown() | |
summary_btn.click( | |
ai_doctor.get_weekly_summary, | |
outputs=weekly_summary | |
) | |
gr.Markdown(""" | |
--- | |
### π‘ Health Tips: | |
- **Consistency** is more important than perfection | |
- Aim for **8 glasses** of water daily | |
- Get **7-9 hours** of quality sleep | |
- **30+ minutes** of physical activity | |
- Practice **gratitude** for mental wellness | |
*Your AI Doctor is here to help you build lasting healthy habits! π* | |
""") | |
if __name__ == "__main__": | |
app.launch() |