Spaces:
Runtime error
Runtime error
| # app.py | |
| import os | |
| from dotenv import load_dotenv | |
| from google import genai | |
| import gradio as gr | |
| # Load environment variables (local .env or HF Secrets) | |
| load_dotenv() | |
| # Initialize Gemini client (will read GEMINI_API_KEY from environment) | |
| client = genai.Client() | |
| MODEL = "gemini-2.5-flash" # quickstart example uses gemini-2.5-flash; change to gemini-2.5-flash-pro if you have access | |
| # --- Utilities --- | |
| def calculate_calorie_requirements(age, gender, weight, height, fitness_goal): | |
| try: | |
| age = float(age); weight = float(weight); height = float(height) | |
| except Exception: | |
| return 0 | |
| if gender == "Male": | |
| bmr = 10 * weight + 6.25 * height - 5 * age + 5 | |
| else: | |
| bmr = 10 * weight + 6.25 * height - 5 * age - 161 | |
| if fitness_goal == "Weight Loss": | |
| return int(bmr * 1.2) | |
| if fitness_goal == "Weight Gain": | |
| return int(bmr * 1.5) | |
| return int(bmr * 1.375) | |
| AYURVEDA_PROMPT = """ | |
| You are an expert in modern medicine and Ayurveda. Create a concise personalized weekly diet & exercise plan for {name}, a {age}-year-old {gender} with BMI {bmi} ({health_status}). | |
| Fitness Goal: {fitness_goal} | |
| Daily Calories: {daily_calories} kcal | |
| Diet Preference: {dietary_preference} | |
| Food Allergies: {food_allergies} | |
| Local Cuisine: {local_cuisine} | |
| Month: {month} | |
| Return short bullets for each weekday (Mon..Sun). | |
| """ | |
| REGULAR_PROMPT = """ | |
| You are a health expert. Create a concise personalized weekly diet & exercise plan for {name}, a {age}-year-old {gender} with BMI {bmi} ({health_status}). | |
| Fitness Goal: {fitness_goal} | |
| Daily Calories: {daily_calories} kcal | |
| Diet Preference: {dietary_preference} | |
| Food Allergies: {food_allergies} | |
| Local Cuisine: {local_cuisine} | |
| Month: {month} | |
| Return short bullets for each weekday (Mon..Sun). | |
| """ | |
| def call_gemini(prompt_text, model_name=MODEL): | |
| """ | |
| Calls client.models.generate_content exactly as in the official quickstart: | |
| client.models.generate_content(model=..., contents=...) | |
| Returns the best available text representation (response.text or fallbacks). | |
| """ | |
| try: | |
| # Per quickstart: use `contents=` (can be a string or structured contents) | |
| response = client.models.generate_content(model=model_name, contents=prompt_text) | |
| except Exception as e: | |
| return f"Error calling Gemini API: {e}" | |
| # Preferred accessor per docs/examples | |
| if hasattr(response, "text") and response.text: | |
| return response.text | |
| # Fallbacks for various SDK response shapes: | |
| # - candidates -> content -> parts -> text | |
| try: | |
| cand = getattr(response, "candidates", None) | |
| if cand: | |
| first = cand[0] | |
| # dict-like candidate with nested content->parts | |
| if isinstance(first, dict): | |
| content = first.get("content") or {} | |
| parts = content.get("parts") or [] | |
| if parts: | |
| texts = [] | |
| for p in parts: | |
| if isinstance(p, dict) and p.get("text"): | |
| texts.append(p.get("text")) | |
| elif isinstance(p, str): | |
| texts.append(p) | |
| if texts: | |
| return "\n".join(texts) | |
| # if candidate object has .content.parts style | |
| try: | |
| parts = first.get("content", {}).get("parts", []) | |
| except Exception: | |
| parts = [] | |
| if parts: | |
| out = [] | |
| for p in parts: | |
| t = p.get("text") if isinstance(p, dict) else str(p) | |
| out.append(t) | |
| return "\n".join(out) | |
| except Exception: | |
| pass | |
| # Last resort: try response.output or stringified response | |
| try: | |
| if hasattr(response, "output"): | |
| return str(response.output) | |
| except Exception: | |
| pass | |
| return str(response) | |
| def generate_plan(name, age, weight, height, gender, fitness_goal, dietary_preference, | |
| food_allergies, local_cuisine, month, include_ayurveda): | |
| # validate numeric values | |
| try: | |
| age_f = float(age); weight_f = float(weight); height_f = float(height) | |
| except Exception: | |
| return "Please enter valid numeric values for age, weight, and height." | |
| bmi = round(weight_f / (height_f / 100) ** 2, 2) | |
| health_status = "Underweight" if bmi < 18.5 else "Normal weight" if bmi <= 24.9 else "Overweight" | |
| daily_calories = calculate_calorie_requirements(age_f, gender, weight_f, height_f, fitness_goal) | |
| metrics = { | |
| "name": name or "User", | |
| "age": int(age_f), | |
| "gender": gender, | |
| "bmi": bmi, | |
| "health_status": health_status, | |
| "fitness_goal": fitness_goal, | |
| "dietary_preference": dietary_preference, | |
| "food_allergies": food_allergies or "None", | |
| "daily_calories": daily_calories, | |
| "local_cuisine": local_cuisine or "Local", | |
| "month": month or "" | |
| } | |
| prompt_template = AYURVEDA_PROMPT if include_ayurveda else REGULAR_PROMPT | |
| prompt = prompt_template.format(**metrics) | |
| text = call_gemini(prompt, model_name=MODEL) | |
| header = f"BMI: {bmi} ({health_status})\nEstimated calories/day: {daily_calories} kcal\n\n" | |
| return header + text | |
| # --- Gradio UI --- | |
| with gr.Blocks(title="AI Health Advisor") as demo: | |
| gr.Markdown("# 🩺 AI-Based Personalized Weekly Diet & Exercise Planner (Gemini quickstart style)") | |
| with gr.Row(): | |
| with gr.Column(): | |
| name_in = gr.Textbox(label="Name") | |
| age_in = gr.Number(label="Age", value=25) | |
| weight_in = gr.Number(label="Weight (kg)", value=70) | |
| height_in = gr.Number(label="Height (cm)", value=170) | |
| gender_in = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"], value="Male") | |
| goal_in = gr.Dropdown(label="Fitness Goal", choices=["Weight Loss", "Weight Gain", "Maintenance"], value="Maintenance") | |
| diet_in = gr.Dropdown(label="Diet Preference", choices=["Vegetarian", "Vegan", "Keto", "Halal", "None"], value="None") | |
| allergy_in = gr.Textbox(label="Food Allergies") | |
| cuisine_in = gr.Textbox(label="Local Cuisine") | |
| month_in = gr.Dropdown(label="Month", choices=[ | |
| "January","February","March","April","May","June","July","August","September","October","November","December" | |
| ], value="October") | |
| ayurveda_in = gr.Checkbox(label="Include Ayurvedic Insights", value=True) | |
| btn = gr.Button("Generate Plan") | |
| with gr.Column(): | |
| output = gr.Textbox(label="Generated Plan", lines=25) | |
| btn.click( | |
| generate_plan, | |
| inputs=[name_in, age_in, weight_in, height_in, gender_in, goal_in, diet_in, allergy_in, cuisine_in, month_in, ayurveda_in], | |
| outputs=output | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", share=False) | |