# راهنمای پیاده‌سازی 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=` اگر لازم شد از نظر convention داخلی پروژه همه‌چیز داخل `crop_simulation` بماند، می‌توانید معادل زیر را هم نگه دارید: `GET /api/crop-simulation/yield-harvest-summary/?farm_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=&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 قابل اعتماد می‌شود، هم توسعه بعدی آن تمیز و قابل نگهداری می‌ماند.