Spaces:
Sleeping
Sleeping
import sys | |
from .icmr import analyze_nutrients | |
from .rda import find_nutrition, rda_analysis, analyze_nutrition_icmr_rda | |
import os | |
import json, asyncio | |
from fastapi import FastAPI, HTTPException | |
from typing import List, Dict, Any | |
from pydantic import BaseModel | |
app = FastAPI() | |
def find_product_nutrients(product_info_from_db): | |
#GET Response: {'_id': '6714f0487a0e96d7aae2e839', | |
#'brandName': 'Parle', 'claims': ['This product does not contain gold'], | |
#'fssaiLicenseNumbers': [10013022002253], | |
#'ingredients': [{'metadata': '', 'name': 'Refined Wheat Flour (Maida)', 'percent': '63%'}, {'metadata': '', 'name': 'Sugar', 'percent': ''}, {'metadata': '', 'name': 'Refined Palm Oil', 'percent': ''}, {'metadata': '(Glucose, Levulose)', 'name': 'Invert Sugar Syrup', 'percent': ''}, {'metadata': 'I', 'name': 'Sugar Citric Acid', 'percent': ''}, {'metadata': '', 'name': 'Milk Solids', 'percent': '1%'}, {'metadata': '', 'name': 'Iodised Salt', 'percent': ''}, {'metadata': '503(I), 500 (I)', 'name': 'Raising Agents', 'percent': ''}, {'metadata': '1101 (i)', 'name': 'Flour Treatment Agent', 'percent': ''}, {'metadata': 'Diacetyl Tartaric and Fatty Acid Esters of Glycerol (of Vegetable Origin)', 'name': 'Emulsifier', 'percent': ''}, {'metadata': 'Vanilla', 'name': 'Artificial Flavouring Substances', 'percent': ''}], | |
#'nutritionalInformation': [{'name': 'Energy', 'unit': 'kcal', 'values': [{'base': 'per 100 g','value': 462}]}, | |
#{'name': 'Protein', 'unit': 'g', 'values': [{'base': 'per 100 g', 'value': 6.7}]}, | |
#{'name': 'Carbohydrate', 'unit': 'g', 'values': [{'base': 'per 100 g', 'value': 76.0}, {'base': 'of which sugars', 'value': 26.9}]}, | |
#{'name': 'Fat', 'unit': 'g', 'values': [{'base': 'per 100 g', 'value': 14.6}, {'base': 'Saturated Fat', 'value': 6.8}, {'base': 'Trans Fat', 'value': 0}]}, | |
#{'name': 'Total Sugars', 'unit': 'g', 'values': [{'base': 'per 100 g', 'value': 27.7}]}, | |
#{'name': 'Added Sugars', 'unit': 'g', 'values': [{'base': 'per 100 g', 'value': 26.9}]}, | |
#{'name': 'Cholesterol', 'unit': 'mg', 'values': [{'base': 'per 100 g', 'value': 0}]}, | |
#{'name': 'Sodium', 'unit': 'mg', 'values': [{'base': 'per 100 g', 'value': 281}]}], | |
#'packagingSize': {'quantity': 82, 'unit': 'g'}, | |
#'productName': 'Parle-G Gold Biscuits', | |
#'servingSize': {'quantity': 18.8, 'unit': 'g'}, | |
#'servingsPerPack': 3.98, | |
#'shelfLife': '7 months from packaging'} | |
product_type = None | |
calories = None | |
sugar = None | |
total_sugar = None | |
added_sugar = None | |
salt = None | |
serving_size = None | |
if product_info_from_db["servingSize"]["unit"].lower() == "g": | |
product_type = "solid" | |
elif product_info_from_db["servingSize"]["unit"].lower() == "ml": | |
product_type = "liquid" | |
serving_size = product_info_from_db["servingSize"]["quantity"] | |
for item in product_info_from_db["nutritionalInformation"]: | |
if 'energy' in item['name'].lower(): | |
calories = item['values'][0]['value'] | |
if 'total sugar' in item['name'].lower(): | |
total_sugar = item['values'][0]['value'] | |
if 'added sugar' in item['name'].lower(): | |
added_sugar = item['values'][0]['value'] | |
if 'sugar' in item['name'].lower() and 'added sugar' not in item['name'].lower() and 'total sugar' not in item['name'].lower(): | |
sugar = item['values'][0]['value'] | |
if 'salt' in item['name'].lower(): | |
if salt is None: | |
salt = 0 | |
salt += item['values'][0]['value'] | |
if salt is None: | |
salt = 0 | |
for item in product_info_from_db["nutritionalInformation"]: | |
if 'sodium' in item['name'].lower(): | |
salt += item['values'][0]['value'] | |
if added_sugar is not None and added_sugar > 0 and sugar is None: | |
sugar = added_sugar | |
elif total_sugar is not None and total_sugar > 0 and added_sugar is None and sugar is None: | |
sugar = total_sugar | |
return product_type, calories, sugar, salt, serving_size | |
# Define the request body using a simple BaseModel (without complex pydantic models if not needed) | |
class NutrientAnalysisRequest(BaseModel): | |
product_info_from_db: dict | |
async def get_nutrient_analysis(request: NutrientAnalysisRequest): | |
product_info = request.product_info_from_db | |
try: | |
if ("nutritionalInformation" not in product_info or "servingSize" not in product_info or "quantity" not in product_info["servingSize"]): | |
return {"nutrition_analysis" : ""} | |
if (len(product_info["nutritionalInformation"]) == 0 or product_info["servingSize"]["quantity"] == 0): | |
return {"nutrition_analysis" : ""} | |
nutritional_information = product_info["nutritionalInformation"] | |
serving_size = product_info["servingSize"]["quantity"] | |
if nutritional_information: | |
try: | |
product_type, calories, sugar, salt, serving_size = find_product_nutrients(product_info) | |
except Exception as e: | |
print(f"Error in find_product_nutrients: {str(e)}", exc_info=True) | |
raise | |
if product_type is not None and serving_size is not None and serving_size > 0: | |
# Parallel execution of nutrient analysis tasks | |
try: | |
nutrient_analysis, nutrient_analysis_rda_data = await asyncio.gather( | |
analyze_nutrients(product_type, calories, sugar, salt, serving_size), | |
rda_analysis(nutritional_information, serving_size) | |
) | |
print(f"DEBUG : ICMR based analysis is {nutrient_analysis}") | |
# Or with a try-except approach | |
try: | |
print(f"DEBUG : RDA Data is {nutrient_analysis_rda_data} with userServingSize of type {type(nutrient_analysis_rda_data['userServingSize'])} and nutritionPerServing of type {type(nutrient_analysis_rda_data['nutritionPerServing'])}") | |
except KeyError as e: | |
print(f"DEBUG: Missing key in nutrient_analysis_rda_data - {e}") | |
except Exception as e: | |
raise | |
try: | |
nutrient_analysis_rda = find_nutrition(nutrient_analysis_rda_data) | |
print(f"DEBUG : RDA based analysis is {nutrient_analysis_rda}") | |
except Exception as e: | |
raise | |
try: | |
nutritional_level = await analyze_nutrition_icmr_rda(nutrient_analysis, nutrient_analysis_rda) | |
print(f"DEBUG : ICMR and RDA based analysis is {nutritional_level}") | |
return {"nutrition_analysis" : nutritional_level} | |
except Exception as e: | |
raise | |
else: | |
error_msg = "Product information in the db is corrupt" | |
raise HTTPException(status_code=400, detail=error_msg) | |
else: | |
error_msg = "Nutritional information is required" | |
raise HTTPException(status_code=400, detail=error_msg) | |
except HTTPException as http_ex: | |
raise http_ex | |
except Exception as e: | |
raise HTTPException(status_code=500, detail=str(e)) | |