Spaces:
Sleeping
Sleeping
from flask import Flask, request, jsonify, redirect, flash, send_from_directory | |
from werkzeug.utils import secure_filename | |
import os | |
import google.generativeai as genai | |
from pymongo import MongoClient | |
import tempfile | |
import PyPDF2 | |
import docx | |
import mammoth | |
from datetime import datetime | |
from PIL import Image | |
import base64 | |
app = Flask(__name__) | |
app.secret_key = 'your_secret_key_here' | |
# Configure Gemini AI | |
genai.configure(api_key="AIzaSyC5-RTbNHj7PX7R-8JOwwUxk6RgWDQtfcA") | |
# Text model | |
text_model = genai.GenerativeModel("gemini-1.5-pro-latest") | |
# Vision model | |
vision_model = genai.GenerativeModel("gemini-1.5-flash") | |
# MongoDB Connection | |
client = MongoClient("mongodb+srv://1mp22cg013:xbnV0QQzx6FMBm2V@cluster0.ilo8duc.mongodb.net/bakery?retryWrites=true&w=majority&appName=Cluster0") | |
db = client.recipe_db | |
# Upload Folder | |
UPLOAD_FOLDER = '/tmp/uploads' # ✅ Use safe writable directory | |
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'pdf', 'docx'} | |
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER | |
os.makedirs(UPLOAD_FOLDER, exist_ok=True) # ✅ Won't throw PermissionError in /tmp | |
def allowed_file(filename): | |
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS | |
def ask_baking_bot(user_input): | |
prompt = f""" | |
You are a professional pastry chef and baking expert. | |
Answer only baking, pastry, and cooking-related questions. | |
User's Question: {user_input} | |
""" | |
response = text_model.generate_content(prompt) | |
return response.text | |
def extract_text_from_pdf(pdf_path): | |
try: | |
text = "" | |
with open(pdf_path, 'rb') as file: | |
pdf_reader = PyPDF2.PdfReader(file) | |
for page in pdf_reader.pages: | |
text += page.extract_text() + "\n" | |
return text | |
except Exception as e: | |
return f"Error extracting text from PDF: {str(e)}" | |
def extract_text_from_docx(docx_path): | |
try: | |
with open(docx_path, "rb") as docx_file: | |
result = mammoth.extract_raw_text(docx_file) | |
return result.value | |
except Exception as e: | |
try: | |
doc = docx.Document(docx_path) | |
text = [para.text for para in doc.paragraphs] | |
return '\n'.join(text) | |
except Exception as e2: | |
return f"Error extracting text from DOCX: {str(e)} and {str(e2)}" | |
def parse_recipe_from_text(text): | |
prompt = f""" | |
You are an expert recipe analyzer. Parse the following text from a recipe document and convert it to a structured recipe format. | |
Extract and organize: | |
1. Recipe title | |
2. Yield/servings | |
3. Ingredients list with quantities | |
4. Step-by-step instructions | |
5. Baking time and temperature if available | |
6. Any tips or notes mentioned | |
Format your response in a clean, well-structured way. | |
Recipe text: | |
{text} | |
""" | |
try: | |
response = text_model.generate_content(prompt) | |
return response.text | |
except Exception as e: | |
return f"Error parsing recipe: {str(e)}" | |
def analyze_recipe_steps(recipe_text): | |
prompt = f""" | |
You are a master baker and recipe expert. | |
Analyze the following recipe and provide: | |
1. Difficulty level (beginner, intermediate, advanced) | |
2. Common pitfalls or mistakes to avoid | |
3. Tips for better results | |
4. Any ingredient substitution suggestions for dietary restrictions | |
5. Estimated total preparation and cooking time | |
Recipe: | |
{recipe_text} | |
""" | |
try: | |
response = text_model.generate_content(prompt) | |
return response.text | |
except Exception as e: | |
return f"Error analyzing recipe: {str(e)}" | |
def analyze_food_image(image_path): | |
try: | |
image = Image.open(image_path).convert("RGB") | |
prompt = """ | |
You are a professional chef and baking expert. | |
Analyze this food image and provide: | |
1. What food item this appears to be | |
2. Key ingredients you can identify | |
3. Brief assessment of its preparation, texture, and doneness if applicable | |
4. One tip to improve it if needed | |
Be specific and detailed in your analysis. | |
""" | |
response = vision_model.generate_content([prompt, image]) | |
return response.text | |
except Exception as e: | |
return f"Error analyzing image: {str(e)}" | |
def recognize_ingredients(image_path): | |
try: | |
image = Image.open(image_path).convert("RGB") | |
prompt = """ | |
You are a professional chef and ingredient expert. | |
Please identify all visible ingredients in this image. | |
For each ingredient: | |
1. Name the ingredient | |
2. Estimate the approximate quantity if possible | |
3. Rate the freshness/quality if visible | |
Be as accurate and specific as possible. | |
""" | |
response = vision_model.generate_content([prompt, image]) | |
return response.text | |
except Exception as e: | |
return f"Error recognizing ingredients: {str(e)}" | |
def assess_baking_problem(image_path): | |
try: | |
image = Image.open(image_path).convert("RGB") | |
prompt = """ | |
You are a master baker and troubleshooter. | |
Analyze this baked item and identify: | |
1. What the item appears to be | |
2. Any visible issues or problems (texture, color, shape, etc.) | |
3. The likely causes of these issues | |
4. Specific remedies and tips to fix these problems next time | |
Be detailed and educational in your response. | |
""" | |
response = vision_model.generate_content([prompt, image]) | |
return response.text | |
except Exception as e: | |
return f"Error assessing baking problem: {str(e)}" | |
def hello_bready(): | |
return "Hello Bready Go!" | |
def ask_question(): | |
user_input = request.form.get('question', '').strip() | |
if not user_input: | |
return jsonify({'error': 'Please enter a question'}), 400 | |
response = ask_baking_bot(user_input) | |
return jsonify({'response': response}) | |
def upload_file(): | |
if 'file' not in request.files: | |
return jsonify({'error': 'No file part'}), 400 | |
file = request.files['file'] | |
if file.filename == '': | |
return jsonify({'error': 'No selected file'}), 400 | |
if not file or not allowed_file(file.filename): | |
return jsonify({'error': 'Invalid file type'}), 400 | |
try: | |
filename = secure_filename(file.filename) | |
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) | |
file.save(filepath) | |
action = request.form.get('action', 'analyze') # Get the action from form data | |
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')): | |
if action == 'identify': | |
result = recognize_ingredients(filepath) | |
elif action == 'troubleshoot': | |
result = assess_baking_problem(filepath) | |
else: # Default to general analysis | |
result = analyze_food_image(filepath) | |
return jsonify({ | |
'analysis': result, | |
'filename': filename | |
}) | |
elif filename.lower().endswith('.pdf'): | |
text = extract_text_from_pdf(filepath) | |
if action == 'analyze_recipe': | |
parsed_recipe = parse_recipe_from_text(text) | |
analysis = analyze_recipe_steps(parsed_recipe) | |
return jsonify({ | |
'recipe_analysis': analysis, | |
'filename': filename | |
}) | |
else: | |
parsed_recipe = parse_recipe_from_text(text) | |
return jsonify({ | |
'analysis': parsed_recipe, | |
'filename': filename | |
}) | |
elif filename.lower().endswith(('.docx', '.doc')): | |
text = extract_text_from_docx(filepath) | |
if action == 'analyze_recipe': | |
parsed_recipe = parse_recipe_from_text(text) | |
analysis = analyze_recipe_steps(parsed_recipe) | |
return jsonify({ | |
'recipe_analysis': analysis, | |
'filename': filename | |
}) | |
else: | |
parsed_recipe = parse_recipe_from_text(text) | |
return jsonify({ | |
'analysis': parsed_recipe, | |
'filename': filename | |
}) | |
except Exception as e: | |
return jsonify({'error': f'Processing failed: {str(e)}'}), 500 | |
def analyze_recipe(): | |
recipe_text = request.form.get('recipe_text', '').strip() | |
if not recipe_text: | |
return jsonify({'error': 'No recipe text provided'}), 400 | |
analysis = analyze_recipe_steps(recipe_text) | |
return jsonify({'analysis': analysis}) | |
def uploaded_file(filename): | |
return send_from_directory(app.config['UPLOAD_FOLDER'], filename) | |
def help(): | |
help_info = { | |
'features': [ | |
{ | |
'title': 'Baking Questions', | |
'description': 'Ask any baking-related questions and get expert answers from our AI chef.' | |
}, | |
{ | |
'title': 'Recipe Analysis', | |
'description': 'Upload recipe documents (PDF/DOCX) and get structured recipe information.' | |
}, | |
{ | |
'title': 'Food Image Analysis', | |
'description': 'Upload images of food to get identification, ingredient analysis, or troubleshooting.' | |
}, | |
{ | |
'title': 'Recipe Scaling', | |
'description': 'Scale recipes up or down based on serving sizes (coming soon).' | |
}, | |
{ | |
'title': 'Baking Troubleshooting', | |
'description': 'Get help diagnosing and fixing baking problems from images of your results.' | |
} | |
] | |
} | |
return jsonify(help_info) | |
# ✅ Modified port to 7860 | |
if __name__ == '__main__': | |
app.run(host='0.0.0.0', port=7860) | |