|
import gradio as gr |
|
import base64 |
|
import requests |
|
import io |
|
from PIL import Image |
|
import json |
|
import os |
|
from together import Together |
|
import tempfile |
|
|
|
def encode_image_to_base64(image_path): |
|
"""Convert image to base64 encoding""" |
|
with open(image_path, "rb") as image_file: |
|
return base64.b64encode(image_file.read()).decode('utf-8') |
|
|
|
def save_uploaded_image(image): |
|
"""Save uploaded image to a temporary file and return the path""" |
|
if image is None: |
|
return None |
|
|
|
with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as temp_file: |
|
if isinstance(image, dict) and "path" in image: |
|
|
|
with open(image["path"], "rb") as img_file: |
|
temp_file.write(img_file.read()) |
|
elif isinstance(image, Image.Image): |
|
|
|
image.save(temp_file.name, format="JPEG") |
|
else: |
|
|
|
try: |
|
Image.open(image).save(temp_file.name, format="JPEG") |
|
except Exception: |
|
return None |
|
|
|
return temp_file.name |
|
|
|
def get_recipe_suggestions(api_key, image, num_recipes=3, dietary_restrictions="None"): |
|
""" |
|
Get recipe suggestions based on the uploaded image of ingredients |
|
""" |
|
if not api_key or not image: |
|
return "Please provide both an API key and an image of ingredients." |
|
|
|
|
|
image_path = save_uploaded_image(image) |
|
if not image_path: |
|
return "Failed to process the uploaded image." |
|
|
|
try: |
|
|
|
client = Together(api_key=api_key) |
|
|
|
|
|
system_prompt = """You are a culinary expert AI assistant that specializes in creating recipes based on available ingredients. |
|
Analyze the provided image of ingredients and suggest creative, detailed recipes. |
|
For each recipe suggestion, include: |
|
1. Recipe name |
|
2. Brief description of the dish |
|
3. Complete ingredients list (including estimated quantities and any additional staple ingredients that might be needed) |
|
4. Step-by-step cooking instructions |
|
5. Approximate cooking time |
|
6. Difficulty level (Easy, Medium, Advanced) |
|
7. Nutritional highlights |
|
|
|
Consider any dietary restrictions mentioned by the user.""" |
|
|
|
user_prompt = f"""Based on the ingredients shown in this image, suggest {num_recipes} creative and delicious recipes. |
|
Dietary restrictions to consider: {dietary_restrictions} |
|
Please be specific about what ingredients you can identify in the image and creative with your recipe suggestions.""" |
|
|
|
|
|
response = client.chat.completions.create( |
|
model="meta-llama/Llama-Vision-Free", |
|
messages=[ |
|
{ |
|
"role": "system", |
|
"content": system_prompt |
|
}, |
|
{ |
|
"role": "user", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"text": user_prompt |
|
}, |
|
{ |
|
"type": "image_url", |
|
"image_url": { |
|
"url": f"file://{image_path}" |
|
} |
|
} |
|
] |
|
} |
|
], |
|
max_tokens=2048, |
|
temperature=0.7 |
|
) |
|
|
|
|
|
try: |
|
os.unlink(image_path) |
|
except: |
|
pass |
|
|
|
return response.choices[0].message.content |
|
|
|
except Exception as e: |
|
|
|
try: |
|
os.unlink(image_path) |
|
except: |
|
pass |
|
return f"Error: {str(e)}" |
|
|
|
|
|
with gr.Blocks(title="Visual Recipe Assistant") as app: |
|
gr.Markdown("# π² Visual Recipe Assistant") |
|
gr.Markdown("Upload an image of ingredients you have, and get creative recipe suggestions!") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
api_key_input = gr.Textbox( |
|
label="Together API Key", |
|
placeholder="Enter your Together API key here...", |
|
type="password" |
|
) |
|
image_input = gr.Image( |
|
label="Upload Image of Ingredients", |
|
type="filepath" |
|
) |
|
|
|
with gr.Row(): |
|
num_recipes = gr.Slider( |
|
minimum=1, |
|
maximum=5, |
|
value=3, |
|
step=1, |
|
label="Number of Recipe Suggestions" |
|
) |
|
dietary_restrictions = gr.Dropdown( |
|
choices=["None", "Vegetarian", "Vegan", "Gluten-Free", "Dairy-Free", "Low-Carb", "Keto"], |
|
value="None", |
|
label="Dietary Restrictions" |
|
) |
|
|
|
submit_button = gr.Button("Get Recipe Suggestions", variant="primary") |
|
|
|
with gr.Column(scale=2): |
|
output = gr.Markdown(label="Recipe Suggestions") |
|
|
|
|
|
submit_button.click( |
|
fn=get_recipe_suggestions, |
|
inputs=[api_key_input, image_input, num_recipes, dietary_restrictions], |
|
outputs=output |
|
) |
|
|
|
gr.Markdown(""" |
|
## How to Use |
|
1. Enter your Together API key |
|
2. Upload an image of ingredients you have available |
|
3. Adjust the number of recipes you'd like to receive |
|
4. Select any dietary restrictions |
|
5. Click "Get Recipe Suggestions" |
|
|
|
## About |
|
This app uses the Llama-Vision-Free multimodal model from Meta to analyze images of ingredients |
|
and suggest creative recipes based on what it identifies. |
|
""") |
|
|
|
|
|
if __name__ == "__main__": |
|
app.launch() |