Prathamesh Sable commited on
Commit
b37d30d
·
1 Parent(s): 21c0d12

Add ingredient IDs to product analysis and storage

Browse files

* **db/models.py**: Add `ingredient_ids` column to `Product` model.
* **db/repositories.py**: Refactor `add_product` method in `ProductRepository` to handle analysis of product data.
* **routers/product.py**: Update `create_product` function to ensure analysis of product data is stored correctly.
* **services/productAnalyzerAgent.py**: Ensure `analyze_product_ingredients` function returns analysis data in the correct format. Update `analyze_product_ingredients` function to include ingredient IDs in the analysis data.

db/models.py CHANGED
@@ -112,4 +112,4 @@ class ScanHistory(Base):
112
  scan_date = Column(DateTime, default=datetime.now)
113
 
114
  # Relationships
115
- user = relationship("User", back_populates="scan_history")
 
112
  scan_date = Column(DateTime, default=datetime.now)
113
 
114
  # Relationships
115
+ user = relationship("User", back_populates="scan_history")
db/repositories.py CHANGED
@@ -90,11 +90,17 @@ class IngredientRepository:
90
  self.db.refresh(db_ingredient)
91
  return db_ingredient
92
  return None
 
93
  class ProductRepository:
94
  def __init__(self, db: Session):
95
  self.db = db
96
 
97
  def add_product(self, product_create: ProductCreate):
 
 
 
 
 
98
  db_product = models.Product(
99
  product_name=product_create.product_name,
100
  ingredients=product_create.ingredients,
@@ -113,4 +119,9 @@ class ProductRepository:
113
  self.db.add(db_product)
114
  self.db.commit()
115
  self.db.refresh(db_product)
116
- return db_product
 
 
 
 
 
 
90
  self.db.refresh(db_ingredient)
91
  return db_ingredient
92
  return None
93
+
94
  class ProductRepository:
95
  def __init__(self, db: Session):
96
  self.db = db
97
 
98
  def add_product(self, product_create: ProductCreate):
99
+ db_product = self._create_product(product_create)
100
+ self._store_analysis_data(db_product, product_create.ingredients_analysis)
101
+ return db_product
102
+
103
+ def _create_product(self, product_create: ProductCreate):
104
  db_product = models.Product(
105
  product_name=product_create.product_name,
106
  ingredients=product_create.ingredients,
 
119
  self.db.add(db_product)
120
  self.db.commit()
121
  self.db.refresh(db_product)
122
+ return db_product
123
+
124
+ def _store_analysis_data(self, db_product, ingredients_analysis):
125
+ db_product.ingredients_analysis = ingredients_analysis
126
+ self.db.commit()
127
+ self.db.refresh(db_product)
routers/product.py CHANGED
@@ -17,6 +17,7 @@ from dotenv import load_dotenv
17
  import requests
18
  import json
19
  from services.ingredients import IngredientService
 
20
 
21
  load_dotenv()
22
 
@@ -155,6 +156,23 @@ async def create_product(
155
  if ingredient:
156
  product_create_data.ingredient_ids.append(ingredient.id)
157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  # use repository to add product
159
  product_repo = ProductRepository(db)
160
  product = product_repo.add_product(product_create_data)
 
17
  import requests
18
  import json
19
  from services.ingredients import IngredientService
20
+ from services.productAnalyzerAgent import analyze_product_ingredients
21
 
22
  load_dotenv()
23
 
 
156
  if ingredient:
157
  product_create_data.ingredient_ids.append(ingredient.id)
158
 
159
+ # Analyze product ingredients and store analysis data
160
+ ingredient_results = []
161
+ for ingredient_name in product_create_data.ingredients:
162
+ ingredient = ingredient_repo.get_ingredient_by_name(ingredient_name)
163
+ if ingredient:
164
+ ingredient_results.append(ingredient)
165
+
166
+ product_analysis = await analyze_product_ingredients(
167
+ ingredients_data=ingredient_results,
168
+ user_preferences={
169
+ "user_id": product_create_data.user_id,
170
+ "allergies": None,
171
+ "dietary_restrictions": None
172
+ }
173
+ )
174
+ product_create_data.ingredients_analysis = product_analysis
175
+
176
  # use repository to add product
177
  product_repo = ProductRepository(db)
178
  product = product_repo.add_product(product_create_data)
services/productAnalyzerAgent.py CHANGED
@@ -31,6 +31,7 @@ async def analyze_product_ingredients(
31
 
32
  # Prepare ingredient data for the prompt
33
  ingredients_summary = []
 
34
  for i, ingredient in enumerate(ingredients_data):
35
  ingredient_info = f"""
36
  Ingredient {i+1}: {ingredient.name}
@@ -41,6 +42,7 @@ Health Effects: {', '.join(ingredient.health_effects) if ingredient.health_effec
41
  Description: {ingredient.description[:200] + '...' if len(ingredient.description) > 200 else ingredient.description}
42
  """
43
  ingredients_summary.append(ingredient_info)
 
44
 
45
  # Add user preferences context if available
46
  user_context = ""
@@ -87,7 +89,8 @@ analysis that would be helpful for a consumer viewing this in an AR application.
87
  "concerns": (array of strings)
88
  }},
89
  "ingredient_interactions": (array of strings),
90
- "key_takeaway": (string)
 
91
  }}
92
 
93
  Only include factual information based on the provided data. If information is unavailable for any field, use appropriate default values. If the data required is too obvious then give appropriate answer.
@@ -111,6 +114,7 @@ Only include factual information based on the provided data. If information is u
111
  if json_match:
112
  try:
113
  analysis = json.loads(json_match.group(0))
 
114
  logger.info("Successfully parsed product analysis")
115
  return analysis
116
  except json.JSONDecodeError as e:
@@ -120,20 +124,22 @@ Only include factual information based on the provided data. If information is u
120
  "overall_safety_score": calculate_average_safety(ingredients_data),
121
  "error": "Failed to parse complete analysis",
122
  "ingredient_count": len(ingredients_data),
123
- "key_takeaway": "Analysis error occurred, please check individual ingredients"
 
124
  }
125
  else:
126
  logger.error("Could not find JSON in LLM response")
127
  return {
128
  "overall_safety_score": calculate_average_safety(ingredients_data),
129
  "error": "Failed to generate structured analysis",
130
- "ingredient_count": len(ingredients_data)
 
131
  }
132
 
133
  except Exception as e:
134
  logger.error(f"Error in product analysis: {e}")
135
  # Fallback analysis based on simple calculations
136
- return generate_fallback_analysis(ingredients_data)
137
 
138
 
139
  def calculate_average_safety(ingredients_data: List[IngredientAnalysisResult]) -> float:
@@ -144,7 +150,7 @@ def calculate_average_safety(ingredients_data: List[IngredientAnalysisResult]) -
144
  return round(sum(safety_scores) / len(safety_scores), 1)
145
 
146
 
147
- def generate_fallback_analysis(ingredients_data: List[IngredientAnalysisResult]) -> Dict[str, Any]:
148
  """Generate a basic analysis when LLM processing fails."""
149
  # Extract known allergens
150
  allergens = []
@@ -176,5 +182,6 @@ def generate_fallback_analysis(ingredients_data: List[IngredientAnalysisResult])
176
  "benefits": [],
177
  "concerns": ["Analysis system encountered an error, please check individual ingredients"]
178
  },
179
- "key_takeaway": f"Product has {len(ingredients_data)} ingredients with average safety score of {safety_score}/10"
180
- }
 
 
31
 
32
  # Prepare ingredient data for the prompt
33
  ingredients_summary = []
34
+ ingredient_ids = []
35
  for i, ingredient in enumerate(ingredients_data):
36
  ingredient_info = f"""
37
  Ingredient {i+1}: {ingredient.name}
 
42
  Description: {ingredient.description[:200] + '...' if len(ingredient.description) > 200 else ingredient.description}
43
  """
44
  ingredients_summary.append(ingredient_info)
45
+ ingredient_ids.append(ingredient.id)
46
 
47
  # Add user preferences context if available
48
  user_context = ""
 
89
  "concerns": (array of strings)
90
  }},
91
  "ingredient_interactions": (array of strings),
92
+ "key_takeaway": (string),
93
+ "ingredient_ids": (array of integers)
94
  }}
95
 
96
  Only include factual information based on the provided data. If information is unavailable for any field, use appropriate default values. If the data required is too obvious then give appropriate answer.
 
114
  if json_match:
115
  try:
116
  analysis = json.loads(json_match.group(0))
117
+ analysis["ingredient_ids"] = ingredient_ids
118
  logger.info("Successfully parsed product analysis")
119
  return analysis
120
  except json.JSONDecodeError as e:
 
124
  "overall_safety_score": calculate_average_safety(ingredients_data),
125
  "error": "Failed to parse complete analysis",
126
  "ingredient_count": len(ingredients_data),
127
+ "key_takeaway": "Analysis error occurred, please check individual ingredients",
128
+ "ingredient_ids": ingredient_ids
129
  }
130
  else:
131
  logger.error("Could not find JSON in LLM response")
132
  return {
133
  "overall_safety_score": calculate_average_safety(ingredients_data),
134
  "error": "Failed to generate structured analysis",
135
+ "ingredient_count": len(ingredients_data),
136
+ "ingredient_ids": ingredient_ids
137
  }
138
 
139
  except Exception as e:
140
  logger.error(f"Error in product analysis: {e}")
141
  # Fallback analysis based on simple calculations
142
+ return generate_fallback_analysis(ingredients_data, ingredient_ids)
143
 
144
 
145
  def calculate_average_safety(ingredients_data: List[IngredientAnalysisResult]) -> float:
 
150
  return round(sum(safety_scores) / len(safety_scores), 1)
151
 
152
 
153
+ def generate_fallback_analysis(ingredients_data: List[IngredientAnalysisResult], ingredient_ids: List[int]) -> Dict[str, Any]:
154
  """Generate a basic analysis when LLM processing fails."""
155
  # Extract known allergens
156
  allergens = []
 
182
  "benefits": [],
183
  "concerns": ["Analysis system encountered an error, please check individual ingredients"]
184
  },
185
+ "key_takeaway": f"Product has {len(ingredients_data)} ingredients with average safety score of {safety_score}/10",
186
+ "ingredient_ids": ingredient_ids
187
+ }