rairo commited on
Commit
8a02e3d
·
verified ·
1 Parent(s): a187285

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -13
app.py CHANGED
@@ -22,6 +22,7 @@ def configure_gemini(api_key):
22
  return genai.GenerativeModel('gemini-2.0-flash-thinking-exp')
23
 
24
  model = configure_gemini(os.environ['GOOGLE_API_KEY'])
 
25
  # Initialize Gemini models
26
  llm_flash_exp = ChatGoogleGenerativeAI(
27
  model="gemini-2.0-flash-exp",
@@ -46,14 +47,16 @@ class SmartShoppingAssistant:
46
  cutoff=threshold
47
  )
48
  return matches if matches else []
49
-
50
  def match_products_with_catalogue(self, extracted_items):
51
  """Match extracted items with catalogue products using Gemini"""
52
  product_list = self.df['ProductName'].tolist()
53
  product_string = ", ".join(product_list)
 
54
  prompt = f"""
55
  Given these extracted items and quantities:
56
  {extracted_items}
 
57
  And this product catalogue:
58
  {product_string}
59
 
@@ -68,16 +71,18 @@ class SmartShoppingAssistant:
68
 
69
  Only include products that have good matches in the catalogue.
70
  """
 
71
  try:
72
  matches = llm_flash_exp.predict(prompt)
73
  return matches.strip()
74
  except Exception as e:
75
  return f"Error matching products: {str(e)}"
76
-
77
  def search_products_fuzzy(self, product_names_with_quantities):
78
  """Improved fuzzy search with batch processing"""
79
  results = pd.DataFrame()
80
  matched_products = set()
 
81
  for item in product_names_with_quantities:
82
  product_info = item.split('quantity:')
83
  clean_name = product_info[0].strip().upper().replace('PRODUCTNAME ==', '').strip(' "\'')
@@ -95,14 +100,16 @@ class SmartShoppingAssistant:
95
  results = pd.concat([results, matched])
96
  matched_products.add(clean_name)
97
  break # Take first good match
 
98
  return results.drop_duplicates(subset=['CleanName'])
99
-
100
  def setup_agent(self):
101
  """Set up the LangChain agent with necessary tools"""
102
  def search_products(query):
103
  try:
104
  # Split into individual product entries
105
  product_entries = [entry.strip() for entry in query.split('or')]
 
106
  results = self.search_products_fuzzy(product_entries)
107
  if not results.empty:
108
  # Format results with quantity
@@ -114,7 +121,7 @@ class SmartShoppingAssistant:
114
  return "No products found matching your criteria."
115
  except Exception as e:
116
  return f"Error executing query: {str(e)}"
117
-
118
  tools = [
119
  Tool(
120
  name="Product Search",
@@ -122,6 +129,7 @@ class SmartShoppingAssistant:
122
  description="Search for products in the supermarket database using fuzzy matching"
123
  )
124
  ]
 
125
  self.agent = initialize_agent(
126
  tools=tools,
127
  memory=self.memory,
@@ -130,7 +138,7 @@ class SmartShoppingAssistant:
130
  verbose=True,
131
  max_iterations=3
132
  )
133
-
134
  def process_natural_language_query(self, query):
135
  """Process natural language query with two-step matching"""
136
  try:
@@ -138,18 +146,23 @@ class SmartShoppingAssistant:
138
  extraction_prompt = f"""
139
  Extract the products and their quantities from this shopping request.
140
  Include any specific requirements mentioned.
 
141
  Shopping request: {query}
 
142
  Format each item with its quantity (assume 1 if not specified).
143
  """
 
144
  extracted_items = llm_flash_exp.predict(extraction_prompt)
 
145
  # Second step: Match with catalogue
146
  matched_products = self.match_products_with_catalogue(extracted_items)
 
147
  # Third step: Search and return results
148
  result = self.agent.run(f"Search for products matching the specified names: {matched_products}")
149
  return result
150
  except Exception as e:
151
  return f"Error processing query: {str(e)}"
152
-
153
  def extract_text_from_image(self, image):
154
  """Extract text from uploaded image using Gemini"""
155
  prompt = """
@@ -162,7 +175,7 @@ class SmartShoppingAssistant:
162
  return response.text
163
  except Exception as e:
164
  return f"Error processing image: {str(e)}"
165
-
166
  def extract_text_from_pdf(self, pdf_file):
167
  """Extract text from uploaded PDF"""
168
  try:
@@ -179,6 +192,7 @@ class SmartShoppingAssistant:
179
  def add_to_cart(product):
180
  if 'cart' not in st.session_state:
181
  st.session_state.cart = []
 
182
  # Check if product exists in cart
183
  existing = next((item for item in st.session_state.cart if item['ProductName'] == product['ProductName']), None)
184
  if existing:
@@ -194,15 +208,18 @@ def generate_receipt():
194
  pdf = FPDF()
195
  pdf.add_page()
196
  pdf.set_font("Arial", size=12)
 
197
  pdf.cell(200, 10, txt="Bon Marche Receipt", ln=1, align='C')
198
  pdf.cell(200, 10, txt=f"Date: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M')}", ln=1)
 
199
  total = 0
200
  for item in st.session_state.cart:
201
  price = item['RetailPrice'] * item['Quantity']
202
- pdf.cell(200, 10,
203
  txt=f"{item['ProductName']} x{item['Quantity']} - ${price:.2f}",
204
  ln=1)
205
  total += price
 
206
  pdf.cell(200, 10, txt=f"Total: ${total:.2f}", ln=1)
207
  return pdf.output(dest='S').encode('latin1')
208
 
@@ -210,20 +227,21 @@ def generate_receipt():
210
  def main():
211
  st.set_page_config(page_title="Smart Shopping Assistant", layout="wide")
212
  st.title("🛒 Smart Shopping Assistant")
213
-
214
  @st.cache_data
215
  def load_product_data():
216
  return pd.read_csv('supermarket4i.csv') # Ensure correct filename
217
-
218
  df = load_product_data()
219
  assistant = SmartShoppingAssistant(df)
220
-
221
  with st.sidebar:
222
  st.header("Upload Shopping List")
223
  uploaded_file = st.file_uploader(
224
  "Upload an image or PDF of your shopping list",
225
  type=['png', 'jpg', 'jpeg', 'pdf']
226
  )
 
227
  if uploaded_file:
228
  try:
229
  if uploaded_file.type.startswith('image'):
@@ -239,6 +257,7 @@ def main():
239
  st.error(f"Error processing file: {str(e)}")
240
 
241
  col1, col2 = st.columns([2, 1])
 
242
  with col1:
243
  st.header("Search Products")
244
  query = st.text_area(
@@ -246,29 +265,32 @@ def main():
246
  height=100,
247
  value=st.session_state.get('query', '')
248
  )
 
249
  if st.button("Search"):
250
  if query:
251
  with st.spinner("Searching..."):
252
  results = assistant.process_natural_language_query(query)
253
  st.session_state.last_results = results
 
254
  # Display results with add to cart buttons
255
  if isinstance(results, str):
256
  st.write(results)
257
  else:
258
  for _, row in results.iterrows():
259
- cola, colb = st.columns([3, 1])
260
  with cola:
261
  st.write(f"**{row['ProductName']}**")
262
  st.write(f"Price: ${row['RetailPrice']} | Qty: {row['Quantity']}")
263
  with colb:
264
  if st.button("Add", key=row['ProductName']):
265
  add_to_cart(row.to_dict())
 
266
  with col2:
267
  st.header("Shopping Cart")
268
  if 'cart' in st.session_state and st.session_state.cart:
269
  total = 0
270
  for item in st.session_state.cart:
271
- cols = st.columns([3, 1, 1])
272
  with cols[0]:
273
  st.write(f"{item['ProductName']} x{item['Quantity']}")
274
  with cols[1]:
@@ -280,6 +302,7 @@ def main():
280
  total += item['RetailPrice'] * item['Quantity']
281
  st.divider()
282
  st.write(f"**Total: ${total:.2f}**")
 
283
  if st.button("Checkout"):
284
  receipt = generate_receipt()
285
  st.download_button(
 
22
  return genai.GenerativeModel('gemini-2.0-flash-thinking-exp')
23
 
24
  model = configure_gemini(os.environ['GOOGLE_API_KEY'])
25
+
26
  # Initialize Gemini models
27
  llm_flash_exp = ChatGoogleGenerativeAI(
28
  model="gemini-2.0-flash-exp",
 
47
  cutoff=threshold
48
  )
49
  return matches if matches else []
50
+
51
  def match_products_with_catalogue(self, extracted_items):
52
  """Match extracted items with catalogue products using Gemini"""
53
  product_list = self.df['ProductName'].tolist()
54
  product_string = ", ".join(product_list)
55
+
56
  prompt = f"""
57
  Given these extracted items and quantities:
58
  {extracted_items}
59
+
60
  And this product catalogue:
61
  {product_string}
62
 
 
71
 
72
  Only include products that have good matches in the catalogue.
73
  """
74
+
75
  try:
76
  matches = llm_flash_exp.predict(prompt)
77
  return matches.strip()
78
  except Exception as e:
79
  return f"Error matching products: {str(e)}"
80
+
81
  def search_products_fuzzy(self, product_names_with_quantities):
82
  """Improved fuzzy search with batch processing"""
83
  results = pd.DataFrame()
84
  matched_products = set()
85
+
86
  for item in product_names_with_quantities:
87
  product_info = item.split('quantity:')
88
  clean_name = product_info[0].strip().upper().replace('PRODUCTNAME ==', '').strip(' "\'')
 
100
  results = pd.concat([results, matched])
101
  matched_products.add(clean_name)
102
  break # Take first good match
103
+
104
  return results.drop_duplicates(subset=['CleanName'])
105
+
106
  def setup_agent(self):
107
  """Set up the LangChain agent with necessary tools"""
108
  def search_products(query):
109
  try:
110
  # Split into individual product entries
111
  product_entries = [entry.strip() for entry in query.split('or')]
112
+
113
  results = self.search_products_fuzzy(product_entries)
114
  if not results.empty:
115
  # Format results with quantity
 
121
  return "No products found matching your criteria."
122
  except Exception as e:
123
  return f"Error executing query: {str(e)}"
124
+
125
  tools = [
126
  Tool(
127
  name="Product Search",
 
129
  description="Search for products in the supermarket database using fuzzy matching"
130
  )
131
  ]
132
+
133
  self.agent = initialize_agent(
134
  tools=tools,
135
  memory=self.memory,
 
138
  verbose=True,
139
  max_iterations=3
140
  )
141
+
142
  def process_natural_language_query(self, query):
143
  """Process natural language query with two-step matching"""
144
  try:
 
146
  extraction_prompt = f"""
147
  Extract the products and their quantities from this shopping request.
148
  Include any specific requirements mentioned.
149
+
150
  Shopping request: {query}
151
+
152
  Format each item with its quantity (assume 1 if not specified).
153
  """
154
+
155
  extracted_items = llm_flash_exp.predict(extraction_prompt)
156
+
157
  # Second step: Match with catalogue
158
  matched_products = self.match_products_with_catalogue(extracted_items)
159
+
160
  # Third step: Search and return results
161
  result = self.agent.run(f"Search for products matching the specified names: {matched_products}")
162
  return result
163
  except Exception as e:
164
  return f"Error processing query: {str(e)}"
165
+
166
  def extract_text_from_image(self, image):
167
  """Extract text from uploaded image using Gemini"""
168
  prompt = """
 
175
  return response.text
176
  except Exception as e:
177
  return f"Error processing image: {str(e)}"
178
+
179
  def extract_text_from_pdf(self, pdf_file):
180
  """Extract text from uploaded PDF"""
181
  try:
 
192
  def add_to_cart(product):
193
  if 'cart' not in st.session_state:
194
  st.session_state.cart = []
195
+
196
  # Check if product exists in cart
197
  existing = next((item for item in st.session_state.cart if item['ProductName'] == product['ProductName']), None)
198
  if existing:
 
208
  pdf = FPDF()
209
  pdf.add_page()
210
  pdf.set_font("Arial", size=12)
211
+
212
  pdf.cell(200, 10, txt="Bon Marche Receipt", ln=1, align='C')
213
  pdf.cell(200, 10, txt=f"Date: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M')}", ln=1)
214
+
215
  total = 0
216
  for item in st.session_state.cart:
217
  price = item['RetailPrice'] * item['Quantity']
218
+ pdf.cell(200, 10,
219
  txt=f"{item['ProductName']} x{item['Quantity']} - ${price:.2f}",
220
  ln=1)
221
  total += price
222
+
223
  pdf.cell(200, 10, txt=f"Total: ${total:.2f}", ln=1)
224
  return pdf.output(dest='S').encode('latin1')
225
 
 
227
  def main():
228
  st.set_page_config(page_title="Smart Shopping Assistant", layout="wide")
229
  st.title("🛒 Smart Shopping Assistant")
230
+
231
  @st.cache_data
232
  def load_product_data():
233
  return pd.read_csv('supermarket4i.csv') # Ensure correct filename
234
+
235
  df = load_product_data()
236
  assistant = SmartShoppingAssistant(df)
237
+
238
  with st.sidebar:
239
  st.header("Upload Shopping List")
240
  uploaded_file = st.file_uploader(
241
  "Upload an image or PDF of your shopping list",
242
  type=['png', 'jpg', 'jpeg', 'pdf']
243
  )
244
+
245
  if uploaded_file:
246
  try:
247
  if uploaded_file.type.startswith('image'):
 
257
  st.error(f"Error processing file: {str(e)}")
258
 
259
  col1, col2 = st.columns([2, 1])
260
+
261
  with col1:
262
  st.header("Search Products")
263
  query = st.text_area(
 
265
  height=100,
266
  value=st.session_state.get('query', '')
267
  )
268
+
269
  if st.button("Search"):
270
  if query:
271
  with st.spinner("Searching..."):
272
  results = assistant.process_natural_language_query(query)
273
  st.session_state.last_results = results
274
+
275
  # Display results with add to cart buttons
276
  if isinstance(results, str):
277
  st.write(results)
278
  else:
279
  for _, row in results.iterrows():
280
+ cola, colb = st.columns([3,1])
281
  with cola:
282
  st.write(f"**{row['ProductName']}**")
283
  st.write(f"Price: ${row['RetailPrice']} | Qty: {row['Quantity']}")
284
  with colb:
285
  if st.button("Add", key=row['ProductName']):
286
  add_to_cart(row.to_dict())
287
+
288
  with col2:
289
  st.header("Shopping Cart")
290
  if 'cart' in st.session_state and st.session_state.cart:
291
  total = 0
292
  for item in st.session_state.cart:
293
+ cols = st.columns([3,1,1])
294
  with cols[0]:
295
  st.write(f"{item['ProductName']} x{item['Quantity']}")
296
  with cols[1]:
 
302
  total += item['RetailPrice'] * item['Quantity']
303
  st.divider()
304
  st.write(f"**Total: ${total:.2f}**")
305
+
306
  if st.button("Checkout"):
307
  receipt = generate_receipt()
308
  st.download_button(