UPDATE
This commit is contained in:
@@ -84,3 +84,12 @@ class FertilizationConfig(AppConfig):
|
||||
|
||||
def get_optimizer_defaults(self):
|
||||
return self.optimizer_defaults
|
||||
|
||||
@cached_property
|
||||
def free_text_plan_parser_service(self):
|
||||
from rag.services.fertilization_plan_parser import FertilizationPlanParserService
|
||||
|
||||
return FertilizationPlanParserService()
|
||||
|
||||
def get_free_text_plan_parser_service(self):
|
||||
return self.free_text_plan_parser_service
|
||||
|
||||
@@ -115,3 +115,37 @@ class FertilizationRecommendationResponseDataSerializer(serializers.Serializer):
|
||||
application_guide = FertilizationApplicationGuideSerializer()
|
||||
alternative_recommendations = AlternativeFertilizationRecommendationSerializer(many=True)
|
||||
sections = FertilizationSectionSerializer(many=True, required=False)
|
||||
|
||||
|
||||
class FertilizationPlanParserRequestSerializer(serializers.Serializer):
|
||||
message = serializers.CharField(required=False, allow_blank=True, help_text="توضیح آزاد کاربر درباره برنامه کودهی")
|
||||
answers = serializers.JSONField(required=False, help_text="پاسخ های تکمیلی کاربر به سوالات مرحله قبل")
|
||||
partial_plan = serializers.JSONField(required=False, help_text="داده استخراج شده مرحله قبل برای ادامه تکمیل")
|
||||
farm_uuid = serializers.CharField(required=False, allow_blank=True, help_text="شناسه مزرعه برای غنی سازی context")
|
||||
|
||||
def validate(self, attrs):
|
||||
message = (attrs.get("message") or "").strip()
|
||||
answers = attrs.get("answers")
|
||||
partial_plan = attrs.get("partial_plan")
|
||||
if not message and not isinstance(answers, dict) and not isinstance(partial_plan, dict):
|
||||
raise serializers.ValidationError(
|
||||
"حداقل یکی از message، answers یا partial_plan باید ارسال شود."
|
||||
)
|
||||
return attrs
|
||||
|
||||
|
||||
class PlanClarificationQuestionSerializer(serializers.Serializer):
|
||||
id = serializers.CharField()
|
||||
field = serializers.CharField()
|
||||
question = serializers.CharField()
|
||||
rationale = serializers.CharField(required=False, allow_blank=True)
|
||||
|
||||
|
||||
class FertilizationPlanParserResponseSerializer(serializers.Serializer):
|
||||
status = serializers.CharField()
|
||||
status_fa = serializers.CharField()
|
||||
summary = serializers.CharField()
|
||||
missing_fields = serializers.ListField(child=serializers.CharField())
|
||||
questions = PlanClarificationQuestionSerializer(many=True)
|
||||
collected_data = serializers.JSONField()
|
||||
final_plan = serializers.JSONField(required=False, allow_null=True)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import FertilizationRecommendView
|
||||
from .views import FertilizationPlanParserView, FertilizationRecommendView
|
||||
|
||||
urlpatterns = [
|
||||
path("recommend/", FertilizationRecommendView.as_view(), name="fertilization-recommend"),
|
||||
path("plan-from-text/", FertilizationPlanParserView.as_view(), name="fertilization-plan-from-text"),
|
||||
]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from django.apps import apps
|
||||
|
||||
from drf_spectacular.utils import OpenApiExample, extend_schema
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
@@ -6,6 +8,8 @@ from rest_framework.views import APIView
|
||||
from config.openapi import build_envelope_serializer, build_response
|
||||
|
||||
from .serializers import (
|
||||
FertilizationPlanParserRequestSerializer,
|
||||
FertilizationPlanParserResponseSerializer,
|
||||
FertilizationRecommendationResponseDataSerializer,
|
||||
FertilizationRecommendRequestSerializer,
|
||||
)
|
||||
@@ -20,6 +24,10 @@ FertilizationResponseSerializer = build_envelope_serializer(
|
||||
"FertilizationResponseSerializer",
|
||||
data_schema=FertilizationRecommendationResponseDataSerializer,
|
||||
)
|
||||
FertilizationPlanParserEnvelopeSerializer = build_envelope_serializer(
|
||||
"FertilizationPlanParserEnvelopeSerializer",
|
||||
data_schema=FertilizationPlanParserResponseSerializer,
|
||||
)
|
||||
|
||||
|
||||
class FertilizationRecommendView(APIView):
|
||||
@@ -147,3 +155,80 @@ class FertilizationRecommendView(APIView):
|
||||
{"code": 200, "msg": "success", "data": final_result},
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class FertilizationPlanParserView(APIView):
|
||||
@extend_schema(
|
||||
tags=["Fertilization Recommendation"],
|
||||
summary="استخراج برنامه کودهی از متن آزاد",
|
||||
description=(
|
||||
"توضیح متنی کاربر درباره برنامه کودهی را می گیرد و آن را به JSON ساختاریافته تبدیل می کند. "
|
||||
"اگر اطلاعات کافی نباشد، سوالات تکمیلی لازم را برمی گرداند تا در درخواست بعدی پاسخ داده شوند."
|
||||
),
|
||||
request=FertilizationPlanParserRequestSerializer,
|
||||
responses={
|
||||
200: build_response(
|
||||
FertilizationPlanParserEnvelopeSerializer,
|
||||
"نتیجه استخراج یا سوالات تکمیلی برنامه کودهی.",
|
||||
),
|
||||
400: build_response(
|
||||
FertilizationValidationErrorSerializer,
|
||||
"داده ورودی نامعتبر است.",
|
||||
),
|
||||
500: build_response(
|
||||
FertilizationValidationErrorSerializer,
|
||||
"خطا در پردازش برنامه کودهی.",
|
||||
),
|
||||
},
|
||||
examples=[
|
||||
OpenApiExample(
|
||||
"نمونه درخواست کامل",
|
||||
value={
|
||||
"message": "برای گندم در مرحله پنجه زنی هر 12 روز یک بار 20-20-20 به مقدار 35 کیلوگرم در هکتار از طریق کودآبیاری می دهم.",
|
||||
"farm_uuid": "11111111-1111-1111-1111-111111111111",
|
||||
},
|
||||
request_only=True,
|
||||
),
|
||||
OpenApiExample(
|
||||
"نمونه درخواست تکمیلی",
|
||||
value={
|
||||
"partial_plan": {
|
||||
"crop_name": "گندم",
|
||||
"applications": [{"fertilizer_name": "20-20-20"}],
|
||||
},
|
||||
"answers": {
|
||||
"amount": "35 کیلوگرم در هکتار",
|
||||
"timing": "هر 12 روز یک بار",
|
||||
},
|
||||
},
|
||||
request_only=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def post(self, request):
|
||||
serializer = FertilizationPlanParserRequestSerializer(data=request.data)
|
||||
if not serializer.is_valid():
|
||||
return Response(
|
||||
{"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
validated = serializer.validated_data
|
||||
service = apps.get_app_config("fertilization").get_free_text_plan_parser_service()
|
||||
try:
|
||||
result = service.parse_plan(
|
||||
message=validated.get("message", ""),
|
||||
answers=validated.get("answers"),
|
||||
partial_plan=validated.get("partial_plan"),
|
||||
farm_uuid=validated.get("farm_uuid"),
|
||||
)
|
||||
except Exception as exc:
|
||||
return Response(
|
||||
{"code": 500, "msg": f"خطا در پردازش برنامه کودهی: {exc}", "data": None},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
)
|
||||
|
||||
return Response(
|
||||
{"code": 200, "msg": "موفق", "data": result},
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user