# راهنمای پیاده‌سازی API صفحه Yield & Harvest با PCSE و RAG

این فایل برای تیم بک‌اند نوشته شده تا صفحه `yield-harvest` را با تکیه بر:

- مستند `psce_doc.txt` پروژه
- سرویس‌های موجود در `crop_simulation/`
- معماری فعلی RAG در `rag/`

به شکل قابل اتکا پیاده‌سازی کند.

نکته: فایل `psce_doc.txt` در عمل مستند PCSE است و در این سند هم با عنوان PCSE به آن اشاره می‌شود.

---

## جمع‌بندی سریع

برای این صفحه، بهترین معماری این است:

1. عددها، تاریخ‌ها، درصدها و سری‌های نمودار از PCSE و داده‌های مزرعه ساخته شوند.
2. RAG فقط برای متن‌های توضیحی، خلاصه‌سازی، و wording کاربرپسند استفاده شود.
3. RAG اجازه نداشته باشد عدد جدید، تاریخ جدید، یا KPI جدید اختراع کند.
4. یک endpoint خلاصه برای فرانت برگردانده شود:

`GET /api/yield-harvest/summary/?farm_uuid=<uuid>`

اگر لازم شد از نظر convention داخلی پروژه همه‌چیز داخل `crop_simulation` بماند، می‌توانید معادل زیر را هم نگه دارید:

`GET /api/crop-simulation/yield-harvest-summary/?farm_uuid=<uuid>`

برای فرانت فعلی، مدل summary بهتر از چند endpoint پراکنده است.

---

## چیزی که همین الان در پروژه دارید

### لایه PCSE / شبیه‌سازی

الان پروژه این اجزا را دارد:

- `crop_simulation/services.py`
- `crop_simulation/growth_simulation.py`
- `crop_simulation/harvest_prediction.py`
- `crop_simulation/yield_prediction.py`

و همین حالا از PCSE این خروجی‌ها را می‌سازید:

- `yield` از `TWSO`
- `biomass` از `TAGP`
- `leaf_area_index` از `LAI`
- `development_stage` از `DVS`
- `soil_moisture` از `SM`

این دقیقاً با چیزی که در `psce_doc.txt` آمده هم‌راستا است: PCSE برای state/rate variables و خروجی روزانه مناسب است و برای ساخت KPI، trend و harvest timing گزینه خوبی است.

### لایه RAG

الان پروژه الگوی خوبی برای سرویس‌های ترکیبی deterministic + RAG دارد:

- `rag/services/irrigation.py`
- `rag/services/fertilization.py`
- `rag/chat.py`
- `config/rag_config.yaml`

الگوی درست در این پروژه این است:

- اول عددها و تصمیم‌های پایه از منطق deterministic ساخته می‌شوند
- بعد RAG فقط متن نهایی را polish می‌کند
- در صورت خراب شدن خروجی LLM، fallback ساختاریافته دارید

برای `yield-harvest` هم باید دقیقاً همین الگو تکرار شود.

---

## اصل طراحی مهم

### چه چیزی باید deterministic باشد

این فیلدها نباید از RAG بیایند:

- `daysUntil`
- `readiness`
- `share`
- `series[].data`
- `averageReadiness`
- `predicted yield`
- `harvest date`
- هر عددی که در progress bar، chart، KPI یا sorting استفاده می‌شود

### چه چیزی می‌تواند از RAG بیاید

این فیلدها مناسب RAG هستند:

- `season_highlights_card.subtitle`
- `season_highlights_card.spotlight.caption`
- `harvest_prediction_card.description`
- `harvest_operations_card.summary`
- `steps[].note`
- badgeها و labelهای توصیفی کوتاه

### قانون طلایی

RAG باید فقط روی context قطعی زیر کار کند:

- farm details
- خروجی‌های PCSE
- داده‌های آب‌وهوا
- داده‌های سنسور
- در صورت وجود: داده کیفیت، آفات، اقتصاد، بازار

و prompt آن باید صریح بگوید:

- عدد جدید نساز
- فقط از مقادیر داده‌شده استفاده کن
- اگر داده کافی نیست، کمبود را بگو
- خروجی را در JSON معتبر برگردان

---

## پیشنهاد معماری برای این صفحه

بهترین راه این است که یک orchestrator service جدید بسازید:

- `crop_simulation/yield_harvest_summary.py`

و داخل آن چند builder کوچک داشته باشید:

- `_build_yield_prediction_block()`
- `_build_harvest_prediction_block()`
- `_build_yield_prediction_chart_block()`
- `_build_harvest_readiness_zones_block()`
- `_build_yield_quality_bands_block()`
- `_build_harvest_operations_block()`
- `_build_season_highlights_block()`

و یک facade نهایی:

- `YieldHarvestSummaryService.get_summary(farm_uuid, season_year=None, crop_name=None)`

این service باید:

1. داده مزرعه را از `farm_data.services.get_farm_details()` بگیرد.
2. خروجی شبیه‌سازی را از `CurrentFarmChartSimulator` و سرویس‌های فعلی بگیرد.
3. بلوک‌های deterministic را بسازد.
4. اگر RAG فعال بود، متن‌های narrative را enrich کند.
5. یک payload نهایی برای فرانت برگرداند.

---

## Mapping پیشنهادی هر کارت به منبع داده

| بلوک | منبع اصلی | وضعیت امکان پیاده‌سازی |
|---|---|---|
| `yield_prediction` | `crop_simulation/yield_prediction.py` + chart metrics | قابل پیاده‌سازی همین الآن |
| `harvest_prediction_card` | `crop_simulation/harvest_prediction.py` | قابل پیاده‌سازی همین الآن |
| `yield_prediction_chart` | `CurrentFarmChartSimulator` + historical baseline | نیمه‌آماده، نیاز به تصمیم درباره سری مقایسه‌ای |
| `season_highlights_card` | aggregate از بقیه بلوک‌ها + RAG | قابل پیاده‌سازی اگر بقیه بلوک‌ها حاضر باشند |
| `harvest_readiness_zones` | داده قطعه/زون + PCSE per zone | فعلاً gap داده‌ای دارد |
| `yield_quality_bands` | quality model / grading rules / lab data | فعلاً gap داده‌ای دارد |
| `harvest_operations_card` | rules + optimizer + RAG | قابل پیاده‌سازی به‌صورت اولیه |

---

## نکته مهم: همه بلوک‌ها را PCSE به‌تنهایی تولید نمی‌کند

PCSE برای این بخش‌ها خیلی مناسب است:

- زمان برداشت
- روند رشد
- عملکرد پیش‌بینی‌شده
- stage / maturity / readiness proxy
- trend chart

اما PCSE به‌صورت پیش‌فرض برای این‌ها کافی نیست:

- `بریکس`
- `گرید ممتاز / درجه یک / فرآوری`
- `پتانسیل صادرات`
- `قیمت فروش`
- `premium`
- readiness per block وقتی مدل block-level ندارید

پس برای صفحه کامل، باید سه لایه را از هم جدا ببینید:

1. `PCSE layer`: عددهای زیستی و رشد
2. `Rules/Aggregation layer`: تبدیل خروجی PCSE به KPIهای محصولی
3. `RAG layer`: توضیح، جمع‌بندی، و متن قابل نمایش

---

## طراحی endpoint پیشنهادی

### Route

پیشنهاد اصلی:

- `GET /api/yield-harvest/summary/?farm_uuid=<uuid>&season_year=1404&crop_name=wheat`

### Query params

- `farm_uuid`: اجباری
- `season_year`: اختیاری
- `crop_name`: اختیاری
- `include_narrative`: اختیاری، پیش‌فرض `true`

### چرا `include_narrative` خوب است

چون اگر RAG کند یا موقتاً غیرفعال باشد، باز هم فرانت می‌تواند با داده deterministic رندر شود.

---

## ساختار پیشنهادی response

همان envelope فعلی پروژه مناسب است:

```json
{
  "code": 200,
  "msg": "success",
  "data": {
    "farm_uuid": "11111111-1111-1111-1111-111111111111",
    "season_highlights_card": {},
    "yield_prediction": {},
    "harvest_prediction_card": {},
    "harvest_readiness_zones": {},
    "yield_quality_bands": {},
    "harvest_operations_card": {},
    "yield_prediction_chart": {}
  }
}
```

---

## پیشنهاد فنی برای ساخت هر بلوک

## 1) `yield_prediction`

### منبع

- `YieldPredictionService`
- یا مستقیم `CurrentFarmChartSimulator.simulate()`

### منطق پیشنهادی

- `predicted yield` از `TWSO`
- `harvest readiness` از `DVS` و فاصله تا maturity
- `quality score` فعلاً rule-based، نه RAG-based
- `loss risk` از ترکیب moisture/weather/pest signals اگر دارید، وگرنه با fallback ساده

### توصیه

اگر الآن فقط داده قطعی می‌خواهید:

- KPI اول را دقیق بسازید
- KPIهای دوم تا چهارم را با rules ساده و شفاف بسازید
- آن‌ها را به عنوان `estimated` در کد داخلی mark کنید

---

## 2) `harvest_prediction_card`

### منبع

- `crop_simulation/harvest_prediction.py`

### وضعیت

این بلوک تقریباً آماده است.

### توصیه

- `dateFormatted` را از serializer-ready formatter بگیرید
- `daysUntil` حتماً `number` بماند
- متن `description` اگر خواستید با RAG بهتر شود، version deterministic را هم نگه دارید

یعنی بهتر است این دو فیلد را داشته باشید:

- `description`
- `descriptionSource = "deterministic" | "rag"`

این source flag برای debugging خیلی کمک می‌کند.

---

## 3) `yield_prediction_chart`

### واقعیت فعلی

خروجی chart فعلی شما در `CurrentFarmChartSimulator` بیشتر این‌ها را می‌دهد:

- leaf count estimate
- biomass
- storage organ weight
- lai
- soil moisture

اما payload فرانت `yield-harvest` در سند شما نمودار `سال قبل / سال جاری` می‌خواهد.

### نتیجه

این بخش هنوز one-to-one با کد فعلی آماده نیست.

### راه درست

یکی از این دو مسیر را انتخاب کنید:

#### مسیر A - سریع‌تر

همان chart فعلی را به contract فرانت نزدیک کنید و فعلاً به‌جای `سال قبل/سال جاری` از:

- `عملکرد تجمعی پیش‌بینی‌شده`
- `بیوماس`

استفاده کنید.

#### مسیر B - محصولی‌تر

دو سری واقعی تولید کنید:

- `سال جاری`: از simulation جاری
- `سال قبل`: از historical scenario یا historical harvest data

اگر داده سال قبل ندارید، این سری را fake نکنید.

### توصیه نهایی

برای production بهتر است تا وقتی historical source ندارید، label سری‌ها را صادقانه تغییر دهید.

---

## 4) `harvest_readiness_zones`

### بزرگ‌ترین gap فعلی

مدل داده فعلی شما عمدتاً farm-level است:

- `SensorData`
- `center_location`
- `farm_details`

اما این کارت block-level data می‌خواهد:

- `A1`
- `A2`
- cultivar per block
- readiness per block

### نتیجه

بدون model یا source جدید برای block/zone، این کارت را نباید fake کنید.

### راه درست

یا باید یکی از این‌ها را اضافه کنید:

1. مدل `FarmBlock` یا `FarmZone`
2. چند sensor/polygon برای هر مزرعه
3. block metadata در JSON مزرعه

### پیاده‌سازی پیشنهادی

برای هر block:

1. weather/location را resolve کنید
2. crop parameters block-specific بسازید
3. یک simulation جدا اجرا کنید
4. `DVS`, `TWSO`, `SM`, `maturity date` را بگیرید
5. readiness را از rule زیر بسازید

مثال rule:

```text
readiness = clamp((current_dvs / 2.0) * 100, 0, 100)
```

یا:

```text
readiness = clamp(100 - days_until_harvest * 4, 0, 100)
```

بهتر است این rule داخل code comment شفاف توضیح داده شود.

---

## 5) `yield_quality_bands`

### نکته مهم

PCSE به‌صورت پیش‌فرض grade یا brix تولید نمی‌کند.

پس این کارت را باید از یکی از این منابع ساخت:

1. داده آزمایشگاهی
2. rule engine بر اساس moisture + disease risk + maturity + crop profile
3. مدل quality جدا

### چیزی که نباید انجام شود

این‌که RAG خودش بگوید:

- 46% گرید ممتاز
- 34% گرید یک

بدون منطق deterministic

این کار برای dashboard اشتباه است.

### پیشنهاد عملی

فاز اول:

- اگر quality data ندارید، این کارت را با flag `unavailable` برگردانید
- یا bands را از rule-based scoring بسازید و در backend صریح mark کنید که estimated هستند

مثلاً:

- `quality_score >= 85 -> premium`
- `70..84 -> grade_1`
- `< 70 -> processing`

اما این rule باید crop-specific باشد، نه universal.

---

## 6) `harvest_operations_card`

### بهترین جا برای ترکیب deterministic + RAG

این کارت candidate خیلی خوبی برای RAG است، چون:

- order و timing می‌تواند از rules و simulation بیاید
- متن summary و noteها می‌تواند از RAG بیاید

### طراحی پیشنهادی

ابتدا backend یک payload قطعی بسازد:

```json
{
  "recommended_shift_count": 2,
  "sorting_capacity_ton_per_day": 15,
  "required_workers": 12,
  "max_transfer_hours": 6,
  "priority_blocks": ["A1", "A2"],
  "reasoning": [
    "A1 readiness بالاتر دارد",
    "moisture در محدوده مناسب است"
  ]
}
```

بعد این payload را به RAG بدهید تا فقط این‌ها را تولید کند:

- `summary`
- `steps[].note`
- `steps[].status`

و حتی‌المقدور:

- `outputs[]` را deterministic نگه دارید

---

## 7) `season_highlights_card`

### بهترین روش

این کارت را از بقیه بلوک‌ها derive کنید، نه از یک منبع مستقل.

یعنی:

- `seasonLabel` از ورودی season
- `badges` از readiness/quality/risk
- `spotlight.value` از harvest window یا best sale window
- `metrics` از yield, grade, revenue estimate

### نکته

اگر هنوز economy data ندارید، فیلدهایی مثل:

- `درآمد هدف`
- `پنجره طلایی فروش`

نباید با RAG اختراع شوند.

یا باید:

- حذف شوند
- یا با `null`
- یا با fallback business rule

برگردند.

---

## پیشنهاد برای RAG service جدید

مثل `irrigation` و `fertilization` یک سرویس جدید اضافه کنید:

- `rag/services/yield_harvest.py`

و در `config/rag_config.yaml` هم service جدید تعریف کنید:

- `yield_harvest`

### نقش این سرویس

این سرویس نباید خودش KPI بسازد.

فقط باید:

- summary بنویسد
- subtitle بسازد
- operation notes تولید کند
- badge text را human-friendly کند

### ورودی پیشنهادی به RAG

```json
{
  "farm_uuid": "...",
  "plant_name": "...",
  "deterministic_metrics": {
    "predicted_yield_tons": 42.8,
    "days_until_harvest": 18,
    "readiness_avg": 84,
    "quality_score": 91,
    "loss_risk_percent": 6.5
  },
  "operations": {
    "shift_count": 2,
    "required_workers": 12,
    "max_transfer_hours": 6
  }
}
```

### خروجی پیشنهادی از RAG

فقط این بخش‌ها:

```json
{
  "season_highlights_card": {
    "subtitle": "...",
    "spotlight": {
      "caption": "..."
    },
    "badges": ["...", "..."]
  },
  "harvest_prediction_card": {
    "description": "..."
  },
  "harvest_operations_card": {
    "summary": "...",
    "steps": [
      {
        "title": "...",
        "note": "...",
        "status": "..."
      }
    ]
  }
}
```

### Rule مهم

اگر JSON RAG خراب بود:

- fallback deterministic برگردان
- endpoint fail نکند

---

## فایل‌هایی که پیشنهاد می‌شود تغییر کنند

### در `crop_simulation/`

- `crop_simulation/apps.py`
  - اضافه کردن getter برای summary service

- `crop_simulation/serializers.py`
  - serializer درخواست و پاسخ summary

- `crop_simulation/views.py`
  - view جدید برای summary

- `crop_simulation/urls.py`
  - route جدید

- `crop_simulation/yield_harvest_summary.py`
  - orchestrator اصلی

### در `Schemas/`

- `Schemas/crop_simulation_yield_harvest_summary.py`
  - contract برای مستندسازی route

- `Schemas/__init__.py`
  - register کردن contract جدید

### در `rag/`

- `rag/services/yield_harvest.py`
  - narrative enrichment

### در config

- `config/rag_config.yaml`
  - service جدید `yield_harvest`

- `config/tones/yield_harvest_tone.txt`
  - tone مخصوص summary صفحه

- در صورت نیاز:
  - `config/knowledge_base/yield_harvest/`

---

## ترتیب پیشنهادی پیاده‌سازی

### فاز 1 - سریع و قابل اتکا

فقط این بلوک‌ها را واقعی کنید:

- `yield_prediction`
- `harvest_prediction_card`
- `yield_prediction_chart`
- `harvest_operations_card` با rules ساده

و برای بقیه اگر داده ندارید:

- `null`
- یا `available: false`

برگردانید.

### فاز 2 - RAG narrative

به summary و operation notes متن کاربرپسند اضافه کنید.

### فاز 3 - block-level readiness

بعد از اضافه شدن مدل zone/block، `harvest_readiness_zones` را واقعی کنید.

### فاز 4 - quality/economy

بعد از اضافه شدن منبع quality یا market:

- `yield_quality_bands`
- revenue
- sale window

را کامل کنید.

---

## توصیه مهم درباره contract

اگر بعضی بلوک‌ها هنوز data source واقعی ندارند، بهتر است از همین حالا response را این‌طور طراحی کنید:

```json
{
  "harvest_readiness_zones": {
    "available": false,
    "reason": "block_level_data_missing",
    "averageReadiness": null,
    "blocks": []
  }
}
```

این بهتر از mock پنهان است، چون:

- فرانت می‌فهمد چرا کارت کامل نیست
- QA راحت‌تر تست می‌کند
- بعداً migration ساده‌تر می‌شود

---

## ریسک‌های اصلی

### 1. استفاده از RAG برای عددسازی

بزرگ‌ترین خطر این صفحه همین است. RAG فقط برای narrative مناسب است.

### 2. نبود داده block-level

`harvest_readiness_zones` بدون مدل block عملاً دقیق نمی‌شود.

### 3. نبود quality source

`yield_quality_bands` بدون مدل کیفیت یا rule engine crop-specific قابل اتکا نیست.

### 4. ناهماهنگی chart contract

chart فعلی backend دقیقاً همان chart مورد انتظار فرانت نیست.

---

## پیشنهاد نهایی من

اگر بخواهم برای همین repo کم‌ریسک‌ترین مسیر را انتخاب کنم:

1. یک summary service در `crop_simulation` بسازید.
2. `yield_prediction` و `harvest_prediction_card` را از سرویس‌های فعلی reuse کنید.
3. `yield_prediction_chart` را فعلاً با داده واقعی current simulation برگردانید، نه مقایسه fake سال قبل.
4. `harvest_operations_card` را با rules deterministic + optional RAG summary بسازید.
5. `season_highlights_card` را از همین بلوک‌ها aggregate کنید.
6. `harvest_readiness_zones` و `yield_quality_bands` را فقط وقتی source واقعی دارید production کنید.

این مسیر با معماری فعلی پروژه، با `psce_doc.txt`، و با pattern موجود RAG بیشترین سازگاری را دارد.

---

## یک pseudo flow پیشنهادی

```text
GET /api/yield-harvest/summary/?farm_uuid=...
  ->
load farm details
  ->
run/reuse PCSE simulation outputs
  ->
build deterministic blocks
  ->
optionally call RAG for narrative fields only
  ->
merge response
  ->
return code/msg/data
```

---

## نتیجه

برای این صفحه:

- PCSE باید موتور عددها باشد
- rules باید موتور KPIهای محصولی باشد
- RAG باید موتور متن و explanation باشد

اگر این مرزبندی رعایت شود، هم dashboard قابل اعتماد می‌شود، هم توسعه بعدی آن تمیز و قابل نگهداری می‌ماند.
