import gradio as gr from jinja2 import Environment, FileSystemLoader from log_util import logger from meal_image_search import search_meal_image from recipe_generator import get_altered_recipe, get_image_from_recipe, get_recipe_from_image from util import yield_lines_from_file BRAND = 'HealthAI' TITLE = f'{BRAND} Chef' env = Environment(loader=FileSystemLoader('templates')) template = env.get_template('recipe.html') DISCLAIMER = 'This recipe is a healthier option generated by AI. A registered dietitian can provide expert dietary advice 😀' async def process_image(file): if not file: yield None, None return image_path = file.name yield image_path, None try: recipe = await get_recipe_from_image(image_path) html = template.render(recipe=recipe) yield image_path, html except Exception as e: logger.error(e) yield None, None if 'not a meal' in str(e).lower(): raise gr.Error("This image doesn't contain a meal.") raise gr.Error("Sorry, this image can't be processed.") async def get_new_recipe(orig_recipe: str, restrictions: list[str], diagnoses: list[str]): if not orig_recipe or (not restrictions and not diagnoses): yield None, None if not orig_recipe: raise gr.Error('Please upload a meal pic first.') if not restrictions and not diagnoses: raise gr.Error( 'Please select dietary restrictions or medical diagnoses, then try again. I will give you a new recipe based on your selections!') try: recipe = await get_altered_recipe(orig_recipe, restrictions, diagnoses) recipe['disclaimer'] = DISCLAIMER html = template.render(recipe=recipe) yield html, None except Exception as e: logger.error(e) yield None, None raise gr.Error(f"Sorry, a new recipe can't be made.") try: image_url = get_image_from_recipe(recipe) yield html, image_url except Exception as e: logger.error(e) yield html, None def search_image(search_text: str) -> str: if not search_text: return None try: image_url = search_meal_image(search_text) if image_url: return image_url except Exception as e: logger.error(e) raise gr.Error(f"Sorry, can't find a meal pic for {search_text}.") with gr.Blocks(title=TITLE, theme=gr.themes.Monochrome(), css=''' footer {visibility: hidden} /* make container full width */ .gradio-container { width: 100% !important; /* flll width */ max-width: 100% !important; /* prevent max-width restriction */ margin: 5px 0px 5px 0px !important; /* top, right, bottom, left */ } '''.strip()) as demo: with gr.Row(): gr.Markdown(f'# {TITLE} 🍽️') new_recipe_button = gr.Button(f'Get {BRAND} Recipe 😋', scale=0) file_select = gr.File(label='Upload Meal Pic', container=True, file_types=['.jpg', '.jpeg', '.png', '.gif', '.webp']) search_text = gr.Textbox(placeholder='Or enter a meal to search for an image of it', submit_btn=True, container=False, interactive=True, max_lines=1) with gr.Row(): restrictions_dropdown = gr.Dropdown(label='Dietary Restrictions', choices=yield_lines_from_file('dietary_restrictions.txt'), interactive=True, multiselect=True, value=None) diagnoses_dropdown = gr.Dropdown(label='Medical Diagnoses', choices=yield_lines_from_file('medical_diagnoses.txt'), interactive=True, multiselect=True, value=None) with gr.Row(): orig_meal = gr.Image(label='Original Meal', interactive=False) new_meal = gr.Image(label=f'{BRAND} Meal', interactive=False) with gr.Row(): orig_recipe = gr.HTML(label='Original Recipe', container=True, show_label=True) new_recipe = gr.HTML(label=f'{BRAND} Recipe', container=True, show_label=True) search_text.submit(search_image, inputs=search_text, outputs=file_select) file_select.change( process_image, inputs=file_select, outputs=[orig_meal, orig_recipe] ) new_recipe_button.click(fn=get_new_recipe, inputs=[orig_recipe, restrictions_dropdown, diagnoses_dropdown], outputs=[new_recipe, new_meal]) demo.launch(server_name='0.0.0.0')