import os
from dotenv import load_dotenv
import gradio as gr
from langchain_huggingface import HuggingFaceEndpoint
from datetime import datetime
# Load environment variables
load_dotenv()
HF_TOKEN = os.getenv("HF_TOKEN")
# Check if token exists and handle error gracefully
if not HF_TOKEN:
raise ValueError("HF_TOKEN environment variable not found. Please set it in your .env file.")
# Initialize the HuggingFace inference endpoint
llm = HuggingFaceEndpoint(
repo_id="mistralai/Mistral-7B-Instruct-v0.3",
huggingfacehub_api_token=HF_TOKEN.strip(),
temperature=0.7,
)
# Input validation function
def validate_ingredients(ingredients):
if not ingredients or ingredients.strip() == "":
return "Invalid"
prompt = (
f"Review the provided list of items: {ingredients}. "
f"Determine if all items are valid food ingredients. "
f"Respond only with 'Valid' if all are valid food items or 'Invalid' if any are not."
)
response = llm(prompt)
return response.strip()
# Recipe generation function
def generate_recipe(ingredients):
prompt = (
f"You are an expert chef. Using the ingredients: {ingredients}, "
f"suggest two recipes. Provide a title, preparation time, and step-by-step instructions. "
f"It is not mandatory to include all ingredients, pick the ingredients required for each recipe. "
f"Do not include the ingredient list explicitly in the response."
)
response = llm(prompt)
return response.strip()
# Combined function for Gradio
def suggest_recipes(ingredients):
if not ingredients or ingredients.strip() == "":
return "Please enter ingredients before submitting."
validation_result = validate_ingredients(ingredients)
if "Valid" in validation_result: # More flexible check for "Valid" in response
return generate_recipe(ingredients)
else:
return "I'm sorry, but I can't process this request due to invalid ingredients. Please provide valid food ingredients for cooking!"
# Feedback function
def save_feedback(feedback):
if feedback.strip():
try:
with open("feedback.txt", "a") as file:
file.write(f"{datetime.now()}: {feedback}\n")
return "Thank you for your feedback!"
except Exception as e:
return f"Error saving feedback: {str(e)}"
return "Please enter feedback before submitting."
# Gradio interface with professional color theme
with gr.Blocks(theme=gr.themes.Monochrome(primary_hue="blue")) as app:
# Header section with professional background and white text
with gr.Row():
gr.HTML(
"""
🍳 Recipe Generator
Enter the ingredients you have, and we'll validate them and suggest delightful recipes!
"""
)
# Banner Image - Check if file exists first
try:
with gr.Row():
gr.Image("./recipe-generator-banner.png", show_label=False, elem_id="banner-image", width="100%")
except Exception:
# Skip banner if image doesn't exist
pass
# Ingredient input and output with borders and padding for more contrast
with gr.Row():
with gr.Column():
ingredients_input = gr.Textbox(
label="Enter Ingredients (comma-separated):",
placeholder="e.g., eggs, milk, flour",
elem_id="input-box",
show_label=True,
interactive=True,
lines=2,
max_lines=5
)
with gr.Column():
recipe_output = gr.Textbox(
label="Suggested Recipes or Validation Result:",
lines=15,
interactive=False,
elem_id="output-box"
)
# Buttons with professional color design and hover effect
with gr.Row():
generate_button = gr.Button("Get Recipes", elem_id="generate-btn", size="lg")
reset_button = gr.Button("Reset", elem_id="reset-btn", size="lg")
generate_button.click(suggest_recipes, inputs=ingredients_input, outputs=recipe_output)
reset_button.click(lambda: "", inputs=None, outputs=ingredients_input)
# Feedback Section with professional styled input fields
with gr.Row():
feedback_input = gr.Textbox(
label="Feedback:",
placeholder="Let us know how we can improve!",
elem_id="feedback-input",
lines=1
)
feedback_button = gr.Button("Submit", elem_id="feedback-btn", size="lg")
feedback_output = gr.Textbox(
label="Feedback Response:",
lines=1,
interactive=False,
elem_id="feedback-output"
)
feedback_button.click(save_feedback, inputs=feedback_input, outputs=feedback_output)
# Footer with contact link
with gr.Row():
gr.Markdown(
"""
Developed by CloudYuga! Your feedback is valuable. Have questions?
Contact us!
"""
)
# Apply custom professional theme styling
app.css = """
body {
background-color: #f4f4f9; /* Soft background */
color: #333333;
font-family: 'Arial', sans-serif;
}
#input-box, #output-box, #feedback-input {
background-color: #ffffff;
border: 2px solid #cccccc;
border-radius: 8px;
padding: 12px;
color: #333333;
font-size: 1.1em;
}
#generate-btn, #reset-btn, #feedback-btn {
border-radius: 8px;
padding: 15px 30px;
font-size: 1.2em;
transition: background-color 0.3s ease;
}
#generate-btn {
background-color: #4caf50; /* Green for recipe button */
color: #fff;
}
#generate-btn:hover {
background-color: #45a049;
}
#reset-btn {
background-color: #ff9800; /* Orange for reset button */
color: #fff;
}
#reset-btn:hover {
background-color: #fb8c00;
}
#feedback-btn {
background-color: #2196f3; /* Blue for feedback button */
color: #fff;
}
#feedback-btn:hover {
background-color: #1e88e5;
}
#banner-image {
width: 100%;
height: auto;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
"""
# Launch the app
if __name__ == "__main__":
app.launch()