Skip to content

Commit

Permalink
fix: import nutrient_extraction insight if it brings at least 1 nutrient
Browse files Browse the repository at this point in the history
  • Loading branch information
raphael0202 committed Oct 25, 2024
1 parent 1512fe5 commit 1eb09ef
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 26 deletions.
36 changes: 10 additions & 26 deletions robotoff/insights/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1540,33 +1540,17 @@ def generate_candidates(
predictions: list[Prediction],
product_id: ProductIdentifier,
) -> Iterator[ProductInsight]:
# Don't generate candidates if the product already has nutrients
if (
product is not None
and product.nutriments
# If we delete all nutrient values, these computed values are still
# present. We therefore ignore these keys.
and bool(
set(
key
for key in product.nutriments.keys()
if not (
key.startswith("carbon-footprint-from-known-ingredients")
or key.startswith(
"fruits-vegetables-legumes-estimate-from-ingredients"
)
or key.startswith(
"fruits-vegetables-nuts-estimate-from-ingredients"
)
or key.startswith("nova-group")
or key.startswith("nutrition-score-fr")
)
)
)
):
return

for prediction in predictions:
if product is not None and product.nutriments:
current_keys = set(key for key in product.nutriments.keys())
prediction_keys = set(prediction.data["nutrients"].keys())

# If the prediction brings a nutrient value that is missing in
# the product, we generate an insight, otherwise we
# skip it
if not len(prediction_keys - current_keys):
continue

yield ProductInsight(**prediction.to_dict())

@classmethod
Expand Down
145 changes: 145 additions & 0 deletions tests/unit/insights/test_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
ExpirationDateImporter,
InsightImporter,
LabelInsightImporter,
NutrientExtractionImporter,
NutritionImageImporter,
PackagerCodeInsightImporter,
PackagingImporter,
Expand Down Expand Up @@ -1531,6 +1532,150 @@ def generate_candidates_for_image(
)


class TestNutrientExtractionImporter:
def test_generate_candidates_no_nutrient(self):
product = Product({"code": DEFAULT_BARCODE, "nutriments": {}})
data = {
"nutrients": {
"energy-kj_100g": {
"entity": "energy-kj_100g",
"value": "100",
"unit": "kj",
"text": "100 kj",
"start": 0,
"end": 1,
"char_start": 0,
"char_end": 6,
}
}
}
predictions = [
Prediction(
type=PredictionType.nutrient_extraction,
data=data,
barcode=DEFAULT_BARCODE,
source_image=DEFAULT_SOURCE_IMAGE,
predictor="nutrition_extractor",
predictor_version="nutrition_extractor-1.0",
automatic_processing=False,
)
]
candidates = list(
NutrientExtractionImporter.generate_candidates(
product, predictions, DEFAULT_PRODUCT_ID
)
)
assert len(candidates) == 1
candidate = candidates[0]
assert candidate.type == "nutrient_extraction"
assert candidate.barcode == DEFAULT_BARCODE
assert candidate.type == InsightType.nutrient_extraction.name
assert candidate.value_tag is None
assert candidate.data == data
assert candidate.source_image == DEFAULT_SOURCE_IMAGE
assert candidate.automatic_processing is False
assert candidate.predictor == "nutrition_extractor"
assert candidate.predictor_version == "nutrition_extractor-1.0"

def test_generate_candidates_no_new_nutrient(self):
product = Product(
{
"code": DEFAULT_BARCODE,
"nutriments": {
"energy-kj_100g": "100",
"energy-kj_unit": "kJ",
"fat_100g": "10",
"fat_unit": "g",
},
}
)
data = {
"nutrients": {
"energy-kj_100g": {
"entity": "energy-kj_100g",
"value": "100",
"unit": "kj",
"text": "100 kj",
"start": 0,
"end": 2,
"char_start": 0,
"char_end": 6,
}
}
}
predictions = [
Prediction(
type=PredictionType.nutrient_extraction,
data=data,
barcode=DEFAULT_BARCODE,
source_image=DEFAULT_SOURCE_IMAGE,
predictor="nutrition_extractor",
predictor_version="nutrition_extractor-1.0",
automatic_processing=False,
)
]
candidates = list(
NutrientExtractionImporter.generate_candidates(
product, predictions, DEFAULT_PRODUCT_ID
)
)
assert len(candidates) == 0

def test_generate_candidates_new_nutrient(self):
product = Product(
{
"code": DEFAULT_BARCODE,
"nutriments": {
"energy-kj_100g": "100",
"energy-kj_unit": "kJ",
"fat_100g": "10",
"fat_unit": "g",
},
}
)
data = {
"nutrients": {
"energy-kj_100g": {
"entity": "energy-kj_100g",
"value": "100",
"unit": "kj",
"text": "100 kj",
"start": 0,
"end": 2,
"char_start": 0,
"char_end": 6,
},
"saturated-fat_100g": {
"entity": "saturated-fat_100g",
"value": "5",
"unit": "g",
"text": "5 g",
"start": 3,
"end": 4,
"char_start": 7,
"char_end": 10,
},
}
}
predictions = [
Prediction(
type=PredictionType.nutrient_extraction,
data=data,
barcode=DEFAULT_BARCODE,
source_image=DEFAULT_SOURCE_IMAGE,
predictor="nutrition_extractor",
predictor_version="nutrition_extractor-1.0",
automatic_processing=False,
)
]
candidates = list(
NutrientExtractionImporter.generate_candidates(
product, predictions, DEFAULT_PRODUCT_ID
)
)
assert len(candidates) == 1


class TestImportInsightsForProducts:
def test_import_insights_no_element(self, mocker):
get_product_predictions_mock = mocker.patch(
Expand Down

0 comments on commit 1eb09ef

Please sign in to comment.