Merged in release/async (pull request #53)

ENCOA-312

Approved-by: Tiago Ribeiro
This commit is contained in:
carlos.mesquita
2025-01-13 22:42:04 +00:00
committed by Tiago Ribeiro
7 changed files with 69 additions and 32 deletions

View File

@@ -2,10 +2,12 @@ from .file import FileHelper
from .text import TextHelper
from .token_counter import count_tokens
from .exercises import ExercisesHelper
from .difficulty import DifficultyHelper
__all__ = [
"FileHelper",
"TextHelper",
"count_tokens",
"ExercisesHelper",
"DifficultyHelper"
]

View 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)

View File

@@ -8,12 +8,12 @@ import random
from ielts_be.configs.constants import EducationalContent
from ielts_be.dtos.level import LevelExercisesDTO
from ielts_be.helpers import DifficultyHelper
from ielts_be.repositories import IDocumentStore
from ielts_be.services import (
ILevelService, ILLMService, IReadingService,
IWritingService, IListeningService, ISpeakingService
)
from ielts_be.utils import pick_difficulty
from .exercises import MultipleChoice, BlankSpace, PassageUtas, FillBlanks
from .full_exams import CustomLevelModule, LevelUtas
from .upload import UploadLevelModule
@@ -51,8 +51,7 @@ class LevelService(ILevelService):
async def upload_level(self, upload: UploadFile, solutions: Optional[UploadFile] = None) -> Dict:
return await self._upload_module.generate_level_from_file(upload, solutions)
async def _generate_exercise(self, req_exercise, start_id, difficulties):
difficulty = pick_difficulty(req_exercise.difficulty, difficulties)
async def _generate_exercise(self, req_exercise, start_id, difficulty):
if req_exercise.type == "mcBlank":
questions = await self._mc.gen_multiple_choice("blank_space", req_exercise.quantity, difficulty, start_id)
questions["variant"] = "mcBlank"
@@ -95,16 +94,21 @@ class LevelService(ILevelService):
return exercise
async def generate_exercises(self, dto: LevelExercisesDTO):
start_ids = []
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:
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
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 = [{'id': str(uuid4()), **exercise} for exercise in questions]

View File

@@ -13,15 +13,13 @@ from ielts_be.configs.constants import (
NeuralVoices, GPTModels, TemperatureSettings, EducationalContent,
FieldsAndExercises
)
from ielts_be.helpers import FileHelper
from ielts_be.helpers import FileHelper, DifficultyHelper
from .audio_to_dialog import AudioToDialog
from .import_listening import ImportListeningModule
from .write_blank_forms import WriteBlankForms
from .write_blanks import WriteBlanks
from .write_blank_notes import WriteBlankNotes
from ..shared import TrueFalse, MultipleChoice
from ielts_be.utils import pick_difficulty
class ListeningService(IListeningService):
@@ -137,6 +135,11 @@ class ListeningService(IListeningService):
start_id = 1
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:
exercise_tasks.append(
self._generate_exercise(
@@ -144,7 +147,7 @@ class ListeningService(IListeningService):
"dialog or monologue",
dto.text,
start_id,
pick_difficulty(req_exercise.difficulty, dto.difficulty)
diff_helper.pick_difficulty(req_exercise.difficulty)
)
)
start_id += req_exercise.quantity

View File

@@ -5,9 +5,8 @@ from fastapi import UploadFile
from ielts_be.configs.constants import GPTModels, FieldsAndExercises, TemperatureSettings
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.utils import pick_difficulty
from .fill_blanks import FillBlanks
from .idea_match import IdeaMatch
from .paragraph_match import ParagraphMatch
@@ -138,13 +137,18 @@ class ReadingService(IReadingService):
exercise_tasks = []
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:
exercise_tasks.append(
self._generate_single_exercise(
req_exercise,
dto.text,
start_id,
pick_difficulty(req_exercise.difficulty, dto.difficulty)
diff_helper.pick_difficulty(req_exercise.difficulty)
)
)
start_id += req_exercise.quantity

View File

@@ -1,9 +1,7 @@
from .handle_exception import handle_exception
from .logger import suppress_loggers
from .pick_difficulty import pick_difficulty
__all__ = [
"handle_exception",
"suppress_loggers",
"pick_difficulty"
]

View File

@@ -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)