-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Personalized Workout and Diet Recommendation System (#274)
* Added Personalized Workout and Diet Recommendation System * Updated styles
- Loading branch information
1 parent
839c0f9
commit 3cdb8e6
Showing
5 changed files
with
450 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
Oops, something went wrong.