Skip to content

Commit

Permalink
Added Personalized Workout and Diet Recommendation System (#274)
Browse files Browse the repository at this point in the history
* Added Personalized Workout and Diet Recommendation System

* Updated styles
  • Loading branch information
J-B-Mugundh authored Oct 19, 2024
1 parent 839c0f9 commit 3cdb8e6
Show file tree
Hide file tree
Showing 5 changed files with 450 additions and 0 deletions.
109 changes: 109 additions & 0 deletions diet-recommendation-api/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from flask import Flask, request, jsonify
from flask_cors import CORS
import os
import re
from dotenv import load_dotenv
import google.generativeai as genai

# Load environment variables from .env file
load_dotenv()

app = Flask(__name__)
CORS(app) # Enable CORS for all routes

# Configure the Gemini API with your API key
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))

# Define the prompt template for diet recommendations
prompt_template_resto = (
"Diet Recommendation System:\n"
"I want you to recommend 6 restaurants names, 6 breakfast names, 5 dinner names, and 6 workout names, "
"based on the following criteria:\n"
"Person age: {age}\n"
"Person gender: {gender}\n"
"Person weight: {weight}\n"
"Person height: {height}\n"
"Person veg_or_nonveg: {veg_or_nonveg}\n"
"Person generic disease: {disease}\n"
"Person region: {region}\n"
"Person allergics: {allergics}\n"
"Person foodtype: {foodtype}."
)

# Load the Gemini Pro model
model = genai.GenerativeModel("gemini-pro")
chat = model.start_chat(history=[])

@app.route('/')
def index():
return jsonify({"message": "Welcome to the Diet Recommendation API!"})

@app.route('/recommend', methods=['POST'])
def recommend():
if request.method == "POST":
data = request.json # Get JSON data from the request

print(data)

age = data['age']
gender = data['gender']
weight = data['weight']
height = data['height']
veg_or_nonveg = data['veg_or_nonveg']
disease = data['disease']
region = data['region']
allergics = data['allergics']
foodtype = data['foodtype']

# Prepare the prompt with user inputs
input_data = {
'age': age,
'gender': gender,
'weight': weight,
'height': height,
'veg_or_nonveg': veg_or_nonveg,
'disease': disease,
'region': region,
'allergics': allergics,
'foodtype': foodtype
}

# Create the prompt by formatting the template with input data
prompt = prompt_template_resto.format(**input_data)

# Send the prompt to the Gemini API and get the response
response = chat.send_message(prompt, stream=True)

# Capture the full response text
response_text = ""
for chunk in response:
response_text += chunk.text

print("Response: ", response_text)

# Extract recommendations using regular expressions
restaurant_names = re.findall(r'Restaurants:(.*?)Breakfast:', response_text, re.DOTALL)
breakfast_names = re.findall(r'Breakfast:(.*?)Dinner:', response_text, re.DOTALL)
dinner_names = re.findall(r'Dinner:(.*?)Workouts:', response_text, re.DOTALL)
workout_names = re.findall(r'Workouts:(.*?)$', response_text, re.DOTALL)

# Function to clean up extracted names safely
def extract_names(name_list):
if name_list:
return [name.strip() for name in name_list[0].strip().split('\n') if name.strip()]
return []

# Cleaning up the extracted lists
restaurant_names = extract_names(restaurant_names)
breakfast_names = extract_names(breakfast_names)
dinner_names = extract_names(dinner_names)
workout_names = extract_names(workout_names)

print(restaurant_names, "\n", breakfast_names)

# Return JSON response with recommendations
return jsonify(response_text)
return jsonify({"error": "Invalid request"}), 400

if __name__ == '__main__':
app.run(debug=True)
2 changes: 2 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const Services = lazy(() => import("./views/Services.jsx"));

import FItFlexChatBot from "./components/FItFlexChatBot.jsx";
import ProgressBar from "./components/ProgressBar.jsx";
import DietRecommendation from "./components/DietRecommendation.jsx";

function App() {
const [mode, setMode] = useState("light");
Expand Down Expand Up @@ -92,6 +93,7 @@ function App() {
element={<Services mode={mode} textcolor={textcolor} />}
/>
<Route path="/privacy-policy" element={<PrivacyPolicy />} />
<Route path="/dietrecommendation" element={<DietRecommendation/>} />
<Route path="/terms-of-use" element={<TermsOfUse />} />
</Routes>
<Footer />
Expand Down
Binary file added src/assets/img/Food_Diet_Bg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
210 changes: 210 additions & 0 deletions src/components/DietRecommendation.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import React, { useState } from 'react';
import '../styles/DietRecommendation.css'; // Ensure to create a CSS file for styling

const DietRecommendation = () => {
const [formData, setFormData] = useState({
age: '',
gender: '',
weight: '',
height: '',
veg_or_nonveg: '',
disease: '',
region: '',
allergics: '',
foodtype: '',
});

const [recommendations, setRecommendations] = useState({
restaurants: [],
breakfast: [],
dinner: [],
workouts: [],
});
const [error, setError] = useState('');

const handleChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value,
});
};

const handleSubmit = async (e) => {
e.preventDefault();
setError(''); // Reset error

try {
const response = await fetch('http://localhost:5000/recommend', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});

if (!response.ok) {
throw new Error('Network response was not ok');
}

const data = await response.json();
parseRecommendations(data); // Parse and set recommendations
} catch (error) {
setError('Failed to fetch recommendations. Please try again later.');
}
};

// Function to parse the response text into separate categories
const parseRecommendations = (data) => {
const recommendationsRegex = /Restaurant Recommendations:\s*(.*?)\*\*Breakfast Recommendations:\s*(.*?)\*\*Dinner Recommendations:\s*(.*?)\*\*Workout Recommendations:\s*(.*)$/s;
const matches = data.match(recommendationsRegex);

if (matches) {
const restaurantNames = matches[1].split('*').map(item => item.trim()).filter(item => item);
const breakfastNames = matches[2].split('*').map(item => item.trim()).filter(item => item);
const dinnerNames = matches[3].split('*').map(item => item.trim()).filter(item => item);
const workoutNames = matches[4].split('*').map(item => item.trim()).filter(item => item);

setRecommendations({
restaurants: restaurantNames,
breakfast: breakfastNames,
dinner: dinnerNames,
workouts: workoutNames,
});
} else {
setError('Failed to parse recommendations. Please try again later.');
}
};

return (
<div className="diet-recommendation-container">
<h1 className="heading">Personalized Workout and Diet Recommendation System</h1>
<div className="glassmorphic-box">
<form className="recommendation-form" onSubmit={handleSubmit}>
<label>Age</label>
<input
type="number"
name="age"
placeholder="Enter your age"
value={formData.age}
onChange={handleChange}
required
/>
<label>Gender</label>
<input
type="text"
name="gender"
placeholder="Enter your gender"
value={formData.gender}
onChange={handleChange}
required
/>
<label>Weight (kg)</label>
<input
type="number"
name="weight"
placeholder="Enter your weight"
value={formData.weight}
onChange={handleChange}
required
/>
<label>Height (cm)</label>
<input
type="number"
name="height"
placeholder="Enter your height"
value={formData.height}
onChange={handleChange}
required
/>
<label>Diet Type</label>
<select
name="veg_or_nonveg"
value={formData.veg_or_nonveg}
onChange={handleChange}
required
>
<option value="" disabled>Select Type</option>
<option value="veg">Vegetarian</option>
<option value="nonveg">Non-Vegetarian</option>
</select>
<label>Any Existing Disease</label>
<input
type="text"
name="disease"
placeholder="Enter any existing disease"
value={formData.disease}
onChange={handleChange}
/>
<label>Region</label>
<input
type="text"
name="region"
placeholder="Enter your region"
value={formData.region}
onChange={handleChange}
/>
<label>Allergies</label>
<input
type="text"
name="allergics"
placeholder="Enter any allergies"
value={formData.allergics}
onChange={handleChange}
/>
<label>Preferred Food Type</label>
<input
type="text"
name="foodtype"
placeholder="Enter your preferred food type"
value={formData.foodtype}
onChange={handleChange}
/>
<button type="submit">Get Recommendations</button>
</form>
</div>

{error && <div className="error-message">{error}</div>}

{recommendations.restaurants.length > 0 && (
<div className="recommendations-box">
<h2>Recommendations:</h2>
<div className="recommendation-category">
<h3>Restaurant Recommendations:</h3>
<ul>
{recommendations.restaurants.map((name, index) => (
<li key={index}>{name}</li>
))}
</ul>
</div>
<div className="recommendation-category">
<h3>Breakfast Recommendations:</h3>
<ul>
{recommendations.breakfast.map((name, index) => (
<li key={index}>{name}</li>
))}
</ul>
</div>
<div className="recommendation-category">
<h3>Dinner Recommendations:</h3>
<ul>
{recommendations.dinner.map((name, index) => (
<li key={index}>{name}</li>
))}
</ul>
</div>
<div className="recommendation-category">
<h3>Workout Recommendations:</h3>
<ul>
{recommendations.workouts.map((name, index) => (
<li key={index}>{name}</li>
))}
</ul>
</div>
</div>
)}
</div>
);
};

export default DietRecommendation;
Loading

0 comments on commit 3cdb8e6

Please sign in to comment.