musawar32ali's picture
Create app.py
c43beff verified
# 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)