Amrutha04 commited on
Commit
717b446
·
verified ·
1 Parent(s): 44fc9b9

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +115 -67
src/streamlit_app.py CHANGED
@@ -5,16 +5,17 @@ import torch
5
  # 1. Page Configuration
6
  st.set_page_config(page_title="Fitness Profile Generator", layout="wide")
7
 
8
- # 2. Load AI Model
9
  @st.cache_resource
10
  def load_model():
 
11
  tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-large")
12
  model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-large")
13
  return tokenizer, model
14
 
15
  tokenizer, model = load_model()
16
 
17
- # 3. Custom Styling (Forced Black Text & Alignment)
18
  st.markdown("""
19
  <style>
20
  .stApp {
@@ -31,32 +32,33 @@ st.markdown("""
31
  color: #2D3436 !important;
32
  font-weight: 600;
33
  }
34
- /* Fixed Day Card Visibility and Text Color */
35
- .day-card {
36
- background-color: #ffffff !important;
37
- padding: 20px;
38
- border-radius: 12px;
39
- margin-bottom: 20px;
40
- border-left: 8px solid #004d57;
41
- color: #000000 !important; /* Force Pure Black */
42
- white-space: pre-wrap !important;
43
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
44
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
45
  }
46
- .day-header {
47
- color: #004d57 !important;
48
- font-size: 20px;
49
- font-weight: bold;
50
- margin-bottom: 10px;
51
- display: block;
 
 
52
  }
53
  .result-card {
54
- background-color: #ffffff !important;
55
  padding: 25px;
56
  border-radius: 15px;
 
57
  margin-top: 25px;
58
  border-left: 10px solid #004d57;
59
- color: #000000 !important;
 
 
 
 
 
 
60
  }
61
  </style>
62
  """, unsafe_allow_html=True)
@@ -65,85 +67,131 @@ st.markdown("""
65
  with st.sidebar:
66
  st.markdown("# 👤 Personalised Fitness Plan")
67
  st.write("---")
 
68
 
69
  # --- MAIN CONTENT ---
70
  st.title("🏋️ Create Your Fitness Profile")
71
 
72
- # INPUTS
 
73
  col_name, col_gender, col_age = st.columns([2, 1, 1])
74
  with col_name:
75
- name = st.text_input("Full Name *")
76
  with col_gender:
77
  gender = st.selectbox("Gender *", ["Male", "Female", "Other"])
78
  with col_age:
79
- age = st.number_input("Age *", min_value=1, value=25)
80
 
81
  col_h, col_w = st.columns(2)
82
  with col_h:
83
- height_cm = st.number_input("Height (cm) *", min_value=0.0)
84
  with col_w:
85
- weight_kg = st.number_input("Weight (kg) *", min_value=0.0)
86
 
87
- goal = st.selectbox("Goal", ["Build Muscle", "Weight Loss", "Strength Gain", "Abs Building", "Flexible"])
88
- fitness_level = st.selectbox("Level", ["Beginner", "Intermediate", "Advanced"])
89
- equipment = st.multiselect("Equipment", ["Dumbbells", "Resistance Band", "Yoga Mat", "Kettlebells", "Pull-up Bar", "No Equipment"], default=["No Equipment"])
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  if st.button("Submit Profile"):
92
- if not name or height_cm <= 0 or weight_kg <= 0:
93
- st.error("Please fill all fields.")
94
  else:
95
- bmi = weight_kg / ((height_cm/100)**2)
96
- bmi_status = "Normal" if 18.5 <= bmi < 25 else "Underweight" if bmi < 18.5 else "Overweight"
97
-
98
- st.markdown(f'<div class="result-card"><h2>Assessment for {name}</h2><p>BMI: {bmi:.2f} ({bmi_status})</p></div>', unsafe_allow_html=True)
99
-
100
- # 5. REFINED PROMPT
101
- eq_list = ", ".join(equipment)
102
- prompt = f"""Task: Create a unique 5-day workout routine for a {gender} ({fitness_level}) aiming for {goal}.
103
- Available Equipment: {eq_list}.
104
- BMI: {bmi:.2f}.
105
-
106
- Provide specific exercise names, sets, and reps for each day.
107
- Day 3 must be a recovery/rest day.
108
- Finish completely at Day 5.
109
-
110
- Plan:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  Day 1:"""
112
 
113
- with st.spinner("Generating exercises..."):
 
114
  try:
115
  inputs = tokenizer(prompt, return_tensors="pt", truncation=True)
116
- # ADJUSTED PARAMETERS FOR BETTER DIVERSITY
117
  outputs = model.generate(
118
  **inputs,
119
- max_new_tokens=700,
120
- min_new_tokens=350,
121
  do_sample=True,
122
- temperature=0.85, # Higher temperature for more variety
123
- top_k=50, # Limits weird word choices
124
- repetition_penalty=3.0 # Forces the model to move to next days
125
  )
126
 
127
- result = tokenizer.decode(outputs[0], skip_special_tokens=True).strip()
128
- full_text = "Day 1: " + result.split("Day 6")[0] # Safety cut
129
-
 
 
 
130
  st.markdown("### 📋 Your Personalized Routine")
131
 
 
 
 
132
  days = ["Day 1:", "Day 2:", "Day 3:", "Day 4:", "Day 5:"]
 
133
  for i in range(len(days)):
134
  start = full_text.find(days[i])
135
  if start != -1:
 
136
  end = full_text.find(days[i+1]) if i+1 < len(days) else len(full_text)
137
- content = full_text[start:end].replace(days[i], "").strip()
138
 
139
- # Only display if there's actual content
140
- if len(content) > 5:
141
- st.markdown(f"""
142
- <div class="day-card">
143
- <span class="day-header">{days[i]}</span>
144
- {content}
145
- </div>
146
- """, unsafe_allow_html=True)
147
  except Exception as e:
148
- st.error(f"Error: {e}")
149
 
 
5
  # 1. Page Configuration
6
  st.set_page_config(page_title="Fitness Profile Generator", layout="wide")
7
 
8
+ # 2. Load AI Model (Large Version)
9
  @st.cache_resource
10
  def load_model():
11
+ # Note: flan-t5-large is ~3GB.
12
  tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-large")
13
  model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-large")
14
  return tokenizer, model
15
 
16
  tokenizer, model = load_model()
17
 
18
+ # 3. Custom Styling (Preserved Gradient & Black Sidebar)
19
  st.markdown("""
20
  <style>
21
  .stApp {
 
32
  color: #2D3436 !important;
33
  font-weight: 600;
34
  }
35
+ div[data-baseweb="input"], div[data-baseweb="select"] {
36
+ background-color: rgba(255, 255, 255, 0.9) !important;
37
+ border-radius: 8px !important;
 
 
 
 
 
 
 
 
38
  }
39
+ .stButton > button {
40
+ background-color: #004d57 !important;
41
+ color: white !important;
42
+ border-radius: 8px !important;
43
+ padding: 10px 24px !important;
44
+ font-weight: bold !important;
45
+ width: 100% !important;
46
+ border: none !important;
47
  }
48
  .result-card {
49
+ background-color: white;
50
  padding: 25px;
51
  border-radius: 15px;
52
+ box-shadow: 0 10px 25px rgba(0,0,0,0.1);
53
  margin-top: 25px;
54
  border-left: 10px solid #004d57;
55
+ }
56
+ .day-card {
57
+ background-color: rgba(255, 255, 255, 0.8);
58
+ padding: 15px;
59
+ border-radius: 10px;
60
+ margin-bottom: 10px;
61
+ border-left: 5px solid #fda085;
62
  }
63
  </style>
64
  """, unsafe_allow_html=True)
 
67
  with st.sidebar:
68
  st.markdown("# 👤 Personalised Fitness Plan")
69
  st.write("---")
70
+ st.write("Your digital fitness profile manager.")
71
 
72
  # --- MAIN CONTENT ---
73
  st.title("🏋️ Create Your Fitness Profile")
74
 
75
+ # SECTION 1: PERSONAL INFORMATION
76
+ st.markdown("### 1️⃣ Personal Information")
77
  col_name, col_gender, col_age = st.columns([2, 1, 1])
78
  with col_name:
79
+ name = st.text_input("Full Name *", placeholder="e.g. John Doe")
80
  with col_gender:
81
  gender = st.selectbox("Gender *", ["Male", "Female", "Other"])
82
  with col_age:
83
+ age = st.number_input("Age *", min_value=1, max_value=120, value=25)
84
 
85
  col_h, col_w = st.columns(2)
86
  with col_h:
87
+ height_cm = st.number_input("Height in centimeters *", min_value=0.0, step=0.1)
88
  with col_w:
89
+ weight_kg = st.number_input("Weight in kilograms *", min_value=0.0, step=0.1)
90
 
91
+ st.write("---")
 
 
92
 
93
+ # SECTION 2: FITNESS DETAILS
94
+ st.markdown("### 2️⃣ Fitness Details")
95
+ col_goal, col_level = st.columns(2)
96
+ with col_goal:
97
+ goal = st.selectbox("Fitness Goal", ["Build Muscle", "Weight Loss", "Strength Gain", "Abs Building", "Flexible"])
98
+ with col_level:
99
+ fitness_level = st.selectbox("Fitness Level", ["Beginner", "Intermediate", "Advanced"])
100
+
101
+ equipment = st.multiselect(
102
+ "Available Equipment *",
103
+ ["Dumbbells", "Resistance Band", "Yoga Mat", "Kettlebells", "Pull-up Bar", "No Equipment"],
104
+ default=["No Equipment"]
105
+ )
106
+
107
+ st.write("---")
108
+
109
+ # --- SUBMIT BUTTON & LOGIC ---
110
  if st.button("Submit Profile"):
111
+ if not name or height_cm <= 0 or weight_kg <= 0 or not equipment:
112
+ st.error("Please fill in all required fields (*) correctly.")
113
  else:
114
+ # BMI Logic
115
+ height_m = height_cm / 100
116
+ bmi = weight_kg / (height_m ** 2)
117
+ bmi_rounded = round(bmi, 2)
118
+
119
+ if bmi_rounded < 18.5:
120
+ bmi_status, status_color = "Underweight", "#3498db"
121
+ elif 18.5 <= bmi_rounded < 25:
122
+ bmi_status, status_color = "Normal", "#2ecc71"
123
+ elif 25 <= bmi_rounded < 30:
124
+ bmi_status, status_color = "Overweight", "#f1c40f"
125
+ else:
126
+ bmi_status, status_color = "Obese", "#e74c3c"
127
+
128
+ st.success("Profile Submitted Successfully!")
129
+
130
+ st.markdown(f"""
131
+ <div class="result-card">
132
+ <h2 style="color: #004d57; margin-top:0;">Assessment for {name}</h2>
133
+ <p>{gender} | {age} Years Old</p>
134
+ <p>Calculated BMI: <strong>{bmi_rounded}</strong> | Category: <span style="color: {status_color}; font-weight: bold;">{bmi_status}</span></p>
135
+ </div>
136
+ """, unsafe_allow_html=True)
137
+
138
+ # 5. AI Prompt (Optimized to Stop at Day 5)
139
+ equipment_list = ", ".join(equipment)
140
+ prompt = f"""Task: Write a 5-day workout plan for {name}.
141
+ Details: {gender}, Goal: {goal}, Level: {fitness_level}, Equipment: {equipment_list}.
142
+ Requirement: Stop exactly after Day 5. Do not include Day 6.
143
+
144
+ Structure:
145
+ Day 1: [Exercises]
146
+ Day 2: [Exercises]
147
+ Day 3: [Rest/Recovery]
148
+ Day 4: [Exercises]
149
+ Day 5: [Exercises]
150
+
151
+ Workout Plan:
152
  Day 1:"""
153
 
154
+ # 6. AI Generation
155
+ with st.spinner("Generating your aligned workout plan..."):
156
  try:
157
  inputs = tokenizer(prompt, return_tensors="pt", truncation=True)
 
158
  outputs = model.generate(
159
  **inputs,
160
+ max_new_tokens=450,
161
+ min_new_tokens=150,
162
  do_sample=True,
163
+ temperature=0.7,
164
+ repetition_penalty=2.5
 
165
  )
166
 
167
+ raw_result = tokenizer.decode(outputs[0], skip_special_tokens=True).strip()
168
+
169
+ # Cut off anything from "Day 6" onwards
170
+ clean_result = raw_result.split("Day 6")[0]
171
+
172
+ # Alignment Logic: Splitting the text by "Day" keywords to create visual blocks
173
  st.markdown("### 📋 Your Personalized Routine")
174
 
175
+ # Re-assembling the full text to ensure we don't miss Day 1
176
+ full_text = "Day 1: " + clean_result
177
+
178
  days = ["Day 1:", "Day 2:", "Day 3:", "Day 4:", "Day 5:"]
179
+
180
  for i in range(len(days)):
181
  start = full_text.find(days[i])
182
  if start != -1:
183
+ # Find where the next day starts to cut the text
184
  end = full_text.find(days[i+1]) if i+1 < len(days) else len(full_text)
185
+ day_content = full_text[start:end].strip()
186
 
187
+ # Display in a styled card
188
+ st.markdown(f"""
189
+ <div class="day-card">
190
+ <strong>{day_content[:6]}</strong><br>
191
+ {day_content[6:].strip()}
192
+ </div>
193
+ """, unsafe_allow_html=True)
194
+
195
  except Exception as e:
196
+ st.error(f"AI Generation failed: {e}")
197