UPDATE
This commit is contained in:
@@ -137,7 +137,7 @@ def _risk_level(score: float) -> str:
|
||||
return "low"
|
||||
|
||||
|
||||
def _build_risk_fallback(farm_details: dict[str, Any], plant_name: str | None, growth_stage: str | None) -> dict[str, Any]:
|
||||
def _build_risk_context(farm_details: dict[str, Any], plant_name: str | None, growth_stage: str | None) -> dict[str, Any]:
|
||||
risk = _weather_risk_summary(farm_details)
|
||||
disease_level = _risk_level(risk["fungal_score"])
|
||||
pest_level = _risk_level(risk["pest_score"])
|
||||
@@ -199,24 +199,44 @@ def _build_risk_fallback(farm_details: dict[str, Any], plant_name: str | None, g
|
||||
}
|
||||
|
||||
|
||||
def _build_detection_fallback(images: list[dict[str, str]], plant_name: str | None) -> dict[str, Any]:
|
||||
return {
|
||||
"has_issue": False,
|
||||
"category": "unknown",
|
||||
"confidence": 0.2,
|
||||
"severity": "low",
|
||||
"summary": "تحلیل خودکار تصویر انجام نشد یا برای نتیجه قطعی داده کافی نبود.",
|
||||
"detected_signs": [],
|
||||
"possible_causes": ["کیفیت یا زاویه تصویر برای تشخیص کافی نیست"],
|
||||
"immediate_actions": [
|
||||
"یک تصویر نزدیک تر از برگ و ساقه ارسال شود.",
|
||||
"در صورت مشاهده گسترش علائم، بازدید میدانی انجام شود.",
|
||||
],
|
||||
"reasoning": [
|
||||
f"تعداد تصاویر دریافتی: {len(images)}",
|
||||
f"نام گیاه: {plant_name or 'نامشخص'}",
|
||||
],
|
||||
def _validate_detection_result(parsed: dict[str, Any]) -> dict[str, Any]:
|
||||
required_keys = {
|
||||
"has_issue",
|
||||
"category",
|
||||
"confidence",
|
||||
"severity",
|
||||
"summary",
|
||||
"detected_signs",
|
||||
"possible_causes",
|
||||
"immediate_actions",
|
||||
"reasoning",
|
||||
}
|
||||
missing = [key for key in required_keys if key not in parsed]
|
||||
if missing:
|
||||
raise ValueError(
|
||||
"Pest disease detection response is missing required fields: "
|
||||
+ ", ".join(missing)
|
||||
)
|
||||
return parsed
|
||||
|
||||
|
||||
def _validate_risk_result(parsed: dict[str, Any]) -> dict[str, Any]:
|
||||
required_keys = {
|
||||
"summary",
|
||||
"forecast_window",
|
||||
"overall_risk",
|
||||
"disease_risk",
|
||||
"pest_risk",
|
||||
"key_drivers",
|
||||
"recommended_actions",
|
||||
}
|
||||
missing = [key for key in required_keys if key not in parsed]
|
||||
if missing:
|
||||
raise ValueError(
|
||||
"Pest disease risk response is missing required fields: "
|
||||
+ ", ".join(missing)
|
||||
)
|
||||
return parsed
|
||||
|
||||
|
||||
def _build_detection_messages(
|
||||
@@ -320,29 +340,11 @@ def get_pest_disease_detection(
|
||||
_complete_audit_log(audit_log, raw)
|
||||
except Exception as exc:
|
||||
logger.error("Pest disease detection failed for %s: %s", farm_uuid, exc)
|
||||
fallback = _build_detection_fallback(normalized_images, resolved_plant_name)
|
||||
_fail_audit_log(audit_log, str(exc), json.dumps(fallback, ensure_ascii=False))
|
||||
return {
|
||||
**fallback,
|
||||
"farm_uuid": farm_uuid,
|
||||
"knowledge_base": KB_NAME,
|
||||
"tone_file": service.tone_file,
|
||||
"raw_response": None,
|
||||
}
|
||||
_fail_audit_log(audit_log, str(exc))
|
||||
raise RuntimeError(f"Pest disease detection failed for farm {farm_uuid}.") from exc
|
||||
|
||||
if not parsed:
|
||||
parsed = _build_detection_fallback(normalized_images, resolved_plant_name)
|
||||
parsed.setdefault("has_issue", parsed.get("category") not in {"no_issue", "unknown"})
|
||||
parsed.setdefault("category", "unknown")
|
||||
parsed.setdefault("confidence", 0.4)
|
||||
parsed.setdefault("severity", "low")
|
||||
parsed.setdefault("detected_signs", [])
|
||||
parsed.setdefault("possible_causes", [])
|
||||
parsed.setdefault("immediate_actions", [])
|
||||
parsed.setdefault("reasoning", [])
|
||||
parsed = _validate_detection_result(parsed)
|
||||
parsed["farm_uuid"] = farm_uuid
|
||||
parsed["knowledge_base"] = KB_NAME
|
||||
parsed["tone_file"] = service.tone_file
|
||||
parsed["raw_response"] = raw
|
||||
return parsed
|
||||
|
||||
@@ -358,7 +360,7 @@ def get_pest_disease_risk(
|
||||
service, client, model = _build_service_client(cfg)
|
||||
farm_details = _load_farm_or_error(farm_uuid)
|
||||
resolved_plant_name = plant_name or (farm_details.get("plants") or [{}])[0].get("name")
|
||||
fallback = _build_risk_fallback(farm_details, resolved_plant_name, growth_stage)
|
||||
risk_context = _build_risk_context(farm_details, resolved_plant_name, growth_stage)
|
||||
user_query = query or "ریسک آفات و بیماری این مزرعه را برای چند روز آینده پیش بینی کن."
|
||||
plant_text = build_plant_text(resolved_plant_name, growth_stage or "") if resolved_plant_name else ""
|
||||
rag_context = build_rag_context(
|
||||
@@ -374,7 +376,7 @@ def get_pest_disease_risk(
|
||||
cfg=cfg,
|
||||
query=user_query,
|
||||
rag_context=rag_context,
|
||||
structured_context=fallback,
|
||||
structured_context=risk_context,
|
||||
plant_text=plant_text or "",
|
||||
)
|
||||
audit_log = _create_audit_log(
|
||||
@@ -392,24 +394,10 @@ def get_pest_disease_risk(
|
||||
_complete_audit_log(audit_log, raw)
|
||||
except Exception as exc:
|
||||
logger.error("Pest disease risk prediction failed for %s: %s", farm_uuid, exc)
|
||||
_fail_audit_log(audit_log, str(exc), json.dumps(fallback, ensure_ascii=False))
|
||||
fallback["farm_uuid"] = farm_uuid
|
||||
fallback["knowledge_base"] = KB_NAME
|
||||
fallback["tone_file"] = service.tone_file
|
||||
fallback["raw_response"] = None
|
||||
return fallback
|
||||
_fail_audit_log(audit_log, str(exc))
|
||||
raise RuntimeError(f"Pest disease risk prediction failed for farm {farm_uuid}.") from exc
|
||||
|
||||
if not parsed:
|
||||
parsed = fallback
|
||||
parsed.setdefault("summary", fallback["summary"])
|
||||
parsed.setdefault("forecast_window", fallback["forecast_window"])
|
||||
parsed.setdefault("overall_risk", fallback["overall_risk"])
|
||||
parsed.setdefault("disease_risk", fallback["disease_risk"])
|
||||
parsed.setdefault("pest_risk", fallback["pest_risk"])
|
||||
parsed.setdefault("key_drivers", fallback["key_drivers"])
|
||||
parsed.setdefault("recommended_actions", fallback["recommended_actions"])
|
||||
parsed = _validate_risk_result(parsed)
|
||||
parsed["farm_uuid"] = farm_uuid
|
||||
parsed["knowledge_base"] = KB_NAME
|
||||
parsed["tone_file"] = service.tone_file
|
||||
parsed["raw_response"] = raw
|
||||
return parsed
|
||||
|
||||
Reference in New Issue
Block a user