Download app.py from og-arin/Fit-Byte: direct link, hf CLI and curl.
- Browser
- Download file 13.3 kB
-
https://huggingface.co/spaces/og-arin/Fit-Byte/resolve/main/app.py
- Command line
-
hf download hf://spaces/og-arin/Fit-Byte/app.py
-
curl -L -o app.py https://huggingface.co/spaces/og-arin/Fit-Byte/resolve/main/app.py
13.3 kB
| """ | |
| FitByte β Personalized AI Fitness Coach | |
| ======================================== | |
| Tech Stack : Groq API (LLaMA 3.3 70B) | Gradio | Hugging Face Spaces | |
| Concepts : System Prompt Engineering, Prompt Chaining, Dynamic Prompts, | |
| BMI Calculation, Input Validation, Secure API Key Handling | |
| """ | |
| import os | |
| import gradio as gr | |
| from groq import Groq | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # API SETUP (Colab β HF Spaces compatible) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_api_key() -> str: | |
| try: | |
| from google.colab import userdata | |
| return userdata.get("GROQ_API_KEY") | |
| except Exception: | |
| key = os.getenv("GROQ_API_KEY") | |
| if not key: | |
| raise EnvironmentError("GROQ_API_KEY not found in environment.") | |
| return key | |
| try: | |
| client = Groq(api_key=get_api_key()) | |
| API_READY = True | |
| except Exception as e: | |
| API_READY = False | |
| API_ERROR = str(e) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # BMI CALCULATION | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| def calculate_bmi(weight_kg: float, height_cm: float) -> tuple: | |
| if height_cm <= 0 or weight_kg <= 0: | |
| raise ValueError("Weight and height must be positive numbers.") | |
| height_m = height_cm / 100 | |
| bmi = round(weight_kg / (height_m ** 2), 1) | |
| if bmi < 18.5: | |
| category = "Underweight" | |
| elif bmi < 25.0: | |
| category = "Normal weight" | |
| elif bmi < 30.0: | |
| category = "Overweight" | |
| else: | |
| category = "Obese" | |
| return bmi, category | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # PROMPT ENGINEERING | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| COACHING_MODES = { | |
| "Motivational Coach π₯": ( | |
| "You are an energetic, motivational fitness coach. " | |
| "Use powerful, encouraging language. Include motivational quotes. " | |
| "Make the user feel unstoppable. Use emojis sparingly but effectively." | |
| ), | |
| "Scientific Advisor π¬": ( | |
| "You are a sports scientist and certified nutritionist. " | |
| "Use precise, evidence-based language. Cite physiological principles " | |
| "(e.g., progressive overload, TDEE, macronutrient ratios). " | |
| "Be clinical but clear. No fluff." | |
| ), | |
| "Friendly Buddy π": ( | |
| "You are the user's supportive gym buddy. " | |
| "Keep the tone casual, warm, and relatable. " | |
| "Use simple language. Make fitness feel approachable and fun." | |
| ), | |
| "Strict Drill Sergeant πͺ": ( | |
| "You are a no-nonsense military fitness trainer. " | |
| "Be direct, demanding, and results-focused. " | |
| "No excuses. Short, punchy sentences. Push the user hard." | |
| ), | |
| } | |
| def build_system_prompt(mode: str) -> str: | |
| base = COACHING_MODES.get(mode, COACHING_MODES["Motivational Coach π₯"]) | |
| return ( | |
| f"{base}\n\n" | |
| "Always structure your response with these clearly labeled sections:\n" | |
| "1. **BMI Analysis** β Interpret their BMI and what it means for them.\n" | |
| "2. **Weekly Workout Plan** β Plan with specific exercises, sets, reps.\n" | |
| "3. **Daily Meal Plan** β Breakfast, Lunch, Dinner, Snacks with approximate calories.\n" | |
| "4. **Key Tips** β 3 personalized tips based on their goal and fitness level.\n" | |
| "5. **Motivational Closing** β End with an inspiring one-liner.\n\n" | |
| "Use markdown formatting with bold headers. Be specific, not generic.\n\n" | |
| "IMPORTANT: Build the meal plan strictly around the user's available foods and cuisine. " | |
| "Do NOT suggest foods they cannot access or afford. Use locally available, budget-friendly alternatives." | |
| ) | |
| def build_user_prompt( | |
| name, age, gender, body_condition, | |
| weight, height, bmi, bmi_cat, | |
| goal, fitness_level, dietary_pref, | |
| cuisine_pref, food_context, | |
| workout_days, workout_duration, | |
| health_conditions | |
| ) -> str: | |
| conditions_str = health_conditions.strip() if health_conditions else "None reported" | |
| food_str = food_context.strip() if food_context else "No specific constraints" | |
| return ( | |
| f"Create a fully personalized fitness plan for the following individual:\n\n" | |
| f"**Personal Details:**\n" | |
| f"- Name: {name}\n" | |
| f"- Age: {age} years | Gender: {gender}\n" | |
| f"- Weight: {weight} kg | Height: {height} cm\n" | |
| f"- BMI: {bmi} ({bmi_cat}) | Body Condition: {body_condition}\n\n" | |
| f"**Goals & Preferences:**\n" | |
| f"- Primary Goal: {goal}\n" | |
| f"- Current Fitness Level: {fitness_level}\n" | |
| f"- Dietary Type: {dietary_pref}\n" | |
| f"- Cuisine / Food Region: {cuisine_pref}\n" | |
| f"- Food Availability & Budget: {food_str}\n" | |
| f"- Workout Days per Week: {workout_days}\n" | |
| f"- Workout Duration per Day: {workout_duration} minutes\n" | |
| f"- Health Conditions / Injuries: {conditions_str}\n\n" | |
| f"Generate a realistic, safe, and highly personalized plan. " | |
| f"Account for their BMI category, body condition, and health conditions " | |
| f"when recommending exercises and diet." | |
| ) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # GROQ API CALL | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| def call_groq(system_prompt: str, user_prompt: str) -> str: | |
| response = client.chat.completions.create( | |
| model="llama-3.3-70b-versatile", | |
| messages=[ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_prompt} | |
| ], | |
| max_tokens=2048 | |
| ) | |
| return response.choices[0].message.content | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # MAIN ORCHESTRATION | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| def generate_fitness_plan( | |
| name, age, gender, body_condition, | |
| weight, height, | |
| goal, fitness_level, dietary_pref, | |
| cuisine_pref, food_context, | |
| workout_days, workout_duration, | |
| health_conditions, coaching_mode | |
| ): | |
| if not name.strip(): | |
| return "β Error", "Please enter your name.", "" | |
| if not (10 <= int(age) <= 100): | |
| return "β Error", "Age must be between 10 and 100.", "" | |
| if weight <= 0 or height <= 0: | |
| return "β Error", "Weight and height must be positive values.", "" | |
| if not API_READY: | |
| return "β API Error", f"Groq API not configured: {API_ERROR}", "" | |
| try: | |
| bmi, bmi_cat = calculate_bmi(weight, height) | |
| bmi_display = f"**BMI: {bmi}** β {bmi_cat}" | |
| system_prompt = build_system_prompt(coaching_mode) | |
| user_prompt = build_user_prompt( | |
| name, age, gender, body_condition, | |
| weight, height, bmi, bmi_cat, | |
| goal, fitness_level, dietary_pref, | |
| cuisine_pref, food_context, | |
| int(workout_days), int(workout_duration), | |
| health_conditions | |
| ) | |
| plan = call_groq(system_prompt, user_prompt) | |
| download_text = ( | |
| f"FITBYTE β PERSONALIZED FITNESS PLAN\n" | |
| f"Name: {name}\n" | |
| f"{'='*50}\n\n" | |
| f"BMI: {bmi} ({bmi_cat})\n" | |
| f"Goal: {goal} | Level: {fitness_level} | Mode: {coaching_mode}\n" | |
| f"{'='*50}\n\n" | |
| + plan | |
| ) | |
| return bmi_display, plan, download_text | |
| except ValueError as ve: | |
| return "β Input Error", str(ve), "" | |
| except Exception as e: | |
| return "β Error", f"Something went wrong: {str(e)}", "" | |
| def save_plan(download_text: str): | |
| if not download_text: | |
| return None | |
| filepath = "/tmp/fitbyte_plan.txt" | |
| with open(filepath, "w") as f: | |
| f.write(download_text) | |
| return filepath | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # GRADIO UI | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| CSS = """ | |
| footer { display: none !important; } | |
| """ | |
| with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald"), css=CSS, title="FitByte") as demo: | |
| gr.Markdown(""" | |
| # ποΈ FitByte β Personalized AI Fitness Coach | |
| > **Powered by Groq (LLaMA 3.3 70B)** | Built with Gradio | Deployed on Hugging Face Spaces | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π€ Personal Info") | |
| name = gr.Textbox(label="Full Name", placeholder="e.g. Rohit Sharma") | |
| age = gr.Number(label="Age", value=21, minimum=10, maximum=100) | |
| gender = gr.Radio(["Male", "Female", "Other"], label="Gender", value="Male") | |
| body_condition = gr.Dropdown( | |
| ["Not Sure", "Skinny", "Skinny-Fat", "Average", "Overweight/Fat", "Muscular"], | |
| label="Current Body Condition", value="Average" | |
| ) | |
| gr.Markdown("### π Body Metrics") | |
| weight = gr.Number(label="Weight (kg)", value=70) | |
| height = gr.Number(label="Height (cm)", value=175) | |
| gr.Markdown("### π― Fitness Profile") | |
| goal = gr.Dropdown( | |
| ["Weight Loss", "Muscle Gain", "Maintain Weight", "Improve Stamina", "Flexibility & Mobility"], | |
| label="Primary Goal", value="Muscle Gain" | |
| ) | |
| fitness_level = gr.Dropdown( | |
| ["Beginner (0β6 months)", "Intermediate (6 monthsβ2 years)", "Advanced (2+ years)"], | |
| label="Fitness Level", value="Beginner (0β6 months)" | |
| ) | |
| dietary_pref = gr.Dropdown( | |
| ["No Preference", "Vegetarian", "Eggetarian", "Vegan", "Non-Vegetarian", "Keto", "High Protein"], | |
| label="Dietary Preference", value="No Preference" | |
| ) | |
| workout_days = gr.Slider(minimum=2, maximum=7, step=1, value=4, label="Workout Days per Week") | |
| workout_duration = gr.Slider(minimum=20, maximum=120, step=10, value=45, label="Workout Duration per Day (minutes)") | |
| gr.Markdown("### π½οΈ Food & Cuisine") | |
| cuisine_pref = gr.Dropdown( | |
| ["No Preference", "Indian", "South Indian", "Middle Eastern", "East Asian", "Mediterranean", "Western"], | |
| label="Cuisine / Region", value="No Preference" | |
| ) | |
| food_context = gr.Textbox( | |
| label="Food Availability & Budget (optional)", | |
| placeholder="e.g. I eat chapati, dal, sabzi daily. No bread or pasta. Tight budget.", | |
| lines=2 | |
| ) | |
| gr.Markdown("### βοΈ Health") | |
| health_conditions = gr.Textbox( | |
| label="Health Conditions / Injuries (optional)", | |
| placeholder="e.g. Lower back pain, knee injury..." | |
| ) | |
| gr.Markdown("### π€ Coaching Style") | |
| coaching_mode = gr.Radio( | |
| list(COACHING_MODES.keys()), | |
| label="Select Your Coach", | |
| value="Motivational Coach π₯" | |
| ) | |
| generate_btn = gr.Button("β‘ Generate My Plan", variant="primary", size="lg") | |
| with gr.Column(scale=2): | |
| gr.Markdown("### π Your BMI") | |
| bmi_output = gr.Markdown(value="_Your BMI will appear here._") | |
| gr.Markdown("### π Your Personalized Plan") | |
| plan_output = gr.Markdown(value="_Fill in your details and hit Generate._", height=600) | |
| with gr.Row(): | |
| download_state = gr.State("") | |
| download_btn = gr.Button("πΎ Download My Plan", variant="secondary") | |
| download_file = gr.File(label="Your Plan (TXT)", visible=False) | |
| gr.Markdown(""" | |
| --- | |
| **π Disclaimer:** AI-generated for educational purposes. Consult a certified trainer and nutritionist before starting any fitness program. | |
| """) | |
| generate_btn.click( | |
| fn=generate_fitness_plan, | |
| inputs=[ | |
| name, age, gender, body_condition, | |
| weight, height, | |
| goal, fitness_level, dietary_pref, | |
| cuisine_pref, food_context, | |
| workout_days, workout_duration, | |
| health_conditions, coaching_mode | |
| ], | |
| outputs=[bmi_output, plan_output, download_state] | |
| ) | |
| download_btn.click( | |
| fn=save_plan, | |
| inputs=[download_state], | |
| outputs=[download_file] | |
| ).then( | |
| fn=lambda: gr.File(visible=True), | |
| outputs=[download_file] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |