dev2607 commited on
Commit
68cd547
·
verified ·
1 Parent(s): 603017a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -257
app.py CHANGED
@@ -1,44 +1,99 @@
1
-
2
  import os
3
  import subprocess
4
  import sys
5
  import re
6
  import numpy as np
7
- from PIL import Image
8
  import gradio as gr
9
  import requests
10
  import json
11
  from dotenv import load_dotenv
12
 
13
- # Attempt to install pytesseract if not found
14
- try:
15
- import pytesseract
16
- except ImportError:
17
- subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'pytesseract'])
18
- import pytesseract
19
-
20
- # AFTER importing pytesseract, then set the path
21
- try:
22
- # First try the default path
23
- if os.path.exists('/usr/bin/tesseract'):
24
- pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract'
25
- # Try to find it on the PATH
26
- else:
27
- tesseract_path = subprocess.check_output(['which', 'tesseract']).decode().strip()
28
- if tesseract_path:
29
- pytesseract.pytesseract.tesseract_cmd = tesseract_path
30
- except:
31
- # If all else fails, try the default installation path
32
- pytesseract.pytesseract.tesseract_cmd = 'tesseract'
33
-
34
  # Load environment variables
35
  load_dotenv()
36
 
37
  # Mistral API Key
38
- MISTRAL_API_KEY = "GlrVCBWyvTYjWGKl5jqtK4K41uWWJ79F"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  # Import and configure Mistral API
41
- def analyze_ingredients_with_mistral(ingredients_list, health_conditions=None):
42
  """
43
  Use Mistral AI to analyze ingredients and provide health insights.
44
  """
@@ -47,11 +102,13 @@ def analyze_ingredients_with_mistral(ingredients_list, health_conditions=None):
47
 
48
  # Prepare the list of ingredients for the prompt
49
  ingredients_text = ", ".join(ingredients_list)
 
 
50
 
51
  # Create a prompt for Mistral
52
  if health_conditions and health_conditions.strip():
53
  prompt = f"""
54
- Analyze the following food ingredients for a person with these health conditions: {health_conditions}
55
  Ingredients: {ingredients_text}
56
  For each ingredient:
57
  1. Provide its potential health benefits
@@ -62,7 +119,7 @@ def analyze_ingredients_with_mistral(ingredients_list, health_conditions=None):
62
  """
63
  else:
64
  prompt = f"""
65
- Analyze the following food ingredients:
66
  Ingredients: {ingredients_text}
67
  For each ingredient:
68
  1. Provide its potential health benefits
@@ -98,11 +155,13 @@ def analyze_ingredients_with_mistral(ingredients_list, health_conditions=None):
98
 
99
  return analysis + disclaimer
100
 
 
 
 
101
  except Exception as e:
102
  # Fallback to basic analysis if API call fails
103
  return dummy_analyze(ingredients_list, health_conditions) + f"\n\n(Using fallback analysis: {str(e)})"
104
 
105
-
106
  # Dummy analysis function for when API is not available
107
  def dummy_analyze(ingredients_list, health_conditions=None):
108
  ingredients_text = ", ".join(ingredients_list)
@@ -134,217 +193,55 @@ def dummy_analyze(ingredients_list, health_conditions=None):
134
 
135
  return report
136
 
137
- # Function to extract text from images using OCR
138
- def extract_text_from_image(image):
139
- try:
140
- if image is None:
141
- return "No image captured. Please try again."
142
-
143
- # Verify Tesseract executable is accessible
144
- try:
145
- subprocess.run([pytesseract.pytesseract.tesseract_cmd, "--version"],
146
- check=True, capture_output=True, text=True)
147
- except (subprocess.SubprocessError, FileNotFoundError):
148
- return "Tesseract OCR is not installed or not properly configured. Please check installation."
149
-
150
- # Import necessary libraries
151
- import cv2
152
- import numpy as np
153
- from PIL import Image, ImageOps, ImageEnhance
154
-
155
- # First approach: Invert the image for light text on dark background
156
- inverted_image = ImageOps.invert(image)
157
-
158
- # Try OCR on inverted image
159
- custom_config = r'--oem 3 --psm 6 -l eng --dpi 300'
160
- inverted_text = pytesseract.image_to_string(inverted_image, config=custom_config)
161
-
162
- # Second approach: OpenCV processing for colored backgrounds
163
- img_cv = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
164
-
165
- # Convert to grayscale
166
- gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
167
-
168
- # Apply bilateral filter to preserve edges while reducing noise
169
- filtered = cv2.bilateralFilter(gray, 11, 17, 17)
170
-
171
- # Adaptive thresholding to handle varied lighting
172
- thresh = cv2.adaptiveThreshold(filtered, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
173
- cv2.THRESH_BINARY, 11, 2)
174
-
175
- # Invert the image (if text is light on dark background)
176
- inverted_thresh = cv2.bitwise_not(thresh)
177
-
178
- # Try OCR on processed image
179
- cv_text = pytesseract.image_to_string(
180
- Image.fromarray(inverted_thresh),
181
- config=custom_config
182
- )
183
-
184
- # Third approach: Color filtering to isolate text from colored background
185
- # Convert to HSV color space to better isolate colors
186
- hsv = cv2.cvtColor(img_cv, cv2.COLOR_BGR2HSV)
187
-
188
- # Create a mask to extract light colored text (assuming white/light text)
189
- lower_white = np.array([0, 0, 150])
190
- upper_white = np.array([180, 30, 255])
191
- mask = cv2.inRange(hsv, lower_white, upper_white)
192
-
193
- # Apply morphological operations to clean up the mask
194
- kernel = np.ones((2, 2), np.uint8)
195
- mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
196
- mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
197
-
198
- # Improve character connectivity
199
- mask = cv2.dilate(mask, kernel, iterations=1)
200
-
201
- # Try OCR on color filtered image
202
- color_text = pytesseract.image_to_string(
203
- Image.fromarray(mask),
204
- config=r'--oem 3 --psm 6 -l eng --dpi 300'
205
- )
206
-
207
- # Fourth approach: Try directly with the image but with different configs
208
- direct_text = pytesseract.image_to_string(
209
- image,
210
- config=r'--oem 3 --psm 11 -l eng --dpi 300'
211
- )
212
-
213
- # Compare results and select the best one
214
- results = [inverted_text, cv_text, color_text, direct_text]
215
-
216
- # Select the result with the most alphanumeric characters
217
- def count_alphanumeric(text):
218
- return sum(c.isalnum() for c in text)
219
-
220
- best_text = max(results, key=count_alphanumeric)
221
-
222
- # If still poor results, try with explicit text color inversion in tesseract
223
- if count_alphanumeric(best_text) < 20:
224
- # Try with tesseract's built-in inversion
225
- neg_text = pytesseract.image_to_string(
226
- image,
227
- config=r'--oem 3 --psm 6 -c textord_heavy_nr=1 -c textord_debug_printable=0 -l eng --dpi 300'
228
- )
229
- if count_alphanumeric(neg_text) > count_alphanumeric(best_text):
230
- best_text = neg_text
231
-
232
- # Clean up the text
233
- best_text = re.sub(r'[^\w\s,;:%.()\n\'-]', '', best_text)
234
- best_text = best_text.replace('\n\n', '\n')
235
-
236
- # Special case for ingredients list format
237
- if "ingredient" in best_text.lower() or any(x in best_text.lower() for x in ["sugar", "cocoa", "milk", "contain"]):
238
- # Specific cleaning for ingredient lists
239
- best_text = re.sub(r'([a-z])([A-Z])', r'\1 \2', best_text) # Add space between lowercase and uppercase
240
- best_text = re.sub(r'(\d+)([a-zA-Z])', r'\1 \2', best_text) # Add space between number and letter
241
-
242
- if not best_text.strip():
243
- return "No text could be extracted. Ensure image is clear and readable."
244
-
245
- return best_text.strip()
246
- except Exception as e:
247
- return f"Error extracting text: {str(e)}"
248
-
249
- # Function to parse ingredients from text
250
- def parse_ingredients(text):
251
- if not text:
252
- return []
253
-
254
- # Clean up the text
255
- text = re.sub(r'^ingredients:?\s*', '', text.lower(), flags=re.IGNORECASE)
256
-
257
- # Remove common OCR errors and extraneous characters
258
- text = re.sub(r'[|\\/@#$%^&*()_+=]', '', text)
259
-
260
- # Replace common OCR errors
261
- text = re.sub(r'\bngredients\b', 'ingredients', text)
262
-
263
- # Handle common OCR misreads
264
- replacements = {
265
- '0': 'o', 'l': 'i', '1': 'i',
266
- '5': 's', '8': 'b', 'Q': 'g',
267
- }
268
-
269
- for error, correction in replacements.items():
270
- text = text.replace(error, correction)
271
-
272
- # Split by common ingredient separators
273
- ingredients = re.split(r',|;|\n', text)
274
-
275
- # Clean up each ingredient
276
- cleaned_ingredients = []
277
- for i in ingredients:
278
- i = i.strip().lower()
279
- if i and len(i) > 1: # Ignore single characters which are likely OCR errors
280
- cleaned_ingredients.append(i)
281
-
282
- return cleaned_ingredients
283
-
284
-
285
- # Function to process input based on method (camera, upload, or manual entry)
286
- def process_input(input_method, text_input, camera_input, upload_input, health_conditions):
287
- if input_method == "Camera":
288
- if camera_input is not None:
289
- extracted_text = extract_text_from_image(camera_input)
290
- # If OCR fails, inform the user they can try manual entry
291
- if "Error" in extracted_text or "No text could be extracted" in extracted_text:
292
- return extracted_text + "\n\nPlease try using the 'Manual Entry' option instead."
293
-
294
- ingredients = parse_ingredients(extracted_text)
295
- return analyze_ingredients_with_mistral(ingredients, health_conditions)
296
- else:
297
- return "No camera image captured. Please try again."
298
-
299
- elif input_method == "Image Upload":
300
- if upload_input is not None:
301
- extracted_text = extract_text_from_image(upload_input)
302
- # If OCR fails, inform the user they can try manual entry
303
- if "Error" in extracted_text or "No text could be extracted" in extracted_text:
304
- return extracted_text + "\n\nPlease try using the 'Manual Entry' option instead."
305
-
306
- ingredients = parse_ingredients(extracted_text)
307
- return analyze_ingredients_with_mistral(ingredients, health_conditions)
308
- else:
309
- return "No image uploaded. Please try again."
310
-
311
- elif input_method == "Manual Entry":
312
- if text_input and text_input.strip():
313
- ingredients = parse_ingredients(text_input)
314
- return analyze_ingredients_with_mistral(ingredients, health_conditions)
315
  else:
316
- return "No ingredients entered. Please try again."
317
-
318
- return "Please provide input using one of the available methods."
 
 
 
 
 
 
 
 
 
319
 
320
  # Create the Gradio interface
321
  with gr.Blocks(title="AI Ingredient Scanner") as app:
322
  gr.Markdown("# AI Ingredient Scanner")
323
- gr.Markdown("Scan product ingredients and analyze them for health benefits, risks, and potential allergens.")
324
 
325
  with gr.Row():
326
  with gr.Column():
327
- input_method = gr.Radio(
328
- ["Camera", "Image Upload", "Manual Entry"],
329
- label="Input Method",
330
- value="Camera"
331
  )
332
-
333
- # Camera input
334
- camera_input = gr.Image(label="Capture ingredients with camera", type="pil", visible=True)
335
-
336
- # Image upload
337
- upload_input = gr.Image(label="Upload image of ingredients label", type="pil", visible=False)
338
-
339
- # Text input
340
- text_input = gr.Textbox(
 
341
  label="Enter ingredients list (comma separated)",
342
  placeholder="milk, sugar, flour, eggs, vanilla extract",
343
  lines=3,
344
  visible=False
345
  )
346
 
347
- # Health conditions input - now optional and more flexible
348
  health_conditions = gr.Textbox(
349
  label="Enter your health concerns (optional)",
350
  placeholder="diabetes, high blood pressure, peanut allergy, etc.",
@@ -356,48 +253,32 @@ with gr.Blocks(title="AI Ingredient Scanner") as app:
356
 
357
  with gr.Column():
358
  output = gr.Markdown(label="Analysis Results")
359
- extracted_text_output = gr.Textbox(label="Extracted Text (for verification)", lines=3)
360
 
361
- # Show/hide inputs based on selection
362
- def update_visible_inputs(choice):
363
  return {
364
- upload_input: gr.update(visible=(choice == "Image Upload")),
365
- camera_input: gr.update(visible=(choice == "Camera")),
366
- text_input: gr.update(visible=(choice == "Manual Entry"))
367
  }
368
 
369
- input_method.change(update_visible_inputs, input_method, [upload_input, camera_input, text_input])
370
-
371
- # Extract and display the raw text (for verification purposes)
372
- def show_extracted_text(input_method, text_input, camera_input, upload_input):
373
- if input_method == "Camera" and camera_input is not None:
374
- return extract_text_from_image(camera_input)
375
- elif input_method == "Image Upload" and upload_input is not None:
376
- return extract_text_from_image(upload_input)
377
- elif input_method == "Manual Entry":
378
- return text_input
379
- return "No input detected"
380
 
381
  # Set up event handlers
382
  analyze_button.click(
383
- fn=process_input,
384
- inputs=[input_method, text_input, camera_input, upload_input, health_conditions],
385
- outputs=output
386
- )
387
-
388
- analyze_button.click(
389
- fn=show_extracted_text,
390
- inputs=[input_method, text_input, camera_input, upload_input],
391
- outputs=extracted_text_output
392
  )
393
 
394
  gr.Markdown("### How to use")
395
  gr.Markdown("""
396
- 1. Choose your input method (Camera, Image Upload, or Manual Entry)
397
- 2. Take a photo of the ingredients label or enter ingredients manually
398
  3. Optionally enter your health concerns
399
  4. Click "Analyze Ingredients" to get your personalized analysis
400
- The AI will automatically analyze the ingredients, their health implications, and their potential impact on your specific health concerns.
 
401
  """)
402
 
403
  gr.Markdown("### Examples of what you can ask")
@@ -413,10 +294,9 @@ with gr.Blocks(title="AI Ingredient Scanner") as app:
413
 
414
  gr.Markdown("### Tips for best results")
415
  gr.Markdown("""
416
- - Hold the camera steady and ensure good lighting
417
- - Focus directly on the ingredients list
418
- - Make sure the text is clear and readable
419
  - Be specific about your health concerns for more targeted analysis
 
420
  """)
421
 
422
  gr.Markdown("### Disclaimer")
@@ -427,4 +307,4 @@ with gr.Blocks(title="AI Ingredient Scanner") as app:
427
 
428
  # Launch the app
429
  if __name__ == "__main__":
430
- app.launch()
 
 
1
  import os
2
  import subprocess
3
  import sys
4
  import re
5
  import numpy as np
 
6
  import gradio as gr
7
  import requests
8
  import json
9
  from dotenv import load_dotenv
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  # Load environment variables
12
  load_dotenv()
13
 
14
  # Mistral API Key
15
+ MISTRAL_API_KEY = os.getenv("MISTRAL_API_KEY", "GlrVCBWyvTYjWGKl5jqtK4K41uWWJ79F") # Retrieve from environment or default
16
+
17
+ # Open Food Facts API for product lookup
18
+ def get_product_ingredients(product_name):
19
+ """
20
+ Look up a product by name using the Open Food Facts API and return its ingredients
21
+ """
22
+ if not product_name or not product_name.strip():
23
+ return None, "Please enter a product name"
24
+
25
+ try:
26
+ # Search for products matching the name
27
+ search_url = f"https://world.openfoodfacts.org/cgi/search.pl?search_terms={product_name}&search_simple=1&action=process&json=1"
28
+ response = requests.get(search_url)
29
+
30
+ if response.status_code != 200:
31
+ return None, f"Error connecting to food database: {response.status_code}"
32
+
33
+ data = response.json()
34
+
35
+ # Check if any products were found
36
+ if data["count"] == 0:
37
+ return None, f"No products found matching '{product_name}'"
38
+
39
+ # Get the first (most relevant) product
40
+ product = data["products"][0]
41
+
42
+ # Extract product information
43
+ product_info = {
44
+ "name": product.get("product_name", "Unknown product"),
45
+ "brand": product.get("brands", "Unknown brand"),
46
+ "ingredients_text": product.get("ingredients_text", ""),
47
+ "image_url": product.get("image_url", ""),
48
+ "ingredients_list": []
49
+ }
50
+
51
+ # If ingredients are available in structured format
52
+ if "ingredients" in product and isinstance(product["ingredients"], list):
53
+ for ing in product["ingredients"]:
54
+ if "text" in ing and ing["text"]:
55
+ product_info["ingredients_list"].append(ing["text"].lower())
56
+
57
+ # If no structured ingredients but we have text, parse it
58
+ elif product_info["ingredients_text"]:
59
+ product_info["ingredients_list"] = parse_ingredients(product_info["ingredients_text"])
60
+
61
+ # If we still don't have ingredients
62
+ if not product_info["ingredients_list"]:
63
+ return None, f"Found product '{product_info['name']}' by {product_info['brand']}, but no ingredients information is available"
64
+
65
+ return product_info, None
66
+
67
+ except requests.exceptions.RequestException as e:
68
+ return None, f"Network error retrieving product information: {str(e)}"
69
+ except Exception as e:
70
+ return None, f"Error retrieving product information: {str(e)}"
71
+
72
+ # Function to parse ingredients from text
73
+ def parse_ingredients(text):
74
+ if not text:
75
+ return []
76
+
77
+ # Clean up the text
78
+ text = re.sub(r'^ingredients:?\s*', '', text.lower(), flags=re.IGNORECASE)
79
+
80
+ # Remove common OCR errors and extraneous characters
81
+ text = re.sub(r'[|\\/@#$%^&*()_+=]', '', text)
82
+
83
+ # Split by common ingredient separators
84
+ ingredients = re.split(r',|;|\n', text)
85
+
86
+ # Clean up each ingredient
87
+ cleaned_ingredients = []
88
+ for i in ingredients:
89
+ i = i.strip().lower()
90
+ if i and len(i) > 1: # Ignore single characters which are likely errors
91
+ cleaned_ingredients.append(i)
92
+
93
+ return cleaned_ingredients
94
 
95
  # Import and configure Mistral API
96
+ def analyze_ingredients_with_mistral(ingredients_list, product_name="", health_conditions=None):
97
  """
98
  Use Mistral AI to analyze ingredients and provide health insights.
99
  """
 
102
 
103
  # Prepare the list of ingredients for the prompt
104
  ingredients_text = ", ".join(ingredients_list)
105
+
106
+ product_context = f"for the product '{product_name}'" if product_name else ""
107
 
108
  # Create a prompt for Mistral
109
  if health_conditions and health_conditions.strip():
110
  prompt = f"""
111
+ Analyze the following food ingredients {product_context} for a person with these health conditions: {health_conditions}
112
  Ingredients: {ingredients_text}
113
  For each ingredient:
114
  1. Provide its potential health benefits
 
119
  """
120
  else:
121
  prompt = f"""
122
+ Analyze the following food ingredients {product_context}:
123
  Ingredients: {ingredients_text}
124
  For each ingredient:
125
  1. Provide its potential health benefits
 
155
 
156
  return analysis + disclaimer
157
 
158
+ except requests.exceptions.RequestException as e:
159
+ # Fallback to basic analysis if API call fails
160
+ return dummy_analyze(ingredients_list, health_conditions) + f"\n\n(Using fallback analysis: Network error - {str(e)})"
161
  except Exception as e:
162
  # Fallback to basic analysis if API call fails
163
  return dummy_analyze(ingredients_list, health_conditions) + f"\n\n(Using fallback analysis: {str(e)})"
164
 
 
165
  # Dummy analysis function for when API is not available
166
  def dummy_analyze(ingredients_list, health_conditions=None):
167
  ingredients_text = ", ".join(ingredients_list)
 
193
 
194
  return report
195
 
196
+ # Function to process product name input
197
+ def process_product_input(product_name, manual_ingredients, use_manual, health_conditions):
198
+ if use_manual:
199
+ if manual_ingredients and manual_ingredients.strip():
200
+ ingredients = parse_ingredients(manual_ingredients)
201
+ return f"Analyzing manually entered ingredients:\n\n{analyze_ingredients_with_mistral(ingredients, '', health_conditions)}", manual_ingredients
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  else:
203
+ return "No ingredients entered. Please try again.", ""
204
+ else:
205
+ if not product_name or not product_name.strip():
206
+ return "Please enter a product name", ""
207
+
208
+ product_info, error = get_product_ingredients(product_name)
209
+
210
+ if error:
211
+ return error, ""
212
+
213
+ # Display analysis using the ingredients
214
+ return f"# Analysis for {product_info['name']} by {product_info['brand']}\n\n{analyze_ingredients_with_mistral(product_info['ingredients_list'], product_info['name'], health_conditions)}", ", ".join(product_info['ingredients_list'])
215
 
216
  # Create the Gradio interface
217
  with gr.Blocks(title="AI Ingredient Scanner") as app:
218
  gr.Markdown("# AI Ingredient Scanner")
219
+ gr.Markdown("Find and analyze product ingredients for health benefits, risks, and potential allergens.")
220
 
221
  with gr.Row():
222
  with gr.Column():
223
+ # Option to use manual ingredients or product lookup
224
+ use_manual_ingredients = gr.Checkbox(
225
+ label="Enter ingredients manually instead of product lookup",
226
+ value=False
227
  )
228
+
229
+ # Product name input
230
+ product_name_input = gr.Textbox(
231
+ label="Enter product name",
232
+ placeholder="Oreo cookies, Coca Cola, Nutella, etc.",
233
+ lines=1
234
+ )
235
+
236
+ # Manual ingredients input (initially hidden)
237
+ manual_ingredients_input = gr.Textbox(
238
  label="Enter ingredients list (comma separated)",
239
  placeholder="milk, sugar, flour, eggs, vanilla extract",
240
  lines=3,
241
  visible=False
242
  )
243
 
244
+ # Health conditions input
245
  health_conditions = gr.Textbox(
246
  label="Enter your health concerns (optional)",
247
  placeholder="diabetes, high blood pressure, peanut allergy, etc.",
 
253
 
254
  with gr.Column():
255
  output = gr.Markdown(label="Analysis Results")
256
+ ingredients_output = gr.Textbox(label="Identified Ingredients", lines=3)
257
 
258
+ # Show/hide inputs based on checkbox
259
+ def update_visible_inputs(use_manual):
260
  return {
261
+ product_name_input: gr.update(visible=not use_manual),
262
+ manual_ingredients_input: gr.update(visible=use_manual)
 
263
  }
264
 
265
+ use_manual_ingredients.change(update_visible_inputs, use_manual_ingredients, [product_name_input, manual_ingredients_input])
 
 
 
 
 
 
 
 
 
 
266
 
267
  # Set up event handlers
268
  analyze_button.click(
269
+ fn=process_product_input,
270
+ inputs=[product_name_input, manual_ingredients_input, use_manual_ingredients, health_conditions],
271
+ outputs=[output, ingredients_output]
 
 
 
 
 
 
272
  )
273
 
274
  gr.Markdown("### How to use")
275
  gr.Markdown("""
276
+ 1. Enter a product name (e.g., "Oreo cookies", "Coca Cola", "Nutella")
277
+ 2. Or check the box to enter ingredients manually if you prefer
278
  3. Optionally enter your health concerns
279
  4. Click "Analyze Ingredients" to get your personalized analysis
280
+
281
+ The AI will automatically find the product's ingredients and analyze their health implications and potential impact on your specific health concerns.
282
  """)
283
 
284
  gr.Markdown("### Examples of what you can ask")
 
294
 
295
  gr.Markdown("### Tips for best results")
296
  gr.Markdown("""
297
+ - Use the full product name and brand if possible
 
 
298
  - Be specific about your health concerns for more targeted analysis
299
+ - If a product can't be found, try entering the ingredients manually
300
  """)
301
 
302
  gr.Markdown("### Disclaimer")
 
307
 
308
  # Launch the app
309
  if __name__ == "__main__":
310
+ app.launch()