Spaces:
Running
Running
Commit
·
e18b17c
1
Parent(s):
8f08648
added API for vuforia to get analysis testing pending
Browse files- routers/analysis.py +21 -0
- services/analysis_service.py +44 -0
- utils/analysis_utils.py +63 -0
routers/analysis.py
CHANGED
|
@@ -18,6 +18,7 @@ from langsmith import traceable
|
|
| 18 |
from services.ingredientFinderAgent import IngredientInfoAgentLangGraph
|
| 19 |
from services.productAnalyzerAgent import analyze_product_ingredients
|
| 20 |
from utils.db_utils import ingredient_db_to_pydantic
|
|
|
|
| 21 |
from utils.ingredient_utils import process_single_ingredient
|
| 22 |
|
| 23 |
# Load environment variables
|
|
@@ -120,3 +121,23 @@ async def process_ingredients_endpoint(product_ingredient: ProductIngredientsReq
|
|
| 120 |
except Exception as e:
|
| 121 |
log_error(f"Error in process_ingredients_endpoint: {str(e)}",e)
|
| 122 |
raise HTTPException(status_code=500, detail="Internal Server Error")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
from services.ingredientFinderAgent import IngredientInfoAgentLangGraph
|
| 19 |
from services.productAnalyzerAgent import analyze_product_ingredients
|
| 20 |
from utils.db_utils import ingredient_db_to_pydantic
|
| 21 |
+
from services.analysis_service import get_product_data_by_marker_id as get_analysis_service_data
|
| 22 |
from utils.ingredient_utils import process_single_ingredient
|
| 23 |
|
| 24 |
# Load environment variables
|
|
|
|
| 121 |
except Exception as e:
|
| 122 |
log_error(f"Error in process_ingredients_endpoint: {str(e)}",e)
|
| 123 |
raise HTTPException(status_code=500, detail="Internal Server Error")
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
@router.get("/get_by_marker_id/{target_id}", response_model=ProductAnalysisResponse)
|
| 127 |
+
async def get_analysis_by_marker_id(target_id: str, db: Session = Depends(get_db)):
|
| 128 |
+
"""
|
| 129 |
+
Retrieves product analysis and ingredient information by marker ID.
|
| 130 |
+
"""
|
| 131 |
+
log_info(f"Received request for analysis by marker ID: {target_id}")
|
| 132 |
+
try:
|
| 133 |
+
product_data = get_analysis_service_data(db, target_id)
|
| 134 |
+
|
| 135 |
+
if not product_data:
|
| 136 |
+
raise HTTPException(status_code=404, detail=f"Product not found for marker ID: {target_id}")
|
| 137 |
+
|
| 138 |
+
log_info(f"Successfully retrieved product data for marker ID: {target_id}")
|
| 139 |
+
return product_data
|
| 140 |
+
|
| 141 |
+
except Exception as e:
|
| 142 |
+
log_error(f"Error in get_analysis_by_marker_id: {str(e)}", e)
|
| 143 |
+
raise HTTPException(status_code=500, detail="Internal Server Error")
|
services/analysis_service.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sqlalchemy.orm import Session
|
| 2 |
+
from db.models import Marker, Product
|
| 3 |
+
from utils.analysis_utils import format_product_analysis_response
|
| 4 |
+
from utils.logger_manager import log_info, log_error
|
| 5 |
+
|
| 6 |
+
def get_product_data_by_marker_id(db: Session, target_id: str):
|
| 7 |
+
"""
|
| 8 |
+
Retrieves product analysis and ingredient information by marker ID.
|
| 9 |
+
|
| 10 |
+
Args:
|
| 11 |
+
db: The database session.
|
| 12 |
+
target_id: The target ID from the marker table.
|
| 13 |
+
|
| 14 |
+
Returns:
|
| 15 |
+
A dictionary containing product analysis and ingredient information,
|
| 16 |
+
or None if no product is found.
|
| 17 |
+
"""
|
| 18 |
+
log_info(f"Attempting to retrieve product data for marker ID: {target_id}")
|
| 19 |
+
try:
|
| 20 |
+
# Find the marker with the given target_id
|
| 21 |
+
marker = db.query(Marker).filter(Marker.target_id == target_id).first()
|
| 22 |
+
|
| 23 |
+
if not marker:
|
| 24 |
+
log_info(f"No marker found for target ID: {target_id}")
|
| 25 |
+
return {"found": False, "message": f"No product found for marker ID: {target_id}"}
|
| 26 |
+
|
| 27 |
+
# Get the product associated with the marker
|
| 28 |
+
product = db.query(Product).filter(Product.id == marker.product_id).first()
|
| 29 |
+
|
| 30 |
+
if not product:
|
| 31 |
+
log_info(f"No product found for product_id: {marker.product_id} linked to marker ID: {target_id}")
|
| 32 |
+
return {"found": False, "message": f"No product found for marker ID: {target_id}"}
|
| 33 |
+
|
| 34 |
+
log_info(f"Product found for marker ID {target_id}: {product.name}")
|
| 35 |
+
|
| 36 |
+
# Format the response using the utility function
|
| 37 |
+
response_data = format_product_analysis_response(product)
|
| 38 |
+
|
| 39 |
+
return response_data
|
| 40 |
+
|
| 41 |
+
except Exception as e:
|
| 42 |
+
log_error(f"Error retrieving product data for marker ID {target_id}: {str(e)}", e)
|
| 43 |
+
# Return a structured error response
|
| 44 |
+
return {"found": False, "message": "An error occurred while retrieving product data."}
|
utils/analysis_utils.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Dict, Any, Optional
|
| 2 |
+
|
| 3 |
+
def format_analysis_response(product_data: Optional[Dict[str, Any]]) -> Dict[str, Any]:
|
| 4 |
+
"""
|
| 5 |
+
Formats the retrieved product analysis data into a consistent response structure.
|
| 6 |
+
|
| 7 |
+
Args:
|
| 8 |
+
product_data: A dictionary containing product data, or None if not found.
|
| 9 |
+
|
| 10 |
+
Returns:
|
| 11 |
+
A dictionary representing the formatted response.
|
| 12 |
+
"""
|
| 13 |
+
if product_data is None:
|
| 14 |
+
return {
|
| 15 |
+
"found": False,
|
| 16 |
+
"safety_score": {"isPresent": False, "value": None},
|
| 17 |
+
"product_info": None,
|
| 18 |
+
"ingredient_info": None,
|
| 19 |
+
"allergen_info": None,
|
| 20 |
+
"diet_info": None,
|
| 21 |
+
"nutritional_info": None,
|
| 22 |
+
"manufacturing_info": None,
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
# Assuming product_data is a dictionary representing the joined data from product, ingredients, etc.
|
| 26 |
+
# Adjust field names based on your actual database schema and query results.
|
| 27 |
+
safety_score_value = product_data.get("safety_score")
|
| 28 |
+
safety_score_isPresent = safety_score_value is not None
|
| 29 |
+
|
| 30 |
+
return {
|
| 31 |
+
"found": True,
|
| 32 |
+
"safety_score": {
|
| 33 |
+
"calculated": safety_score_calculated,
|
| 34 |
+
"value": safety_score_value,
|
| 35 |
+
},
|
| 36 |
+
"product_info": {
|
| 37 |
+
"id": product_data.get("product_id"),
|
| 38 |
+
"name": product_data.get("product_name"),
|
| 39 |
+
"barcode": product_data.get("product_barcode"),
|
| 40 |
+
"image_url": product_data.get("product_image_url"),
|
| 41 |
+
"brand": product_data.get("product_brand"),
|
| 42 |
+
"manufacturing_places": product_data.get("product_manufacturing_places"),
|
| 43 |
+
"stores": product_data.get("product_stores"),
|
| 44 |
+
"countries": product_data.get("product_countries"),
|
| 45 |
+
} if product_data.get("product_id") is not None else None,
|
| 46 |
+
"ingredient_info": {
|
| 47 |
+
"ingredients_text": product_data.get("ingredients_text"),
|
| 48 |
+
"ingredients_analysis": product_data.get("ingredients_analysis"),
|
| 49 |
+
"additives": product_data.get("additives"),
|
| 50 |
+
} if product_data.get("ingredients_text") is not None else None,
|
| 51 |
+
"allergen_info": {
|
| 52 |
+
"allergens": product_data.get("allergens"),
|
| 53 |
+
"traces": product_data.get("traces"),
|
| 54 |
+
} if product_data.get("allergens") is not None or product_data.get("traces") is not None else None,
|
| 55 |
+
"diet_info": {
|
| 56 |
+
"vegan": product_data.get("vegan"),
|
| 57 |
+
"vegetarian": product_data.get("vegetarian"),
|
| 58 |
+
} if product_data.get("vegan") is not None or product_data.get("vegetarian") is not None else None,
|
| 59 |
+
"nutritional_info": product_data.get("nutritional_info"), # Assuming this is already a dict
|
| 60 |
+
"manufacturing_info": product_data.get("manufacturing_info"), # Assuming this is already a dict
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
# Add other helper functions as needed for analysis
|