Merged in release/async (pull request #53)
ENCOA-312 Approved-by: Tiago Ribeiro
This commit is contained in:
@@ -2,10 +2,12 @@ from .file import FileHelper
|
|||||||
from .text import TextHelper
|
from .text import TextHelper
|
||||||
from .token_counter import count_tokens
|
from .token_counter import count_tokens
|
||||||
from .exercises import ExercisesHelper
|
from .exercises import ExercisesHelper
|
||||||
|
from .difficulty import DifficultyHelper
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"FileHelper",
|
"FileHelper",
|
||||||
"TextHelper",
|
"TextHelper",
|
||||||
"count_tokens",
|
"count_tokens",
|
||||||
"ExercisesHelper",
|
"ExercisesHelper",
|
||||||
|
"DifficultyHelper"
|
||||||
]
|
]
|
||||||
|
|||||||
40
ielts_be/helpers/difficulty.py
Normal file
40
ielts_be/helpers/difficulty.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import math
|
||||||
|
import random
|
||||||
|
from typing import Optional, List, Iterator
|
||||||
|
|
||||||
|
from ielts_be.configs.constants import EducationalContent
|
||||||
|
|
||||||
|
|
||||||
|
class DifficultyHelper:
|
||||||
|
|
||||||
|
def __init__(self, difficulties: Optional[List[str]]):
|
||||||
|
self.difficulties = difficulties
|
||||||
|
self.distributed: Optional[Iterator[str]] = None
|
||||||
|
|
||||||
|
def distribute_for_count(self, count: int) -> None:
|
||||||
|
if not self.difficulties or count == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
result = []
|
||||||
|
remaining = count
|
||||||
|
difficulties_count = len(self.difficulties)
|
||||||
|
|
||||||
|
for i, diff in enumerate(self.difficulties):
|
||||||
|
if i == difficulties_count - 1:
|
||||||
|
slots = remaining
|
||||||
|
else:
|
||||||
|
slots = math.ceil(remaining / (difficulties_count - i))
|
||||||
|
|
||||||
|
result.extend([diff] * slots)
|
||||||
|
remaining -= slots
|
||||||
|
|
||||||
|
self.distributed = iter(result)
|
||||||
|
|
||||||
|
def pick_difficulty(self, difficulty: Optional[str]) -> str:
|
||||||
|
if difficulty:
|
||||||
|
return difficulty if difficulty != "Random" else random.choice(EducationalContent.DIFFICULTIES)
|
||||||
|
|
||||||
|
if self.distributed:
|
||||||
|
return next(self.distributed)
|
||||||
|
|
||||||
|
return random.choice(EducationalContent.DIFFICULTIES)
|
||||||
@@ -8,12 +8,12 @@ import random
|
|||||||
|
|
||||||
from ielts_be.configs.constants import EducationalContent
|
from ielts_be.configs.constants import EducationalContent
|
||||||
from ielts_be.dtos.level import LevelExercisesDTO
|
from ielts_be.dtos.level import LevelExercisesDTO
|
||||||
|
from ielts_be.helpers import DifficultyHelper
|
||||||
from ielts_be.repositories import IDocumentStore
|
from ielts_be.repositories import IDocumentStore
|
||||||
from ielts_be.services import (
|
from ielts_be.services import (
|
||||||
ILevelService, ILLMService, IReadingService,
|
ILevelService, ILLMService, IReadingService,
|
||||||
IWritingService, IListeningService, ISpeakingService
|
IWritingService, IListeningService, ISpeakingService
|
||||||
)
|
)
|
||||||
from ielts_be.utils import pick_difficulty
|
|
||||||
from .exercises import MultipleChoice, BlankSpace, PassageUtas, FillBlanks
|
from .exercises import MultipleChoice, BlankSpace, PassageUtas, FillBlanks
|
||||||
from .full_exams import CustomLevelModule, LevelUtas
|
from .full_exams import CustomLevelModule, LevelUtas
|
||||||
from .upload import UploadLevelModule
|
from .upload import UploadLevelModule
|
||||||
@@ -51,8 +51,7 @@ class LevelService(ILevelService):
|
|||||||
async def upload_level(self, upload: UploadFile, solutions: Optional[UploadFile] = None) -> Dict:
|
async def upload_level(self, upload: UploadFile, solutions: Optional[UploadFile] = None) -> Dict:
|
||||||
return await self._upload_module.generate_level_from_file(upload, solutions)
|
return await self._upload_module.generate_level_from_file(upload, solutions)
|
||||||
|
|
||||||
async def _generate_exercise(self, req_exercise, start_id, difficulties):
|
async def _generate_exercise(self, req_exercise, start_id, difficulty):
|
||||||
difficulty = pick_difficulty(req_exercise.difficulty, difficulties)
|
|
||||||
if req_exercise.type == "mcBlank":
|
if req_exercise.type == "mcBlank":
|
||||||
questions = await self._mc.gen_multiple_choice("blank_space", req_exercise.quantity, difficulty, start_id)
|
questions = await self._mc.gen_multiple_choice("blank_space", req_exercise.quantity, difficulty, start_id)
|
||||||
questions["variant"] = "mcBlank"
|
questions["variant"] = "mcBlank"
|
||||||
@@ -95,16 +94,21 @@ class LevelService(ILevelService):
|
|||||||
return exercise
|
return exercise
|
||||||
|
|
||||||
async def generate_exercises(self, dto: LevelExercisesDTO):
|
async def generate_exercises(self, dto: LevelExercisesDTO):
|
||||||
start_ids = []
|
|
||||||
current_id = 1
|
current_id = 1
|
||||||
|
tasks = []
|
||||||
|
|
||||||
|
distributor = DifficultyHelper(dto.difficulty)
|
||||||
|
|
||||||
|
none_count = sum(1 for ex in dto.exercises if ex.difficulty is None)
|
||||||
|
distributor.distribute_for_count(none_count)
|
||||||
|
|
||||||
for req_exercise in dto.exercises:
|
for req_exercise in dto.exercises:
|
||||||
start_ids.append(current_id)
|
difficulty = distributor.pick_difficulty(req_exercise.difficulty)
|
||||||
|
tasks.append(
|
||||||
|
self._generate_exercise(req_exercise, current_id, difficulty)
|
||||||
|
)
|
||||||
current_id += req_exercise.quantity
|
current_id += req_exercise.quantity
|
||||||
|
|
||||||
tasks = [
|
|
||||||
self._generate_exercise(req_exercise, start_id, dto.difficulty)
|
|
||||||
for req_exercise, start_id in zip(dto.exercises, start_ids)
|
|
||||||
]
|
|
||||||
questions = await gather(*tasks)
|
questions = await gather(*tasks)
|
||||||
questions = [{'id': str(uuid4()), **exercise} for exercise in questions]
|
questions = [{'id': str(uuid4()), **exercise} for exercise in questions]
|
||||||
|
|
||||||
|
|||||||
@@ -13,15 +13,13 @@ from ielts_be.configs.constants import (
|
|||||||
NeuralVoices, GPTModels, TemperatureSettings, EducationalContent,
|
NeuralVoices, GPTModels, TemperatureSettings, EducationalContent,
|
||||||
FieldsAndExercises
|
FieldsAndExercises
|
||||||
)
|
)
|
||||||
from ielts_be.helpers import FileHelper
|
from ielts_be.helpers import FileHelper, DifficultyHelper
|
||||||
from .audio_to_dialog import AudioToDialog
|
from .audio_to_dialog import AudioToDialog
|
||||||
from .import_listening import ImportListeningModule
|
from .import_listening import ImportListeningModule
|
||||||
from .write_blank_forms import WriteBlankForms
|
from .write_blank_forms import WriteBlankForms
|
||||||
from .write_blanks import WriteBlanks
|
from .write_blanks import WriteBlanks
|
||||||
from .write_blank_notes import WriteBlankNotes
|
from .write_blank_notes import WriteBlankNotes
|
||||||
from ..shared import TrueFalse, MultipleChoice
|
from ..shared import TrueFalse, MultipleChoice
|
||||||
from ielts_be.utils import pick_difficulty
|
|
||||||
|
|
||||||
|
|
||||||
class ListeningService(IListeningService):
|
class ListeningService(IListeningService):
|
||||||
|
|
||||||
@@ -137,6 +135,11 @@ class ListeningService(IListeningService):
|
|||||||
start_id = 1
|
start_id = 1
|
||||||
exercise_tasks = []
|
exercise_tasks = []
|
||||||
|
|
||||||
|
diff_helper = DifficultyHelper(dto.difficulty)
|
||||||
|
|
||||||
|
none_count = sum(1 for ex in dto.exercises if ex.difficulty is None)
|
||||||
|
diff_helper.distribute_for_count(none_count)
|
||||||
|
|
||||||
for req_exercise in dto.exercises:
|
for req_exercise in dto.exercises:
|
||||||
exercise_tasks.append(
|
exercise_tasks.append(
|
||||||
self._generate_exercise(
|
self._generate_exercise(
|
||||||
@@ -144,7 +147,7 @@ class ListeningService(IListeningService):
|
|||||||
"dialog or monologue",
|
"dialog or monologue",
|
||||||
dto.text,
|
dto.text,
|
||||||
start_id,
|
start_id,
|
||||||
pick_difficulty(req_exercise.difficulty, dto.difficulty)
|
diff_helper.pick_difficulty(req_exercise.difficulty)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
start_id += req_exercise.quantity
|
start_id += req_exercise.quantity
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ from fastapi import UploadFile
|
|||||||
|
|
||||||
from ielts_be.configs.constants import GPTModels, FieldsAndExercises, TemperatureSettings
|
from ielts_be.configs.constants import GPTModels, FieldsAndExercises, TemperatureSettings
|
||||||
from ielts_be.dtos.reading import ReadingDTO
|
from ielts_be.dtos.reading import ReadingDTO
|
||||||
from ielts_be.helpers import ExercisesHelper
|
from ielts_be.helpers import ExercisesHelper, DifficultyHelper
|
||||||
from ielts_be.services import IReadingService, ILLMService
|
from ielts_be.services import IReadingService, ILLMService
|
||||||
from ielts_be.utils import pick_difficulty
|
|
||||||
from .fill_blanks import FillBlanks
|
from .fill_blanks import FillBlanks
|
||||||
from .idea_match import IdeaMatch
|
from .idea_match import IdeaMatch
|
||||||
from .paragraph_match import ParagraphMatch
|
from .paragraph_match import ParagraphMatch
|
||||||
@@ -138,13 +137,18 @@ class ReadingService(IReadingService):
|
|||||||
exercise_tasks = []
|
exercise_tasks = []
|
||||||
start_id = 1
|
start_id = 1
|
||||||
|
|
||||||
|
diff_helper = DifficultyHelper(dto.difficulty)
|
||||||
|
|
||||||
|
none_count = sum(1 for ex in dto.exercises if ex.difficulty is None)
|
||||||
|
diff_helper.distribute_for_count(none_count)
|
||||||
|
|
||||||
for req_exercise in dto.exercises:
|
for req_exercise in dto.exercises:
|
||||||
exercise_tasks.append(
|
exercise_tasks.append(
|
||||||
self._generate_single_exercise(
|
self._generate_single_exercise(
|
||||||
req_exercise,
|
req_exercise,
|
||||||
dto.text,
|
dto.text,
|
||||||
start_id,
|
start_id,
|
||||||
pick_difficulty(req_exercise.difficulty, dto.difficulty)
|
diff_helper.pick_difficulty(req_exercise.difficulty)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
start_id += req_exercise.quantity
|
start_id += req_exercise.quantity
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
from .handle_exception import handle_exception
|
from .handle_exception import handle_exception
|
||||||
from .logger import suppress_loggers
|
from .logger import suppress_loggers
|
||||||
from .pick_difficulty import pick_difficulty
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"handle_exception",
|
"handle_exception",
|
||||||
"suppress_loggers",
|
"suppress_loggers",
|
||||||
"pick_difficulty"
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
import random
|
|
||||||
from typing import Optional, List
|
|
||||||
|
|
||||||
from ielts_be.configs.constants import EducationalContent
|
|
||||||
|
|
||||||
|
|
||||||
def pick_difficulty(difficulty: Optional[str], difficulties: Optional[List[str]]) -> str:
|
|
||||||
if difficulty:
|
|
||||||
return difficulty
|
|
||||||
|
|
||||||
if difficulties:
|
|
||||||
return random.choice(difficulties)
|
|
||||||
|
|
||||||
return random.choice(EducationalContent.DIFFICULTIES)
|
|
||||||
Reference in New Issue
Block a user