import logging from flask import Blueprint, request, jsonify from concurrent.futures import ThreadPoolExecutor from app.utils.ocr import extract_text_from_image from app.utils.ner import extract_ingredients from app.utils.prediction import predict_with_description from app.utils.helper import correct_spelling, load_data analyze_blueprint = Blueprint('analyze', __name__) logging.basicConfig(level=logging.INFO) # Load data + model only once df_cosing, df_brand, product_embeddings = load_data() @analyze_blueprint.route("/analyze", methods=["POST"]) def analyze_ingredients(): try: logging.info("Start analyzing ingredients") ingredients_input = [] # OCR from image (optional) if 'ingredients' in request.files: logging.info("Extracting ingredients from uploaded image using OCR") text = extract_text_from_image(request.files['ingredients']) logging.info(f"OCR text result: {text}") if text.strip(): extracted = extract_ingredients(text) logging.info(f"Extracted ingredients from OCR: {extracted}") ingredients_input.extend(extracted) # From JSON or form data = request.get_json(silent=True) or {} text_input = data.get('ingredients') or request.form.get('ingredients') logging.info(f"Text input from JSON/form: {text_input}") # Parse text input if isinstance(text_input, str): import re manual_split = [i.strip() for i in re.split(r',|;', text_input) if i.strip()] parsed = manual_split or extract_ingredients(text_input) logging.info(f"Parsed ingredients from string input: {parsed}") ingredients_input.extend(parsed) elif isinstance(text_input, list): cleaned_list = [i.strip().lower() for i in text_input if i.strip()] logging.info(f"Parsed ingredients from list input: {cleaned_list}") ingredients_input.extend(cleaned_list) if not ingredients_input: logging.warning("No ingredients recognized after processing input.") return jsonify({"error": "No ingredients recognized."}), 400 # Clean & deduplicate ingredients_input = list(set(ingredients_input)) logging.info(f"Unique ingredients before spell check: {ingredients_input}") corrected = [correct_spelling(ing, df_cosing) for ing in ingredients_input] logging.info(f"Corrected ingredients: {corrected}") # Predict individual ingredient effects logging.info("Predicting individual ingredient effects") with ThreadPoolExecutor() as executor: results = list(executor.map(lambda ing: predict_with_description(ing, df_cosing), corrected)) logging.info(f"Prediction results: {results}") return jsonify({ "Ingredient Analysis": results, }) except Exception as e: logging.exception(f"Error in analyze_ingredients: {e}") return jsonify({"error": str(e)}), 500