breadygo / app.py
roshcheeku's picture
Update app.py
08b2ea6 verified
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)}"
@app.route('/')
def hello_bready():
return "Hello Bready Go!"
@app.route('/ask', methods=['POST'])
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})
@app.route('/upload', methods=['POST'])
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
@app.route('/analyze_recipe', methods=['POST'])
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})
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
@app.route('/help')
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)