vatmuri commited on
Commit
f866bca
·
1 Parent(s): cef8c1c

Adding web app

Browse files
List.css ADDED
File without changes
List.html ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ <div id="accordian"
2
+ style=" background-color: #c1d8a9; height: 500px; overflow-y: auto;">
3
+
4
+ </div>
__pycache__ /intro.cpython-311.pyc ADDED
Binary file (8.72 kB). View file
 
app.py ADDED
@@ -0,0 +1,374 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from io import BytesIO
2
+ import pandas as pd
3
+ import numpy as np
4
+ import requests
5
+ import streamlit as st
6
+ import easyocr
7
+ import PIL
8
+ from PIL import Image, ImageDraw
9
+ from matplotlib import pyplot as plt
10
+ import streamlit.components.v1 as components
11
+ import re
12
+ from streamlit import session_state
13
+ # from streamlit_lottie import st_lottie
14
+ import streamlit as st
15
+ import os
16
+
17
+ from dotenv import load_dotenv, find_dotenv
18
+
19
+ # Load environment variables
20
+ _ = load_dotenv(find_dotenv())
21
+
22
+ # Get OpenAI API key
23
+ openai_api_key = os.getenv('OPENAI_API_KEY')
24
+
25
+ # Google Drive file ID for the video
26
+ video_file_id = '1miZ6Zz4lt0wxTGbrtR8IltVr_fOPX6Vr'
27
+ video_url = f'https://drive.google.com/uc?export=view&id={video_file_id}'
28
+
29
+
30
+ @st.cache_data
31
+ def initialize_grocery_data():
32
+ return pd.DataFrame(columns=['Name', 'Quantity', 'Additional Notes/Expiration Date'])
33
+
34
+ def manually_input_items(grocery_data):
35
+ return grocery_data
36
+
37
+
38
+ def upload_receipt():
39
+ st.header("Upload Receipt")
40
+ uploaded_file = st.file_uploader("Choose a receipt file", type=["jpg", "jpeg", "png", "pdf"])
41
+ if uploaded_file is not None:
42
+ st.success("Receipt uploaded successfully!")
43
+ # Add your code here for processing the uploaded receipt
44
+ st.set_page_config(layout="wide")
45
+
46
+
47
+ if 'clicked' not in st.session_state:
48
+ st.session_state.clicked = False
49
+
50
+ if 'total_groceries' not in st.session_state:
51
+ st.session_state.total_groceries = {}
52
+
53
+ if 'grocery_data' not in st.session_state:
54
+ st.session_state.grocery_data = pd.DataFrame(columns=['Name', 'Quantity', 'Additional Notes/Expiration Date'])
55
+
56
+ if 'editor_key' not in st.session_state:
57
+ st.session_state.editor_key = 0
58
+
59
+ if 'manual_entry' not in st.session_state:
60
+ st.session_state.manual_entry = True
61
+
62
+ if 'file_uploaded' not in st.session_state:
63
+ st.session_state.file_uploaded = False
64
+
65
+ if 'ocr_extracted_values' not in st.session_state:
66
+ session_state.ocr_extracted_values = pd.DataFrame()
67
+
68
+ def click_save():
69
+ session_state.clicked = True
70
+
71
+ def switch_style():
72
+ session_state.manual_entry = not session_state.manual_entry
73
+
74
+ # Define the HTML and CSS styling for the title
75
+ title_html = """
76
+ <html>
77
+ <head>
78
+ <link href='https://fonts.googleapis.com/css?family=Cedarville Cursive' rel='stylesheet'>
79
+ <style>
80
+ body {
81
+ font-family: 'serif;
82
+ font-size: 22px;
83
+ text-align: center;
84
+ }
85
+ h1 {
86
+ font-family: 'Cedarville Cursive';
87
+ font-size: 56px;
88
+ display: inline-block;
89
+ margin_bottom: 3px;
90
+ }
91
+ </style>
92
+ </head>
93
+ <body>
94
+ <h1>Nom Nom!</h1>
95
+ </body>
96
+ </html>
97
+ """
98
+
99
+ # Use st.markdown to display the title with the specified font
100
+ st.markdown(title_html, unsafe_allow_html=True)
101
+
102
+ caption_html = """
103
+ <div style="display: flex; justify-content: center; align-items: center; font-style: italic; font-weight: bold;">
104
+ <p>Helping College Students Manage Their Groceries</p>
105
+ </div>
106
+ """
107
+
108
+ st.markdown(caption_html, unsafe_allow_html=True)
109
+
110
+ # Initialize or retrieve the existing dataframe to store grocery items
111
+ grocery_data = initialize_grocery_data()
112
+
113
+ tab1, tab2, tab3 = st.tabs(["Add Groceries", "Available Groceries", "Create recipes"])
114
+
115
+
116
+ df = pd.DataFrame()
117
+
118
+ with tab1:
119
+ st.button("Switch to OCR Input", on_click=switch_style)
120
+ col1, col2 = st.columns([2, 1])
121
+ if session_state.manual_entry:
122
+ with col1:
123
+ if not session_state.clicked:
124
+ st.subheader("Add Groceries - Manually Input Items")
125
+ session_state.grocery_data = st.data_editor(pd.DataFrame(columns=['Name', 'Quantity', 'Additional Notes/Expiration Date']), key=session_state.editor_key, num_rows="dynamic", hide_index=True, use_container_width=True)
126
+ else:
127
+ session_state.editor_key += 1
128
+
129
+
130
+
131
+ with col2:
132
+ file_id = '1_3FjYmWlJcY182qnLIjFPTZYj4gneUMg'
133
+ base_url = 'https://drive.google.com/uc?id='
134
+
135
+ image_url = base_url + file_id
136
+ response = requests.get(image_url)
137
+ img = Image.open(BytesIO(response.content))
138
+ # image1 = Image.open(r'https://drive.google.com/file/d/1_3FjYmWlJcY182qnLIjFPTZYj4gneUMg/view?usp=sharing')
139
+ st.image(img, width=400)
140
+
141
+ st.write("---")
142
+ else:
143
+
144
+ with col1:
145
+ st.subheader("Upload receipt instead")
146
+ uploaded_file = st.file_uploader("Choose a receipt file", type=["jpg", "jpeg", "png"])
147
+ if uploaded_file is not None:
148
+ session_state.file_uploaded = True
149
+ st.success("Receipt uploaded successfully!")
150
+ st.write("")
151
+ if session_state.file_uploaded:
152
+ receipt_image = Image.open(uploaded_file)
153
+ st.image(receipt_image)
154
+ reader = easyocr.Reader(['en'], gpu=False)
155
+ result = reader.readtext(np.array(receipt_image))
156
+
157
+ text_list = []
158
+ confidence_list = []
159
+
160
+ for idx in range(len(result)):
161
+ pred_coor = result[idx][0]
162
+ pred_text = result[idx][1]
163
+ pred_confidence = result[idx][2]
164
+
165
+ text_list.append(pred_text)
166
+ confidence_list.append(pred_confidence)
167
+
168
+ df = pd.DataFrame({'Text': text_list, 'Confidence': confidence_list})
169
+
170
+ with col2:
171
+ if session_state.file_uploaded:
172
+ st.subheader("Updated Grocery List")
173
+ df = df[~df['Text'].str.contains(r'[\d]')]
174
+ df['Add to List?'] = None
175
+ df2 = st.data_editor(df, use_container_width=True, num_rows = 'dynamic', column_config={"Text": "Item",
176
+ "Add to List?" : st.column_config.CheckboxColumn(
177
+ "Add to List?",
178
+ help="Select if you want to add this to the list.",
179
+ default=False
180
+ )}, key="OCR_DataFrame")
181
+ st.write(session_state["OCR_DataFrame"])
182
+ session_state.ocr_extracted_values = df2
183
+
184
+ st.button("Press me to update Tab 2", on_click=click_save)
185
+
186
+
187
+
188
+ def ingredient_html_maker(ingredient, num_ingredients, map_for_grocery):
189
+ return_val = f"<div class=\"card\" style=\"background-color: #dedede; padding: 10px; margin: 5px; border-radius: 10px;\">\n"
190
+ return_val += f"<h3>{ingredient}</h3>\n" # Ingredient name
191
+ return_val += f"<p>Quantity: <span id='quantity_{ingredient}'>{num_ingredients}</span></p>\n"
192
+ return_val += f"<button onclick=\"updateQuantity('{ingredient}', '-', {map_for_grocery})\">-</button>\n"
193
+ return_val += f"<button onclick=\"updateQuantity('{ingredient}', '+', {map_for_grocery})\">+</button>\n"
194
+ return_val += f"</div>\n"
195
+ return return_val
196
+
197
+ def list_display(total_groceries):
198
+ list_html = ''
199
+ with open('List.html') as list_file:
200
+ list_html = list_file.read()
201
+
202
+ list_html_without_end = list_html[:-6]
203
+ end = list_html[-6:]
204
+ final_list_html = list_html_without_end + "\n"
205
+
206
+ for item in total_groceries:
207
+ final_list_html += ingredient_html_maker(item, total_groceries[item], total_groceries)
208
+
209
+ final_list_html += "\n" + end
210
+
211
+ return components.html(final_list_html + javascript_code, height=500)
212
+
213
+
214
+
215
+ with tab2:
216
+ javascript_code = """
217
+ <script>
218
+ function updateQuantity(ingredient, operation, grocery_data) {
219
+ // Get the current quantity
220
+ var quantityElement = document.getElementById('quantity_' + ingredient);
221
+ var currentQuantity = parseInt(quantityElement.innerText);
222
+
223
+ // Update the quantity based on the operation
224
+ if (operation === '+') {
225
+ currentQuantity += 1;
226
+ } else if (operation === '-') {
227
+ currentQuantity = Math.max(0, currentQuantity - 1);
228
+ }
229
+ grocery_data[ingredient] = currentQuantity;
230
+ console.log(grocery_data);
231
+ // Update the quantity display
232
+ quantityElement.innerText = currentQuantity;
233
+ }
234
+ </script>
235
+ """
236
+ if session_state.clicked and session_state.manual_entry:
237
+ for i in range(len(session_state.grocery_data)):
238
+ existing_quantity = st.session_state.total_groceries.get(session_state.grocery_data["Name"][i], 0)
239
+ st.session_state.total_groceries[session_state.grocery_data["Name"][i]] = int(existing_quantity) + int(session_state.grocery_data["Quantity"][i])
240
+ list_display(st.session_state.total_groceries)
241
+ session_state.clicked = False
242
+ st.rerun()
243
+ elif session_state.clicked and not session_state.manual_entry and session_state.file_uploaded:
244
+ for idx in session_state["OCR_DataFrame"]['edited_rows']:
245
+ ingredient = session_state.ocr_extracted_values['Text'].iloc[idx]
246
+ existing_quantity = st.session_state.total_groceries.get(ingredient, 0)
247
+ st.session_state.total_groceries[ingredient]= int(existing_quantity) + 1
248
+ list_display(st.session_state.total_groceries)
249
+ session_state.clicked = False
250
+ st.rerun()
251
+ else:
252
+ list_display(st.session_state.total_groceries)
253
+
254
+
255
+ with tab3:
256
+ st.write("hi")
257
+ # # Create columns for layout
258
+ # col1, col2 = st.columns([0.20, 0.80])
259
+
260
+ # # Column 1: Display the embedded video without controls
261
+ # with col1:
262
+ # video_html = f"""
263
+ # <video width="100%" height="auto" autoplay muted style="margin-top: -30px;">
264
+ # <source src="{video_url}" type="video/mp4">
265
+ # Your browser does not support the video tag.
266
+ # </video>
267
+ # """
268
+ # st.markdown(video_html, unsafe_allow_html=True)
269
+
270
+ # with col2:
271
+ # st.header("NomNom Bot")
272
+ # st.markdown('<style>div.Widget.row-widget.stRadio > div{flex-direction:row;}</style>', unsafe_allow_html=True)
273
+
274
+ # st.caption("🍳 Your personal recipe generator!")
275
+ # st.caption("Enter a cuisine and your dietary restrictions to get started :)")
276
+
277
+ # with st.sidebar:
278
+ # cuisine = st.text_input("Cuisine you're craving", key="cuisine")
279
+ # diet_res = st.text_input("Dietary Restrictions", key="diet_res")
280
+
281
+ # ingredients = {
282
+ # 'Tomatoes': 3,
283
+ # 'Rice': 1
284
+ # }
285
+
286
+ # content_template = """
287
+ # I have scanned/entered my grocery store receipts. Here are the items and their quantity (in the form of a dictionary) I have purchased:
288
+ # {ingredients}.
289
+ # My dietary restrictions include {diet_res}. I am in the mood for {cuisine} recipes. Give me a detailed recipe using ONLY
290
+ # the ingredients I have. I also have common pantry items like salt, pepper, olive oil, and basic spices.
291
+ # Make sure to take the cuisine and dietary restrictions into consideration definitively.
292
+ # Provide a recipe that aligns with the preferred cuisine given by the user. A cuisine is a style or method of cooking, especially of a particular country
293
+ # or region. Use ingredients, foods, and techniques from the cuisine from that specific region.
294
+ # If the user says their dietary restriction is an X allergy or allergic to X where X is any ingredient, make sure to exclude X from the recipe
295
+ # since the user could die of an allergic reaction and you will be responsible.
296
+ # Start your response with "Howdy, I'm the NomNom Bot!" and end by asking if the user has any follow-up questions or needs any additional resources.
297
+ # """
298
+ # print("Content Template:", content_template.format(ingredients=ingredients, diet_res=diet_res, cuisine=cuisine))
299
+ # # Initialize the chat with an initial user message
300
+ # if cuisine and diet_res:
301
+ # if "messages" not in st.session_state:
302
+ # print("Content Template:", content_template.format(ingredients=ingredients, diet_res=diet_res, cuisine=cuisine))
303
+ # st.session_state["messages"] = [
304
+ # {"role": "user", "content": content_template.format(ingredients=ingredients, diet_res=diet_res, cuisine=cuisine)}]
305
+
306
+ # # Display the chat messages
307
+ # for msg in st.session_state.messages[1:]:
308
+ # st.chat_message(msg["role"]).write(msg["content"])
309
+
310
+ # # Generate a response for the initial user message
311
+ # if len(st.session_state.messages) == 1:
312
+ # client = OpenAI(api_key=openai_api_key)
313
+ # response = client.chat.completions.create(
314
+ # model="gpt-3.5-turbo",
315
+ # messages=st.session_state.messages,
316
+ # max_tokens=2048,
317
+ # n=1,
318
+ # stop=None,
319
+ # temperature=0.5
320
+ # )
321
+
322
+ # msg = response.choices[0].message.content
323
+ # st.session_state.messages.append({"role": "assistant", "content": msg})
324
+ # st.chat_message("assistant").write(msg)
325
+
326
+ # # User can ask follow-up questions
327
+ # if prompt := st.chat_input():
328
+ # if not openai_api_key:
329
+ # st.info("API key is not valid.")
330
+ # st.stop()
331
+
332
+ # client = OpenAI(api_key=openai_api_key)
333
+ # st.session_state.messages.append({"role": "user", "content": prompt})
334
+ # st.chat_message("user").write(prompt)
335
+
336
+ # response = client.chat.completions.create(
337
+ # model="gpt-3.5-turbo",
338
+ # messages=st.session_state.messages,
339
+ # max_tokens=2048,
340
+ # n=1,
341
+ # stop=None,
342
+ # temperature=0.5
343
+ # )
344
+
345
+ # msg = response.choices[0].message.content
346
+ # st.session_state.messages.append({"role": "assistant", "content": msg})
347
+ # st.chat_message("assistant").write(msg)
348
+ st.markdown("""
349
+ <style>
350
+
351
+ .stTabs [data-baseweb="tab-list"] {
352
+ gap: 10px;
353
+ }
354
+
355
+ .stTabs [data-baseweb="tab"] {
356
+ height: 50px;
357
+ width: 100%;
358
+ white-space: pre-wrap;
359
+ background-color: #F1C0B9;
360
+ border-radius: 4px 4px 0px 0px;
361
+ gap: 1px;
362
+ padding-top: 10px;
363
+ padding-bottom: 10px;
364
+ color: black; /* Added this line to set the text color */
365
+ font-weight: bold; /* Added this line to make the text bold */
366
+ }
367
+
368
+ .stTabs [aria-selected="true"] {
369
+ background-color: #F1C0B9;
370
+ color: black;
371
+ font-weight: bold; /* Added this line to make the text bold */
372
+ }
373
+
374
+ </style>""", unsafe_allow_html=True)
intro.py ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from io import BytesIO
2
+ import pandas as pd
3
+ import numpy as np
4
+ import requests
5
+ import streamlit as st
6
+ import easyocr
7
+ import PIL
8
+ from PIL import Image, ImageDraw
9
+ from matplotlib import pyplot as plt
10
+ import streamlit.components.v1 as components
11
+ import re
12
+ from streamlit import session_state
13
+ # from streamlit_lottie import st_lottie
14
+ import streamlit as st
15
+ import os
16
+
17
+ from dotenv import load_dotenv, find_dotenv
18
+
19
+ st.set_page_config(
20
+ page_title="Intro",
21
+ layout='wide'
22
+ )
23
+
24
+ # Load environment variables
25
+ _ = load_dotenv(find_dotenv())
26
+
27
+ # Get OpenAI API key
28
+ openai_api_key = os.getenv('OPENAI_API_KEY')
29
+
30
+ # Google Drive file ID for the video
31
+ video_file_id = '1miZ6Zz4lt0wxTGbrtR8IltVr_fOPX6Vr'
32
+ video_url = f'https://drive.google.com/uc?export=view&id={video_file_id}'
33
+
34
+ @st.cache_data
35
+ def initialize_grocery_data():
36
+ return pd.DataFrame(columns=['Name', 'Quantity', 'Additional Notes/Expiration Date'])
37
+
38
+ def manually_input_items(grocery_data):
39
+ return grocery_data
40
+
41
+ def upload_receipt():
42
+ st.header("Upload Receipt")
43
+ uploaded_file = st.file_uploader("Choose a receipt file", type=["jpg", "jpeg", "png", "pdf"])
44
+ if uploaded_file is not None:
45
+ st.success("Receipt uploaded successfully!")
46
+ # Add your code here for processing the uploaded receipt
47
+
48
+
49
+
50
+ if 'clicked' not in st.session_state:
51
+ st.session_state.clicked = False
52
+
53
+ if 'total_groceries' not in st.session_state:
54
+ st.session_state.total_groceries = {}
55
+
56
+ if 'grocery_data' not in st.session_state:
57
+ st.session_state.grocery_data = pd.DataFrame(columns=['Name', 'Quantity', 'Additional Notes/Expiration Date'])
58
+
59
+ if 'editor_key' not in st.session_state:
60
+ st.session_state.editor_key = 0
61
+
62
+ if 'manual_entry' not in st.session_state:
63
+ st.session_state.manual_entry = True
64
+
65
+ if 'file_uploaded' not in st.session_state:
66
+ st.session_state.file_uploaded = False
67
+
68
+ if 'ocr_extracted_values' not in st.session_state:
69
+ session_state.ocr_extracted_values = pd.DataFrame()
70
+
71
+ def click_save():
72
+ session_state.clicked = True
73
+
74
+ def switch_style():
75
+ session_state.manual_entry = not session_state.manual_entry
76
+
77
+ # Define the HTML and CSS styling for the title
78
+ title_html = """
79
+ <html>
80
+ <head>
81
+ <link href='https://fonts.googleapis.com/css?family=Cedarville Cursive' rel='stylesheet'>
82
+ <style>
83
+ body {
84
+ font-family: 'serif;
85
+ font-size: 22px;
86
+ text-align: center;
87
+ }
88
+ h1 {
89
+ font-family: 'Cedarville Cursive';
90
+ font-size: 56px;
91
+ display: inline-block;
92
+ }
93
+ </style>
94
+ </head>
95
+ <body>
96
+ <h1>Nom Nom!</h1>
97
+ </body>
98
+ </html>
99
+ """
100
+
101
+ # Use st.markdown to display the title with the specified font
102
+ st.markdown(title_html, unsafe_allow_html=True)
103
+
104
+ caption_html = """
105
+ <div style="display: flex; justify-content: center; align-items: center; font-style: italic; font-weight: bold;">
106
+ <p>Helping College Students Keep Track of Groceries</p>
107
+ </div>
108
+ """
109
+
110
+ st.markdown(caption_html, unsafe_allow_html=True)
111
+ ingredient_quantities = {}
112
+ # Initialize or retrieve the existing dataframe to store grocery items
113
+ #grocery_data = initialize_grocery_data()
114
+
115
+ tab1, tab2 = st.tabs(["Add Groceries", "Available Groceries"])
116
+
117
+ df = pd.DataFrame()
118
+
119
+ with tab1:
120
+ st.button("Switch to OCR Input", on_click=switch_style)
121
+ col1, col2 = st.columns([1.5, 1])
122
+ if session_state.manual_entry:
123
+ with col1:
124
+ if not session_state.clicked:
125
+ st.subheader("Add Groceries - Manually Input Items")
126
+ session_state.grocery_data = st.data_editor(pd.DataFrame(columns=['Name', 'Quantity', 'Additional Notes/Expiration Date']), key=session_state.editor_key, num_rows="dynamic", hide_index=True, use_container_width=True)
127
+ print(session_state.grocery_data)
128
+ st.button("Press me to update Tab 2", on_click=click_save)
129
+ else:
130
+ session_state.editor_key += 1
131
+
132
+
133
+
134
+
135
+ with col2:
136
+ file_id = '1_3FjYmWlJcY182qnLIjFPTZYj4gneUMg'
137
+ base_url = 'https://drive.google.com/uc?id='
138
+
139
+ image_url = base_url + file_id
140
+ response = requests.get(image_url)
141
+ img = Image.open(BytesIO(response.content))
142
+ # image1 = Image.open(r'https://drive.google.com/file/d/1_3FjYmWlJcY182qnLIjFPTZYj4gneUMg/view?usp=sharing')
143
+ st.image(img, width=400)
144
+
145
+ st.write("---")
146
+ else:
147
+
148
+ with col1:
149
+ st.subheader("Upload receipt instead")
150
+ uploaded_file = st.file_uploader("Choose a receipt file", type=["jpg", "jpeg", "png"])
151
+ if uploaded_file is not None:
152
+ session_state.file_uploaded = True
153
+ st.success("Receipt uploaded successfully!")
154
+ st.write("")
155
+ if session_state.file_uploaded:
156
+ receipt_image = Image.open(uploaded_file)
157
+ st.image(receipt_image)
158
+ reader = easyocr.Reader(['en'], gpu=False)
159
+ result = reader.readtext(np.array(receipt_image))
160
+
161
+ text_list = []
162
+ confidence_list = []
163
+
164
+ for idx in range(len(result)):
165
+ pred_coor = result[idx][0]
166
+ pred_text = result[idx][1]
167
+ pred_confidence = result[idx][2]
168
+
169
+ text_list.append(pred_text)
170
+ confidence_list.append(pred_confidence)
171
+
172
+ df = pd.DataFrame({'Text': text_list})
173
+
174
+ with col2:
175
+ if session_state.file_uploaded:
176
+ st.subheader("Updated Grocery List")
177
+ df = df[~df['Text'].str.contains(r'[\d]')]
178
+ df['Add to List?'] = None
179
+ df2 = st.data_editor(df, use_container_width=True, num_rows = 'dynamic', column_config={"Text": "Item",
180
+ "Add to List?" : st.column_config.CheckboxColumn(
181
+ "Add to List?",
182
+ help="Select if you want to add this to the list.",
183
+ default=False
184
+ )}, key="OCR_DataFrame")
185
+ session_state.ocr_extracted_values = df2
186
+
187
+ st.button("Press me to update Tab 2", on_click=click_save)
188
+
189
+
190
+
191
+
192
+
193
+
194
+ def ingredient_html_maker(ingredient, num_ingredients, map_for_grocery):
195
+ return_val = f"<div class=\"card\" style=\"background-color: #dedede; padding: 10px; margin: 5px; border-radius: 10px;\">\n"
196
+ return_val += f"<h3>{ingredient}</h3>\n" # Ingredient name
197
+ return_val += f"<p>Quantity: <span id='quantity_{ingredient}'>{num_ingredients}</span></p>\n"
198
+ return_val += f"<button onclick=\"updateQuantity('{ingredient}', '-', {map_for_grocery})\">-</button>\n"
199
+ return_val += f"<button onclick=\"updateQuantity('{ingredient}', '+', {map_for_grocery})\">+</button>\n"
200
+ return_val += f"</div>\n"
201
+ return return_val
202
+
203
+ def list_display(total_groceries):
204
+ list_html = ''
205
+ with open('List.html') as list_file:
206
+ list_html = list_file.read()
207
+
208
+ list_html_without_end = list_html[:-6]
209
+ end = list_html[-6:]
210
+ final_list_html = list_html_without_end + "\n"
211
+
212
+ for item in total_groceries:
213
+ final_list_html += ingredient_html_maker(item, total_groceries[item], total_groceries)
214
+
215
+ final_list_html += "\n" + end
216
+
217
+ return components.html(final_list_html + javascript_code, height=500)
218
+
219
+
220
+
221
+ with tab2:
222
+ javascript_code = """
223
+ <script>
224
+ function updateQuantity(ingredient, operation, grocery_data) {
225
+ // Get the current quantity
226
+ var quantityElement = document.getElementById('quantity_' + ingredient);
227
+ var currentQuantity = parseInt(quantityElement.innerText);
228
+
229
+ // Update the quantity based on the operation
230
+ if (operation === '+') {
231
+ currentQuantity += 1;
232
+ } else if (operation === '-') {
233
+ currentQuantity = Math.max(0, currentQuantity - 1);
234
+ }
235
+ grocery_data[ingredient] = currentQuantity;
236
+ console.log(grocery_data);
237
+ // Update the quantity display
238
+ quantityElement.innerText = currentQuantity;
239
+ }
240
+ </script>
241
+ """
242
+ if session_state.clicked and session_state.manual_entry:
243
+ for i in range(len(session_state.grocery_data)):
244
+ existing_quantity = st.session_state.total_groceries.get(session_state.grocery_data["Name"][i], 0)
245
+ st.session_state.total_groceries[session_state.grocery_data["Name"][i]] = int(existing_quantity) + int(session_state.grocery_data["Quantity"][i])
246
+ list_display(st.session_state.total_groceries)
247
+ session_state.clicked = False
248
+ st.rerun()
249
+ elif session_state.clicked and not session_state.manual_entry and session_state.file_uploaded:
250
+ for idx in session_state["OCR_DataFrame"]['edited_rows']:
251
+ ingredient = session_state.ocr_extracted_values['Text'].iloc[idx]
252
+ existing_quantity = st.session_state.total_groceries.get(ingredient, 0)
253
+ st.session_state.total_groceries[ingredient]= int(existing_quantity) + 1
254
+ list_display(st.session_state.total_groceries)
255
+ session_state.clicked = False
256
+ st.rerun()
257
+ else:
258
+ list_display(st.session_state.total_groceries)
259
+
260
+
261
+ st.markdown("""
262
+ <style>
263
+
264
+ .stTabs [data-baseweb="tab-list"] {
265
+ gap: 10px;
266
+ }
267
+
268
+ .stTabs [data-baseweb="tab"] {
269
+ height: 50px;
270
+ width: 100%;
271
+ white-space: pre-wrap;
272
+ background-color: #c1d8a9;
273
+ border-radius: 4px 4px 0px 0px;
274
+ gap: 1px;
275
+ padding-top: 10px;
276
+ padding-bottom: 10px;
277
+ color: black; /* Added this line to set the text color */
278
+ font-weight: bold; /* Added this line to make the text bold */
279
+ }
280
+
281
+ .stTabs [aria-selected="true"] {
282
+ background-color: #c1d8a9;
283
+ color: black;
284
+ font-weight: bold; /* Added this line to make the text bold */
285
+ }
286
+
287
+ </style>""", unsafe_allow_html=True)
288
+
289
+ with open("total_groceries.txt", "w") as file:
290
+ file.write(str(session_state.total_groceries))
pages/1_chatbot.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from openai import OpenAI
2
+ import streamlit as st
3
+ import os
4
+ from dotenv import load_dotenv, find_dotenv
5
+
6
+ st.set_page_config(
7
+ page_title="Chatbot",
8
+ layout='wide'
9
+ )
10
+
11
+ if 'total_groceries' not in st.session_state:
12
+ st.session_state.total_groceries = {}
13
+
14
+ with open("total_groceries.txt", "r") as file:
15
+ st.session_state.total_groceries = eval(file.read())
16
+
17
+ # Load environment variables
18
+ _ = load_dotenv(find_dotenv())
19
+
20
+ # Get OpenAI API key
21
+ openai_api_key = os.getenv('OPENAI_API_KEY')
22
+
23
+ # Google Drive file ID for the video
24
+ video_file_id = '1miZ6Zz4lt0wxTGbrtR8IltVr_fOPX6Vr'
25
+ video_url = f'https://drive.google.com/uc?export=view&id={video_file_id}'
26
+
27
+ # Create columns for layout
28
+ col1, col2 = st.columns([0.20, 0.80])
29
+
30
+ # Column 1: Display the embedded video without controls
31
+ with col1:
32
+ video_html = f"""
33
+ <video width="100%" height="auto" autoplay muted style="margin-top: -30px;">
34
+ <source src="{video_url}" type="video/mp4">
35
+ Your browser does not support the video tag.
36
+ </video>
37
+ """
38
+ st.markdown(video_html, unsafe_allow_html=True)
39
+
40
+ with col2:
41
+ st.title("NomNom Bot")
42
+ st.markdown('<style>div.Widget.row-widget.stRadio > div{flex-direction:row;}</style>', unsafe_allow_html=True)
43
+
44
+ st.caption("🍳 Your personal recipe generator!")
45
+ st.caption("Enter a cuisine and your dietary restrictions to get started :)")
46
+
47
+ with st.sidebar:
48
+ cuisine = st.text_input("Cuisine you're craving", key="cuisine")
49
+ diet_res = st.text_input("Dietary Restrictions", key="diet_res")
50
+
51
+ ingredients = {
52
+ 'Tomatoes': 3,
53
+ 'Rice': 1
54
+ }
55
+ ingredients = st.session_state.total_groceries
56
+
57
+ content_template = """
58
+ I have scanned/entered my grocery store receipts. Here are the items and their quantity (in the form of a dictionary) I have purchased:
59
+ {ingredients}.
60
+ My dietary restrictions include {diet_res}. I am in the mood for {cuisine} recipes. Give me a detailed recipe using ONLY
61
+ the ingredients I have. I also have common pantry items like salt, pepper, olive oil, and basic spices.
62
+ Make sure to take the cuisine and dietary restrictions into consideration definitively.
63
+ Provide a recipe that aligns with the preferred cuisine given by the user. A cuisine is a style or method of cooking, especially of a particular country
64
+ or region. Use ingredients, foods, and techniques from the cuisine from that specific region.
65
+ If the user says their dietary restriction is an X allergy or allergic to X where X is any ingredient, make sure to exclude X from the recipe
66
+ since the user could die of an allergic reaction and you will be responsible.
67
+ Start your response with "Howdy, I'm the NomNom Bot!" and end by asking if the user has any follow-up questions or needs any additional resources.
68
+ """
69
+ print("Content Template:", content_template.format(ingredients=ingredients, diet_res=diet_res, cuisine=cuisine))
70
+ # Initialize the chat with an initial user message
71
+ if cuisine and diet_res:
72
+ if "messages" not in st.session_state:
73
+ print("Content Template:", content_template.format(ingredients=ingredients, diet_res=diet_res, cuisine=cuisine))
74
+ st.session_state["messages"] = [
75
+ {"role": "user", "content": content_template.format(ingredients=ingredients, diet_res=diet_res, cuisine=cuisine)}]
76
+
77
+ # Display the chat messages
78
+ for msg in st.session_state.messages[1:]:
79
+ st.chat_message(msg["role"]).write(msg["content"])
80
+
81
+ # Generate a response for the initial user message
82
+ if len(st.session_state.messages) == 1:
83
+ client = OpenAI(api_key=openai_api_key)
84
+ response = client.chat.completions.create(
85
+ model="gpt-3.5-turbo",
86
+ messages=st.session_state.messages,
87
+ max_tokens=2048,
88
+ n=1,
89
+ stop=None,
90
+ temperature=0.5
91
+ )
92
+
93
+ msg = response.choices[0].message.content
94
+ st.session_state.messages.append({"role": "assistant", "content": msg})
95
+ st.chat_message("assistant").write(msg)
96
+
97
+ # User can ask follow-up questions
98
+ if prompt := st.chat_input():
99
+ if not openai_api_key:
100
+ st.info("API key is not valid.")
101
+ st.stop()
102
+
103
+ client = OpenAI(api_key=openai_api_key)
104
+ st.session_state.messages.append({"role": "user", "content": prompt})
105
+ st.chat_message("user").write(prompt)
106
+
107
+ response = client.chat.completions.create(
108
+ model="gpt-3.5-turbo",
109
+ messages=st.session_state.messages,
110
+ max_tokens=2048,
111
+ n=1,
112
+ stop=None,
113
+ temperature=0.5
114
+ )
115
+
116
+ msg = response.choices[0].message.content
117
+ st.session_state.messages.append({"role": "assistant", "content": msg})
118
+ st.chat_message("assistant").write(msg)
requirements.txt ADDED
File without changes
style.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ .list {
2
+ background-color: aliceblue;
3
+ height: 10px;
4
+ overflow-y: auto;
5
+ }
testreceipt1.jpeg ADDED
total_groceries.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ {}