import gradio as gr import matplotlib.pyplot as plt import pandas as np import tempfile from datetime import datetime from langchain_core.messages import HumanMessage from tools import tools from agents import * from config import * from workflow import create_workflow # Initialize workflow graph = create_workflow() # Helper Functions def run_graph(input_message, history, user_details): try: system_prompt = ( "You are a fitness and health assistant. " "Provide advice based on the user's personal details and goals. " "If user details like weight, height, and activity level are provided, prioritize personalized advice. " "Incorporate metrics such as BMI and daily caloric needs directly into your suggestions. " "Visualize the user's metrics and provide actionable advice tailored to their needs. " "If details are missing, provide general advice but encourage users to share their metrics for tailored guidance." ) # Compose input for the LLM user_details_summary = ( f"Name: {user_details.get('name', 'Unknown')}, " f"Age: {user_details.get('age', 'Unknown')}, " f"Gender: {user_details.get('gender', 'Unknown')}, " f"Weight: {user_details.get('weight', 'Unknown')} kg, " f"Height: {user_details.get('height', 'Unknown')} cm, " f"Activity Level: {user_details.get('activity_level', 'Unknown')}" ) messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": f"User details: {user_details_summary}"}, {"role": "user", "content": input_message} ] # Generate the response response = graph.invoke({"messages": messages}) return response["messages"][1]["content"] except Exception as e: return f"An error occurred while processing your request: {e}" def calculate_bmi(height, weight): height_m = height / 100 bmi = weight / (height_m ** 2) if bmi < 18.5: status = "underweight" elif 18.5 <= bmi < 24.9: status = "normal weight" elif 25 <= bmi < 29.9: status = "overweight" else: status = "obese" return bmi, status def visualize_bmi_and_calories(bmi, calories): # Create a combined visualization categories = ["Underweight", "Normal Weight", "Overweight", "Obese"] bmi_values = [18.5, 24.9, 29.9, 40] calorie_range = [1500, 2000, 2500, 3000] fig, ax1 = plt.subplots(figsize=(10, 6)) # BMI visualization ax1.bar(categories, bmi_values, color=['blue', 'green', 'orange', 'red'], alpha=0.6, label="BMI Ranges") ax1.axhline(y=bmi, color='purple', linestyle='--', linewidth=2, label=f"Your BMI: {bmi:.2f}") ax1.set_ylabel("BMI Value") ax1.set_title("BMI and Caloric Needs Visualization") ax1.legend(loc="upper left") # Calorie visualization ax2 = ax1.twinx() ax2.plot(categories, calorie_range, 'o-', color='magenta', label="Calorie Ranges") ax2.axhline(y=calories, color='cyan', linestyle='--', linewidth=2, label=f"Your Calorie Needs: {calories:.2f} kcal") ax2.set_ylabel("Calories") ax2.legend(loc="upper right") plt.tight_layout() # Save to a temporary file temp_file = tempfile.NamedTemporaryFile(suffix=".png", delete=False) plt.savefig(temp_file.name) plt.close() return temp_file.name def calculate_calories(age, weight, height, activity_level, gender): if gender.lower() == "male": bmr = 10 * weight + 6.25 * height - 5 * age + 5 else: bmr = 10 * weight + 6.25 * height - 5 * age - 161 activity_multipliers = { "Sedentary": 1.2, "Lightly active": 1.375, "Moderately active": 1.55, "Very active": 1.725, "Extra active": 1.9, } return bmr * activity_multipliers.get(activity_level, 1.2) # Interface Components with gr.Blocks() as demo: gr.Markdown("FIT.AI - Your Fitness and Wellbeing Coach") # User Info with gr.Row(): user_name = gr.Textbox(placeholder="Enter your name", label="Name") user_age = gr.Number(label="Age (years)", value=25, precision=0) user_gender = gr.Dropdown(choices=["Male", "Female"], label="Gender", value="Male") user_weight = gr.Number(label="Weight (kg)", value=70, precision=1) user_height = gr.Number(label="Height (cm)", value=170, precision=1) activity_level = gr.Dropdown( choices=["Sedentary", "Lightly active", "Moderately active", "Very active", "Extra active"], label="Activity Level", value="Moderately active" ) # Outputs bmi_output = gr.Label(label="BMI Result") calorie_output = gr.Label(label="Calorie Needs") bmi_chart = gr.Image(label="BMI and Calorie Chart") chatbot = gr.Chatbot(label="Chat with FIT.AI") text_input = gr.Textbox(placeholder="Type your question here...", label="Your Question") submit_button = gr.Button("Submit") clear_button = gr.Button("Clear Chat") def submit_message(message, history=[]): user_details = { "name": user_name.value, "age": user_age.value, "weight": user_weight.value, "height": user_height.value, "activity_level": activity_level.value, "gender": user_gender.value } bmi, status = calculate_bmi(user_details['height'], user_details['weight']) calories = calculate_calories( user_details['age'], user_details['weight'], user_details['height'], user_details['activity_level'], user_details['gender'] ) chart_path = visualize_bmi_and_calories(bmi, calories) # Append metrics to response with actionable advice personalized_metrics = ( f"Based on your metrics:\n" f"- BMI: {bmi:.2f} ({status})\n" f"- Daily Caloric Needs: {calories:.2f} kcal\n" f"\nAdvice: " ) if status == "underweight": personalized_metrics += "Your BMI indicates you are underweight. Focus on consuming more calories from nutrient-dense foods, including lean proteins, healthy fats, and whole grains. Consider strength training exercises to build muscle mass." elif status == "normal weight": personalized_metrics += "Your BMI is in the normal range. Maintain your weight by balancing calorie intake with regular physical activity. Incorporate a mix of cardio and strength training for overall fitness." elif status == "overweight": personalized_metrics += "Your BMI indicates you are overweight. Aim for a calorie deficit by reducing portion sizes and increasing physical activity. Focus on a diet rich in vegetables, lean protein, and healthy fats." else: personalized_metrics += "Your BMI indicates you are obese. Consult a healthcare provider for a personalized weight loss plan. Start with small, sustainable changes, such as reducing sugary foods and increasing daily physical activity." response = personalized_metrics history.append((f"User", message)) history.append(("FIT.AI", response)) return history, chart_path submit_button.click(submit_message, inputs=[text_input, chatbot], outputs=[chatbot, bmi_chart]) clear_button.click(lambda: ([], ""), inputs=None, outputs=[chatbot, bmi_chart]) # Actions calculate_button = gr.Button("Calculate") def calculate_metrics(age, weight, height, gender, activity_level): bmi, status = calculate_bmi(height, weight) bmi_path = visualize_bmi_and_calories(bmi, calculate_calories(age, weight, height, activity_level, gender)) calories = calculate_calories(age, weight, height, activity_level, gender) return f"Your BMI is {bmi:.2f}, considered {status}.", f"Daily calorie needs: {calories:.2f} kcal", bmi_path calculate_button.click( calculate_metrics, inputs=[user_age, user_weight, user_height, user_gender, activity_level], outputs=[bmi_output, calorie_output, bmi_chart] ) demo.launch(share=True)