import streamlit as st
import google.generativeai as genai
from PIL import Image
import requests
# Configure Google Generative AI library with an API key
genai.configure(api_key="AIzaSyBuQHthxfR0t-3RtZC44YxTBJWN4roz-O4")
# API configurations for Dobby
DOBBY_API_URL = "https://api.fireworks.ai/inference/v1/chat/completions"
DOBBY_API_KEY = "fw_3ZjtsywUGddwa1wGY4VvB3eW"
DOBBY_LEASHED_MODEL = "accounts/sentientfoundation/models/dobby-mini-leashed-llama-3-1-8b#accounts/sentientfoundation/deployments/22e7b3fd"
DOBBY_UNHINGED_MODEL = "accounts/sentientfoundation/models/dobby-mini-unhinged-llama-3-1-8b#accounts/sentientfoundation/deployments/81e155fc"
# Initialize session state for tracking meals and user info
if "meal_data" not in st.session_state:
st.session_state.meal_data = {"Breakfast": {}, "Lunch": {}, "Dinner": {}}
if "daily_totals" not in st.session_state:
st.session_state.daily_totals = {"Calories": 0, "Protein": 0, "Carbs": 0, "Fat": 0}
if "user_info" not in st.session_state:
st.session_state.user_info = {}
st.markdown("""
""", unsafe_allow_html=True)
st.markdown('
Calorie Bro
', unsafe_allow_html=True)
st.markdown('Your personal AI image calorie tracker, powered by Sentient Dobby AI. Upload you breakfast, lunch and dinner, write your workout for the day and dare to get some 18+ feedback!
', unsafe_allow_html=True)
# Step 1: User inputs weight (in pounds), goal, and Dobby tone
if not st.session_state.user_info:
st.markdown('', unsafe_allow_html=True)
weight = st.number_input(
"Enter your weight (lbs):",
min_value=50, # Minimum weight in pounds (~30 kg)
max_value=1000, # Maximum weight in pounds (~300 kg)
step=1,
value=175
)
goal = st.selectbox("Select your goal:", ["Lose Weight", "Maintain Weight", "Gain Weight"])
tone = "Sarcastic (Unhinged)" # Default tone
if st.button("Submit", help="Save your preferences to start tracking meals."):
st.session_state.user_info = {
"Weight": weight,
"Goal": goal,
"Tone": tone
}
st.success("Your preferences have been saved!")
# Step 2: Meal tracking
if st.session_state.user_info:
meal = st.selectbox("Select Meal:", ["Breakfast", "Lunch", "Dinner"])
uploaded_file = st.file_uploader(f"Upload your {meal} image", type=["jpg", "jpeg", "png"])
# Functions for analysis and comments
def analyze_food_with_gemini(input_prompt, image_data):
model = genai.GenerativeModel("gemini-1.5-pro-latest")
response = model.generate_content([input_prompt, image_data[0]])
return response.text
def prepare_image_data(uploaded_file):
bytes_data = uploaded_file.getvalue()
return [{"mime_type": uploaded_file.type, "data": bytes_data}]
def get_dobby_comment(food_name, total_calories, total_protein, total_carbs, total_fat, meal, goal, tone):
selected_model = DOBBY_UNHINGED_MODEL # Default tone is sarcastic
dobby_prompt = f"""
The user had {meal}: {food_name}.
Nutritional data: {total_calories} kcal, {total_protein} g protein, {total_carbs} g carbs, {total_fat} g fat.
The user's goal is to {goal.lower()}. Provide feedback for this meal.
"""
response = requests.post(
DOBBY_API_URL,
headers={
"Authorization": f"Bearer {DOBBY_API_KEY}",
"Content-Type": "application/json",
},
json={
"model": selected_model,
"messages": [{"role": "user", "content": dobby_prompt}],
},
)
return response.json().get("choices", [{}])[0].get("message", {}).get("content", "No response")
# Process uploaded meal image
if uploaded_file:
st.image(uploaded_file, caption=f"Uploaded {meal} Image", use_container_width=True)
with st.spinner("Analyzing the image..."):
try:
# Prepare image data and analyze with Gemini
image_data = prepare_image_data(uploaded_file)
input_prompt = """
You are an expert nutritionist analyzing the food items in the image.
Start by naming the meal based on the image, identify all ingredients, and estimate calories for each ingredient.
Summarize the total calories, protein, carbs, and fat. Provide data in this format:
Meal Name: [Name of the meal]
Total Calories: X kcal
Protein: X g
Carbs: X g
Fat: X g
say nothing else
"""
analysis = analyze_food_with_gemini(input_prompt, image_data)
# Extract analysis data
lines = analysis.split("\n")
food_name = lines[0].replace("Meal Name: ", "").strip()
total_calories = int(lines[1].replace("Total Calories: ", "").replace("kcal", "").strip())
total_protein = int(lines[2].replace("Protein: ", "").replace("g", "").strip())
total_carbs = int(lines[3].replace("Carbs: ", "").replace("g", "").strip())
total_fat = int(lines[4].replace("Fat: ", "").replace("g", "").strip())
# Save data for this meal
st.session_state.meal_data[meal] = {
"Food Name": food_name,
"Calories": total_calories,
"Protein": total_protein,
"Carbs": total_carbs,
"Fat": total_fat,
}
# Update daily totals
st.session_state.daily_totals["Calories"] += total_calories
st.session_state.daily_totals["Protein"] += total_protein
st.session_state.daily_totals["Carbs"] += total_carbs
st.session_state.daily_totals["Fat"] += total_fat
# Get Dobby's feedback
dobby_comment = get_dobby_comment(
food_name, total_calories, total_protein, total_carbs, total_fat, meal,
st.session_state.user_info["Goal"], st.session_state.user_info["Tone"]
)
# Display results in the desired format
st.write(
f"**{food_name}: {total_calories} kcal, {total_protein}g of Protein, {total_carbs}g of Carbs, {total_fat}g of Fat**"
)
st.write(dobby_comment)
except Exception as e:
st.error(f"Error processing the image: {e}")
# Step 3: Workout tracking and analysis
if all(st.session_state.meal_data[meal] for meal in ["Breakfast", "Lunch", "Dinner"]):
st.subheader("Step 3: Log Your Workout")
workout_input = st.text_area(
"Describe your workout or activity today (e.g., 'I walked for 30 minutes and biked for 1 hour'):",
placeholder="Enter your workout activities here..."
)
if st.button("Analyze Workout"):
if workout_input.strip() == "":
st.error("Please describe your workout before analyzing!")
else:
with st.spinner("Analyzing your workout..."):
try:
# Gemini prompt for workout analysis
workout_prompt = f"""
You are an expert fitness tracker. The user did the following activities today:
{workout_input}
Calculate the total calories burned based on the description.
Provide data in this format: "X calories burned by [activity descriptions]." Say nothing else.
"""
# Analyze workout using Gemini for text
model = genai.GenerativeModel("gemini-1.5-pro-latest")
workout_analysis = model.generate_content([workout_prompt]).text.strip()
st.session_state.daily_totals["Workout"] = workout_analysis
# Dobby's feedback on the workout
dobby_workout_prompt = f"""
The user performed the following workout activities: {workout_input}.
Based on the analysis, {workout_analysis}.
Provide sarcastic or motivational feedback based on the user's goal to {st.session_state.user_info["Goal"].lower()}.
"""
dobby_workout_comment = requests.post(
DOBBY_API_URL,
headers={
"Authorization": f"Bearer {DOBBY_API_KEY}",
"Content-Type": "application/json",
},
json={
"model": DOBBY_UNHINGED_MODEL, # Default to unhinged tone
"messages": [{"role": "user", "content": dobby_workout_prompt}],
},
).json().get("choices", [{}])[0].get("message", {}).get("content", "No response")
st.session_state.daily_totals["Workout Comment"] = dobby_workout_comment
# Display workout results
st.write(f"**{workout_analysis}**")
st.write(dobby_workout_comment)
except Exception as e:
st.error(f"Error processing workout: {e}")
# Step 4: Daily Summary
if "Workout" in st.session_state.daily_totals:
st.subheader("Daily Summary")
st.write(f"**Total Calories Consumed:** {st.session_state.daily_totals['Calories']} kcal")
st.write(f"**Total Protein:** {st.session_state.daily_totals['Protein']} g")
st.write(f"**Total Carbs:** {st.session_state.daily_totals['Carbs']} g")
st.write(f"**Total Fat:** {st.session_state.daily_totals['Fat']} g")
st.write(f"**Workout Summary:** {st.session_state.daily_totals['Workout']}")
# Final Dobby comment for the entire day
final_prompt = f"""
The user had the following meals today:
Breakfast: {st.session_state.meal_data['Breakfast']['Food Name']}
Lunch: {st.session_state.meal_data['Lunch']['Food Name']}
Dinner: {st.session_state.meal_data['Dinner']['Food Name']}
Total daily intake: {st.session_state.daily_totals['Calories']} kcal,
{st.session_state.daily_totals['Protein']} g protein, {st.session_state.daily_totals['Carbs']} g carbs,
{st.session_state.daily_totals['Fat']} g fat.
They also did the following workout: {st.session_state.daily_totals['Workout']}
Provide a summary of their day, considering both diet AND workout, and feedback for improvement.
"""
final_comment = get_dobby_comment(
"", st.session_state.daily_totals["Calories"], st.session_state.daily_totals["Protein"],
st.session_state.daily_totals["Carbs"], st.session_state.daily_totals["Fat"], "Daily Summary",
st.session_state.user_info["Goal"], st.session_state.user_info["Tone"]
)
st.write(final_comment)