178 lines
6.4 KiB
Python
178 lines
6.4 KiB
Python
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,
|
|
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(
|
|
"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 = []
|
|
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})
|
|
|
|
# Paginate results
|
|
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})
|
|
|
|
paginator = StructurePagination()
|
|
paginated_messages = paginator.paginate_queryset(formatted_messages, request)
|
|
return paginator.get_paginated_response(paginated_messages) |