|
|
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) |
|
|
|
|
|
|
|
|
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 = [] |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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}") |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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}") |
|
|
|
|
|
|
|
|
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 |
|
|
|