import os import base64 from openai import OpenAI import gradio as gr import requests # Set OpenAI API key openai_api_key = os.getenv("OPENAI_API_KEY") edamam_app_id = os.getenv("EDAMAM_APP_ID") edamam_app_key = os.getenv("EDAMAM_API_KEY") def encode_image(image_path): try: with open(image_path, "rb") as image_file: return base64.b64encode(image_file.read()).decode('utf-8') except Exception as e: raise ValueError(f"Failed to encode image: {e}") def image_to_ingredient_list(image_path): """ Transforms an image of food items/dishes into an ingredient list using GPT-4. Args: image_path (str): The file path to the uploaded image. Returns: str: The generated ingredient list or an error message. """ try: # Encode the image to base64 base64_image = encode_image(image_path) client = OpenAI(api_key=openai_api_key) # Prepare the message with the base64-encoded image messages = [ { "role": "user", "content": [ { "type": "text", "text": """Please provide an ingredient list with estimated quantities used to make the following food image. If the image is a drink, list the ingredients in the drink with estimated quantities based on the image. Only estimate the quantities based on the current image not the entire food. For example if the image is a slice of cake, adjust the quantities to fit a single slice and not a whole cake. Be confident in your answer and don't list down ingredients or quantities you are unsure of. Only output the ingredients list with estimated quantities and separate each item with a newline. Example: 100g rice 200g chicken breast 10ml olive oil 1 cup mango slices 1/2 cup plain yogurt 1 tablespoon peanut butter""" }, { "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{base64_image}" }, }, ], } ] # Call OpenAI's Chat Completion API with image response = client.chat.completions.create( model="gpt-4o-mini", messages=messages ) print(response.choices[0].message.content) # Extract the response text ingredient_list = response.choices[0].message.content return ingredient_list, display_nutrition(ingredient_list) except Exception as e: return f"Error processing image: {str(e)}", "" def get_nutritional_info(ingredient_list, app_id=edamam_app_id, app_key=edamam_app_key): """ Fetches nutritional information for a list of ingredients using Edamam's Nutrition Analysis API. Parameters: - ingredient_list (str): A string where each ingredient is on a new line. - app_id (str): Edamam application ID. - app_key (str): Edamam application key. Returns: - dict: Nutritional information returned by the API. """ url = 'https://api.edamam.com/api/nutrition-details' headers = {'Content-Type': 'application/json'} data = { 'title': 'Recipe', 'ingr': ingredient_list.split('\n') } params = { 'app_id': app_id, 'app_key': app_key } response = requests.post(url, headers=headers, json=data, params=params) # response.raise_for_status() # Raise an error for bad status codes return response.json() import requests def format_nutrition(ingredients): nutrition_data = get_nutritional_info(ingredients) # Extract relevant nutritional information calories = nutrition_data.get('calories', 0) total_nutrients = nutrition_data.get('totalNutrients', {}) carbs = total_nutrients.get('CHOCDF', {}).get('quantity', 0) protein = total_nutrients.get('PROCNT', {}).get('quantity', 0) fats = total_nutrients.get('FAT', {}).get('quantity', 0) return { 'Calories': calories, 'Carbs': carbs, 'Protein': protein, 'Fats': fats } def display_nutrition(ingredients): nutrition_info = format_nutrition(ingredients) return ( f"🔥 Calories: {nutrition_info['Calories']} kcal\n" f"🍞 Carbs: {nutrition_info['Carbs']:.2f} g\n" f"🍗 Protein: {nutrition_info['Protein']:.2f} g\n" f"🥑 Fats: {nutrition_info['Fats']:.2f} g" ) # Define Gradio interface iface = gr.Interface( fn=image_to_ingredient_list, inputs=gr.Image(type="filepath", label="Upload Food Image"), outputs=[gr.Textbox(label="Ingredient List"), gr.Textbox(label="Nutritional Information")], title="Nutritional Estimate Demo v1", description="OpenAI for ingredient building and Edamam for nutritional data", examples=[ ["sample_images/Picture1.jpg"], ["sample_images/Picture2.jpg"], ["sample_images/Picture3.jpg"], ["sample_images/Picture4.jpg"], ["sample_images/Picture5.jpg"], ["sample_images/Picture6.jpg"], ["sample_images/Picture7.jpg"], ["sample_images/Picture8.jpg"], ["sample_images/Picture9.jpg"], ["sample_images/Picture10.jpg"], ["sample_images/Picture11.jpg"], ["sample_images/Picture12.jpg"], ["sample_images/Picture13.jpg"], ["sample_images/Picture14.jpg"], ["sample_images/Picture15.jpg"], ["sample_images/Picture16.jpg"], ["sample_images/Picture17.jpg"], ["sample_images/Picture18.jpg"], ["sample_images/Picture19.jpg"], ["sample_images/Picture20.jpg"] ], allow_flagging="never" ) # Launch the app if __name__ == "__main__": iface.launch()