diff --git a/app/api/level.py b/app/api/level.py index 2bf9cd6..d46049c 100644 --- a/app/api/level.py +++ b/app/api/level.py @@ -54,7 +54,6 @@ async def import_level( ): return await level_controller.upload_level(exercises, solutions) - @level_router.post( '/custom/', dependencies=[Depends(Authorized([IsAuthenticatedViaBearerToken]))] diff --git a/app/dtos/exams/level.py b/app/dtos/exams/level.py index 92c217b..f5618cf 100644 --- a/app/dtos/exams/level.py +++ b/app/dtos/exams/level.py @@ -47,10 +47,13 @@ class FillBlanksExercise(BaseModel): Exercise = Union[MultipleChoiceExercise, FillBlanksExercise] +class Text(BaseModel): + content: str + title: str class Part(BaseModel): exercises: List[Exercise] - context: Optional[str] = Field(default=None) + text: Optional[Text] = Field(default=None) class Exam(BaseModel): diff --git a/app/mappers/level.py b/app/mappers/level.py index b009ddd..2863f73 100644 --- a/app/mappers/level.py +++ b/app/mappers/level.py @@ -5,7 +5,7 @@ from pydantic import ValidationError from app.dtos.exams.level import ( MultipleChoiceExercise, FillBlanksExercise, - Part, Exam + Part, Exam, Text ) from app.dtos.sheet import Sheet, Option, MultipleChoiceQuestion, FillBlanksWord @@ -17,7 +17,7 @@ class LevelMapper: parts = [] for part in response['parts']: part_exercises = part['exercises'] - context = part.get('context', None) + text = part.get('text', None) exercises = [] for exercise in part_exercises: @@ -32,8 +32,13 @@ class LevelMapper: exercises.append(exercise_model) part_kwargs = {"exercises": exercises} - if context is not None: - part_kwargs["context"] = context + if text is not None and text.get('content', None): + title = text.get('title', 'Untitled') + if title == '': + title = 'Untitled' + part_kwargs["text"] = Text(title=title, content=text['content']) + else: + part_kwargs["text"] = None part_model = Part(**part_kwargs) parts.append(part_model) diff --git a/app/services/impl/exam/level/upload.py b/app/services/impl/exam/level/upload.py index 06f2363..2e31251 100644 --- a/app/services/impl/exam/level/upload.py +++ b/app/services/impl/exam/level/upload.py @@ -57,7 +57,10 @@ class UploadLevelModule: return { "parts": [ { - "context": "", + "text": { + "content": "", + "title": "", + }, "exercises": [ self._multiple_choice_html(), self._passage_blank_space_html() @@ -86,7 +89,7 @@ class UploadLevelModule: "role": "system", "content": ( 'You are GPT Scraper and your job is to clean dirty html into clean usable JSON formatted data.' - 'Your current task is to scrape html english questions sheets.\n\n' + 'Your current task is to scrape html english questions sheets and structure them into parts NOT sections.\n\n' 'In the question sheet you will only see 4 types of question:\n' '- blank space multiple choice\n' @@ -111,23 +114,24 @@ class UploadLevelModule: 'out the best paragraph separation possible.' 'You will place all the information in a single JSON: ' - '{"parts": [{"exercises": [{...}], "context": ""}]}\n ' + '{"parts": [{"exercises": [{...}], "text": {"title": "", "content": ""} ]}\n ' 'Where {...} are the exercises templates for each part of a question sheet and the optional field ' - 'context.' - - 'IMPORTANT: The question sheet may be divided by sections but you need to only consider the parts, ' - 'so that you can group the exercises by the parts that are in the html, this is crucial since only ' - 'reading passage multiple choice require context and if the context is included in parts where it ' - 'is not required the UI will be messed up. Some make sure to correctly group the exercises by parts.\n' + 'text, which contains the reading passages that are required in order to solve the part questions, ' + '(if there are passages) place them in text.content and if there is a title place it in text.title ' + 'else omit the title field.\n' + + 'IMPORTANT: As stated earlier your job is to structure the questions into PARTS not SECTION, this means ' + 'that if there is for example: Section 1, Part 1 and Part 2, Section 2, Part 1 and Part 2, you MUST ' + 'place in the parts array 4 parts NOT 2 parts with the exercises of both parts! You must strictly ' + 'adhere to this instruction, do not mistake sections for parts!\n' 'The templates for the exercises are the following:\n' '- blank space multiple choice, underline multiple choice and reading passage multiple choice: ' f'{self._multiple_choice_html()}\n' f'- reading passage blank space multiple choice: {self._passage_blank_space_html()}\n' - 'IMPORTANT: For the reading passage multiple choice the context field must be set with the reading ' - 'passages without paragraphs or line numbers, with 2 newlines between paragraphs, for the other ' - 'exercises exclude the context field.' + 'IMPORTANT: The text.content field must be set with the reading passages of a part (if there is one)' + 'without paragraphs or line numbers, with 2 newlines between paragraphs.' ) } @@ -135,30 +139,19 @@ class UploadLevelModule: def _multiple_choice_html(): return { "type": "multipleChoice", - "prompt": "Select the appropriate option.", + "prompt": "", "questions": [ { - "id": "", - "prompt": "", - "solution": "", + "id": "", + "prompt": "", "options": [ { - "id": "A", - "text": "" - }, - { - "id": "B", - "text": "" - }, - { - "id": "C", - "text": "" - }, - { - "id": "D", - "text": "" + "id": "", + "text": "