OmPrakashSingh1704 commited on
Commit
26b4729
1 Parent(s): 3b410a1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +269 -235
app.py CHANGED
@@ -1,7 +1,7 @@
1
  import streamlit as st
2
  import re
3
  import json
4
- import os
5
  import pandas as pd
6
  from huggingface_hub import login, InferenceClient
7
  import pickle
@@ -20,243 +20,277 @@ with open('vectors.pkl', 'rb') as file:
20
  with open('items_dict.pkl', 'rb') as file:
21
  items_dict = pd.DataFrame.from_dict(pickle.load(file))
22
 
23
- # Initialize the inference client for the Mixtral model
24
- client = InferenceClient("mistralai/Mixtral-8x7B-Instruct-v0.1")
25
-
26
- if 'recipe' not in st.session_state:
27
- st.session_state.recipe = None
28
-
29
- if 'recipe_saved' not in st.session_state:
30
- st.session_state.recipe_saved = None
31
-
32
- if 'user_direction' not in st.session_state:
33
- st.session_state.user_direction = None
34
-
35
- if 'serving_size' not in st.session_state:
36
- st.session_state.serving_size = 2
 
 
 
 
 
37
 
38
- if 'selected_difficulty' not in st.session_state:
39
- st.session_state.selected_difficulty = "Quick & Easy"
40
-
41
- if 'exclusions' not in st.session_state:
42
- st.session_state.exclusions = None
43
-
44
- def preprocess_text(text):
45
- # Remove non-alphabet characters and extra spaces
46
- text = re.sub(r'[^a-zA-Z\s]', '', text)
47
- text = re.sub(r'\s+', ' ', text).strip()
48
- return text.lower()
49
-
50
- def get_recommendations(user_description, count_vectorizer, count_matrix):
51
- user_description = preprocess_text(user_description)
52
- user_vector = count_vectorizer.transform([user_description])
53
- cosine_similarities = cosine_similarity(user_vector, count_matrix).flatten()
54
- similar_indices = cosine_similarities.argsort()[::-1][:5]
55
- return similar_indices
56
-
57
- def create_detailed_prompt(user_direction, exclusions, serving_size, difficulty):
58
- if difficulty == "Quick & Easy":
59
- prompt = (
60
- f"Provide a 'Quick and Easy' recipe for {user_direction} that excludes {exclusions} and has a serving size of {serving_size}. "
61
- f"It should require as few ingredients as possible and should be ready in as little time as possible. "
62
- f"The steps should be simple, and the ingredients should be commonly found in a household pantry. "
63
- f"Provide a detailed ingredient list and step-by-step guide that explains the instructions to prepare in detail."
64
- )
65
- elif difficulty == "Intermediate":
66
- prompt = (
67
- f"Provide a classic recipe for {user_direction} that excludes {exclusions} and has a serving size of {serving_size}. "
68
- f"The recipe should offer a bit of a cooking challenge but should not require professional skills. "
69
- f"The recipe should feature traditional ingredients and techniques that are authentic to its cuisine. "
70
- f"Provide a detailed ingredient list and step-by-step guide that explains the instructions to prepare in detail."
71
- )
72
- elif difficulty == "Professional":
73
- prompt = (
74
- f"Provide an advanced recipe for {user_direction} that excludes {exclusions} and has a serving size of {serving_size}. "
75
- f"The recipe should push the boundaries of culinary arts, integrating unique ingredients, advanced cooking techniques, and innovative presentations. "
76
- f"The recipe should be able to be served at a high-end restaurant or would impress at a gourmet food competition. "
77
- f"Provide a detailed ingredient list and step-by-step guide that explains the instructions to prepare in detail."
78
- )
79
- return prompt
80
-
81
-
82
- def generate_recipe(user_inputs):
83
- with st.spinner('Building the perfect recipe...'):
84
- prompt = create_detailed_prompt(user_inputs['user_direction'], user_inputs['exclusions'],
85
- user_inputs['serving_size'], user_inputs['difficulty'])
86
-
87
- functions = [
88
- {
89
- "name": "provide_recipe",
90
- "description": "Provides a detailed recipe strictly adhering to the user input/specifications, especially ingredient exclusions and the recipe difficulty",
91
- "parameters": {
92
- "type": "object",
93
- "properties": {
94
- "name": {
95
- "type": "string",
96
- "description": "A creative name for the recipe"
97
- },
98
- "description": {
99
- "type": "string",
100
- "description": "a brief one-sentence description of the provided recipe"
101
- },
102
- "ingredients": {
103
- "type": "array",
104
- "items": {
105
- "type": "object",
106
- "properties": {
107
- "name": {
108
- "type": "string",
109
- "description": "Quantity and name of the ingredient"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
- }
112
- }
113
- },
114
- "instructions": {
115
- "type": "array",
116
- "items": {
117
- "type": "object",
118
- "properties": {
119
- "step_number": {
120
- "type": "number",
121
- "description": "The sequence number of this step"
122
- },
123
- "instruction": {
124
- "type": "string",
125
- "description": "Detailed description of what to do in this step"
126
  }
127
  }
128
- }
129
- }
130
- },
131
- "required": [
132
- "name",
133
- "description",
134
- "ingredients",
135
- "instructions"
136
- ],
137
- },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  }
139
- ]
140
-
141
- generate_kwargs = dict(
142
- temperature=0.9,
143
- max_new_tokens=10000,
144
- top_p=0.9,
145
- repetition_penalty=1.0,
146
- do_sample=True,
 
 
 
 
 
 
 
147
  )
148
-
149
- prompt += f"\nPlease format the output in JSON. The JSON should include fields for 'name', 'description', 'ingredients', and 'instructions', with each field structured as described below.\n\n{json.dumps(functions)}"
150
-
151
- response = client.text_generation(prompt, **generate_kwargs)
152
- st.session_state.recipe = response
153
- st.session_state.recipe_saved = False
154
-
155
-
156
- def clear_inputs():
157
- st.session_state.user_direction = None
158
- st.session_state.exclusions = None
159
- st.session_state.serving_size = 2
160
- st.session_state.selected_difficulty = "Quick & Easy"
161
-
162
-
163
- st.title("Let's get cooking")
164
- col1,col2=st.columns(2)
165
- with col1:
166
- st.session_state.user_direction = st.text_area(
167
- "What do you want to cook? Describe anything - a dish, cuisine, event, or vibe.",
168
- value=st.session_state.user_direction,
169
- placeholder="quick snack, asian style bowl with either noodles or rice, something italian",
170
- )
171
- with col2:
172
- st.session_state.serving_size = st.number_input(
173
- "How many servings would you like to cook?",
174
- min_value=1,
175
- max_value=100,
176
- value=st.session_state.serving_size,
177
- step=1
178
- )
179
-
180
- difficulty_dictionary = {
181
- "Quick & Easy": {
182
- "description": "Easy recipes with straightforward instructions. Ideal for beginners or those seeking quick and simple cooking.",
183
- },
184
- "Intermediate": {
185
- "description": "Recipes with some intricate steps that invite a little challenge. Perfect for regular cooks wanting to expand their repertoire with new ingredients and techniques.",
186
- },
187
- "Professional": {
188
- "description": "Complex recipes that demand a high level of skill and precision. Suited for seasoned cooks aspiring to professional-level sophistication and creativity.",
189
- }
190
- }
191
-
192
- st.session_state.selected_difficulty = st.radio(
193
- "Choose a difficulty level for your recipe.",
194
- [
195
- list(difficulty_dictionary.keys())[0],
196
- list(difficulty_dictionary.keys())[1],
197
- list(difficulty_dictionary.keys())[2]
198
- ],
199
- captions=[
200
- difficulty_dictionary["Quick & Easy"]["description"],
201
- difficulty_dictionary["Intermediate"]["description"],
202
- difficulty_dictionary["Professional"]["description"]
203
- ],
204
- index=list(difficulty_dictionary).index(st.session_state.selected_difficulty)
205
- )
206
-
207
- st.session_state.exclusions = st.text_area(
208
- "Any ingredients you want to exclude?",
209
- value=st.session_state.exclusions,
210
- placeholder="gluten, dairy, nuts, cilantro",
211
- )
212
-
213
- fancy_exclusions = ""
214
-
215
- if st.session_state.selected_difficulty == "Professional":
216
- exclude_fancy = st.checkbox(
217
- "Exclude cliche professional ingredients? (gold leaf, truffle, edible flowers, microgreens)",
218
- value=True)
219
- if exclude_fancy:
220
- fancy_exclusions = "gold leaf, truffle, edible flowers, microgreens, gold dust"
221
-
222
- user_inputs = {
223
- "user_direction": st.session_state.user_direction,
224
- "exclusions": f"{st.session_state.exclusions}, {fancy_exclusions}".strip(", "),
225
- "serving_size": st.session_state.serving_size,
226
- "difficulty": st.session_state.selected_difficulty
227
- }
228
-
229
- button_cols_submit = st.columns([1, 1, 4])
230
- with button_cols_submit[0]:
231
- st.button(label='Submit', on_click=generate_recipe, kwargs=dict(user_inputs=user_inputs), type="primary",
232
- use_container_width=True)
233
- with button_cols_submit[1]:
234
- st.button(label='Reset', on_click=clear_inputs, type="secondary", use_container_width=True)
235
- with button_cols_submit[2]:
236
- st.empty()
237
-
238
- if st.session_state.recipe is not None:
239
- st.divider()
240
- try:
241
- print(st.session_state.recipe)
242
- recipe = json.loads(st.session_state.recipe)
243
- name_and_dis = f'# {recipe["name"]}\n\n'
244
- name_and_dis += f'{recipe["description"]}\n\n'
245
- ingredients = '## Ingredients:\n'
246
- # for ingredient in recipe["ingredients"]:
247
- # ingredients += f"- {ingredient['name']}\n"
248
- instructions = '\n## Instructions:\n'
249
- for instruction in recipe["instructions"]:
250
- instructions += f"{instruction['step_number']}. {instruction['instruction']}\n"
251
-
252
- st.write(name_and_dis)
253
- col01, col02 = st.columns(2)
254
- with col01:
255
- cont = st.container(border=True, height=500)
256
- for i in recipe["ingredients"]:
257
- cont.selectbox(i['name'],options=items_dict.iloc[get_recommendations(i['name'],cv,vectors)]["PRODUCT_NAME"].values)
258
- with col02:
259
- cont = st.container(border=True, height=500)
260
- cont.write(instructions)
261
- except (json.JSONDecodeError, KeyError) as e:
262
- st.error(f"Failed to parse recipe: {e}")
 
1
  import streamlit as st
2
  import re
3
  import json
4
+ import os,secrets
5
  import pandas as pd
6
  from huggingface_hub import login, InferenceClient
7
  import pickle
 
20
  with open('items_dict.pkl', 'rb') as file:
21
  items_dict = pd.DataFrame.from_dict(pickle.load(file))
22
 
23
+ mode=st.toggle(label="CUSTOMER")
24
+
25
+ def show_recipe(recipe):
26
+ name_and_dis = f'# {recipe["name"]}\n\n'
27
+ name_and_dis += f'{recipe["description"]}\n\n'
28
+ ingredients = '## Ingredients:\n'
29
+ instructions = '\n## Instructions:\n'
30
+ for instruction in recipe["instructions"]:
31
+ instructions += f"{instruction['step_number']}. {instruction['instruction']}\n"
32
+
33
+ st.write(name_and_dis)
34
+ col01, col02 = st.columns(2)
35
+ with col01:
36
+ cont = st.container(border=True, height=500)
37
+ for i in recipe["ingredients"]:
38
+ cont.selectbox(i['name'],options=items_dict.iloc[get_recommendations(i['name'],cv,vectors)]["PRODUCT_NAME"].values)
39
+ with col02:
40
+ cont = st.container(border=True, height=500)
41
+ cont.write(instructions)
42
 
43
+ # Initialize the inference client for the Mixtral model
44
+ if mode:
45
+ cook,saved=st.tabs(['COOK','SAVED'])
46
+ with cook:
47
+ client = InferenceClient("mistralai/Mixtral-8x7B-Instruct-v0.1")
48
+
49
+ if 'recipe' not in st.session_state:
50
+ st.session_state.recipe = None
51
+
52
+ if 'recipe_saved' not in st.session_state:
53
+ st.session_state.recipe_saved = None
54
+
55
+ if 'user_direction' not in st.session_state:
56
+ st.session_state.user_direction = None
57
+
58
+ if 'serving_size' not in st.session_state:
59
+ st.session_state.serving_size = 2
60
+
61
+ if 'selected_difficulty' not in st.session_state:
62
+ st.session_state.selected_difficulty = "Quick & Easy"
63
+
64
+ if 'exclusions' not in st.session_state:
65
+ st.session_state.exclusions = None
66
+
67
+ def preprocess_text(text):
68
+ # Remove non-alphabet characters and extra spaces
69
+ text = re.sub(r'[^a-zA-Z\s]', '', text)
70
+ text = re.sub(r'\s+', ' ', text).strip()
71
+ return text.lower()
72
+
73
+ def get_recommendations(user_description, count_vectorizer, count_matrix):
74
+ user_description = preprocess_text(user_description)
75
+ user_vector = count_vectorizer.transform([user_description])
76
+ cosine_similarities = cosine_similarity(user_vector, count_matrix).flatten()
77
+ similar_indices = cosine_similarities.argsort()[::-1][:5]
78
+ return similar_indices
79
+
80
+ def create_detailed_prompt(user_direction, exclusions, serving_size, difficulty):
81
+ if difficulty == "Quick & Easy":
82
+ prompt = (
83
+ f"Provide a 'Quick and Easy' recipe for {user_direction} that excludes {exclusions} and has a serving size of {serving_size}. "
84
+ f"It should require as few ingredients as possible and should be ready in as little time as possible. "
85
+ f"The steps should be simple, and the ingredients should be commonly found in a household pantry. "
86
+ f"Provide a detailed ingredient list and step-by-step guide that explains the instructions to prepare in detail."
87
+ )
88
+ elif difficulty == "Intermediate":
89
+ prompt = (
90
+ f"Provide a classic recipe for {user_direction} that excludes {exclusions} and has a serving size of {serving_size}. "
91
+ f"The recipe should offer a bit of a cooking challenge but should not require professional skills. "
92
+ f"The recipe should feature traditional ingredients and techniques that are authentic to its cuisine. "
93
+ f"Provide a detailed ingredient list and step-by-step guide that explains the instructions to prepare in detail."
94
+ )
95
+ elif difficulty == "Professional":
96
+ prompt = (
97
+ f"Provide an advanced recipe for {user_direction} that excludes {exclusions} and has a serving size of {serving_size}. "
98
+ f"The recipe should push the boundaries of culinary arts, integrating unique ingredients, advanced cooking techniques, and innovative presentations. "
99
+ f"The recipe should be able to be served at a high-end restaurant or would impress at a gourmet food competition. "
100
+ f"Provide a detailed ingredient list and step-by-step guide that explains the instructions to prepare in detail."
101
+ )
102
+ return prompt
103
+
104
+
105
+ def generate_recipe(user_inputs):
106
+ with st.spinner('Building the perfect recipe...'):
107
+ prompt = create_detailed_prompt(user_inputs['user_direction'], user_inputs['exclusions'],
108
+ user_inputs['serving_size'], user_inputs['difficulty'])
109
+
110
+ functions = [
111
+ {
112
+ "name": "provide_recipe",
113
+ "description": "Provides a detailed recipe strictly adhering to the user input/specifications, especially ingredient exclusions and the recipe difficulty",
114
+ "parameters": {
115
+ "type": "object",
116
+ "properties": {
117
+ "name": {
118
+ "type": "string",
119
+ "description": "A creative name for the recipe"
120
+ },
121
+ "description": {
122
+ "type": "string",
123
+ "description": "a brief one-sentence description of the provided recipe"
124
+ },
125
+ "ingredients": {
126
+ "type": "array",
127
+ "items": {
128
+ "type": "object",
129
+ "properties": {
130
+ "name": {
131
+ "type": "string",
132
+ "description": "Quantity and name of the ingredient"
133
+ }
134
+ }
135
  }
136
+ },
137
+ "instructions": {
138
+ "type": "array",
139
+ "items": {
140
+ "type": "object",
141
+ "properties": {
142
+ "step_number": {
143
+ "type": "number",
144
+ "description": "The sequence number of this step"
145
+ },
146
+ "instruction": {
147
+ "type": "string",
148
+ "description": "Detailed description of what to do in this step"
149
+ }
150
+ }
151
  }
152
  }
153
+ },
154
+ "required": [
155
+ "name",
156
+ "description",
157
+ "ingredients",
158
+ "instructions"
159
+ ],
160
+ },
161
+ }
162
+ ]
163
+
164
+ generate_kwargs = dict(
165
+ temperature=0.9,
166
+ max_new_tokens=10000,
167
+ top_p=0.9,
168
+ repetition_penalty=1.0,
169
+ do_sample=True,
170
+ )
171
+
172
+ prompt += f"\nPlease format the output in JSON. The JSON should include fields for 'name', 'description', 'ingredients', and 'instructions', with each field structured as described below.\n\n{json.dumps(functions)}"
173
+
174
+ response = client.text_generation(prompt, **generate_kwargs)
175
+ st.session_state.recipe = response
176
+ st.session_state.recipe_saved = False
177
+
178
+
179
+ def clear_inputs():
180
+ st.session_state.user_direction = None
181
+ st.session_state.exclusions = None
182
+ st.session_state.serving_size = 2
183
+ st.session_state.selected_difficulty = "Quick & Easy"
184
+
185
+
186
+ st.title("Let's get cooking")
187
+ col1,col2=st.columns(2)
188
+ with col1:
189
+ st.session_state.user_direction = st.text_area(
190
+ "What do you want to cook? Describe anything - a dish, cuisine, event, or vibe.",
191
+ value=st.session_state.user_direction,
192
+ placeholder="quick snack, asian style bowl with either noodles or rice, something italian",
193
+ )
194
+ with col2:
195
+ st.session_state.serving_size = st.number_input(
196
+ "How many servings would you like to cook?",
197
+ min_value=1,
198
+ max_value=100,
199
+ value=st.session_state.serving_size,
200
+ step=1
201
+ )
202
+
203
+ difficulty_dictionary = {
204
+ "Quick & Easy": {
205
+ "description": "Easy recipes with straightforward instructions. Ideal for beginners or those seeking quick and simple cooking.",
206
+ },
207
+ "Intermediate": {
208
+ "description": "Recipes with some intricate steps that invite a little challenge. Perfect for regular cooks wanting to expand their repertoire with new ingredients and techniques.",
209
+ },
210
+ "Professional": {
211
+ "description": "Complex recipes that demand a high level of skill and precision. Suited for seasoned cooks aspiring to professional-level sophistication and creativity.",
212
  }
213
+ }
214
+
215
+ st.session_state.selected_difficulty = st.radio(
216
+ "Choose a difficulty level for your recipe.",
217
+ [
218
+ list(difficulty_dictionary.keys())[0],
219
+ list(difficulty_dictionary.keys())[1],
220
+ list(difficulty_dictionary.keys())[2]
221
+ ],
222
+ captions=[
223
+ difficulty_dictionary["Quick & Easy"]["description"],
224
+ difficulty_dictionary["Intermediate"]["description"],
225
+ difficulty_dictionary["Professional"]["description"]
226
+ ],
227
+ index=list(difficulty_dictionary).index(st.session_state.selected_difficulty)
228
  )
229
+
230
+ st.session_state.exclusions = st.text_area(
231
+ "Any ingredients you want to exclude?",
232
+ value=st.session_state.exclusions,
233
+ placeholder="gluten, dairy, nuts, cilantro",
234
+ )
235
+
236
+ fancy_exclusions = ""
237
+
238
+ if st.session_state.selected_difficulty == "Professional":
239
+ exclude_fancy = st.checkbox(
240
+ "Exclude cliche professional ingredients? (gold leaf, truffle, edible flowers, microgreens)",
241
+ value=True)
242
+ if exclude_fancy:
243
+ fancy_exclusions = "gold leaf, truffle, edible flowers, microgreens, gold dust"
244
+
245
+ user_inputs = {
246
+ "user_direction": st.session_state.user_direction,
247
+ "exclusions": f"{st.session_state.exclusions}, {fancy_exclusions}".strip(", "),
248
+ "serving_size": st.session_state.serving_size,
249
+ "difficulty": st.session_state.selected_difficulty
250
+ }
251
+
252
+ button_cols_submit = st.columns([1, 1, 4])
253
+ with button_cols_submit[0]:
254
+ st.button(label='Submit', on_click=generate_recipe, kwargs=dict(user_inputs=user_inputs), type="primary",
255
+ use_container_width=True)
256
+ with button_cols_submit[1]:
257
+ st.button(label='Reset', on_click=clear_inputs, type="secondary", use_container_width=True)
258
+ with button_cols_submit[2]:
259
+ st.empty()
260
+
261
+ def create_safe_filename(recipe_name):
262
+ # format and generate random URL-safe text string
263
+ safe_name = recipe_name.lower()
264
+ safe_name = safe_name.replace(" ", "_")
265
+ safe_name = re.sub(r"[^a-zA-Z0-9_]", "", safe_name)
266
+ safe_name = (safe_name[:50]) if len(safe_name) > 50 else safe_name
267
+ unique_token = secrets.token_hex(8)
268
+ safe_filename = f"{unique_token}_{safe_name}"
269
+ return safe_filename
270
+
271
+ def save_recipe():
272
+ filename = create_safe_filename(recipe["name"])
273
+ os.makedirs('data', exist_ok=True)
274
+ with open(f'/data/{filename}.json', 'wb') as f:
275
+ json.dump(recipe, f, indent=4)
276
+ st.session_state.recipe_saved = True
277
+
278
+ if st.session_state.recipe is not None:
279
+ st.divider()
280
+ print(st.session_state.recipe)
281
+ recipe = json.loads(st.session_state.recipe)
282
+ show_recipe(recipe)
283
+ if st.session_state.recipe_saved == True:
284
+ disable_button = True
285
+ else:
286
+ disable_button = False
287
+ button_cols_save = st.columns([1, 1, 4])
288
+ with button_cols_save[0]:
289
+ st.button("Save Recipe", on_click=save_recipe, disabled=disable_button, type="primary")
290
+ with button_cols_save[1]:
291
+ st.empty()
292
+ with button_cols_save[2]:
293
+ st.empty()
294
+ if st.session_state.recipe_saved == True:
295
+ st.success("Recipe Saved!")
296
+