UPDATE
This commit is contained in:
@@ -28,6 +28,7 @@ class RecommendationServiceDefaultsTests(TestCase):
|
||||
temperature_mean=18.0,
|
||||
)
|
||||
self.plant = Plant.objects.create(name="گوجهفرنگی")
|
||||
self.onion = Plant.objects.create(name="پیاز")
|
||||
self.irrigation_method = IrrigationMethod.objects.create(name="آبیاری قطرهای")
|
||||
self.farm_uuid = uuid.uuid4()
|
||||
self.farm = SensorData.objects.create(
|
||||
@@ -69,13 +70,22 @@ class RecommendationServiceDefaultsTests(TestCase):
|
||||
{
|
||||
"code": "protective",
|
||||
"label": "آبیاری حمایتی",
|
||||
"score": 80.0,
|
||||
"expected_yield_index": 85.0,
|
||||
"total_irrigation_mm": 28.0,
|
||||
"score": 80.0,
|
||||
"expected_yield_index": 85.0,
|
||||
"total_irrigation_mm": 28.0,
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
def build_irrigation_llm_result(self):
|
||||
return (
|
||||
'{"plan": {"frequencyPerWeek": 3, "durationMinutes": 42, "bestTimeOfDay": "اوایل صبح", '
|
||||
'"moistureLevel": 68, "warning": "بررسی شود"}, '
|
||||
'"timeline": [{"step_number": 1, "title": "بازبینی", "description": "لاین ها بررسی شوند"}], '
|
||||
'"sections": [{"type": "warning", "title": "هشدار", "icon": "alert-triangle", "content": "بررسی شود"}, '
|
||||
'{"type": "tip", "title": "نکته", "icon": "bulb", "content": "مورد سفارشی"}]}'
|
||||
)
|
||||
|
||||
def build_fertilization_optimizer_result(self):
|
||||
return {
|
||||
"engine": "crop_simulation_heuristic",
|
||||
@@ -130,7 +140,7 @@ class RecommendationServiceDefaultsTests(TestCase):
|
||||
self.build_irrigation_optimizer_result()
|
||||
)
|
||||
mock_response = Mock()
|
||||
mock_response.choices = [Mock(message=Mock(content='{"sections": [{"type": "recommendation", "title": "برنامه", "icon": "droplet", "content": "custom"}, {"type": "list", "title": "custom", "icon": "list", "items": ["مورد سفارشی"]}, {"type": "warning", "title": "هشدار", "icon": "alert-triangle", "content": "بررسی شود"}]}'))]
|
||||
mock_response.choices = [Mock(message=Mock(content=self.build_irrigation_llm_result()))]
|
||||
mock_get_chat_client.return_value.chat.completions.create.return_value = mock_response
|
||||
|
||||
result = get_irrigation_recommendation(
|
||||
@@ -138,8 +148,8 @@ class RecommendationServiceDefaultsTests(TestCase):
|
||||
growth_stage="میوهدهی",
|
||||
)
|
||||
|
||||
self.assertEqual(result["sections"][0]["type"], "recommendation")
|
||||
self.assertEqual(result["sections"][0]["content"], "custom")
|
||||
self.assertEqual(result["plan"]["frequencyPerWeek"], 3)
|
||||
self.assertEqual(result["plan"]["bestTimeOfDay"], "اوایل صبح")
|
||||
mock_build_rag_context.assert_called_once()
|
||||
mock_build_plant_text.assert_called_once_with("گوجهفرنگی", "میوهدهی")
|
||||
mock_build_irrigation_method_text.assert_called_once_with("آبیاری قطرهای")
|
||||
@@ -148,7 +158,9 @@ class RecommendationServiceDefaultsTests(TestCase):
|
||||
"آبیاری قطرهای",
|
||||
)
|
||||
self.assertEqual(result["simulation_optimizer"]["engine"], "crop_simulation_heuristic")
|
||||
self.assertEqual(result["sections"][1]["items"], ["مورد سفارشی"])
|
||||
self.assertEqual(result["timeline"][0]["title"], "بازبینی")
|
||||
self.assertEqual(result["sections"][1]["type"], "tip")
|
||||
self.assertEqual(result["water_balance"]["active_kc"], 0.9)
|
||||
|
||||
@patch("rag.services.irrigation.calculate_forecast_water_needs", return_value=[])
|
||||
@patch("rag.services.irrigation.resolve_kc", return_value=0.9)
|
||||
@@ -177,7 +189,7 @@ class RecommendationServiceDefaultsTests(TestCase):
|
||||
self.build_irrigation_optimizer_result()
|
||||
)
|
||||
mock_response = Mock()
|
||||
mock_response.choices = [Mock(message=Mock(content='{"sections": [{"type": "recommendation", "title": "test", "icon": "droplet", "content": "custom"}, {"type": "list", "title": "گام ها", "icon": "list", "items": ["مورد 1"]}, {"type": "warning", "title": "هشدار", "icon": "alert-triangle", "content": "بررسی شود"}]}'))]
|
||||
mock_response.choices = [Mock(message=Mock(content=self.build_irrigation_llm_result()))]
|
||||
mock_get_chat_client.return_value.chat.completions.create.return_value = mock_response
|
||||
|
||||
result = get_irrigation_recommendation(
|
||||
@@ -190,7 +202,43 @@ class RecommendationServiceDefaultsTests(TestCase):
|
||||
self.assertEqual(self.farm.irrigation_method_id, sprinkler.id)
|
||||
self.assertEqual(result["selected_irrigation_method"]["id"], sprinkler.id)
|
||||
mock_build_irrigation_method_text.assert_called_once_with("بارانی")
|
||||
self.assertEqual(result["sections"][0]["content"], "custom")
|
||||
self.assertEqual(result["plan"]["warning"], "بررسی شود")
|
||||
|
||||
@patch("rag.services.irrigation.calculate_forecast_water_needs", return_value=[])
|
||||
@patch("rag.services.irrigation.resolve_kc", return_value=0.9)
|
||||
@patch("rag.services.irrigation.resolve_crop_profile", return_value={})
|
||||
@patch("rag.services.irrigation.build_irrigation_method_text", return_value="method text")
|
||||
@patch("rag.services.irrigation.build_plant_text", return_value="plant text")
|
||||
@patch("rag.services.irrigation.build_rag_context", return_value="")
|
||||
@patch("rag.services.irrigation._get_optimizer")
|
||||
@patch("rag.services.irrigation.get_chat_client")
|
||||
def test_irrigation_recommendation_falls_back_to_optimizer_when_llm_returns_invalid_payload(
|
||||
self,
|
||||
mock_get_chat_client,
|
||||
mock_get_optimizer,
|
||||
_mock_build_rag_context,
|
||||
_mock_build_plant_text,
|
||||
_mock_build_irrigation_method_text,
|
||||
_mock_resolve_crop_profile,
|
||||
_mock_resolve_kc,
|
||||
_mock_calculate_forecast_water_needs,
|
||||
):
|
||||
mock_get_optimizer.return_value.optimize_irrigation.return_value = (
|
||||
self.build_irrigation_optimizer_result()
|
||||
)
|
||||
mock_response = Mock()
|
||||
mock_response.choices = [Mock(message=Mock(content="not-json"))]
|
||||
mock_get_chat_client.return_value.chat.completions.create.return_value = mock_response
|
||||
|
||||
result = get_irrigation_recommendation(
|
||||
farm_uuid=str(self.farm_uuid),
|
||||
growth_stage="میوهدهی",
|
||||
)
|
||||
|
||||
self.assertEqual(result["plan"]["frequencyPerWeek"], 3)
|
||||
self.assertEqual(result["timeline"][0]["step_number"], 1)
|
||||
self.assertEqual(result["sections"][0]["type"], "warning")
|
||||
self.assertEqual(result["simulation_optimizer"]["engine"], "crop_simulation_heuristic")
|
||||
|
||||
@patch("rag.services.fertilization.build_plant_text", return_value="plant text")
|
||||
@patch("rag.services.fertilization.build_rag_context", return_value="")
|
||||
@@ -221,6 +269,36 @@ class RecommendationServiceDefaultsTests(TestCase):
|
||||
self.assertEqual(result["simulation_optimizer"]["engine"], "crop_simulation_heuristic")
|
||||
self.assertEqual(result["data"]["application_guide"]["safety_warning"], "از اختلاط نامناسب خودداری شود.")
|
||||
|
||||
@patch("rag.services.fertilization.build_plant_text", return_value="plant text")
|
||||
@patch("rag.services.fertilization.build_rag_context", return_value="")
|
||||
@patch("rag.services.fertilization._get_optimizer")
|
||||
@patch("rag.services.fertilization.get_chat_client")
|
||||
def test_fertilization_recommendation_resolves_requested_plant_from_catalog(
|
||||
self,
|
||||
mock_get_chat_client,
|
||||
mock_get_optimizer,
|
||||
_mock_build_rag_context,
|
||||
mock_build_plant_text,
|
||||
):
|
||||
mock_get_optimizer.return_value.optimize_fertilization.return_value = (
|
||||
self.build_fertilization_optimizer_result()
|
||||
)
|
||||
mock_response = Mock()
|
||||
mock_response.choices = [Mock(message=Mock(content="not-json"))]
|
||||
mock_get_chat_client.return_value.chat.completions.create.return_value = mock_response
|
||||
|
||||
result = get_fertilization_recommendation(
|
||||
farm_uuid=str(self.farm_uuid),
|
||||
plant_name="پیاز",
|
||||
growth_stage="گلدهی",
|
||||
)
|
||||
|
||||
optimizer_call = mock_get_optimizer.return_value.optimize_fertilization.call_args.kwargs
|
||||
self.assertEqual(getattr(optimizer_call["plant"], "name", None), "پیاز")
|
||||
self.assertEqual(optimizer_call["growth_stage"], "flowering")
|
||||
mock_build_plant_text.assert_called_once_with("پیاز", "flowering")
|
||||
self.assertEqual(result["data"]["primary_recommendation"]["npk_ratio"]["label"], "20-20-20")
|
||||
|
||||
@patch("rag.services.fertilization.build_plant_text", return_value="plant text")
|
||||
@patch("rag.services.fertilization.build_rag_context", return_value="")
|
||||
@patch("rag.services.fertilization._get_optimizer")
|
||||
|
||||
Reference in New Issue
Block a user