-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
159 lines (135 loc) · 5.3 KB
/
app.py
File metadata and controls
159 lines (135 loc) · 5.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import streamlit as st
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.neighbors import NearestNeighbors
st.set_page_config(page_title="Smart Food Recommender", page_icon="🥗", layout="wide")
@st.cache_data
def load_data():
return pd.read_csv("food.csv").fillna(0)
df = load_data()
num_cols = [
"Data.Alpha Carotene","Data.Beta Carotene","Data.Beta Cryptoxanthin",
"Data.Carbohydrate","Data.Cholesterol","Data.Choline","Data.Fiber",
"Data.Lutein and Zeaxanthin","Data.Lycopene","Data.Niacin","Data.Protein",
"Data.Retinol","Data.Riboflavin","Data.Selenium","Data.Sugar Total",
"Data.Thiamin","Data.Water","Data.Fat.Monosaturated Fat",
"Data.Fat.Polysaturated Fat","Data.Fat.Saturated Fat",
"Data.Fat.Total Lipid","Data.Major Minerals.Calcium",
"Data.Major Minerals.Copper","Data.Major Minerals.Iron",
"Data.Major Minerals.Magnesium","Data.Major Minerals.Phosphorus",
"Data.Major Minerals.Potassium","Data.Major Minerals.Sodium",
"Data.Major Minerals.Zinc","Data.Vitamins.Vitamin A - RAE",
"Data.Vitamins.Vitamin B12","Data.Vitamins.Vitamin B6",
"Data.Vitamins.Vitamin C","Data.Vitamins.Vitamin E",
"Data.Vitamins.Vitamin K"
]
@st.cache_resource
def build_model(data):
preprocess = ColumnTransformer([
("text", TfidfVectorizer(stop_words="english", max_features=600), "Description"),
("cat", OneHotEncoder(handle_unknown="ignore"), ["Category"]),
("id", StandardScaler(), ["Nutrient Data Bank Number"]),
("num", StandardScaler(), num_cols)
])
X = preprocess.fit_transform(data)
model = NearestNeighbors(n_neighbors=10, metric="cosine")
model.fit(X)
return preprocess, model
preprocess, model = build_model(df)
st.markdown(
"""
<style>
.card {
padding: 1.2rem;
border-radius: 18px;
background: linear-gradient(135deg, #ffffff, #f2f4f8);
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
margin-bottom: 1rem;
}
</style>
""",
unsafe_allow_html=True
)
st.title("🥗 Smart Food Recommender")
st.caption("Pick your goal. Describe your vibe. Get food that actually matches.")
col1, col2, col3 = st.columns(3)
with col1:
category = st.selectbox(
"Food Category",
[""] + sorted(df["Category"].unique().tolist())
)
with col2:
goal = st.selectbox(
"Main Goal",
[
"Build muscle / High protein",
"Lose weight / Low fat & sugar",
"Heart healthy / Low sodium & fat",
"Vitamin rich / Immunity boost"
]
)
with col3:
diet = st.selectbox(
"Diet Preference",
[
"No preference",
"Low sugar",
"Low fat",
"Low sodium"
]
)
description = st.text_input(
"Describe your ideal food",
placeholder="light, healthy, high protein, easy to digest"
)
run = st.button("Find Food 🔥", use_container_width=True)
if "results" not in st.session_state:
st.session_state.results = []
if run:
query = df.mean(numeric_only=True)
query["Description"] = description if description else "healthy food"
query["Category"] = category if category else df["Category"].mode()[0]
query["Nutrient Data Bank Number"] = df["Nutrient Data Bank Number"].median()
if goal == "Build muscle / High protein":
query["Data.Protein"] = df["Data.Protein"].quantile(0.9)
if goal == "Lose weight / Low fat & sugar":
query["Data.Fat.Total Lipid"] = df["Data.Fat.Total Lipid"].quantile(0.1)
query["Data.Sugar Total"] = df["Data.Sugar Total"].quantile(0.1)
if goal == "Heart healthy / Low sodium & fat":
query["Data.Major Minerals.Sodium"] = df["Data.Major Minerals.Sodium"].quantile(0.1)
query["Data.Fat.Total Lipid"] = df["Data.Fat.Total Lipid"].quantile(0.2)
if goal == "Vitamin rich / Immunity boost":
query["Data.Vitamins.Vitamin C"] = df["Data.Vitamins.Vitamin C"].quantile(0.8)
query["Data.Vitamins.Vitamin A - RAE"] = df["Data.Vitamins.Vitamin A - RAE"].quantile(0.8)
if diet == "Low sugar":
query["Data.Sugar Total"] = df["Data.Sugar Total"].quantile(0.1)
if diet == "Low fat":
query["Data.Fat.Total Lipid"] = df["Data.Fat.Total Lipid"].quantile(0.1)
if diet == "Low sodium":
query["Data.Major Minerals.Sodium"] = df["Data.Major Minerals.Sodium"].quantile(0.1)
query_df = pd.DataFrame([query])
X_query = preprocess.transform(query_df)
_, indices = model.kneighbors(X_query)
st.session_state.results.append(indices[0])
if st.session_state.results:
st.subheader("🔥 Your Recommendations")
cols = st.columns(2)
shown = set()
for batch in st.session_state.results:
for idx, i in enumerate(batch):
if i in shown:
continue
shown.add(i)
row = df.iloc[i]
with cols[idx % 2]:
st.markdown(
f"""
<div class="card">
<h4>{row['Description']}</h4>
<p><b>Category:</b> {row['Category']}</p>
</div>
""",
unsafe_allow_html=True
)