first commit
This commit is contained in:
+119
-7
@@ -1,14 +1,15 @@
|
||||
"""
|
||||
ساخت دیتای خاک کاربر از sensor_data و soil_data — Schema-agnostic
|
||||
ساخت دیتای خاک و هواشناسی کاربر از sensor_data، location_data و weather — Schema-agnostic
|
||||
هر سنسور = یک کاربر. شناسایی با uuid_sensor.
|
||||
|
||||
مدلهای Django داخل توابع import میشوند تا از AppRegistryNotReady جلوگیری شود.
|
||||
"""
|
||||
from datetime import date
|
||||
|
||||
from django.db.models import Model
|
||||
|
||||
|
||||
# فیلدهایی که در متن embed نباید بیایند (شناسهها، رابطهها)
|
||||
EXCLUDE_FIELD_NAMES = {"id", "created_at", "updated_at", "task_id", "recorded_at"}
|
||||
EXCLUDE_FIELD_NAMES = {"id", "created_at", "updated_at", "task_id", "recorded_at", "fetched_at"}
|
||||
|
||||
|
||||
def _model_to_data_fields(instance: Model, exclude: set[str] | None = None) -> dict:
|
||||
@@ -43,7 +44,7 @@ def build_user_soil_text(sensor_uuid: str) -> str | None:
|
||||
متن متنی قابل چانک، یا None اگر سنسور یافت نشد.
|
||||
"""
|
||||
from sensor_data.models import SensorData
|
||||
from soil_data.models import SoilDepthData
|
||||
from location_data.models import SoilDepthData
|
||||
|
||||
try:
|
||||
sensor = SensorData.objects.select_related("location").get(
|
||||
@@ -89,7 +90,7 @@ def build_user_soil_text(sensor_uuid: str) -> str | None:
|
||||
if depth_parts:
|
||||
parts.append("دادههای خاک:\n" + "\n".join(depth_parts))
|
||||
|
||||
return "\n\n".join(parts) if parts else None
|
||||
return "\n\n".join(parts) if len(parts) > 1 else None
|
||||
|
||||
|
||||
def get_all_sensor_uuids() -> list[str]:
|
||||
@@ -102,11 +103,54 @@ def get_all_sensor_uuids() -> list[str]:
|
||||
]
|
||||
|
||||
|
||||
def build_user_weather_text(sensor_uuid: str) -> str | None:
|
||||
"""
|
||||
ساخت متن هواشناسی قابل embed برای یک سنسور (کاربر).
|
||||
پیشبینی ۷ روز آینده از WeatherForecast خوانده میشود.
|
||||
|
||||
Returns:
|
||||
متن فارسی ساختاریافته، یا None اگر دادهای نباشد.
|
||||
"""
|
||||
from sensor_data.models import SensorData
|
||||
from weather.models import WeatherForecast
|
||||
|
||||
try:
|
||||
sensor = SensorData.objects.select_related("location").get(
|
||||
uuid_sensor=sensor_uuid
|
||||
)
|
||||
except SensorData.DoesNotExist:
|
||||
return None
|
||||
|
||||
loc = sensor.location
|
||||
forecasts = (
|
||||
WeatherForecast.objects.filter(
|
||||
location=loc,
|
||||
forecast_date__gte=date.today(),
|
||||
)
|
||||
.order_by("forecast_date")[:7]
|
||||
)
|
||||
if not forecasts:
|
||||
return None
|
||||
|
||||
parts: list[str] = []
|
||||
parts.append(f"پیشبینی هواشناسی سنسور {sensor_uuid} (موقعیت: {loc.latitude}, {loc.longitude})")
|
||||
|
||||
for fc in forecasts:
|
||||
fc_data = _model_to_data_fields(
|
||||
fc, exclude={"location", "location_id", "forecast_date"}
|
||||
)
|
||||
lines = [f" {k}: {v}" for k, v in sorted(fc_data.items())]
|
||||
day_text = f" تاریخ {fc.forecast_date}:\n" + "\n".join(lines)
|
||||
parts.append(day_text)
|
||||
|
||||
return "\n\n".join(parts) if len(parts) > 1 else None
|
||||
|
||||
|
||||
def load_user_sources() -> list[tuple[str, str]]:
|
||||
"""
|
||||
بارگذاری منابع دیتای کاربران از DB.
|
||||
بارگذاری منابع دیتای کاربران از DB (خاک + هواشناسی).
|
||||
Returns: [(source_id, content), ...]
|
||||
source_id = user:{sensor_uuid}
|
||||
source_id = user:{uuid} یا weather:{uuid}
|
||||
"""
|
||||
uuids = get_all_sensor_uuids()
|
||||
sources: list[tuple[str, str]] = []
|
||||
@@ -114,4 +158,72 @@ def load_user_sources() -> list[tuple[str, str]]:
|
||||
text = build_user_soil_text(str(uid))
|
||||
if text and text.strip():
|
||||
sources.append((f"user:{uid}", text))
|
||||
weather_text = build_user_weather_text(str(uid))
|
||||
if weather_text and weather_text.strip():
|
||||
sources.append((f"weather:{uid}", weather_text))
|
||||
return sources
|
||||
|
||||
|
||||
def build_plant_text(plant_name: str, growth_stage: str) -> str | None:
|
||||
"""
|
||||
ساخت متن اطلاعات گیاه از جدول Plant برای استفاده در context LLM.
|
||||
"""
|
||||
from plant.models import Plant
|
||||
|
||||
plant = Plant.objects.filter(name=plant_name).first()
|
||||
if not plant:
|
||||
return None
|
||||
|
||||
lines = [
|
||||
f"نام گیاه: {plant.name}",
|
||||
f"مرحله رشد: {growth_stage}",
|
||||
]
|
||||
if plant.light:
|
||||
lines.append(f"نور مورد نیاز: {plant.light}")
|
||||
if plant.watering:
|
||||
lines.append(f"آبیاری: {plant.watering}")
|
||||
if plant.soil:
|
||||
lines.append(f"خاک مناسب: {plant.soil}")
|
||||
if plant.temperature:
|
||||
lines.append(f"دمای مناسب: {plant.temperature}")
|
||||
if plant.planting_season:
|
||||
lines.append(f"فصل کاشت: {plant.planting_season}")
|
||||
if plant.harvest_time:
|
||||
lines.append(f"زمان برداشت: {plant.harvest_time}")
|
||||
if plant.spacing:
|
||||
lines.append(f"فاصله کاشت: {plant.spacing}")
|
||||
if plant.fertilizer:
|
||||
lines.append(f"کود مناسب: {plant.fertilizer}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def build_irrigation_method_text(method_name: str) -> str | None:
|
||||
"""
|
||||
ساخت متن مشخصات روش آبیاری از جدول IrrigationMethod برای استفاده در context LLM.
|
||||
"""
|
||||
from irrigation.models import IrrigationMethod
|
||||
|
||||
method = IrrigationMethod.objects.filter(name=method_name).first()
|
||||
if not method:
|
||||
return None
|
||||
|
||||
lines = [f"روش آبیاری: {method.name}"]
|
||||
if method.category:
|
||||
lines.append(f"دستهبندی: {method.category}")
|
||||
if method.description:
|
||||
lines.append(f"توضیحات: {method.description}")
|
||||
if method.water_efficiency_percent is not None:
|
||||
lines.append(f"راندمان مصرف آب: {method.water_efficiency_percent}%")
|
||||
if method.water_pressure_required:
|
||||
lines.append(f"فشار مورد نیاز: {method.water_pressure_required}")
|
||||
if method.flow_rate:
|
||||
lines.append(f"دبی جریان: {method.flow_rate}")
|
||||
if method.coverage_area:
|
||||
lines.append(f"مساحت پوشش: {method.coverage_area}")
|
||||
if method.soil_type:
|
||||
lines.append(f"نوع خاک مناسب: {method.soil_type}")
|
||||
if method.climate_suitability:
|
||||
lines.append(f"اقلیم مناسب: {method.climate_suitability}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
Reference in New Issue
Block a user