def process_annotation( self, insight: ProductInsight, data: Optional[Dict] = None, auth: Optional[OFFAuthentication] = None, ) -> AnnotationResult: product = get_product(insight.barcode, ["code"]) if product is None: return MISSING_PRODUCT_RESULT image_id = get_image_id(insight.source_image or "") if not image_id: return AnnotationResult( status="error_invalid_image", description="the image is invalid", ) image_key = "nutrition_{}".format(insight.value_tag) select_rotate_image( barcode=insight.barcode, image_id=image_id, image_key=image_key, rotate=insight.data.get("rotation"), server_domain=insight.server_domain, auth=auth, ) return UPDATED_ANNOTATION_RESULT
def is_automatically_processable(barcode: str, source_image: Optional[str], max_timedelta: datetime.timedelta) -> bool: if not source_image: return False image_path = pathlib.Path(source_image) image_id = image_path.stem if not image_id.isdigit(): return False product = get_product(barcode, projection=["images"]) if product is None: logger.debug("Missing product: {}".format(barcode)) raise InvalidInsight() if "images" not in product: logger.debug("No images for product {}".format(barcode)) raise InvalidInsight() product_images = product["images"] if image_id not in product_images: logger.debug("Missing image for product {}, ID: {}".format( barcode, image_id)) raise InvalidInsight() if is_recent_image(product_images, image_id, max_timedelta): return True if is_selected_image(product_images, image_id): return True return False
def process_annotation( self, insight: ProductInsight, data: Optional[Dict] = None, auth: Optional[OFFAuthentication] = None, ) -> AnnotationResult: product = get_product(insight.barcode, ["quantity"]) if product is None: return MISSING_PRODUCT_RESULT quantity: Optional[str] = product.get("quantity") or None if quantity is not None: return ALREADY_ANNOTATED_RESULT update_quantity( insight.barcode, insight.value, insight_id=insight.id, server_domain=insight.server_domain, auth=auth, ) return UPDATED_ANNOTATION_RESULT
def process_annotation( self, insight: ProductInsight, data: Optional[Dict] = None, auth: Optional[OFFAuthentication] = None, ) -> AnnotationResult: packaging_tag: str = insight.value_tag product = get_product(insight.barcode, ["packaging_tags"]) if product is None: return MISSING_PRODUCT_RESULT packaging_tags: List[str] = product.get("packaging_tags") or [] if packaging_tag in packaging_tags: return ALREADY_ANNOTATED_RESULT add_packaging( insight.barcode, insight.value, insight_id=insight.id, server_domain=insight.server_domain, auth=auth, ) return UPDATED_ANNOTATION_RESULT
def process_annotation( self, insight: ProductInsight, data: Optional[Dict] = None, auth: Optional[OFFAuthentication] = None, ) -> AnnotationResult: barcode = insight.barcode lang = insight.data["lang"] field_name = "ingredients_text_{}".format(lang) product = get_product(barcode, [field_name]) if product is None: return MISSING_PRODUCT_RESULT original_ingredients = insight.data["text"] corrected = insight.data["corrected"] expected_ingredients = product.get(field_name) if expected_ingredients != original_ingredients: logger.warning("ingredients have changed since spellcheck insight " "creation (product {})".format(barcode)) return AnnotationResult( status=AnnotationStatus.error_updated_product.name, description= "the ingredient list has been updated since spellcheck", ) save_ingredients( barcode, corrected, lang=lang, insight_id=insight.id, auth=auth, ) return UPDATED_ANNOTATION_RESULT
def process_annotation( self, insight: ProductInsight, data: Optional[Dict] = None, auth: Optional[OFFAuthentication] = None, ) -> AnnotationResult: emb_code: str = insight.value product = get_product(insight.barcode, ["emb_codes"]) if product is None: return MISSING_PRODUCT_RESULT emb_codes_str: str = product.get("emb_codes", "") emb_codes: List[str] = [] if emb_codes_str: emb_codes = emb_codes_str.split(",") if self.already_exists(emb_code, emb_codes): return ALREADY_ANNOTATED_RESULT emb_codes.append(emb_code) update_emb_codes( insight.barcode, emb_codes, server_domain=insight.server_domain, insight_id=insight.id, auth=auth, ) return UPDATED_ANNOTATION_RESULT
def categorize( barcode: str, deepest_only: bool = False, ) -> None: """Categorise predicts product categories based on the neural category classifier. deepest_only: controls whether the returned predictions should only contain the deepmost categories for a predicted taxonomy chain. For example, if we predict 'fresh vegetables' -> 'legumes' -> 'beans' for a product, setting deepest_only=True will return 'beans'.""" from robotoff.prediction.category.neural.category_classifier import ( CategoryClassifier, ) from robotoff.products import get_product from robotoff.taxonomy import TaxonomyType, get_taxonomy product = get_product(barcode) if product is None: print(f"Product {barcode} not found") return predictions = CategoryClassifier(get_taxonomy( TaxonomyType.category.name)).predict(product, deepest_only) if predictions: for prediction in predictions: print(f"{prediction.value_tag}: {prediction.data['confidence']}") else: print(f"Nothing predicted for product {barcode}")
def update_insights(barcode: str, server_domain: str): # Sleep 10s to let the OFF update request that triggered the webhook call # to finish time.sleep(10) product_dict = get_product(barcode) if product_dict is None: logger.warn("Updated product does not exist: {}".format(barcode)) return updated = updated_product_predict_insights(barcode, product_dict, server_domain) if updated: logger.info("Product {} updated".format(barcode)) update_ingredients(barcode, product_dict, server_domain) product = Product(product_dict) validators: Dict[str, Optional[InsightValidator]] = {} for insight in ( ProductInsight.select() .where( ProductInsight.annotation.is_null(), ProductInsight.barcode == barcode, ProductInsight.server_domain == server_domain, ) .iterator() ): if insight.type not in validators: validators[insight.type] = InsightValidatorFactory.create( insight.type, None ) validator = validators[insight.type] if validator is not None: result = validate_insight(insight, validator=validator, product=product) if result == InsightValidationResult.deleted: logger.info( "Insight {} deleted (type: {})".format(insight.id, insight.type) ) elif result == InsightValidationResult.updated: logger.info( "Insight {} converted to latent (type: {})".format( insight.id, insight.type ) )
def update_insights(barcode: str, server_domain: str): # Sleep 10s to let the OFF update request that triggered the webhook call # to finish logger.info( f"Running `update_insights` for product {barcode} ({server_domain})") product_dict = get_product(barcode) if product_dict is None: logger.warning("Updated product does not exist: %s", barcode) return updated_product_predict_insights(barcode, product_dict, server_domain) logger.info("Refreshing insights...") imported = refresh_insights(barcode, server_domain, automatic=True) logger.info(f"{imported} insights created after refresh")
def process_annotation( self, insight: ProductInsight, data: Optional[Dict] = None, auth: Optional[OFFAuthentication] = None, ) -> AnnotationResult: product = get_product(insight.barcode, ["brands_tags"]) if product is None: return MISSING_PRODUCT_RESULT add_brand( insight.barcode, insight.value, insight_id=insight.id, server_domain=insight.server_domain, auth=auth, ) return UPDATED_ANNOTATION_RESULT
def process_annotation( self, insight: ProductInsight, data: Optional[Dict] = None, auth: Optional[OFFAuthentication] = None, ) -> AnnotationResult: product = get_product(insight.barcode, ["expiration_date"]) if product is None: return MISSING_PRODUCT_RESULT current_expiration_date = product.get("expiration_date") or None if current_expiration_date: return ALREADY_ANNOTATED_RESULT update_expiration_date( insight.barcode, insight.value, insight_id=insight.id, server_domain=insight.server_domain, auth=auth, ) return UPDATED_ANNOTATION_RESULT