This commit is contained in:
2026-04-27 18:02:26 +03:30
parent 7c2ec2144d
commit 190a668355
19 changed files with 193 additions and 825 deletions
+13 -21
View File
@@ -126,7 +126,7 @@ class RecommendationServiceDefaultsTests(TestCase):
self.build_irrigation_optimizer_result()
)
mock_response = Mock()
mock_response.choices = [Mock(message=Mock(content='{"sections": [{"type": "list", "title": "custom", "icon": "list", "items": ["مورد سفارشی"]}]}'))]
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_get_chat_client.return_value.chat.completions.create.return_value = mock_response
result = get_irrigation_recommendation(
@@ -135,7 +135,7 @@ class RecommendationServiceDefaultsTests(TestCase):
)
self.assertEqual(result["sections"][0]["type"], "recommendation")
self.assertEqual(result["sections"][0]["amount"], "8.0 میلی متر در هر نوبت (جمع کل 24.0 میلی متر)")
self.assertEqual(result["sections"][0]["content"], "custom")
mock_build_rag_context.assert_called_once()
mock_build_plant_text.assert_called_once_with("گوجه‌فرنگی", "میوه‌دهی")
mock_build_irrigation_method_text.assert_called_once_with("آبیاری قطره‌ای")
@@ -144,10 +144,7 @@ class RecommendationServiceDefaultsTests(TestCase):
"آبیاری قطره‌ای",
)
self.assertEqual(result["simulation_optimizer"]["engine"], "crop_simulation_heuristic")
self.assertEqual(result["mergeMetadata"]["source"], "llm_with_fallback_merge")
self.assertEqual(result["sections"][1]["provenance"]["sectionType"], "list")
self.assertEqual(result["sections"][1]["provenance"]["fieldSources"]["title"], "llm")
self.assertEqual(result["sections"][0]["provenance"]["fieldSources"]["amount"], "fallback")
self.assertEqual(result["sections"][1]["items"], ["مورد سفارشی"])
@patch("rag.services.irrigation.calculate_forecast_water_needs", return_value=[])
@patch("rag.services.irrigation.resolve_kc", return_value=0.9)
@@ -176,7 +173,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"}]}'))]
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_get_chat_client.return_value.chat.completions.create.return_value = mock_response
result = get_irrigation_recommendation(
@@ -189,7 +186,7 @@ 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]["provenance"]["fieldSources"]["content"], "llm")
self.assertEqual(result["sections"][0]["content"], "custom")
@patch("rag.services.fertilization.build_plant_text", return_value="plant text")
@patch("rag.services.fertilization.build_rag_context", return_value="")
@@ -206,7 +203,7 @@ class RecommendationServiceDefaultsTests(TestCase):
self.build_fertilization_optimizer_result()
)
mock_response = Mock()
mock_response.choices = [Mock(message=Mock(content='{"sections": [{"type": "warning", "title": "هشدار", "icon": "alert-triangle", "content": "از اختلاط نامناسب خودداری شود."}]}'))]
mock_response.choices = [Mock(message=Mock(content='{"sections": [{"type": "recommendation", "title": "برنامه", "icon": "leaf", "content": "مصرف انجام شود", "fertilizerType": "20-20-20", "amount": "45 کیلوگرم در هکتار", "applicationMethod": "کودآبیاری", "timing": "صبح", "validityPeriod": "5 روز", "expandableExplanation": "توضیح"}, {"type": "list", "title": "هشدار", "icon": "list", "items": ["مورد 1"]}, {"type": "warning", "title": "هشدار", "icon": "alert-triangle", "content": "از اختلاط نامناسب خودداری شود."}]}'))]
mock_get_chat_client.return_value.chat.completions.create.return_value = mock_response
result = get_fertilization_recommendation(
@@ -217,14 +214,13 @@ class RecommendationServiceDefaultsTests(TestCase):
self.assertEqual(result["sections"][0]["fertilizerType"], "20-20-20")
mock_build_plant_text.assert_called_once_with("گوجه‌فرنگی", "رویشی")
self.assertEqual(result["simulation_optimizer"]["engine"], "crop_simulation_heuristic")
self.assertEqual(result["sections"][2]["provenance"]["fieldSources"]["content"], "llm")
self.assertEqual(result["sections"][0]["provenance"]["fieldSources"]["fertilizerType"], "fallback")
self.assertEqual(result["sections"][2]["content"], "از اختلاط نامناسب خودداری شود.")
@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_falls_back_to_optimizer_json_when_llm_returns_invalid_payload(
def test_fertilization_recommendation_raises_when_llm_returns_invalid_payload(
self,
mock_get_chat_client,
mock_get_optimizer,
@@ -238,12 +234,8 @@ class RecommendationServiceDefaultsTests(TestCase):
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),
growth_stage="رویشی",
)
self.assertEqual(result["sections"][0]["applicationMethod"], "کودآبیاری")
self.assertEqual(result["sections"][2]["type"], "warning")
self.assertEqual(result["mergeMetadata"]["source"], "fallback_only")
self.assertFalse(result["sections"][0]["provenance"]["llmProvided"])
with self.assertRaises(ValueError):
get_fertilization_recommendation(
farm_uuid=str(self.farm_uuid),
growth_stage="رویشی",
)