diff --git a/backend/api/urls.py b/backend/api/urls.py index 15925a66..088e3d97 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -1,12 +1,12 @@ from django.urls import path from users.views import login, register_user -from flashcards.views import generate_mock_flashcard -from documents.views import create_flashcards +from flashcards.views import create_flashcards, generate_mock_flashcard urlpatterns = [ path("create-user/", register_user, name="create-user"), path("login/", login, name="login"), path("generate-mock-flashcard/", generate_mock_flashcard, name="generate-mock-flashcards"), path("create-flashcards/", create_flashcards, name="create-flashcards"), + path("generate-mock-flashcard/", generate_mock_flashcard, name="generate-mock-flashcard"), ] diff --git a/backend/config.py b/backend/config.py index 7868220c..239ae161 100644 --- a/backend/config.py +++ b/backend/config.py @@ -9,7 +9,7 @@ #a class for defining the config variables class Config(): - def __init__(self, path='config.env', gpt_model="gpt-3.5-turbo"): + def __init__(self, path='.env', gpt_model="gpt-3.5-turbo"): self.path = path self.GPT_MODEL = gpt_model load_dotenv(dotenv_path=path) diff --git a/backend/documents/__init__.py b/backend/documents/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/documents/admin.py b/backend/documents/admin.py deleted file mode 100644 index 8c38f3f3..00000000 --- a/backend/documents/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/backend/documents/apps.py b/backend/documents/apps.py deleted file mode 100644 index ab8a093b..00000000 --- a/backend/documents/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class DocumentsConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'documents' diff --git a/backend/documents/migrations/__init__.py b/backend/documents/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/documents/models.py b/backend/documents/models.py deleted file mode 100644 index 71a83623..00000000 --- a/backend/documents/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/backend/documents/tests.py b/backend/documents/tests.py deleted file mode 100644 index 2f0bd37c..00000000 --- a/backend/documents/tests.py +++ /dev/null @@ -1,35 +0,0 @@ -from django.test import TestCase, Client -from django.core.files.uploadedfile import SimpleUploadedFile -from rest_framework import status -import os - -base = "/api/" - - -class DocumentUploadTests(TestCase): - def setUp(self): - self.client = Client() - self.upload_end_point = f"{base}upload/" - # Use an existing test PDF file or create a dummy file - self.valid_pdf = SimpleUploadedFile( - "test.pdf", b"file_content", content_type="multipart/form-data" - ) - self.non_valid_file = SimpleUploadedFile( - "test.txt", b"file_content", content_type="text/plain" - ) - - def tearDown(self): - # Clean up any created files if necessary - pass - - def test_no_file(self): - response = self.client.post(self.upload_end_point, {"pdf": ""}) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - - def test_wrong_file_format(self): - response = self.client.post(self.upload_end_point, {"pdf": self.non_valid_file}) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - - def test_valid_pdf(self): - response = self.client.post(self.upload_end_point, {"pdf": self.valid_pdf}) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) diff --git a/backend/documents/views.py b/backend/documents/views.py deleted file mode 100644 index a66b308d..00000000 --- a/backend/documents/views.py +++ /dev/null @@ -1,66 +0,0 @@ -from django.shortcuts import render -from rest_framework import status -from rest_framework.response import Response -from rest_framework.decorators import api_view -from drf_yasg.utils import swagger_auto_schema -from drf_yasg import openapi - - -# Flashcard creation view -create_flashcards_success_response = openapi.Response( - description="Create flashcards successfully", - examples={ - "application/json": { - "message": "Flashcards created successfully", - "flashcards": [ - { - "front": "What is the capital of India?", - "back": "New Delhi", - }, - { - "front": "What is the capital of USA?", - "back": "Washington DC", - }, - ], - } - }, -) - -create_flashcards_error_response = openapi.Response( - description="There was a problem creating flashcards", - examples={ - "application/json": {"message": "There was a problem creating flashcards"} - }, -) - - -@swagger_auto_schema( - method="post", - operation_description="Login to the application", - tags=["Document Management"], - response_description="Returns the list of flashcards created", - responses={ - 200: create_flashcards_success_response, - 400: create_flashcards_error_response, - }, -) -@api_view(["POST"]) -def create_flashcards(request): - print(request.data, flush=True) - - # Check if the uploaded file is a PDF - if request.content_type != "application/pdf": - return Response( - {"message": "The uploaded file is not a PDF"}, - status=status.HTTP_400_BAD_REQUEST, - ) - - pdf_file = request.FILES.get("pdf") - - print(pdf_file, flush=True) - # Process or save pdf_file as needed - # ... - - return Response( - {"message": "PDF uploaded successfully!"}, status=status.HTTP_201_CREATED - ) diff --git a/backend/flashcards/convert_pdf_to_txt.py b/backend/flashcards/convert_pdf_to_txt.py index f7dfedb4..63a1e3af 100644 --- a/backend/flashcards/convert_pdf_to_txt.py +++ b/backend/flashcards/convert_pdf_to_txt.py @@ -1,5 +1,5 @@ import os -from pdfminer.high_level import extract_text +import chardet def convert_pdf_to_txt(pdf_file): """Convert a PDF file to text and return the path to the text file. @@ -10,6 +10,11 @@ def convert_pdf_to_txt(pdf_file): Returns: str: Text content of PDF file. """ - # Extract text from the PDF file - text = extract_text(pdf_file, codec='utf-8') + # The pdf_file from the input is a django.core.files.uploadedfile.InMemoryUploadedFile. + # Extract the text content of the file. + + file_content_bytes = pdf_file.read() + encoding = chardet.detect(file_content_bytes)["encoding"] + text = file_content_bytes.decode(encoding) + return text diff --git a/backend/flashcards/views.py b/backend/flashcards/views.py index 0faded8f..2ee7eb01 100644 --- a/backend/flashcards/views.py +++ b/backend/flashcards/views.py @@ -1,33 +1,63 @@ +from django.core.files.storage import default_storage +from django.http import JsonResponse from django.shortcuts import render -from flashcards.textToFlashcards import generate_flashcards, parse_flashcard - -from rest_framework.decorators import api_view +from rest_framework.decorators import api_view, parser_classes +from rest_framework.parsers import MultiPartParser from rest_framework.response import Response from rest_framework import status +from .textToFlashcards import generate_flashcards, parse_flashcard +from .convert_pdf_to_txt import convert_pdf_to_txt + from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi #Flashcard view -get_mock_flashcard_error_response = openapi.Response( +get_flashcard_error_response = openapi.Response( description="Error generating flashcards", examples={"application/json": {"message": "Error generating flashcards"}}, ) -get_mock_flashcard_success_response = openapi.Response( +get_flashcard_success_response = openapi.Response( description="Flashcards generated successfully", examples={"application/json": [{"front": "What is the capital of India?", "back": "New Delhi"}]}, ) @swagger_auto_schema( - method="get", + method="post", operation_description="Generate flashcards from a given text", tags=["Flashcards"], - responses={200: get_mock_flashcard_error_response, 400: get_mock_flashcard_error_response}, -) -@api_view(["GET"]) -def generate_mock_flashcard(request): - flashcards = generate_flashcards() + responses={200: get_flashcard_success_response, 400: get_flashcard_error_response}, +) + +@api_view(["POST"]) +def create_flashcards(request): + # Check if the request has multipart content type + + + if not request.content_type.startswith('multipart/form-data'): + return Response( + {"message": "The uploaded file is not in the correct format"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + pdf_file = request.FILES["pdf"] + if not pdf_file: + print("No PDF file uploaded", flush=True) + return Response( + {"message": "No PDF file uploaded"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + print("PDF file uploaded successfully", flush=True) + + # Convert the pdf file to text + text = convert_pdf_to_txt(pdf_file) + + # TODO: split the text into paragraphs before generating flashcards + text = text[:100] + + flashcards = generate_flashcards(text) flashcards = parse_flashcard(flashcards) if flashcards == "": @@ -35,3 +65,18 @@ def generate_mock_flashcard(request): {"message": "Error generating flashcards"}, status=status.HTTP_400_BAD_REQUEST ) return Response(flashcards, status=status.HTTP_200_OK) + + +@swagger_auto_schema( + method="get", + operation_description="Generate flashcards from a predefined text", + tags=["Flashcards"], + responses={200: get_flashcard_success_response, 400: get_flashcard_error_response}, +) + +@api_view(["GET"]) +def generate_mock_flashcard(request): + flashcards = generate_flashcards() + # flashcards = parse_flashcard(flashcards) + + return Response(flashcards, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt index a07b40f9..958ae300 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -3,6 +3,7 @@ anyio==4.2.0 asgiref==3.7.2 certifi==2023.11.17 cffi==1.16.0 +chardet==5.2.0 charset-normalizer==3.3.2 colorama==0.4.6 cryptography==41.0.7 @@ -13,6 +14,7 @@ django-rest-framework==0.1.0 djangorestframework==3.14.0 djangorestframework-simplejwt==5.3.1 drf-yasg==1.21.7 +exceptiongroup==1.2.0 h11==0.14.0 httpcore==1.0.2 httpx==0.26.0 diff --git a/backend/tutorai/settings.py b/backend/tutorai/settings.py index 5211890f..cb1365b2 100644 --- a/backend/tutorai/settings.py +++ b/backend/tutorai/settings.py @@ -45,7 +45,6 @@ # Own applications "api", "users", - "documents", "flashcards", ] diff --git a/frontend/src/routes/Routes.tsx b/frontend/src/routes/Routes.tsx index 44bd221f..2c0d349f 100644 --- a/frontend/src/routes/Routes.tsx +++ b/frontend/src/routes/Routes.tsx @@ -10,7 +10,7 @@ const AppRoutes = () => { return ( } /> - } /> + } /> } /> } /> } />