Delete app.py
Browse files
app.py
DELETED
|
@@ -1,203 +0,0 @@
|
|
| 1 |
-
# app_llm.py
|
| 2 |
-
import gradio as gr
|
| 3 |
-
from typing import List, Literal, Tuple
|
| 4 |
-
# Import the new LLM-powered functions
|
| 5 |
-
from llm_integration import agent_workout_llm, agent_nutrition_llm
|
| 6 |
-
|
| 7 |
-
# --- [Keep all the original JS, Helper functions, and agent_bmi_tdee] ---
|
| 8 |
-
|
| 9 |
-
# -------------------------------
|
| 10 |
-
# Motivation banner (rotates every 10s via JS)
|
| 11 |
-
# -------------------------------
|
| 12 |
-
MOTIVATION_JS = """
|
| 13 |
-
<div id="motivation" class="motivation">Let’s begin strong! 🚀</div>
|
| 14 |
-
<script>
|
| 15 |
-
const MOTIVATION = [
|
| 16 |
-
"You’re doing great—one step at a time! 💪",
|
| 17 |
-
"Small habits, big results. Keep going. 🔁",
|
| 18 |
-
"Hydrate and move—your future self thanks you. 💧",
|
| 19 |
-
"Form first, weight second. You’ve got this. 🧠",
|
| 20 |
-
"Consistency beats intensity. Show up today. ✅",
|
| 21 |
-
];
|
| 22 |
-
let i = 0;
|
| 23 |
-
function tick(){
|
| 24 |
-
const el = document.getElementById("motivation");
|
| 25 |
-
if (!el) return;
|
| 26 |
-
el.textContent = MOTIVATION[i % MOTIVATION.length];
|
| 27 |
-
i++;
|
| 28 |
-
}
|
| 29 |
-
tick(); // first line immediately
|
| 30 |
-
setInterval(tick, 10000); // then every 10s
|
| 31 |
-
</script>
|
| 32 |
-
"""
|
| 33 |
-
|
| 34 |
-
# -------------------------------
|
| 35 |
-
# Helpers: BMI / BMR / TDEE
|
| 36 |
-
# -------------------------------
|
| 37 |
-
def bmi_value(height_cm: float, weight_kg: float) -> float:
|
| 38 |
-
if height_cm <= 0 or weight_kg <= 0:
|
| 39 |
-
return 0.0
|
| 40 |
-
h_m = height_cm / 100.0
|
| 41 |
-
return round(weight_kg / (h_m ** 2), 2)
|
| 42 |
-
|
| 43 |
-
def bmi_category(bmi: float) -> str:
|
| 44 |
-
if bmi == 0:
|
| 45 |
-
return "Invalid inputs"
|
| 46 |
-
if bmi < 18.5: return "Underweight"
|
| 47 |
-
if bmi < 25: return "Normal"
|
| 48 |
-
if bmi < 30: return "Overweight"
|
| 49 |
-
return "Obese"
|
| 50 |
-
|
| 51 |
-
def bmr_mifflin(sex: Literal["male","female"], age: int, height_cm: float, weight_kg: float) -> float:
|
| 52 |
-
s = 5 if sex == "male" else -161
|
| 53 |
-
return 10*weight_kg + 6.25*height_cm - 5*age + s
|
| 54 |
-
|
| 55 |
-
ACTIVITY = {
|
| 56 |
-
"Sedentary (office/no exercise)": 1.2,
|
| 57 |
-
"Light (1-3x/wk)": 1.375,
|
| 58 |
-
"Moderate (3-5x/wk)": 1.55,
|
| 59 |
-
"Active (6-7x/wk)": 1.725,
|
| 60 |
-
"Athlete (2x/day)": 1.9,
|
| 61 |
-
}
|
| 62 |
-
|
| 63 |
-
def tdee(sex: str, age: int, height_cm: float, weight_kg: float, activity: str) -> Tuple[int, int, int]:
|
| 64 |
-
base = bmr_mifflin(sex, age, height_cm, weight_kg)
|
| 65 |
-
factor = ACTIVITY.get(activity, 1.2)
|
| 66 |
-
maintenance = round(base * factor)
|
| 67 |
-
cut = maintenance - 500
|
| 68 |
-
bulk = maintenance + 300
|
| 69 |
-
return maintenance, cut, bulk
|
| 70 |
-
|
| 71 |
-
def water_intake_ml(weight_kg: float) -> int:
|
| 72 |
-
return int(weight_kg * 35)
|
| 73 |
-
|
| 74 |
-
# -------------------------------
|
| 75 |
-
# Agent 1: BMI & TDEE (Unchanged)
|
| 76 |
-
# -------------------------------
|
| 77 |
-
def agent_bmi_tdee(sex, age, height_cm, weight_kg, activity, goal):
|
| 78 |
-
bmi = bmi_value(height_cm, weight_kg)
|
| 79 |
-
cat = bmi_category(bmi)
|
| 80 |
-
maint, cut, bulk = tdee(sex, age, height_cm, weight_kg, activity)
|
| 81 |
-
target = {"Lose fat": cut, "Maintain": maint, "Build muscle": bulk}[goal]
|
| 82 |
-
water = water_intake_ml(weight_kg)
|
| 83 |
-
water_l = round(water / 1000, 1)
|
| 84 |
-
|
| 85 |
-
md = f"""### 📊 BMI & TDEE
|
| 86 |
-
- **BMI:** `{bmi}` → **{cat}**
|
| 87 |
-
- **Maintenance Calories:** **{maint} kcal/day**
|
| 88 |
-
- **Target for goal ({goal}):** **{target} kcal/day**
|
| 89 |
-
- **Water recommendation:** ~ **{water_l} L/day** (≈ {water} ml)
|
| 90 |
-
|
| 91 |
-
> *These are estimates, not medical advice. Adjust by ±100–150 kcal based on weekly progress.*
|
| 92 |
-
"""
|
| 93 |
-
return md
|
| 94 |
-
|
| 95 |
-
# -------------------------------
|
| 96 |
-
# Chained: All-in-One Coach (Now with LLM)
|
| 97 |
-
# -------------------------------
|
| 98 |
-
def coach_all_in_one_llm(
|
| 99 |
-
sex, age, height_cm, weight_kg, activity, goal,
|
| 100 |
-
level, days, equipment,
|
| 101 |
-
liked_csv, avoid_csv, meals
|
| 102 |
-
):
|
| 103 |
-
# Agent 1 remains the same (deterministic calculations)
|
| 104 |
-
report = agent_bmi_tdee(sex, age, height_cm, weight_kg, activity, goal)
|
| 105 |
-
|
| 106 |
-
# Get target calories for the nutrition agent
|
| 107 |
-
maint, cut, bulk = tdee(sex, age, height_cm, weight_kg, activity)
|
| 108 |
-
target_kcal = {"Lose fat": cut, "Maintain": maint, "Build muscle": bulk}[goal]
|
| 109 |
-
|
| 110 |
-
# Call the LLM-powered agents
|
| 111 |
-
workout_plan = agent_workout_llm(level, days, goal, equipment)
|
| 112 |
-
nutrition_plan = agent_nutrition_llm(weight_kg, target_kcal, liked_csv, avoid_csv, meals)
|
| 113 |
-
|
| 114 |
-
return report + "\n---\n" + workout_plan + "\n---\n" + nutrition_plan
|
| 115 |
-
|
| 116 |
-
# -------------------------------
|
| 117 |
-
# UI (Modified to call LLM agents)
|
| 118 |
-
# -------------------------------
|
| 119 |
-
with gr.Blocks(
|
| 120 |
-
title="Beginner Gym Coach — LLM-Powered",
|
| 121 |
-
css="""
|
| 122 |
-
.motivation{
|
| 123 |
-
background:#fff6e5; border-left:6px solid #ffa84b;
|
| 124 |
-
padding:10px 14px; border-radius:8px; font-size:16px; margin-bottom:10px;
|
| 125 |
-
}
|
| 126 |
-
"""
|
| 127 |
-
) as demo:
|
| 128 |
-
gr.Markdown("## 🏋️ Beginner Gym Coach — LLM-Powered\nGive me your basics and I’ll coach you with personalized AI.")
|
| 129 |
-
gr.HTML(MOTIVATION_JS)
|
| 130 |
-
|
| 131 |
-
with gr.Tabs():
|
| 132 |
-
# --- Tab 1: BMI & TDEE (Unchanged) ---
|
| 133 |
-
with gr.Tab("BMI & TDEE"):
|
| 134 |
-
with gr.Row():
|
| 135 |
-
with gr.Column(scale=1):
|
| 136 |
-
sex = gr.Radio(["male","female"], value="female", label="Sex")
|
| 137 |
-
age = gr.Slider(15, 70, value=24, step=1, label="Age")
|
| 138 |
-
height = gr.Slider(130, 210, value=165, step=1, label="Height (cm)")
|
| 139 |
-
weight = gr.Slider(35, 160, value=60, step=0.5, label="Weight (kg)")
|
| 140 |
-
activity = gr.Dropdown(list(ACTIVITY.keys()), value="Light (1-3x/wk)", label="Activity")
|
| 141 |
-
goal = gr.Radio(["Lose fat","Maintain","Build muscle"], value="Maintain", label="Goal")
|
| 142 |
-
btn1 = gr.Button("Calculate")
|
| 143 |
-
with gr.Column(scale=1):
|
| 144 |
-
out1 = gr.Markdown()
|
| 145 |
-
btn1.click(agent_bmi_tdee, [sex, age, height, weight, activity, goal], out1)
|
| 146 |
-
|
| 147 |
-
# --- Tab 2: Workout Plan (Now uses LLM) ---
|
| 148 |
-
with gr.Tab("Workout Plan"):
|
| 149 |
-
with gr.Row():
|
| 150 |
-
with gr.Column(scale=1):
|
| 151 |
-
level_w = gr.Radio(["Beginner","Intermediate"], value="Beginner", label="Level")
|
| 152 |
-
days_w = gr.Slider(2, 6, value=4, step=1, label="Days/week")
|
| 153 |
-
goal_w = gr.Radio(["Lose fat","Maintain","Build muscle"], value="Build muscle", label="Goal")
|
| 154 |
-
equipment_w = gr.Dropdown(["Gym (machines/dumbbells)", "Home (bands/db)", "Bodyweight only"], value="Gym (machines/dumbbells)", label="Equipment")
|
| 155 |
-
btn2 = gr.Button("Generate Plan with AI")
|
| 156 |
-
with gr.Column(scale=1):
|
| 157 |
-
out2 = gr.Markdown(label="AI-Generated Workout Plan")
|
| 158 |
-
btn2.click(agent_workout_llm, [level_w, days_w, goal_w, equipment_w], out2)
|
| 159 |
-
|
| 160 |
-
# --- Tab 3: Nutrition (Now uses LLM) ---
|
| 161 |
-
with gr.Tab("Nutrition"):
|
| 162 |
-
with gr.Row():
|
| 163 |
-
with gr.Column(scale=1):
|
| 164 |
-
target_kcal_n = gr.Number(value=1900, label="Target calories (kcal)")
|
| 165 |
-
weight_n = gr.Number(value=60, label="Weight (kg)")
|
| 166 |
-
liked_n = gr.Textbox(label="Preferred foods (comma-separated)", placeholder="chicken, eggs, rice, oats, salad, laban")
|
| 167 |
-
avoid_n = gr.Textbox(label="Allergies / avoid (comma-separated)", placeholder="nuts, shrimp, gluten")
|
| 168 |
-
meals_n = gr.Slider(2, 6, value=3, step=1, label="Meals/day")
|
| 169 |
-
btn3 = gr.Button("Build Meal Plan with AI")
|
| 170 |
-
with gr.Column(scale=1):
|
| 171 |
-
out3 = gr.Markdown(label="AI-Generated Nutrition Plan")
|
| 172 |
-
btn3.click(agent_nutrition_llm, [weight_n, target_kcal_n, liked_n, avoid_n, meals_n], out3)
|
| 173 |
-
|
| 174 |
-
# --- Tab 4: All-in-One (Now uses LLM) ---
|
| 175 |
-
with gr.Tab("All-in-One Coach"):
|
| 176 |
-
with gr.Row():
|
| 177 |
-
with gr.Column(scale=1):
|
| 178 |
-
sex2 = gr.Radio(["male","female"], value="female", label="Sex")
|
| 179 |
-
age2 = gr.Slider(15, 70, value=24, step=1, label="Age")
|
| 180 |
-
height2 = gr.Slider(130, 210, value=165, step=1, label="Height (cm)")
|
| 181 |
-
weight2 = gr.Slider(35, 160, value=60, step=0.5, label="Weight (kg)")
|
| 182 |
-
activity2 = gr.Dropdown(list(ACTIVITY.keys()), value="Light (1-3x/wk)", label="Activity")
|
| 183 |
-
goal2 = gr.Radio(["Lose fat","Maintain","Build muscle"], value="Build muscle", label="Goal")
|
| 184 |
-
level2 = gr.Radio(["Beginner","Intermediate"], value="Beginner", label="Level")
|
| 185 |
-
days2 = gr.Slider(2, 6, value=4, step=1, label="Days/week")
|
| 186 |
-
equipment2 = gr.Dropdown(["Gym (machines/dumbbells)", "Home (bands/db)", "Bodyweight only"], value="Gym (machines/dumbbells)", label="Equipment")
|
| 187 |
-
liked2 = gr.Textbox(label="Preferred foods", placeholder="chicken, eggs, rice, potatoes")
|
| 188 |
-
avoid2 = gr.Textbox(label="Allergies / avoid", placeholder="nuts, shrimp")
|
| 189 |
-
meals2 = gr.Slider(2, 6, value=3, step=1, label="Meals/day")
|
| 190 |
-
btn4 = gr.Button("Get My Full AI-Powered Plan 🚀")
|
| 191 |
-
with gr.Column(scale=1):
|
| 192 |
-
out4 = gr.Markdown(label="Full AI-Powered Plan")
|
| 193 |
-
btn4.click(
|
| 194 |
-
coach_all_in_one_llm,
|
| 195 |
-
[sex2, age2, height2, weight2, activity2, goal2,
|
| 196 |
-
level2, days2, equipment2, liked2, avoid2, meals2],
|
| 197 |
-
out4
|
| 198 |
-
)
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
if __name__ == "__main__":
|
| 202 |
-
demo.launch()
|
| 203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|