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)) | |