Brushed up the backend, added writing task 1 academic prompt gen and grading ENCOA-274

This commit is contained in:
Carlos-Mesquita
2024-12-10 22:24:40 +00:00
parent 68cab80851
commit 6982068864
167 changed files with 1411 additions and 1229 deletions

View File

@@ -0,0 +1,5 @@
from .level import LevelMapper
__all__ = [
"LevelMapper"
]

71
ielts_be/mappers/level.py Normal file
View File

@@ -0,0 +1,71 @@
from typing import Dict, Any
from pydantic import ValidationError
from ielts_be.dtos.exams.level import (
MultipleChoiceExercise,
FillBlanksExercise,
Part, Exam, Text
)
from ielts_be.dtos.sheet import Sheet, Option, MultipleChoiceQuestion, FillBlanksWord
class LevelMapper:
@staticmethod
def map_to_exam_model(response: Dict[str, Any]) -> Exam:
parts = []
for part in response['parts']:
part_exercises = part['exercises']
text = part.get('text', None)
exercises = []
for exercise in part_exercises:
exercise_type = exercise['type']
if exercise_type == 'multipleChoice':
exercise_model = MultipleChoiceExercise(**exercise)
elif exercise_type == 'fillBlanks':
exercise_model = FillBlanksExercise(**exercise)
else:
raise ValidationError(f"Unknown exercise type: {exercise_type}")
exercises.append(exercise_model)
part_kwargs = {"exercises": exercises}
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)
return Exam(parts=parts)
@staticmethod
def map_to_sheet(response: Dict[str, Any]) -> Sheet:
components = []
for item in response["components"]:
component_type = item["type"]
if component_type == "multipleChoice":
options = [Option(id=opt["id"], text=opt["text"]) for opt in item["options"]]
components.append(MultipleChoiceQuestion(
id=item["id"],
prompt=item["prompt"],
variant=item.get("variant", "text"),
options=options
))
elif component_type == "fillBlanks":
components.append(FillBlanksWord(
id=item["id"],
options=item["options"]
))
else:
components.append(item)
return Sheet(components=components)

View File

@@ -0,0 +1,112 @@
from typing import Dict, Any, List, Union, Optional
from pydantic import BaseModel
from ielts_be.dtos.exams.listening import (
TrueFalseExercise,
MultipleChoiceExercise,
WriteBlanksExercise,
ListeningExam,
ListeningSection,
WriteBlanksVariant, WriteBlankSolution, WriteBlanksQuestionExercise, WriteBlankQuestion
)
class ListeningQuestionSection(BaseModel):
exercises: List[Union[TrueFalseExercise, MultipleChoiceExercise, WriteBlanksQuestionExercise]]
class ListeningQuestionExam(BaseModel):
parts: List[ListeningQuestionSection]
minTimer: Optional[int]
module: str = "listening"
class WriteBlankProcessor:
@staticmethod
def to_question_model(exercise_data: Dict[str, Any]) -> WriteBlanksQuestionExercise:
questions = [
WriteBlankQuestion(
id=q["id"],
prompt=q["prompt"],
solution=q["solution"]
)
for q in exercise_data.get("questions", [])
]
return WriteBlanksQuestionExercise(
type="writeBlanks",
prompt=exercise_data.get("prompt"),
maxWords=exercise_data.get("maxWords"),
questions=questions,
variant=exercise_data.get("variant", "questions")
)
@staticmethod
def to_text_model(question_model: WriteBlanksQuestionExercise) -> WriteBlanksExercise:
if question_model.variant == WriteBlanksVariant.QUESTIONS:
text = '\\n'.join(f"{q.prompt} {{{{{q.id}}}}}" for q in question_model.questions)
elif question_model.variant == WriteBlanksVariant.FILL:
text = ' '.join(f"{q.prompt}" for q in question_model.questions)
elif question_model.variant == WriteBlanksVariant.FORM:
text = '\\n'.join(f"{q.prompt}" for q in question_model.questions)
else:
raise ValueError(f"Unknown variant: {question_model.variant}")
solutions = [
WriteBlankSolution(id=q.id, solution=q.solution)
for q in question_model.questions
]
return WriteBlanksExercise(
type="writeBlanks",
prompt=question_model.prompt,
maxWords=question_model.maxWords,
text=text,
solutions=solutions,
variant=question_model.variant
)
class ListeningMapper:
@staticmethod
def map_to_test_model(response: Dict[str, Any]) -> ListeningExam:
question_parts = []
for section in response.get('parts', []):
section_exercises = []
for exercise in section['exercises']:
exercise_type = exercise['type']
if exercise_type == 'trueFalse':
section_exercises.append(TrueFalseExercise(**exercise))
elif exercise_type == 'multipleChoice':
section_exercises.append(MultipleChoiceExercise(**exercise))
elif exercise_type == 'writeBlanks':
question_model = WriteBlankProcessor.to_question_model(exercise)
section_exercises.append(question_model)
else:
raise ValueError(f"Unknown exercise type: {exercise_type}")
question_parts.append(ListeningQuestionSection(exercises=section_exercises))
question_exam = ListeningQuestionExam(
parts=question_parts,
minTimer=response.get('minTimer'),
module="listening"
)
final_parts = []
for section in question_exam.parts:
final_exercises = []
for exercise in section.exercises:
if isinstance(exercise, WriteBlanksQuestionExercise):
final_exercises.append(WriteBlankProcessor.to_text_model(exercise))
else:
final_exercises.append(exercise)
final_parts.append(ListeningSection(exercises=final_exercises))
return ListeningExam(
parts=final_parts,
minTimer=response.get('minTimer'),
module="listening"
)

View File

@@ -0,0 +1,44 @@
from typing import Dict, Any
from ielts_be.dtos.exams.reading import (
Part, Exam, Context, FillBlanksExercise,
TrueFalseExercise, MatchSentencesExercise,
WriteBlanksExercise, MultipleChoice
)
class ReadingMapper:
@staticmethod
def map_to_exam_model(response: Dict[str, Any]) -> Exam:
parts = []
for part in response['parts']:
part_exercises = part['exercises']
context = Context(**part['text'])
model_map = {
'fillBlanks': FillBlanksExercise,
'trueFalse': TrueFalseExercise,
'matchSentences': MatchSentencesExercise,
'writeBlanks': WriteBlanksExercise,
'multipleChoice': MultipleChoice,
}
exercises = []
for exercise in part_exercises:
exercise_type = exercise['type']
if exercise_type in model_map:
model_class = model_map[exercise_type]
exercises.append(model_class(**exercise))
else:
raise ValueError(f"Unknown exercise type: {exercise_type}")
part_kwargs = {
"exercises": exercises,
"text": context
}
part_model = Part(**part_kwargs)
parts.append(part_model)
return Exam(parts=parts, minTimer=response["minTimer"])