from django.core.paginator import Paginator from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated from rest_framework import status from rest_framework.response import Response from django.shortcuts import get_object_or_404 from django.db.models import Q from time import sleep import json from drf_spectacular.utils import ( extend_schema, extend_schema_view, OpenApiParameter, OpenApiExample, ) from rest_framework import serializers from rest_framework.pagination import LimitOffsetPagination from .models import ProductModel, ProductChatModel from utils.pagination import StructurePagination import openai from django.conf import settings ASSISTANT_ID = 'asst_1wOnCKncEHkOfp0FjOIz4Xkp' # Serializer for the `new_message` field in POST requests class NewMessageSerializer(serializers.Serializer): new_message = serializers.CharField( required=True, help_text="The message content to send to the chat." ) # Custom Pagination Class class StructurePagination(LimitOffsetPagination): default_limit = 10 max_limit = 100 # Documentation for the ProductChatView @extend_schema_view( get=extend_schema( summary="Retrieve messages for a product chat", parameters=[ OpenApiParameter( name="limit", description="Number of results to return per page.", required=False, type=int, default=10, ), OpenApiParameter( name="offset", description="The starting position of the results.", required=False, type=int, default=0, ), ], responses={ 200: OpenApiExample( "Chat messages retrieved", value={ "messages": [ {"sender": "user", "content": "Hello!"}, {"sender": "assistant", "content": "How can I help you?"} ] } ), }, ), post=extend_schema( summary="Send a new message in the product chat", request=NewMessageSerializer, responses={ 200: OpenApiExample( "Message sent successfully", value={ "messages": [ {"sender": "user", "content": "Hello!"}, {"sender": "assistant", "content": "How can I help you?"} ] } ), 400: OpenApiExample( "Error example", value={"detail": "پیام جدید نمی‌تواند خالی باشد"}, ), }, ), ) class ProductChatView(APIView): permission_classes = [IsAuthenticated] pagination_class = StructurePagination def get(self, request, pk): """ Retrieve all messages for a product chat. """ user = request.user product = get_object_or_404(ProductModel, id=pk) chat, created = ProductChatModel.objects.get_or_create(user=user, product=product) client = openai.OpenAI(api_key=settings.OPENAI_API_KEY) message_response = client.beta.threads.messages.list(thread_id=chat.thread) # Format messages formatted_messages = [] counter = 1 for message in message_response.data: for content in message.content: if content.type == "text" and 'this is the start of the chat greet the user this chat is about the product with given detail:' not in content.text.value: sender = 'user' if message.role == 'user' else 'ai' formatted_messages.append({'sender': sender, 'content': content.text.value, 'id': counter}) counter += 1 paginator = StructurePagination() paginated_messages = paginator.paginate_queryset(formatted_messages, request) return paginator.get_paginated_response(paginated_messages) def post(self, request, pk): """ Send a new message in the product chat. """ user = request.user product = get_object_or_404(ProductModel, id=pk) chat, created = ProductChatModel.objects.get_or_create(user=user, product=product) if created: return Response({'detail': 'چت این کاربر با این محصول هنوز ساخته نشده'}, status=status.HTTP_400_BAD_REQUEST) new_message = request.data.get('new_message', '').strip() if not new_message: return Response({'detail': 'پیام جدید نمی‌تواند خالی باشد'}, status=status.HTTP_400_BAD_REQUEST) client = openai.OpenAI(api_key=settings.OPENAI_API_KEY) # Send the user message client.beta.threads.messages.create( thread_id=chat.thread, role="user", content=new_message ) # Start the assistant's run run = client.beta.threads.runs.create(thread_id=chat.thread, assistant_id=ASSISTANT_ID) while run.status != "completed": run = client.beta.threads.runs.retrieve(thread_id=chat.thread, run_id=run.id) sleep(1) # Fetch the updated messages message_response = client.beta.threads.messages.list(thread_id=chat.thread) formatted_messages = [] for message in message_response.data: for content in message.content: if content.type == "text" and 'this is the start of the chat greet the user this chat is about the product with given detail:' not in content.text.value: sender = 'user' if message.role == 'user' else 'ai' formatted_messages.append({'sender': sender, 'content': content.text.value}) formatted_messages = formatted_messages[:2] return Response(formatted_messages, status=status.HTTP_201_CREATED)