shivanis14
commited on
Commit
•
2db7785
1
Parent(s):
6980695
Update app.py
Browse files
app.py
CHANGED
@@ -5,6 +5,7 @@ import requests, time
|
|
5 |
from data_extractor import extract_data, find_product, get_product
|
6 |
from nutrient_analyzer import analyze_nutrients
|
7 |
from rda import find_nutrition
|
|
|
8 |
|
9 |
#Used the @st.cache_resource decorator on this function.
|
10 |
#This Streamlit decorator ensures that the function is only executed once and its result (the OpenAI client) is cached.
|
@@ -37,54 +38,92 @@ def get_product_list(product_name_by_user, data_extractor_url):
|
|
37 |
return response
|
38 |
|
39 |
|
40 |
-
def rda_analysis(product_info_from_db_nutritionalInformation,
|
41 |
-
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
"properties": {
|
60 |
-
"energy": {"type": "number"},
|
61 |
-
"protein": {"type": "number"},
|
62 |
-
"carbohydrates": {"type": "number"},
|
63 |
-
"addedSugars": {"type": "number"},
|
64 |
-
"dietaryFiber": {"type": "number"},
|
65 |
-
"totalFat": {"type": "number"},
|
66 |
-
"saturatedFat": {"type": "number"},
|
67 |
-
"monounsaturatedFat": {"type": "number"},
|
68 |
-
"polyunsaturatedFat": {"type": "number"},
|
69 |
-
"transFat": {"type": "number"},
|
70 |
-
"sodium": {"type": "number"},
|
71 |
-
"servingSize": {"type": "number"} # Ensures you get serving size too
|
72 |
-
},
|
73 |
-
"required": nutrient_name_list + ["servingSize"]
|
74 |
}
|
|
|
|
|
|
|
|
|
|
|
75 |
}
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
|
90 |
def find_product_nutrients(product_info_from_db):
|
|
|
5 |
from data_extractor import extract_data, find_product, get_product
|
6 |
from nutrient_analyzer import analyze_nutrients
|
7 |
from rda import find_nutrition
|
8 |
+
from typing import Dict, Any
|
9 |
|
10 |
#Used the @st.cache_resource decorator on this function.
|
11 |
#This Streamlit decorator ensures that the function is only executed once and its result (the OpenAI client) is cached.
|
|
|
38 |
return response
|
39 |
|
40 |
|
41 |
+
def rda_analysis(product_info_from_db_nutritionalInformation: Dict[str, Any],
|
42 |
+
product_info_from_db_servingSize: float) -> Dict[str, Any]:
|
43 |
+
"""
|
44 |
+
Analyze nutritional information and return RDA analysis data in a structured format.
|
45 |
+
|
46 |
+
Args:
|
47 |
+
product_info_from_db_nutritionalInformation: Dictionary containing nutritional information
|
48 |
+
product_info_from_db_servingSize: Serving size value
|
49 |
+
|
50 |
+
Returns:
|
51 |
+
Dictionary containing nutrition per serving and user serving size
|
52 |
+
"""
|
53 |
+
nutrient_name_list = [
|
54 |
+
'energy', 'protein', 'carbohydrates', 'addedSugars', 'dietaryFiber',
|
55 |
+
'totalFat', 'saturatedFat', 'monounsaturatedFat', 'polyunsaturatedFat',
|
56 |
+
'transFat', 'sodium'
|
57 |
+
]
|
58 |
+
|
59 |
+
# Define the JSON schema
|
60 |
+
json_schema = {
|
61 |
+
"type": "object",
|
62 |
+
"properties": {
|
63 |
+
"energy": {"type": "number"},
|
64 |
+
"protein": {"type": "number"},
|
65 |
+
"carbohydrates": {"type": "number"},
|
66 |
+
"addedSugars": {"type": "number"},
|
67 |
+
"dietaryFiber": {"type": "number"},
|
68 |
+
"totalFat": {"type": "number"},
|
69 |
+
"saturatedFat": {"type": "number"},
|
70 |
+
"monounsaturatedFat": {"type": "number"},
|
71 |
+
"polyunsaturatedFat": {"type": "number"},
|
72 |
+
"transFat": {"type": "number"},
|
73 |
+
"sodium": {"type": "number"},
|
74 |
+
"servingSize": {"type": "number"}
|
75 |
+
},
|
76 |
+
"required": nutrient_name_list + ["servingSize"],
|
77 |
+
"additionalProperties": False
|
78 |
+
}
|
79 |
|
80 |
+
try:
|
81 |
+
completion = client.chat.completions.create(
|
82 |
+
model="gpt-4o",
|
83 |
+
messages=[
|
84 |
+
{
|
85 |
+
"role": "system",
|
86 |
+
"content": """You will be given nutritional information of a food product.
|
87 |
+
Return the data in the exact JSON format specified in the schema,
|
88 |
+
with all required fields."""
|
89 |
+
},
|
90 |
+
{
|
91 |
+
"role": "user",
|
92 |
+
"content": f"Nutritional content of food product is {json.dumps(product_info_from_db_nutritionalInformation)}. "
|
93 |
+
f"Extract the values of the following nutrients: {', '.join(nutrient_name_list)}."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
+
],
|
96 |
+
response_format={
|
97 |
+
"type": "json_schema",
|
98 |
+
"schema": json_schema,
|
99 |
+
"strict": True
|
100 |
}
|
101 |
+
)
|
102 |
+
|
103 |
+
# Parse the JSON response
|
104 |
+
nutrition_data = json.loads(completion.choices[0].message["content"])
|
105 |
+
|
106 |
+
# Validate that all required fields are present
|
107 |
+
missing_fields = [field for field in nutrient_name_list + ["servingSize"]
|
108 |
+
if field not in nutrition_data]
|
109 |
+
if missing_fields:
|
110 |
+
print(f"Missing required fields in API response: {missing_fields}")
|
111 |
+
|
112 |
+
# Validate that all values are numbers
|
113 |
+
non_numeric_fields = [field for field, value in nutrition_data.items()
|
114 |
+
if not isinstance(value, (int, float))]
|
115 |
+
if non_numeric_fields:
|
116 |
+
raise ValueError(f"Non-numeric values found in fields: {non_numeric_fields}")
|
117 |
+
|
118 |
+
return {
|
119 |
+
'nutritionPerServing': nutrition_data,
|
120 |
+
'userServingSize': product_info_from_db_servingSize
|
121 |
+
}
|
122 |
+
|
123 |
+
except Exception as e:
|
124 |
+
# Log the error and raise it for proper handling
|
125 |
+
print(f"Error in RDA analysis: {str(e)}")
|
126 |
+
raise
|
127 |
|
128 |
|
129 |
def find_product_nutrients(product_info_from_db):
|