Spaces:
Running
Running
import streamlit as st | |
from dataclasses import dataclass | |
from typing import List, Dict, Optional | |
from datetime import datetime | |
import google.generativeai as genai | |
import os | |
from dotenv import load_dotenv | |
from PIL import Image | |
from langchain_groq import ChatGroq | |
from langchain.schema import HumanMessage, SystemMessage | |
import torch | |
import numpy as np | |
import plotly.graph_objects as go | |
from fpdf import FPDF | |
import time | |
# Load environment variables | |
load_dotenv() | |
# Configure LLMs | |
llm = ChatGroq( | |
temperature=0.2, | |
groq_api_key=os.environ.get("GROQ_API_KEY"), | |
model_name="llama-3.1-70b-versatile" | |
) | |
genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) | |
model = genai.GenerativeModel( | |
model_name="gemini-1.5-pro", | |
generation_config={ | |
"temperature": 0.2, | |
"top_p": 0.8, | |
"top_k": 40, | |
"max_output_tokens": 2048, | |
} | |
) | |
# Initialize session state for realtime.py components | |
if 'chat_history' not in st.session_state: | |
st.session_state.chat_history = [] | |
if 'user_data' not in st.session_state: | |
st.session_state.user_data = { | |
'progress': [], | |
'meal_logs': [], | |
'workout_logs': [] | |
} | |
# Code from acountable.py | |
class TransformationJourney: | |
user_id: str | |
goal_type: str # fitness, skill, personal growth etc | |
start_date: datetime | |
progress_images: List[Dict[str, str]] # [{date: image_path}] | |
feedback_history: List[Dict[str, str]] # [{date: feedback}] | |
chat_history: List[Dict[str, str]] # [{role: content}] | |
class TransformationCoach: | |
def __init__(self): | |
self.model = model | |
self.llm = llm | |
def analyze_image(self, image: Image) -> str: | |
prompt = """ | |
As a transformation coach, analyze this image in relation to the user's goals. | |
Provide detailed observations about: | |
1. Current state/progress visible in the image | |
2. Areas of improvement | |
3. Notable achievements | |
Be specific and objective in your analysis. | |
""" | |
response = self.model.generate_content([prompt, image]) | |
return response.text | |
def generate_feedback(self, analysis: str, goal_type: str) -> Dict[str, List[str]]: | |
prompt = f""" | |
Based on the following analysis of the user's progress image for their {goal_type} transformation: | |
{analysis} | |
Provide structured feedback in the following format: | |
1. Specific "DO" recommendations (3-5 points) | |
2. Specific "DON'T" recommendations (2-3 points) | |
3. A motivational message | |
Make all feedback actionable and tailored to the analysis. | |
""" | |
response = self.model.generate_content(prompt) | |
feedback_parts = response.text.split("\n\n") | |
return { | |
"dos": feedback_parts[0].split("\n")[1:], | |
"donts": feedback_parts[1].split("\n")[1:], | |
"motivation": feedback_parts[2] | |
} | |
def chat_response(self, question: str, context: List[Dict[str, str]], analysis: str = None) -> str: | |
prompt = f""" | |
You are a supportive transformation coach. Based on the following context: | |
Previous chat: {str(context)} | |
Latest analysis: {analysis if analysis else 'No recent analysis'} | |
User question: {question} | |
Provide a helpful, encouraging response focused on their transformation journey. | |
""" | |
response = self.llm.invoke(prompt) | |
return response.content | |
# Functions from realtime.py | |
def load_llm(): | |
api_key = os.environ.get("GROQ_API_KEY") | |
if api_key is None: | |
st.error("GROQ_API_KEY is not set in the environment variables.") | |
return None | |
llm = ChatGroq( | |
api_key=api_key, | |
model_name="llama-3.1-70b-versatile", | |
temperature=0.7, | |
max_tokens=2048 | |
) | |
return llm | |
def analyze_image_realtime(image, task="meal"): | |
try: | |
if task == "meal": | |
prompt = """ | |
As a nutrition expert, analyze this meal image and provide: | |
1. Estimated caloric content | |
2. Macro-nutrient breakdown | |
3. Nutritional assessment | |
4. Suggestions for improvement | |
5. Any potential health concerns | |
Be specific and detailed in your analysis. | |
""" | |
else: # workout form analysis | |
prompt = """ | |
As a fitness expert, analyze this workout form and provide: | |
1. Form assessment | |
2. Potential injury risks | |
3. Specific corrections needed | |
4. Benefits of proper form | |
Be specific and detailed in your analysis. | |
""" | |
response = model.generate_content([prompt, image]) | |
return response.text | |
except Exception as e: | |
return f"Error analyzing image: {str(e)}" | |
def track_progress(metric, value, date=None): | |
if date is None: | |
date = datetime.now().strftime("%Y-%m-%d") | |
st.session_state.user_data['progress'].append({ | |
'date': date, | |
'metric': metric, | |
'value': value | |
}) | |
def display_progress_chart(): | |
if not st.session_state.user_data['progress']: | |
return | |
data = st.session_state.user_data['progress'] | |
fig = go.Figure() | |
metrics = set(item['metric'] for item in data) | |
for metric in metrics: | |
metric_data = [item for item in data if item['metric'] == metric] | |
dates = [item['date'] for item in metric_data] | |
values = [item['value'] for item in metric_data] | |
fig.add_trace(go.Scatter(x=dates, y=values, name=metric)) | |
fig.update_layout(title="Your Progress Over Time", | |
xaxis_title="Date", | |
yaxis_title="Value") | |
st.plotly_chart(fig) | |
# Functions from workout.py | |
def generate_meal_plan(weight, height, age, gender, activity_level, goal, dietary_restrictions, health_history, current_eating_habits, meal_preparation, budget, sleep): | |
"""Generate personalized meal plan using LLM""" | |
prompt = f""" | |
Based on the following user data, generate a highly personalized and detailed daily meal plan with easily available ingredients: | |
User Profile: | |
- Weight: {weight} kg | |
- Height: {height} cm | |
- Age: {age} | |
- Gender: {gender} | |
- Activity Level: {activity_level} | |
- Goal: {goal} | |
- Dietary Restrictions: {', '.join(dietary_restrictions)} | |
- Health History: {health_history} | |
- Current Eating Habits: {current_eating_habits} | |
- Meal Preparation: {meal_preparation} | |
- Budget: {budget} | |
- Sleep: {sleep} | |
Generate a clear and structured meal plan with: | |
1. Total Daily Calorie Requirements | |
2. Macronutrient Distribution (in grams): | |
- Protein | |
- Carbohydrates | |
- Fats | |
Daily Meal Schedule: | |
[Detailed meal schedule content...] | |
""" | |
response = llm.invoke(prompt) | |
return response.content | |
def generate_workout_plan(goal, activity_level, target_areas, workout_time, current_fitness_level, exercise_preferences): | |
"""Generate personalized workout plan using LLM""" | |
prompt = f""" | |
Based on: | |
- Fitness Goal: {goal} | |
- Activity Level: {activity_level} | |
- Target Areas: {target_areas} | |
- Workout Time: {workout_time} | |
- Current Fitness Level: {current_fitness_level} | |
- Exercise Preferences: {exercise_preferences} | |
Generate a clear and structured weekly workout plan: | |
[Detailed workout plan content...] | |
""" | |
response = llm.invoke(prompt) | |
return response.content | |
def create_pdf(name, meal_plan, workout_plan): | |
pdf = FPDF() | |
pdf.add_page() | |
pdf.set_font('Arial', 'B', 20) | |
pdf.cell(0, 10, f'Personalized Fitness Plan for {name}', ln=True, align='C') | |
pdf.ln(10) | |
pdf.set_font('Arial', 'B', 16) | |
pdf.cell(0, 10, 'Meal Plan', ln=True) | |
pdf.set_font('Arial', '', 12) | |
pdf.multi_cell(0, 10, meal_plan) | |
pdf.add_page() | |
pdf.set_font('Arial', 'B', 16) | |
pdf.cell(0, 10, 'Workout Plan', ln=True) | |
pdf.set_font('Arial', '', 12) | |
pdf.multi_cell(0, 10, workout_plan) | |
return pdf | |
def main(): | |
st.set_page_config(page_title="AI Fitness Coach", layout="wide") | |
# Chat input needs to be outside tabs | |
user_input = st.chat_input("Type your message here...") | |
if user_input: | |
st.session_state.chat_history.append({"role": "user", "content": user_input}) | |
# Process user input with LLM | |
llm = load_llm() | |
if llm is not None: | |
messages = [ | |
SystemMessage(content="You are an expert health and fitness coach. Provide detailed and personalized advice."), | |
HumanMessage(content=user_input) | |
] | |
response = llm(messages) | |
st.session_state.chat_history.append({"role": "assistant", "content": response.content}) | |
tab1, tab2, tab3 = st.tabs(["Transformation Journey", "Realtime Tracking", "Workout & Meal Plans"]) | |
with tab1: | |
# Implementation from acountable.py | |
st.title("Transformation Journey Tracker") | |
if 'coach' not in st.session_state: | |
st.session_state.coach = TransformationCoach() | |
if 'journey' not in st.session_state: | |
st.session_state.journey = None | |
# Initialize or load journey | |
if not st.session_state.journey: | |
with st.form("journey_setup"): | |
st.write("Let's start your transformation journey!") | |
user_id = st.text_input("Enter your user ID") | |
goal_type = st.selectbox( | |
"What type of transformation?", | |
["Fitness", "Skill Development", "Personal Growth", "Other"] | |
) | |
if st.form_submit_button("Start Journey"): | |
st.session_state.journey = TransformationJourney( | |
user_id=user_id, | |
goal_type=goal_type, | |
start_date=datetime.now(), | |
progress_images=[], | |
feedback_history=[], | |
chat_history=[] | |
) | |
# Main interaction area | |
if st.session_state.journey: | |
st.subheader("Upload Progress Image") | |
uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"], key="transform_uploader") | |
if uploaded_file: | |
image = Image.open(uploaded_file) | |
st.image(image, caption="Uploaded Image", use_column_width=True) | |
if st.button("Analyze and Get Feedback"): | |
with st.spinner("Analyzing your progress..."): | |
analysis = st.session_state.coach.analyze_image(image) | |
feedback = st.session_state.coach.generate_feedback( | |
analysis, | |
st.session_state.journey.goal_type | |
) | |
# Display feedback | |
st.subheader("Your Personalized Feedback") | |
st.write("🎯 DO:") | |
for do in feedback["dos"]: | |
st.write(f"✓ {do}") | |
st.write("⚠️ DON'T:") | |
for dont in feedback["donts"]: | |
st.write(f"✗ {dont}") | |
st.write("💪 Motivation:") | |
st.write(feedback["motivation"]) | |
# Store progress | |
current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") | |
image_path = f"progress_images/{st.session_state.journey.user_id}_{current_time}.jpg" | |
st.session_state.journey.progress_images.append({ | |
current_time: image_path | |
}) | |
st.session_state.journey.feedback_history.append({ | |
current_time: feedback | |
}) | |
# Chat interface | |
st.write("---") | |
st.subheader("Chat with Your Coach") | |
# Display chat history | |
for message in st.session_state.journey.chat_history: | |
if message["role"] == "user": | |
st.write("You: " + message["content"]) | |
else: | |
st.write("Coach: " + message["content"]) | |
# Chat input | |
user_question = st.text_input("Ask your coach anything:", key="transform_chat") | |
if st.button("Send", key="transform_send"): | |
if user_question: | |
# Add user message | |
st.session_state.journey.chat_history.append({ | |
"role": "user", | |
"content": user_question | |
}) | |
# Get coach's response | |
latest_analysis = st.session_state.coach.analyze_image(image) if uploaded_file else None | |
response = st.session_state.coach.chat_response( | |
user_question, | |
st.session_state.journey.chat_history, | |
latest_analysis | |
) | |
# Add coach's response | |
st.session_state.journey.chat_history.append({ | |
"role": "coach", | |
"content": response | |
}) | |
st.experimental_rerun() | |
with tab2: | |
# Implementation from realtime.py | |
st.title("AI Health Coach") | |
st.warning("""This system is for informational purposes only and is not a substitute for professional medical advice, | |
diagnosis, or treatment. Always seek the advice of your physician or other qualified health provider.""") | |
# Display chat history | |
for message in st.session_state.chat_history: | |
with st.chat_message(message["role"]): | |
st.write(message["content"]) | |
# Image upload and analysis | |
uploaded_file = st.file_uploader("Upload an image for analysis (meal or workout form)", type=['png', 'jpg', 'jpeg'], key="realtime_uploader") | |
if uploaded_file: | |
image = Image.open(uploaded_file) | |
st.image(image, caption="Uploaded Image") | |
analysis_type = st.radio("What would you like to analyze?", ["Meal", "Workout Form"]) | |
if st.button("Analyze Image", key="realtime_analyze"): | |
with st.spinner("Analyzing image..."): | |
results = analyze_image_realtime(image, analysis_type.lower()) | |
st.write("Analysis Results:", results) | |
# Progress tracking section | |
with st.expander("Track Your Progress"): | |
metric = st.selectbox("Select metric to track", ["Weight", "Body Fat %", "Workout Duration", "Calories"]) | |
value = st.number_input("Enter value", key="progress_value") | |
if st.button("Log Progress", key="log_progress"): | |
track_progress(metric, value) | |
st.success("Progress logged successfully!") | |
# Display progress charts | |
display_progress_chart() | |
with tab3: | |
# Implementation from workout.py | |
st.title("AI Fitness Coach") | |
st.markdown("<h1 style='text-align: center; color: #4CAF50;'>Welcome to Your Personalized Fitness Journey!</h1>", unsafe_allow_html=True) | |
# Get user inputs | |
st.header("Personal Information") | |
col1, col2, col3 = st.columns(3) | |
with col1: | |
name = st.text_input("What's your name?", placeholder="Enter your name") | |
age = st.number_input("What's your age?", min_value=1, max_value=120, value=25) | |
gender = st.selectbox("What's your gender?", ["Male", "Female"]) | |
health_history = st.text_input("Do you have any medical conditions?") | |
with col2: | |
weight = st.number_input("What's your weight (in kg)?", min_value=1, value=70) | |
height = st.number_input("What's your height (in cm)?", min_value=1, value=170) | |
goal = st.selectbox( | |
"What's your fitness goal?", | |
["Weight Loss", "Muscle Gain", "Maintenance", "General Fitness"], | |
index=0 | |
) | |
activity_level = st.selectbox( | |
"What's your activity level?", | |
[ | |
"Sedentary (little to no exercise)", | |
"Lightly Active (1-3 days/week)", | |
"Moderately Active (3-5 days/week)", | |
"Very Active (6-7 days/week)", | |
"Extra Active (very intense exercise daily)" | |
] | |
) | |
with col3: | |
dietary_restrictions = st.multiselect( | |
"Do you have any dietary restrictions?", | |
["None", "Vegetarian", "Vegan", "Gluten-Free", "Dairy-Free", "Keto"] | |
) | |
current_eating_habits = st.text_input("What does your current diet look like?") | |
meal_preparation = st.text_input("Do you cook your meals or rely on takeout?") | |
budget = st.number_input("What is your monthly budget for groceries/food?", min_value=0) | |
if st.button("Generate Plans", key="generate_plans"): | |
if not name or not goal or not age or not gender or not weight or not height or not activity_level: | |
st.error("Please fill in all required fields") | |
return | |
with st.spinner("Generating your personalized plans..."): | |
meal_plan = generate_meal_plan( | |
weight=weight, | |
height=height, | |
age=age, | |
gender=gender, | |
activity_level=activity_level, | |
goal=goal, | |
dietary_restrictions=dietary_restrictions if dietary_restrictions else ["None"], | |
health_history=health_history, | |
current_eating_habits=current_eating_habits, | |
meal_preparation=meal_preparation, | |
budget=budget, | |
sleep="8 hours" # Default value | |
) | |
workout_plan = generate_workout_plan( | |
goal=goal, | |
activity_level=activity_level, | |
target_areas="full body", # Default value | |
workout_time=60, # Default value | |
current_fitness_level="Beginner", # Default value | |
exercise_preferences="None" # Default value | |
) | |
# Create PDF | |
pdf = create_pdf(name, meal_plan, workout_plan) | |
# Display plans in two columns | |
col1, col2 = st.columns(2) | |
with col1: | |
st.subheader("Your Meal Plan") | |
st.write(meal_plan) | |
with col2: | |
st.subheader("Your Workout Plan") | |
st.write(workout_plan) | |
# Add download button | |
st.download_button( | |
label="Download Plan as PDF", | |
data=pdf.output(dest='S').encode('latin-1'), | |
file_name=f"fitness_plan_{name}.pdf", | |
mime="application/pdf" | |
) | |
if __name__ == "__main__": | |
main() |