first commit
This commit is contained in:
+297
-1
@@ -2,14 +2,25 @@
|
||||
ویوهای RAG — چت با استریم
|
||||
"""
|
||||
from django.http import StreamingHttpResponse
|
||||
from drf_spectacular.utils import (
|
||||
OpenApiExample,
|
||||
OpenApiResponse,
|
||||
extend_schema,
|
||||
inline_serializer,
|
||||
)
|
||||
from rest_framework import status
|
||||
from rest_framework import serializers as drf_serializers
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
import logging
|
||||
|
||||
from .chat import chat_rag_stream
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ChatView(APIView):
|
||||
"""
|
||||
چت RAG با استریم.
|
||||
@@ -17,11 +28,38 @@ class ChatView(APIView):
|
||||
sensor_uuid اجباری — هر کاربر فقط به دیتای خودش دسترسی دارد.
|
||||
"""
|
||||
|
||||
@extend_schema(
|
||||
tags=["RAG Chat"],
|
||||
summary="چت RAG با استریم",
|
||||
description="پیام کاربر را دریافت و پاسخ را به صورت استریم برمیگرداند.",
|
||||
request=inline_serializer(
|
||||
name="ChatRequest",
|
||||
fields={
|
||||
"message": drf_serializers.CharField(help_text="متن سوال کاربر"),
|
||||
"sensor_uuid": drf_serializers.CharField(help_text="شناسه یکتای سنسور"),
|
||||
},
|
||||
),
|
||||
responses={
|
||||
200: OpenApiResponse(
|
||||
description="پاسخ استریم متنی (text/plain)",
|
||||
),
|
||||
400: OpenApiResponse(
|
||||
description="پارامتر ورودی نامعتبر",
|
||||
),
|
||||
},
|
||||
examples=[
|
||||
OpenApiExample(
|
||||
"نمونه درخواست",
|
||||
value={"message": "وضعیت خاک من چطوره؟", "sensor_uuid": "550e8400-e29b-41d4-a716-446655440000"},
|
||||
request_only=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def post(self, request: Request):
|
||||
data = request.data if request.method == "POST" else request.query_params
|
||||
message = data.get("message")
|
||||
sensor_uuid = data.get("sensor_uuid")
|
||||
|
||||
logging.info("jhh")
|
||||
if not message or not isinstance(message, str):
|
||||
return Response(
|
||||
{"code": 400, "msg": "پارامتر message الزامی است."},
|
||||
@@ -44,6 +82,7 @@ class ChatView(APIView):
|
||||
{"code": 400, "msg": "sensor_uuid نباید خالی باشد."},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
|
||||
def generate():
|
||||
try:
|
||||
@@ -56,3 +95,260 @@ class ChatView(APIView):
|
||||
generate(),
|
||||
content_type="text/plain; charset=utf-8",
|
||||
)
|
||||
|
||||
|
||||
class IrrigationRecommendationView(APIView):
|
||||
"""
|
||||
توصیه آبیاری با Celery.
|
||||
POST با sensor_uuid، plant_name، growth_stage، irrigation_method_name.
|
||||
تسک در صف قرار میگیرد و task_id برگشت داده میشود.
|
||||
"""
|
||||
|
||||
@extend_schema(
|
||||
tags=["RAG Recommendations"],
|
||||
summary="درخواست توصیه آبیاری",
|
||||
description=(
|
||||
"دادههای سنسور، گیاه و روش آبیاری را دریافت کرده و یک تسک Celery "
|
||||
"برای تولید توصیه آبیاری در صف قرار میدهد."
|
||||
),
|
||||
request=inline_serializer(
|
||||
name="IrrigationRecommendationRequest",
|
||||
fields={
|
||||
"sensor_uuid": drf_serializers.CharField(help_text="شناسه یکتای سنسور (اجباری)"),
|
||||
"plant_name": drf_serializers.CharField(required=False, help_text="نام گیاه"),
|
||||
"growth_stage": drf_serializers.CharField(required=False, help_text="مرحله رشد گیاه"),
|
||||
"irrigation_method_name": drf_serializers.CharField(required=False, help_text="نام روش آبیاری"),
|
||||
"query": drf_serializers.CharField(required=False, help_text="سوال اختیاری"),
|
||||
},
|
||||
),
|
||||
responses={
|
||||
202: inline_serializer(
|
||||
name="IrrigationRecommendationResponse",
|
||||
fields={
|
||||
"code": drf_serializers.IntegerField(),
|
||||
"msg": drf_serializers.CharField(),
|
||||
"data": inline_serializer(
|
||||
name="IrrigationRecommendationData",
|
||||
fields={
|
||||
"task_id": drf_serializers.CharField(),
|
||||
"status_url": drf_serializers.CharField(),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
400: OpenApiResponse(description="پارامتر ورودی نامعتبر"),
|
||||
},
|
||||
examples=[
|
||||
OpenApiExample(
|
||||
"نمونه درخواست",
|
||||
value={
|
||||
"sensor_uuid": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"plant_name": "گوجهفرنگی",
|
||||
"growth_stage": "میوهدهی",
|
||||
"irrigation_method_name": "آبیاری قطرهای",
|
||||
},
|
||||
request_only=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def post(self, request: Request):
|
||||
from rag.tasks import irrigation_recommendation_task
|
||||
|
||||
sensor_uuid = request.data.get("sensor_uuid")
|
||||
if not sensor_uuid:
|
||||
return Response(
|
||||
{"code": 400, "msg": "پارامتر sensor_uuid الزامی است.", "data": None},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
task = irrigation_recommendation_task.delay(
|
||||
sensor_uuid=str(sensor_uuid),
|
||||
plant_name=request.data.get("plant_name"),
|
||||
growth_stage=request.data.get("growth_stage"),
|
||||
irrigation_method_name=request.data.get("irrigation_method_name"),
|
||||
query=request.data.get("query"),
|
||||
)
|
||||
return Response(
|
||||
{
|
||||
"code": 202,
|
||||
"msg": "تسک توصیه آبیاری در صف قرار گرفت.",
|
||||
"data": {
|
||||
"task_id": task.id,
|
||||
"status_url": f"/api/rag/recommend/irrigation/{task.id}/status/",
|
||||
},
|
||||
},
|
||||
status=status.HTTP_202_ACCEPTED,
|
||||
)
|
||||
|
||||
|
||||
class IrrigationRecommendationStatusView(APIView):
|
||||
"""وضعیت تسک توصیه آبیاری."""
|
||||
|
||||
@extend_schema(
|
||||
tags=["RAG Recommendations"],
|
||||
summary="وضعیت تسک توصیه آبیاری",
|
||||
description="وضعیت تسک Celery توصیه آبیاری را برمیگرداند.",
|
||||
responses={
|
||||
200: inline_serializer(
|
||||
name="IrrigationRecommendationStatusResponse",
|
||||
fields={
|
||||
"code": drf_serializers.IntegerField(),
|
||||
"msg": drf_serializers.CharField(),
|
||||
"data": inline_serializer(
|
||||
name="IrrigationRecommendationStatusData",
|
||||
fields={
|
||||
"task_id": drf_serializers.CharField(),
|
||||
"status": drf_serializers.CharField(),
|
||||
"result": drf_serializers.JSONField(required=False),
|
||||
"progress": drf_serializers.DictField(required=False),
|
||||
"error": drf_serializers.CharField(required=False),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
)
|
||||
def get(self, request, task_id):
|
||||
from celery.result import AsyncResult
|
||||
|
||||
result = AsyncResult(task_id)
|
||||
data = {"task_id": task_id, "status": result.state}
|
||||
if result.state == "PENDING":
|
||||
data["message"] = "تسک در صف یا یافت نشد."
|
||||
elif result.state == "PROGRESS":
|
||||
data["progress"] = result.info
|
||||
elif result.state == "SUCCESS":
|
||||
data["result"] = result.result
|
||||
elif result.state == "FAILURE":
|
||||
data["error"] = str(result.result)
|
||||
return Response(
|
||||
{"code": 200, "msg": "success", "data": data},
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class FertilizationRecommendationView(APIView):
|
||||
"""
|
||||
توصیه کودهی با Celery.
|
||||
POST با sensor_uuid، plant_name، growth_stage.
|
||||
تسک در صف قرار میگیرد و task_id برگشت داده میشود.
|
||||
"""
|
||||
|
||||
@extend_schema(
|
||||
tags=["RAG Recommendations"],
|
||||
summary="درخواست توصیه کودهی",
|
||||
description=(
|
||||
"دادههای سنسور و گیاه را دریافت کرده و یک تسک Celery "
|
||||
"برای تولید توصیه کودهی در صف قرار میدهد."
|
||||
),
|
||||
request=inline_serializer(
|
||||
name="FertilizationRecommendationRequest",
|
||||
fields={
|
||||
"sensor_uuid": drf_serializers.CharField(help_text="شناسه یکتای سنسور (اجباری)"),
|
||||
"plant_name": drf_serializers.CharField(required=False, help_text="نام گیاه"),
|
||||
"growth_stage": drf_serializers.CharField(required=False, help_text="مرحله رشد گیاه"),
|
||||
"query": drf_serializers.CharField(required=False, help_text="سوال اختیاری"),
|
||||
},
|
||||
),
|
||||
responses={
|
||||
202: inline_serializer(
|
||||
name="FertilizationRecommendationResponse",
|
||||
fields={
|
||||
"code": drf_serializers.IntegerField(),
|
||||
"msg": drf_serializers.CharField(),
|
||||
"data": inline_serializer(
|
||||
name="FertilizationRecommendationData",
|
||||
fields={
|
||||
"task_id": drf_serializers.CharField(),
|
||||
"status_url": drf_serializers.CharField(),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
400: OpenApiResponse(description="پارامتر ورودی نامعتبر"),
|
||||
},
|
||||
examples=[
|
||||
OpenApiExample(
|
||||
"نمونه درخواست",
|
||||
value={
|
||||
"sensor_uuid": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"plant_name": "گوجهفرنگی",
|
||||
"growth_stage": "رویشی",
|
||||
},
|
||||
request_only=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def post(self, request: Request):
|
||||
from rag.tasks import fertilization_recommendation_task
|
||||
|
||||
sensor_uuid = request.data.get("sensor_uuid")
|
||||
if not sensor_uuid:
|
||||
return Response(
|
||||
{"code": 400, "msg": "پارامتر sensor_uuid الزامی است.", "data": None},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
task = fertilization_recommendation_task.delay(
|
||||
sensor_uuid=str(sensor_uuid),
|
||||
plant_name=request.data.get("plant_name"),
|
||||
growth_stage=request.data.get("growth_stage"),
|
||||
query=request.data.get("query"),
|
||||
)
|
||||
return Response(
|
||||
{
|
||||
"code": 202,
|
||||
"msg": "تسک توصیه کودهی در صف قرار گرفت.",
|
||||
"data": {
|
||||
"task_id": task.id,
|
||||
"status_url": f"/api/rag/recommend/fertilization/{task.id}/status/",
|
||||
},
|
||||
},
|
||||
status=status.HTTP_202_ACCEPTED,
|
||||
)
|
||||
|
||||
|
||||
class FertilizationRecommendationStatusView(APIView):
|
||||
"""وضعیت تسک توصیه کودهی."""
|
||||
|
||||
@extend_schema(
|
||||
tags=["RAG Recommendations"],
|
||||
summary="وضعیت تسک توصیه کودهی",
|
||||
description="وضعیت تسک Celery توصیه کودهی را برمیگرداند.",
|
||||
responses={
|
||||
200: inline_serializer(
|
||||
name="FertilizationRecommendationStatusResponse",
|
||||
fields={
|
||||
"code": drf_serializers.IntegerField(),
|
||||
"msg": drf_serializers.CharField(),
|
||||
"data": inline_serializer(
|
||||
name="FertilizationRecommendationStatusData",
|
||||
fields={
|
||||
"task_id": drf_serializers.CharField(),
|
||||
"status": drf_serializers.CharField(),
|
||||
"result": drf_serializers.JSONField(required=False),
|
||||
"progress": drf_serializers.DictField(required=False),
|
||||
"error": drf_serializers.CharField(required=False),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
)
|
||||
def get(self, request, task_id):
|
||||
from celery.result import AsyncResult
|
||||
|
||||
result = AsyncResult(task_id)
|
||||
data = {"task_id": task_id, "status": result.state}
|
||||
if result.state == "PENDING":
|
||||
data["message"] = "تسک در صف یا یافت نشد."
|
||||
elif result.state == "PROGRESS":
|
||||
data["progress"] = result.info
|
||||
elif result.state == "SUCCESS":
|
||||
data["result"] = result.result
|
||||
elif result.state == "FAILURE":
|
||||
data["error"] = str(result.result)
|
||||
return Response(
|
||||
{"code": 200, "msg": "success", "data": data},
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user