18 KiB
Free-Text Plan Parser APIs
این فایل برای تیم فرانتاند آماده شده و دو API جدید زیر را توضیح میدهد:
POST /api/irrigation/plan-from-text/POST /api/fertilization/plan-from-text/
هدف هر دو API:
- کاربر یک متن آزاد مینویسد
- بکاند تلاش میکند برنامه آبیاری یا کودهی را به JSON ساختاریافته تبدیل کند
- اگر اطلاعات کامل باشد، JSON نهایی برمیگردد
- اگر اطلاعات ناقص باشد، API سوالهای تکمیلی برمیگرداند
- فرانتاند سوالها را از کاربر میپرسد و پاسخها را دوباره برای API میفرستد
رفتار کلی هر دو API
هر دو endpoint یک flow یکسان دارند:
- کاربر متن آزاد اولیه را میفرستد
- اگر متن کامل باشد:
status = "completed"final_planبرمیگردد
- اگر متن ناقص باشد:
status = "needs_clarification"missing_fieldsبرمیگرددquestionsبرمیگردد
- فرانتاند پاسخ کاربر به سوالها را جمع میکند
- دوباره همان endpoint را با
answersوpartial_planصدا میزند - این روند تا ساخته شدن
final_planادامه پیدا میکند
الگوی کلی response
هر دو API از envelope استاندارد استفاده میکنند:
{
"code": 200,
"msg": "موفق",
"data": {}
}
معنی فیلدهای envelope
| فیلد | نوع | توضیح |
|---|---|---|
code |
number | کد منطقی پاسخ |
msg |
string | پیام کوتاه پاسخ |
data |
object | داده اصلی API |
1) API استخراج برنامه آبیاری
Endpoint
POST /api/irrigation/plan-from-text/
کاربرد
این API متن آزاد کاربر درباره برنامه آبیاری را به JSON ساختاریافته تبدیل میکند.
Request Body
هر سه فیلد زیر اختیاری هستند، اما حداقل یکی از اینها باید ارسال شود:
messageanswerspartial_plan
ساختار request
{
"message": "برای گوجه فرنگی با آبیاری قطره ای هر سه روز یک بار صبح زود 25 دقیقه آبیاری می کنم و حدود 18 لیتر برای هر بوته می دهم.",
"answers": {
"growth_stage": "گلدهی"
},
"partial_plan": {
"crop_name": "گوجه فرنگی",
"irrigation_method": "قطره ای"
},
"farm_uuid": "11111111-1111-1111-1111-111111111111"
}
فیلدهای request
| فیلد | نوع | اجباری | توضیح |
|---|---|---|---|
message |
string | خیر | متن آزاد کاربر |
answers |
object | خیر | پاسخهای تکمیلی کاربر به سوالهایی که قبلا API داده |
partial_plan |
object | خیر | خروجی مرحله قبل برای ادامه تکمیل |
farm_uuid |
string | خیر | برای غنیسازی context مزرعه در RAG |
قانون validation
اگر هیچکدام از message، answers یا partial_plan ارسال نشوند:
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"non_field_errors": [
"حداقل یکی از message، answers یا partial_plan باید ارسال شود."
]
}
}
پاسخ موفق - حالت تکمیل شده
وقتی همه اطلاعات لازم موجود باشد:
{
"code": 200,
"msg": "موفق",
"data": {
"status": "completed",
"status_fa": "تکمیل شد",
"summary": "برنامه آبیاری برای گوجهفرنگی به روش قطرهای هر سه روز یکبار صبح زود به مدت 25 دقیقه اجرا میشود.",
"missing_fields": [],
"questions": [],
"collected_data": {
"crop_name": "گوجهفرنگی",
"growth_stage": "گلدهی",
"irrigation_method": "قطرهای",
"water_amount_per_event": "18 لیتر برای هر بوته",
"duration_minutes": 25,
"frequency_text": "هر سه روز یکبار",
"interval_days": 3,
"preferred_time_of_day": "صبح زود",
"start_date": "از امروز",
"target_area": "کل مزرعه",
"trigger_conditions": [],
"notes": []
},
"final_plan": {
"crop_name": "گوجهفرنگی",
"growth_stage": "گلدهی",
"irrigation_method": "قطرهای",
"water_amount_per_event": "18 لیتر برای هر بوته",
"duration_minutes": 25,
"frequency_text": "هر سه روز یکبار",
"interval_days": 3,
"preferred_time_of_day": "صبح زود",
"start_date": "از امروز",
"target_area": "کل مزرعه",
"trigger_conditions": [],
"notes": []
}
}
}
فیلدهای data
| فیلد | نوع | توضیح |
|---|---|---|
status |
string | یکی از completed یا needs_clarification |
status_fa |
string | نسخه فارسی وضعیت |
summary |
string | خلاصه قابل نمایش برای کاربر |
missing_fields |
array[string] | فیلدهای ناقص |
questions |
array[object] | سوالهای تکمیلی |
collected_data |
object | دادهای که تا الان از متن و جوابها استخراج شده |
final_plan |
object/null | برنامه نهایی؛ فقط در حالت completed |
فیلدهای collected_data و final_plan
| فیلد | نوع | توضیح |
|---|---|---|
crop_name |
string | نام محصول |
growth_stage |
string | مرحله رشد محصول |
irrigation_method |
string | روش آبیاری |
water_amount_per_event |
string | مقدار آب هر نوبت |
duration_minutes |
number | مدت هر نوبت آبیاری به دقیقه |
frequency_text |
string | توصیف متنی فاصله آبیاری |
interval_days |
number | فاصله آبیاری بر حسب روز |
preferred_time_of_day |
string | زمان مناسب اجرای آبیاری |
start_date |
string | زمان یا تاریخ شروع برنامه |
target_area |
string | محدوده هدف برنامه |
trigger_conditions |
array[string] | شرایط تریگر اختیاری |
notes |
array[string] | نکات تکمیلی |
پاسخ موفق - حالت نیاز به سوال تکمیلی
اگر اطلاعات کامل نباشد:
{
"code": 200,
"msg": "موفق",
"data": {
"status": "needs_clarification",
"status_fa": "نیازمند پرسش تکمیلی",
"summary": "اطلاعات برنامه آبیاری برای ساخت JSON نهایی کافی نیست و به چند پاسخ تکمیلی نیاز است.",
"missing_fields": [
"growth_stage",
"start_date",
"target_area"
],
"questions": [
{
"id": "growth_stage",
"field": "growth_stage",
"question": "محصول الان در چه مرحله رشدی قرار دارد؟",
"rationale": "مرحله رشد برای کامل شدن برنامه لازم است."
},
{
"id": "start_date",
"field": "start_date",
"question": "این برنامه از چه تاریخی یا از چه زمانی باید شروع شود؟",
"rationale": "زمان شروع برنامه هنوز مشخص نشده است."
},
{
"id": "target_area",
"field": "target_area",
"question": "این برنامه برای کل مزرعه است یا بخش/ناحیه خاصی از مزرعه؟",
"rationale": "محدوده اجرای برنامه باید مشخص باشد."
}
],
"collected_data": {
"crop_name": "گوجهفرنگی",
"growth_stage": null,
"irrigation_method": "قطرهای",
"water_amount_per_event": "18 لیتر برای هر بوته",
"duration_minutes": 25,
"frequency_text": "هر سه روز یکبار",
"interval_days": 3,
"preferred_time_of_day": "صبح زود",
"start_date": null,
"target_area": null,
"trigger_conditions": [],
"notes": []
},
"final_plan": null
}
}
ساختار questions
| فیلد | نوع | توضیح |
|---|---|---|
id |
string | شناسه سوال |
field |
string | فیلدی که این سوال برای آن پرسیده شده |
question |
string | متن سوال برای نمایش به کاربر |
rationale |
string | توضیح کوتاه برای اینکه چرا این سوال لازم است |
flow پیشنهادی فرانتاند برای آبیاری
مرحله 1
کاربر متن آزاد میفرستد:
{
"message": "برای گوجه فرنگی هر سه روز یک بار آبیاری می کنم."
}
مرحله 2
اگر status = needs_clarification بود:
- سوالها را از
data.questionsبه کاربر نمایش بده - پاسخها را جمع کن
مرحله 3
درخواست تکمیلی بزن:
{
"partial_plan": {
"crop_name": "گوجه فرنگی",
"growth_stage": null,
"irrigation_method": null,
"water_amount_per_event": null,
"duration_minutes": null,
"frequency_text": "هر سه روز یک بار",
"interval_days": 3,
"preferred_time_of_day": null,
"start_date": null,
"target_area": null,
"trigger_conditions": [],
"notes": []
},
"answers": {
"growth_stage": "گلدهی",
"irrigation_method": "قطره ای",
"water_amount_per_event": "18 لیتر برای هر بوته",
"duration_minutes": 25,
"preferred_time_of_day": "صبح زود",
"start_date": "از امروز",
"target_area": "کل مزرعه"
}
}
مرحله 4
اگر status = completed شد:
- از
data.final_planبه عنوان JSON نهایی استفاده کن
2) API استخراج برنامه کودهی
Endpoint
POST /api/fertilization/plan-from-text/
کاربرد
این API متن آزاد کاربر درباره برنامه کودهی را به JSON ساختاریافته تبدیل میکند.
Request Body
{
"message": "برای گندم در مرحله پنجه زنی هر 12 روز یک بار 20-20-20 به مقدار 35 کیلوگرم در هکتار از طریق کودآبیاری می دهم.",
"answers": {
"timing": "هر 12 روز یک بار"
},
"partial_plan": {
"crop_name": "گندم"
},
"farm_uuid": "11111111-1111-1111-1111-111111111111"
}
فیلدهای request
| فیلد | نوع | اجباری | توضیح |
|---|---|---|---|
message |
string | خیر | متن آزاد کاربر |
answers |
object | خیر | پاسخهای تکمیلی کاربر |
partial_plan |
object | خیر | داده استخراج شده مرحله قبل |
farm_uuid |
string | خیر | برای context مزرعه |
validation error
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"non_field_errors": [
"حداقل یکی از message، answers یا partial_plan باید ارسال شود."
]
}
}
پاسخ موفق - حالت تکمیل شده
{
"code": 200,
"msg": "موفق",
"data": {
"status": "completed",
"status_fa": "تکمیل شد",
"summary": "برنامه کودهی برای گندم در مرحله پنجه زنی با کود 20-20-20 به صورت کودآبیاری هر 12 روز یک بار اجرا می شود.",
"missing_fields": [],
"questions": [],
"collected_data": {
"crop_name": "گندم",
"growth_stage": "پنجه زنی",
"objective": "تقویت رشد رویشی",
"applications": [
{
"fertilizer_name": "کود کامل 20-20-20",
"formula": "20-20-20",
"amount": "35 کیلوگرم در هکتار",
"application_method": "کودآبیاری",
"timing": "هر 12 روز یک بار",
"interval_days": 12,
"purpose": "تقویت رشد رویشی"
}
],
"notes": []
},
"final_plan": {
"crop_name": "گندم",
"growth_stage": "پنجه زنی",
"objective": "تقویت رشد رویشی",
"applications": [
{
"fertilizer_name": "کود کامل 20-20-20",
"formula": "20-20-20",
"amount": "35 کیلوگرم در هکتار",
"application_method": "کودآبیاری",
"timing": "هر 12 روز یک بار",
"interval_days": 12,
"purpose": "تقویت رشد رویشی"
}
],
"notes": []
}
}
}
فیلدهای collected_data و final_plan
| فیلد | نوع | توضیح |
|---|---|---|
crop_name |
string | نام محصول |
growth_stage |
string | مرحله رشد |
objective |
string/null | هدف برنامه |
applications |
array[object] | لیست نوبتها یا اقلام کودی |
notes |
array[string] | نکات تکمیلی |
ساختار هر application
| فیلد | نوع | توضیح |
|---|---|---|
fertilizer_name |
string | نام کود |
formula |
string | فرمول یا آنالیز کود |
amount |
string | مقدار مصرف |
application_method |
string | روش مصرف |
timing |
string | زمانبندی مصرف |
interval_days |
number | فاصله بین نوبتها |
purpose |
string/null | هدف آن نوبت |
پاسخ موفق - حالت نیاز به سوال تکمیلی
{
"code": 200,
"msg": "موفق",
"data": {
"status": "needs_clarification",
"status_fa": "نیازمند پرسش تکمیلی",
"summary": "اطلاعات برنامه کودهی برای ساخت JSON نهایی کافی نیست و به چند پاسخ تکمیلی نیاز است.",
"missing_fields": [
"growth_stage",
"formula",
"interval_days"
],
"questions": [
{
"id": "growth_stage",
"field": "growth_stage",
"question": "محصول الان در چه مرحله رشدی قرار دارد؟",
"rationale": "مرحله رشد برای تکمیل برنامه لازم است."
},
{
"id": "formula",
"field": "formula",
"question": "فرمول یا آنالیز کود چیست؟ مثلا 20-20-20.",
"rationale": "ترکیب دقیق کود هنوز مشخص نشده است."
},
{
"id": "interval_days",
"field": "interval_days",
"question": "فاصله بین نوبت های مصرف کود چند روز است؟",
"rationale": "عدد فاصله بین نوبت ها برای JSON نهایی لازم است."
}
],
"collected_data": {
"crop_name": "گندم",
"growth_stage": null,
"objective": null,
"applications": [
{
"fertilizer_name": "کود کامل",
"formula": null,
"amount": "35 کیلوگرم در هکتار",
"application_method": "کودآبیاری",
"timing": "هر چند وقت یک بار",
"interval_days": null,
"purpose": null
}
],
"notes": []
},
"final_plan": null
}
}
flow پیشنهادی فرانتاند برای کودهی
درخواست اولیه
{
"message": "برای گندم از کود کامل استفاده می کنم."
}
اگر incomplete بود
- از
questionsسوالها را بگیر - در UI نمایش بده
- پاسخها را جمع کن
درخواست تکمیلی
{
"partial_plan": {
"crop_name": "گندم",
"growth_stage": null,
"objective": null,
"applications": [
{
"fertilizer_name": "کود کامل",
"formula": null,
"amount": null,
"application_method": null,
"timing": null,
"interval_days": null,
"purpose": null
}
],
"notes": []
},
"answers": {
"growth_stage": "پنجه زنی",
"formula": "20-20-20",
"amount": "35 کیلوگرم در هکتار",
"application_method": "کودآبیاری",
"timing": "هر 12 روز یک بار",
"interval_days": 12
}
}
اگر complete شد
- از
final_planاستفاده کن
نکات مهم برای فرانتاند
1. به status تکیه کنید
مهمترین فیلد برای کنترل flow:
completedneeds_clarification
2. اگر needs_clarification بود
باید:
questionsرا به کاربر نمایش دهیدpartial_planرا نگه دارید- پاسخهای کاربر را در
answersارسال کنید
3. اگر completed بود
باید:
final_planرا به عنوان نسخه نهایی برنامه ذخیره یا نمایش دهید
4. collected_data همیشه مهم است
حتی اگر برنامه ناقص باشد، collected_data نشان میدهد سیستم تا این لحظه چه چیزهایی را فهمیده است.
5. null در حالت ناقص طبیعی است
در حالت needs_clarification ممکن است بعضی فیلدهای collected_data null باشند.
اما در حالت completed نباید فیلدهای اصلی ناقص باشند.
6. فرانتاند بهتر است سوالها را به صورت step-by-step بپرسد
پیشنهاد:
- سوال اول را نشان بده
- جواب را بگیر
- همه جوابها را در
answersجمع کن - دوباره API را صدا بزن
جمعبندی تفاوت دو API
| API | موضوع | خروجی نهایی |
|---|---|---|
/api/irrigation/plan-from-text/ |
استخراج برنامه آبیاری | final_plan با ساختار آبیاری |
/api/fertilization/plan-from-text/ |
استخراج برنامه کودهی | final_plan با ساختار کودهی |
مسیر فایل
این داکیومنت در این مسیر ذخیره شده:
docs/irrigation_fertilization_plan_parser_apis.md