Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +36 -36
src/streamlit_app.py
CHANGED
|
@@ -103,7 +103,7 @@ def get_nutrinutional_info(dish_name, cuisine_type):
|
|
| 103 |
model="gpt-4o-mini",
|
| 104 |
messages=[{
|
| 105 |
"role": "user",
|
| 106 |
-
"content": f"""For the {cuisine_type} dish
|
| 107 |
{{
|
| 108 |
"calories": 350,
|
| 109 |
"protein": 10g,
|
|
@@ -125,10 +125,10 @@ def get_nutrinutional_info(dish_name, cuisine_type):
|
|
| 125 |
menu_data = json.loads(menu_text[json_start:json_end])
|
| 126 |
return menu_data
|
| 127 |
else:
|
| 128 |
-
return { "calories":
|
| 129 |
|
| 130 |
except Exception as e:
|
| 131 |
-
return { "calories":
|
| 132 |
|
| 133 |
def generate_food_image(dish_name, description, cuisine_type, image_style):
|
| 134 |
"""Generate food image with enhanced prompting"""
|
|
@@ -161,7 +161,7 @@ def generate_food_image(dish_name, description, cuisine_type, image_style):
|
|
| 161 |
}
|
| 162 |
}
|
| 163 |
|
| 164 |
-
selected_style = style_config.get(image_style, style_config[
|
| 165 |
|
| 166 |
# Create detailed food photography prompt
|
| 167 |
food_prompt = f"""
|
|
@@ -170,10 +170,10 @@ Professional food photography of {dish_name} ({cuisine_type} cuisine).
|
|
| 170 |
Dish details: {description}
|
| 171 |
|
| 172 |
Photography specifications:
|
| 173 |
-
- {selected_style[
|
| 174 |
-
- {selected_style[
|
| 175 |
-
- {selected_style[
|
| 176 |
-
- {selected_style[
|
| 177 |
|
| 178 |
Technical Requirements:
|
| 179 |
- High resolution, commercial food photography quality
|
|
@@ -227,7 +227,7 @@ if client:
|
|
| 227 |
|
| 228 |
uploaded_file = st.file_uploader(
|
| 229 |
"Choose menu image",
|
| 230 |
-
type=[
|
| 231 |
help="Upload a clear image of your menu with readable text"
|
| 232 |
)
|
| 233 |
|
|
@@ -241,7 +241,7 @@ if client:
|
|
| 241 |
if "error" in menu_data:
|
| 242 |
st.error(f"Error extracting menu data: {menu_data['error']}")
|
| 243 |
if "raw_text" in menu_data:
|
| 244 |
-
st.text_area("Raw extracted Text", menu_data[
|
| 245 |
|
| 246 |
else:
|
| 247 |
st.success("Menu items extracted successfully!")
|
|
@@ -253,21 +253,21 @@ if client:
|
|
| 253 |
col1, col2 = st.columns([2, 1])
|
| 254 |
|
| 255 |
with col1:
|
| 256 |
-
st.markdown(f"**Restaurant** {menu_data.get(
|
| 257 |
-
st.markdown(f"**Cuisine Type** {menu_data.get(
|
| 258 |
|
| 259 |
-
for category, items in menu_data.get(
|
| 260 |
st.markdown(f"**{category}**")
|
| 261 |
for item in items:
|
| 262 |
st.markdown(f"- {item['name']} - {item.get('price', 'N/A')}")
|
| 263 |
-
if item.get(
|
| 264 |
st.markdown(f" *{item['description']}*")
|
| 265 |
|
| 266 |
with col2:
|
| 267 |
st.markdown("**Menu Statistics**")
|
| 268 |
-
total_items = sum(len(items) for items in menu_data.get(
|
| 269 |
st.metric("Total Items", total_items)
|
| 270 |
-
st.metric("Categories", len(menu_data.get(
|
| 271 |
|
| 272 |
if "menu_data" in st.session_state:
|
| 273 |
st.markdown("---")
|
|
@@ -322,7 +322,7 @@ if client:
|
|
| 322 |
|
| 323 |
# get all dishes
|
| 324 |
all_dishes = []
|
| 325 |
-
for category, items in menu_data.get(
|
| 326 |
for item in items:
|
| 327 |
all_dishes.append((category, item))
|
| 328 |
|
|
@@ -330,8 +330,8 @@ if client:
|
|
| 330 |
|
| 331 |
# Generate images and nutrition for each dish
|
| 332 |
for i, (category, item) in enumerate(all_dishes):
|
| 333 |
-
dish_name = item[
|
| 334 |
-
description = item.get(
|
| 335 |
|
| 336 |
status_text.text(f"Generating food photo for {dish_name} ({i+1}/{total_dishes})")
|
| 337 |
|
|
@@ -339,13 +339,13 @@ if client:
|
|
| 339 |
image_bytes, image_url = generate_food_image(
|
| 340 |
dish_name,
|
| 341 |
description,
|
| 342 |
-
menu_data.get(
|
| 343 |
image_style
|
| 344 |
)
|
| 345 |
|
| 346 |
# Get nutritional information
|
| 347 |
if include_nutrition:
|
| 348 |
-
nutritional_data[dish_name] = get_nutrinutional_info(dish_name, menu_data.get(
|
| 349 |
|
| 350 |
# update progress
|
| 351 |
progress_bar.progress((i+1)/total_dishes)
|
|
@@ -360,12 +360,12 @@ if client:
|
|
| 360 |
# Show individual food photo
|
| 361 |
st.markdown("### Generated Food Photos with Nutritional Information")
|
| 362 |
|
| 363 |
-
for category, items in menu_data.get(
|
| 364 |
st.markdown(f"**{category}**")
|
| 365 |
cols = st.columns(min(len(items), 3))
|
| 366 |
|
| 367 |
for i, item in enumerate(items):
|
| 368 |
-
dish_name = item[
|
| 369 |
col_index = i % 3
|
| 370 |
|
| 371 |
with cols[col_index]:
|
|
@@ -379,10 +379,10 @@ if client:
|
|
| 379 |
if include_nutrition and dish_name in nutritional_data:
|
| 380 |
nutrition = nutritional_data[dish_name]
|
| 381 |
st.markdown(
|
| 382 |
-
f"**Nutrition** {nutrition.get(
|
| 383 |
)
|
| 384 |
|
| 385 |
-
if item.get(
|
| 386 |
st.markdown(f" *{item['description']}*")
|
| 387 |
|
| 388 |
|
|
@@ -395,10 +395,10 @@ if client:
|
|
| 395 |
|
| 396 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 397 |
|
| 398 |
-
for category, items in menu_data.get(
|
| 399 |
st.markdown(f"**Download {category} Photos:**")
|
| 400 |
for item in items:
|
| 401 |
-
dish_name = item[
|
| 402 |
if dish_name in dish_images:
|
| 403 |
clean_name = re.sub(r'[^a-zA-Z0-9]', '', dish_name)
|
| 404 |
|
|
@@ -413,7 +413,7 @@ if client:
|
|
| 413 |
)
|
| 414 |
col_count += 1
|
| 415 |
|
| 416 |
-
restaurant_name_clean = re.sub(r'[^a-zA-Z0-9]', '', menu_data.get(
|
| 417 |
|
| 418 |
st.markdown("### Download Menu Report")
|
| 419 |
|
|
@@ -427,8 +427,8 @@ if client:
|
|
| 427 |
menu_summary = f"""VISUAL MENU GENERATED REPORT
|
| 428 |
Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
| 429 |
|
| 430 |
-
Restaurant: {menu_data.get(
|
| 431 |
-
Cuisine Type: {menu_data.get(
|
| 432 |
Image Style: {image_style}
|
| 433 |
Food Description Display: {layout_style}
|
| 434 |
Nutritional Information: {'Included' if include_nutrition else 'Excluded'}
|
|
@@ -436,18 +436,18 @@ Nutritional Information: {'Included' if include_nutrition else 'Excluded'}
|
|
| 436 |
Menu Items Generated: {total_dishes}
|
| 437 |
"""
|
| 438 |
|
| 439 |
-
for category, items in menu_data.get(
|
| 440 |
menu_summary += f"\n{category}:\n"
|
| 441 |
for item in items:
|
| 442 |
-
menu_summary += f"- {item[
|
| 443 |
-
if include_nutrition and item[
|
| 444 |
-
nutrition = nutritional_data[item[
|
| 445 |
menu_summary += f" Nutrition: {nutrition.get('calories', 'N/A')} cal, {nutrition.get('protein', 'N/A')} protein\n"
|
| 446 |
|
| 447 |
menu_summary += f"""
|
| 448 |
Generation Statistics:
|
| 449 |
-
- Total Items: {sum(len(items) for items in menu_data.get(
|
| 450 |
-
- Categories: {len(menu_data.get(
|
| 451 |
- Food Photos Generated: {len(dish_images)}
|
| 452 |
- Processing Time: Several minutes
|
| 453 |
|
|
|
|
| 103 |
model="gpt-4o-mini",
|
| 104 |
messages=[{
|
| 105 |
"role": "user",
|
| 106 |
+
"content": f"""For the {cuisine_type} dish '{dish_name}', provide estimated nutritional information in JSON format:
|
| 107 |
{{
|
| 108 |
"calories": 350,
|
| 109 |
"protein": 10g,
|
|
|
|
| 125 |
menu_data = json.loads(menu_text[json_start:json_end])
|
| 126 |
return menu_data
|
| 127 |
else:
|
| 128 |
+
return { "calories": 'N/A', "protein": 'N/A', "carbs": 'N/A', "fat": 'N/A', "fiber": 'N/A' }
|
| 129 |
|
| 130 |
except Exception as e:
|
| 131 |
+
return { "calories": 'N/A', "protein": 'N/A', "carbs": 'N/A', "fat": 'N/A', "fiber": 'N/A' }
|
| 132 |
|
| 133 |
def generate_food_image(dish_name, description, cuisine_type, image_style):
|
| 134 |
"""Generate food image with enhanced prompting"""
|
|
|
|
| 161 |
}
|
| 162 |
}
|
| 163 |
|
| 164 |
+
selected_style = style_config.get(image_style, style_config['Professional Food Photography'])
|
| 165 |
|
| 166 |
# Create detailed food photography prompt
|
| 167 |
food_prompt = f"""
|
|
|
|
| 170 |
Dish details: {description}
|
| 171 |
|
| 172 |
Photography specifications:
|
| 173 |
+
- {selected_style['lighting']}
|
| 174 |
+
- {selected_style['background']}
|
| 175 |
+
- {selected_style['composition']}
|
| 176 |
+
- {selected_style['quality']}
|
| 177 |
|
| 178 |
Technical Requirements:
|
| 179 |
- High resolution, commercial food photography quality
|
|
|
|
| 227 |
|
| 228 |
uploaded_file = st.file_uploader(
|
| 229 |
"Choose menu image",
|
| 230 |
+
type=['jpg', "jpeg", "png"],
|
| 231 |
help="Upload a clear image of your menu with readable text"
|
| 232 |
)
|
| 233 |
|
|
|
|
| 241 |
if "error" in menu_data:
|
| 242 |
st.error(f"Error extracting menu data: {menu_data['error']}")
|
| 243 |
if "raw_text" in menu_data:
|
| 244 |
+
st.text_area("Raw extracted Text", menu_data['raw_text'], height=200)
|
| 245 |
|
| 246 |
else:
|
| 247 |
st.success("Menu items extracted successfully!")
|
|
|
|
| 253 |
col1, col2 = st.columns([2, 1])
|
| 254 |
|
| 255 |
with col1:
|
| 256 |
+
st.markdown(f"**Restaurant** {menu_data.get('restaurant_image', 'Not detected')}")
|
| 257 |
+
st.markdown(f"**Cuisine Type** {menu_data.get('cuisine_type', 'Not detected')}")
|
| 258 |
|
| 259 |
+
for category, items in menu_data.get('categories', {}).items():
|
| 260 |
st.markdown(f"**{category}**")
|
| 261 |
for item in items:
|
| 262 |
st.markdown(f"- {item['name']} - {item.get('price', 'N/A')}")
|
| 263 |
+
if item.get('description'):
|
| 264 |
st.markdown(f" *{item['description']}*")
|
| 265 |
|
| 266 |
with col2:
|
| 267 |
st.markdown("**Menu Statistics**")
|
| 268 |
+
total_items = sum(len(items) for items in menu_data.get('categories', {}).values())
|
| 269 |
st.metric("Total Items", total_items)
|
| 270 |
+
st.metric("Categories", len(menu_data.get('categories', {})))
|
| 271 |
|
| 272 |
if "menu_data" in st.session_state:
|
| 273 |
st.markdown("---")
|
|
|
|
| 322 |
|
| 323 |
# get all dishes
|
| 324 |
all_dishes = []
|
| 325 |
+
for category, items in menu_data.get('categories', {}).items():
|
| 326 |
for item in items:
|
| 327 |
all_dishes.append((category, item))
|
| 328 |
|
|
|
|
| 330 |
|
| 331 |
# Generate images and nutrition for each dish
|
| 332 |
for i, (category, item) in enumerate(all_dishes):
|
| 333 |
+
dish_name = item['name']
|
| 334 |
+
description = item.get('description', "")
|
| 335 |
|
| 336 |
status_text.text(f"Generating food photo for {dish_name} ({i+1}/{total_dishes})")
|
| 337 |
|
|
|
|
| 339 |
image_bytes, image_url = generate_food_image(
|
| 340 |
dish_name,
|
| 341 |
description,
|
| 342 |
+
menu_data.get('cuisine_type', "Fine Dining"),
|
| 343 |
image_style
|
| 344 |
)
|
| 345 |
|
| 346 |
# Get nutritional information
|
| 347 |
if include_nutrition:
|
| 348 |
+
nutritional_data[dish_name] = get_nutrinutional_info(dish_name, menu_data.get('cuisine_type', "Fine Dining"))
|
| 349 |
|
| 350 |
# update progress
|
| 351 |
progress_bar.progress((i+1)/total_dishes)
|
|
|
|
| 360 |
# Show individual food photo
|
| 361 |
st.markdown("### Generated Food Photos with Nutritional Information")
|
| 362 |
|
| 363 |
+
for category, items in menu_data.get('categories', {}).items():
|
| 364 |
st.markdown(f"**{category}**")
|
| 365 |
cols = st.columns(min(len(items), 3))
|
| 366 |
|
| 367 |
for i, item in enumerate(items):
|
| 368 |
+
dish_name = item['name']
|
| 369 |
col_index = i % 3
|
| 370 |
|
| 371 |
with cols[col_index]:
|
|
|
|
| 379 |
if include_nutrition and dish_name in nutritional_data:
|
| 380 |
nutrition = nutritional_data[dish_name]
|
| 381 |
st.markdown(
|
| 382 |
+
f"**Nutrition** {nutrition.get('calories', 'N/A')} cal, {nutrition.get('protein', 'N/A')} protein"
|
| 383 |
)
|
| 384 |
|
| 385 |
+
if item.get('description'):
|
| 386 |
st.markdown(f" *{item['description']}*")
|
| 387 |
|
| 388 |
|
|
|
|
| 395 |
|
| 396 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 397 |
|
| 398 |
+
for category, items in menu_data.get('categories', {}).items():
|
| 399 |
st.markdown(f"**Download {category} Photos:**")
|
| 400 |
for item in items:
|
| 401 |
+
dish_name = item['name']
|
| 402 |
if dish_name in dish_images:
|
| 403 |
clean_name = re.sub(r'[^a-zA-Z0-9]', '', dish_name)
|
| 404 |
|
|
|
|
| 413 |
)
|
| 414 |
col_count += 1
|
| 415 |
|
| 416 |
+
restaurant_name_clean = re.sub(r'[^a-zA-Z0-9]', '', menu_data.get('restaurant_name', "menu"))
|
| 417 |
|
| 418 |
st.markdown("### Download Menu Report")
|
| 419 |
|
|
|
|
| 427 |
menu_summary = f"""VISUAL MENU GENERATED REPORT
|
| 428 |
Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
| 429 |
|
| 430 |
+
Restaurant: {menu_data.get('restaurant_name', 'N/A')}
|
| 431 |
+
Cuisine Type: {menu_data.get('cuisine_type', 'N/A')}
|
| 432 |
Image Style: {image_style}
|
| 433 |
Food Description Display: {layout_style}
|
| 434 |
Nutritional Information: {'Included' if include_nutrition else 'Excluded'}
|
|
|
|
| 436 |
Menu Items Generated: {total_dishes}
|
| 437 |
"""
|
| 438 |
|
| 439 |
+
for category, items in menu_data.get('categories', {}).items():
|
| 440 |
menu_summary += f"\n{category}:\n"
|
| 441 |
for item in items:
|
| 442 |
+
menu_summary += f"- {item['name']} - {item.get('price', 'N/A')}\n"
|
| 443 |
+
if include_nutrition and item['name'] in nutritional_data:
|
| 444 |
+
nutrition = nutritional_data[item['name']]
|
| 445 |
menu_summary += f" Nutrition: {nutrition.get('calories', 'N/A')} cal, {nutrition.get('protein', 'N/A')} protein\n"
|
| 446 |
|
| 447 |
menu_summary += f"""
|
| 448 |
Generation Statistics:
|
| 449 |
+
- Total Items: {sum(len(items) for items in menu_data.get('categories', {}).values())}
|
| 450 |
+
- Categories: {len(menu_data.get('categories', {}))}
|
| 451 |
- Food Photos Generated: {len(dish_images)}
|
| 452 |
- Processing Time: Several minutes
|
| 453 |
|