ENCOA-94: Added user to training content docs, added support for shuffles, tweaked training prompt
This commit is contained in:
@@ -5,3 +5,4 @@ README.md
|
|||||||
*.pyd
|
*.pyd
|
||||||
__pycache__
|
__pycache__
|
||||||
.pytest_cache
|
.pytest_cache
|
||||||
|
/scripts
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ __pycache__
|
|||||||
.env
|
.env
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/firebase-configs/test_firebase.json
|
/firebase-configs/test_firebase.json
|
||||||
|
/scripts
|
||||||
|
|||||||
506
app.py
506
app.py
@@ -70,25 +70,7 @@ def get_listening_section_1_question():
|
|||||||
req_exercises = request.args.getlist('exercises')
|
req_exercises = request.args.getlist('exercises')
|
||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
|
|
||||||
if (len(req_exercises) == 0):
|
return gen_listening_section_1(topic, difficulty, req_exercises)
|
||||||
req_exercises = random.sample(LISTENING_1_EXERCISE_TYPES, 1)
|
|
||||||
|
|
||||||
number_of_exercises_q = divide_number_into_parts(TOTAL_LISTENING_SECTION_1_EXERCISES, len(req_exercises))
|
|
||||||
|
|
||||||
processed_conversation = generate_listening_1_conversation(topic)
|
|
||||||
|
|
||||||
app.logger.info("Generated conversation: " + str(processed_conversation))
|
|
||||||
|
|
||||||
start_id = 1
|
|
||||||
exercises = generate_listening_conversation_exercises(parse_conversation(processed_conversation),
|
|
||||||
req_exercises,
|
|
||||||
number_of_exercises_q,
|
|
||||||
start_id, difficulty)
|
|
||||||
return {
|
|
||||||
"exercises": exercises,
|
|
||||||
"text": processed_conversation,
|
|
||||||
"difficulty": difficulty
|
|
||||||
}
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -103,22 +85,7 @@ def get_listening_section_2_question():
|
|||||||
req_exercises = request.args.getlist('exercises')
|
req_exercises = request.args.getlist('exercises')
|
||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
|
|
||||||
if (len(req_exercises) == 0):
|
return gen_listening_section_2(topic, difficulty, req_exercises)
|
||||||
req_exercises = random.sample(LISTENING_2_EXERCISE_TYPES, 2)
|
|
||||||
|
|
||||||
number_of_exercises_q = divide_number_into_parts(TOTAL_LISTENING_SECTION_2_EXERCISES, len(req_exercises))
|
|
||||||
|
|
||||||
monologue = generate_listening_2_monologue(topic)
|
|
||||||
|
|
||||||
app.logger.info("Generated monologue: " + str(monologue))
|
|
||||||
start_id = 11
|
|
||||||
exercises = generate_listening_monologue_exercises(str(monologue), req_exercises, number_of_exercises_q,
|
|
||||||
start_id, difficulty)
|
|
||||||
return {
|
|
||||||
"exercises": exercises,
|
|
||||||
"text": monologue,
|
|
||||||
"difficulty": difficulty
|
|
||||||
}
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -133,24 +100,7 @@ def get_listening_section_3_question():
|
|||||||
req_exercises = request.args.getlist('exercises')
|
req_exercises = request.args.getlist('exercises')
|
||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
|
|
||||||
if (len(req_exercises) == 0):
|
return gen_listening_section_3(topic, difficulty, req_exercises)
|
||||||
req_exercises = random.sample(LISTENING_3_EXERCISE_TYPES, 1)
|
|
||||||
|
|
||||||
number_of_exercises_q = divide_number_into_parts(TOTAL_LISTENING_SECTION_3_EXERCISES, len(req_exercises))
|
|
||||||
|
|
||||||
processed_conversation = generate_listening_3_conversation(topic)
|
|
||||||
|
|
||||||
app.logger.info("Generated conversation: " + str(processed_conversation))
|
|
||||||
|
|
||||||
start_id = 21
|
|
||||||
exercises = generate_listening_conversation_exercises(parse_conversation(processed_conversation), req_exercises,
|
|
||||||
number_of_exercises_q,
|
|
||||||
start_id, difficulty)
|
|
||||||
return {
|
|
||||||
"exercises": exercises,
|
|
||||||
"text": processed_conversation,
|
|
||||||
"difficulty": difficulty
|
|
||||||
}
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -165,22 +115,7 @@ def get_listening_section_4_question():
|
|||||||
req_exercises = request.args.getlist('exercises')
|
req_exercises = request.args.getlist('exercises')
|
||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
|
|
||||||
if (len(req_exercises) == 0):
|
return gen_listening_section_4(topic, difficulty, req_exercises)
|
||||||
req_exercises = random.sample(LISTENING_EXERCISE_TYPES, 2)
|
|
||||||
|
|
||||||
number_of_exercises_q = divide_number_into_parts(TOTAL_LISTENING_SECTION_4_EXERCISES, len(req_exercises))
|
|
||||||
|
|
||||||
monologue = generate_listening_4_monologue(topic)
|
|
||||||
|
|
||||||
app.logger.info("Generated monologue: " + str(monologue))
|
|
||||||
start_id = 31
|
|
||||||
exercises = generate_listening_monologue_exercises(str(monologue), req_exercises, number_of_exercises_q,
|
|
||||||
start_id, difficulty)
|
|
||||||
return {
|
|
||||||
"exercises": exercises,
|
|
||||||
"text": monologue,
|
|
||||||
"difficulty": difficulty
|
|
||||||
}
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -347,37 +282,7 @@ def get_writing_task_1_general_question():
|
|||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
topic = request.args.get("topic", default=random.choice(mti_topics))
|
topic = request.args.get("topic", default=random.choice(mti_topics))
|
||||||
try:
|
try:
|
||||||
messages = [
|
return gen_writing_task_1(topic, difficulty)
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": ('You are a helpful assistant designed to output JSON on this format: '
|
|
||||||
'{"prompt": "prompt content"}')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": ('Craft a prompt for an IELTS Writing Task 1 General Training exercise that instructs the '
|
|
||||||
'student to compose a letter. The prompt should present a specific scenario or situation, '
|
|
||||||
'based on the topic of "' + topic + '", requiring the student to provide information, '
|
|
||||||
'advice, or instructions within the letter. '
|
|
||||||
'Make sure that the generated prompt is '
|
|
||||||
'of ' + difficulty + 'difficulty and does not contain '
|
|
||||||
'forbidden subjects in muslim '
|
|
||||||
'countries.')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": 'The prompt should end with "In the letter you should" followed by 3 bullet points of what '
|
|
||||||
'the answer should include.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
token_count = count_total_tokens(messages)
|
|
||||||
response = make_openai_call(GPT_3_5_TURBO, messages, token_count, "prompt",
|
|
||||||
GEN_QUESTION_TEMPERATURE)
|
|
||||||
return {
|
|
||||||
"question": add_newline_before_hyphen(response["prompt"].strip()),
|
|
||||||
"difficulty": difficulty,
|
|
||||||
"topic": topic
|
|
||||||
}
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -512,32 +417,7 @@ def get_writing_task_2_general_question():
|
|||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
topic = request.args.get("topic", default=random.choice(mti_topics))
|
topic = request.args.get("topic", default=random.choice(mti_topics))
|
||||||
try:
|
try:
|
||||||
messages = [
|
return gen_writing_task_2(topic, difficulty)
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": ('You are a helpful assistant designed to output JSON on this format: '
|
|
||||||
'{"prompt": "prompt content"}')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": (
|
|
||||||
'Craft a comprehensive question of ' + difficulty + 'difficulty like the ones for IELTS Writing Task 2 General Training that directs the candidate '
|
|
||||||
'to delve into an in-depth analysis of contrasting perspectives on the topic of "' + topic + '". '
|
|
||||||
'The candidate should be asked to discuss the strengths and weaknesses of both viewpoints.')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": 'The question should lead to an answer with either "theories", "complicated information" or '
|
|
||||||
'be "very descriptive" on the topic.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
token_count = count_total_tokens(messages)
|
|
||||||
response = make_openai_call(GPT_4_O, messages, token_count, "prompt", GEN_QUESTION_TEMPERATURE)
|
|
||||||
return {
|
|
||||||
"question": response["prompt"].strip(),
|
|
||||||
"difficulty": difficulty,
|
|
||||||
"topic": topic
|
|
||||||
}
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -719,56 +599,8 @@ def get_speaking_task_1_question():
|
|||||||
first_topic = request.args.get("first_topic", default=random.choice(mti_topics))
|
first_topic = request.args.get("first_topic", default=random.choice(mti_topics))
|
||||||
second_topic = request.args.get("second_topic", default=random.choice(mti_topics))
|
second_topic = request.args.get("second_topic", default=random.choice(mti_topics))
|
||||||
|
|
||||||
json_format = {
|
|
||||||
"first_topic": "topic 1",
|
|
||||||
"second_topic": "topic 2",
|
|
||||||
"questions": [
|
|
||||||
"Introductory question about the first topic, starting the topic with 'Let's talk about x' and then the "
|
|
||||||
"question.",
|
|
||||||
"Follow up question about the first topic",
|
|
||||||
"Follow up question about the first topic",
|
|
||||||
"Question about second topic",
|
|
||||||
"Follow up question about the second topic",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
messages = [
|
return gen_speaking_part_1(first_topic, second_topic, difficulty)
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": (
|
|
||||||
'You are a helpful assistant designed to output JSON on this format: ' + str(json_format))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": (
|
|
||||||
'Craft 5 simple and single questions of easy difficulty for IELTS Speaking Part 1 '
|
|
||||||
'that encourages candidates to delve deeply into '
|
|
||||||
'personal experiences, preferences, or insights on the topic '
|
|
||||||
'of "' + first_topic + '" and the topic of "' + second_topic + '". '
|
|
||||||
'Make sure that the generated '
|
|
||||||
'question'
|
|
||||||
'does not contain forbidden '
|
|
||||||
'subjects in'
|
|
||||||
'muslim countries.')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": 'The questions should lead to the usage of 4 verb tenses (present perfect, present, '
|
|
||||||
'past and future).'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": 'They must be 1 single question each and not be double-barreled questions.'
|
|
||||||
|
|
||||||
}
|
|
||||||
]
|
|
||||||
token_count = count_total_tokens(messages)
|
|
||||||
response = make_openai_call(GPT_4_O, messages, token_count, ["first_topic"],
|
|
||||||
GEN_QUESTION_TEMPERATURE)
|
|
||||||
response["type"] = 1
|
|
||||||
response["difficulty"] = difficulty
|
|
||||||
return response
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -918,50 +750,8 @@ def get_speaking_task_2_question():
|
|||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
topic = request.args.get("topic", default=random.choice(mti_topics))
|
topic = request.args.get("topic", default=random.choice(mti_topics))
|
||||||
|
|
||||||
json_format = {
|
|
||||||
"topic": "topic",
|
|
||||||
"question": "question",
|
|
||||||
"prompts": [
|
|
||||||
"prompt_1",
|
|
||||||
"prompt_2",
|
|
||||||
"prompt_3"
|
|
||||||
],
|
|
||||||
"suffix": "And explain why..."
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
messages = [
|
return gen_speaking_part_2(topic, difficulty)
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": 'You are a helpful assistant designed to output JSON on this format: ' + str(json_format)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": (
|
|
||||||
'Create a question of medium difficulty for IELTS Speaking Part 2 '
|
|
||||||
'that encourages candidates to narrate a '
|
|
||||||
'personal experience or story related to the topic '
|
|
||||||
'of "' + topic + '". Include 3 prompts that '
|
|
||||||
'guide the candidate to describe '
|
|
||||||
'specific aspects of the experience, '
|
|
||||||
'such as details about the situation, '
|
|
||||||
'their actions, and the reasons it left a '
|
|
||||||
'lasting impression. Make sure that the '
|
|
||||||
'generated question does not contain '
|
|
||||||
'forbidden subjects in muslim countries.')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": 'The prompts must not be questions. Also include a suffix like the ones in the IELTS exams '
|
|
||||||
'that start with "And explain why".'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
token_count = count_total_tokens(messages)
|
|
||||||
response = make_openai_call(GPT_4_O, messages, token_count, GEN_FIELDS, GEN_QUESTION_TEMPERATURE)
|
|
||||||
response["type"] = 2
|
|
||||||
response["difficulty"] = difficulty
|
|
||||||
response["topic"] = topic
|
|
||||||
return response
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -972,47 +762,8 @@ def get_speaking_task_3_question():
|
|||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
topic = request.args.get("topic", default=random.choice(mti_topics))
|
topic = request.args.get("topic", default=random.choice(mti_topics))
|
||||||
|
|
||||||
json_format = {
|
|
||||||
"topic": "topic",
|
|
||||||
"questions": [
|
|
||||||
"Introductory question about the topic.",
|
|
||||||
"Follow up question about the topic",
|
|
||||||
"Follow up question about the topic",
|
|
||||||
"Follow up question about the topic",
|
|
||||||
"Follow up question about the topic"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
try:
|
try:
|
||||||
messages = [
|
return gen_speaking_part_3(topic, difficulty)
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": (
|
|
||||||
'You are a helpful assistant designed to output JSON on this format: ' + str(json_format))
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": (
|
|
||||||
'Formulate a set of 5 single questions of hard difficulty for IELTS Speaking Part 3 that encourage candidates to engage in a '
|
|
||||||
'meaningful discussion on the topic of "' + topic + '". Provide inquiries, ensuring '
|
|
||||||
'they explore various aspects, perspectives, and implications related to the topic.'
|
|
||||||
'Make sure that the generated question does not contain forbidden subjects in muslim countries.')
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": 'They must be 1 single question each and not be double-barreled questions.'
|
|
||||||
|
|
||||||
}
|
|
||||||
]
|
|
||||||
token_count = count_total_tokens(messages)
|
|
||||||
response = make_openai_call(GPT_4_O, messages, token_count, GEN_FIELDS, GEN_QUESTION_TEMPERATURE)
|
|
||||||
# Remove the numbers from the questions only if the string starts with a number
|
|
||||||
response["questions"] = [re.sub(r"^\d+\.\s*", "", question) if re.match(r"^\d+\.", question) else question for
|
|
||||||
question in response["questions"]]
|
|
||||||
response["type"] = 3
|
|
||||||
response["difficulty"] = difficulty
|
|
||||||
response["topic"] = topic
|
|
||||||
return response
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -1407,7 +1158,7 @@ def get_reading_passage_1_question():
|
|||||||
topic = request.args.get('topic', default=random.choice(topics))
|
topic = request.args.get('topic', default=random.choice(topics))
|
||||||
req_exercises = request.args.getlist('exercises')
|
req_exercises = request.args.getlist('exercises')
|
||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
return gen_reading_passage_1(topic, req_exercises, difficulty)
|
return gen_reading_passage_1(topic, difficulty, req_exercises)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -1420,7 +1171,7 @@ def get_reading_passage_2_question():
|
|||||||
topic = request.args.get('topic', default=random.choice(topics))
|
topic = request.args.get('topic', default=random.choice(topics))
|
||||||
req_exercises = request.args.getlist('exercises')
|
req_exercises = request.args.getlist('exercises')
|
||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
return gen_reading_passage_2(topic, req_exercises, difficulty)
|
return gen_reading_passage_2(topic, difficulty, req_exercises)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -1433,7 +1184,7 @@ def get_reading_passage_3_question():
|
|||||||
topic = request.args.get('topic', default=random.choice(topics))
|
topic = request.args.get('topic', default=random.choice(topics))
|
||||||
req_exercises = request.args.getlist('exercises')
|
req_exercises = request.args.getlist('exercises')
|
||||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||||
return gen_reading_passage_3(topic, req_exercises, difficulty)
|
return gen_reading_passage_3(topic, difficulty, req_exercises)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -1565,6 +1316,18 @@ class CustomLevelExerciseTypes(Enum):
|
|||||||
MULTIPLE_CHOICE_UNDERLINED = "multiple_choice_underlined"
|
MULTIPLE_CHOICE_UNDERLINED = "multiple_choice_underlined"
|
||||||
BLANK_SPACE_TEXT = "blank_space_text"
|
BLANK_SPACE_TEXT = "blank_space_text"
|
||||||
READING_PASSAGE_UTAS = "reading_passage_utas"
|
READING_PASSAGE_UTAS = "reading_passage_utas"
|
||||||
|
WRITING_LETTER = "writing_letter"
|
||||||
|
WRITING_2 = "writing_2"
|
||||||
|
SPEAKING_1 = "speaking_1"
|
||||||
|
SPEAKING_2 = "speaking_2"
|
||||||
|
SPEAKING_3 = "speaking_3"
|
||||||
|
READING_1 = "reading_1"
|
||||||
|
READING_2 = "reading_2"
|
||||||
|
READING_3 = "reading_3"
|
||||||
|
LISTENING_1 = "listening_1"
|
||||||
|
LISTENING_2 = "listening_2"
|
||||||
|
LISTENING_3 = "listening_3"
|
||||||
|
LISTENING_4 = "listening_4"
|
||||||
|
|
||||||
|
|
||||||
@app.route('/custom_level', methods=['GET'])
|
@app.route('/custom_level', methods=['GET'])
|
||||||
@@ -1579,11 +1342,24 @@ def get_custom_level():
|
|||||||
}
|
}
|
||||||
for i in range(1, nr_exercises + 1, 1):
|
for i in range(1, nr_exercises + 1, 1):
|
||||||
exercise_type = request.args.get('exercise_' + str(i) + '_type')
|
exercise_type = request.args.get('exercise_' + str(i) + '_type')
|
||||||
|
exercise_difficulty = request.args.get('exercise_' + str(i) + '_difficulty',
|
||||||
|
random.choice(['easy', 'medium', 'hard']))
|
||||||
exercise_qty = int(request.args.get('exercise_' + str(i) + '_qty', -1))
|
exercise_qty = int(request.args.get('exercise_' + str(i) + '_qty', -1))
|
||||||
exercise_topic = request.args.get('exercise_' + str(i) + '_topic', random.choice(topics))
|
exercise_topic = request.args.get('exercise_' + str(i) + '_topic', random.choice(topics))
|
||||||
|
exercise_topic_2 = request.args.get('exercise_' + str(i) + '_topic_2', random.choice(topics))
|
||||||
exercise_text_size = int(request.args.get('exercise_' + str(i) + '_text_size', 700))
|
exercise_text_size = int(request.args.get('exercise_' + str(i) + '_text_size', 700))
|
||||||
exercise_sa_qty = int(request.args.get('exercise_' + str(i) + '_sa_qty', -1))
|
exercise_sa_qty = int(request.args.get('exercise_' + str(i) + '_sa_qty', -1))
|
||||||
exercise_mc_qty = int(request.args.get('exercise_' + str(i) + '_mc_qty', -1))
|
exercise_mc_qty = int(request.args.get('exercise_' + str(i) + '_mc_qty', -1))
|
||||||
|
exercise_mc3_qty = int(request.args.get('exercise_' + str(i) + '_mc3_qty', -1))
|
||||||
|
exercise_fillblanks_qty = int(request.args.get('exercise_' + str(i) + '_fillblanks_qty', -1))
|
||||||
|
exercise_writeblanks_qty = int(request.args.get('exercise_' + str(i) + '_writeblanks_qty', -1))
|
||||||
|
exercise_writeblanksquestions_qty = int(
|
||||||
|
request.args.get('exercise_' + str(i) + '_writeblanksquestions_qty', -1))
|
||||||
|
exercise_writeblanksfill_qty = int(request.args.get('exercise_' + str(i) + '_writeblanksfill_qty', -1))
|
||||||
|
exercise_writeblanksform_qty = int(request.args.get('exercise_' + str(i) + '_writeblanksform_qty', -1))
|
||||||
|
exercise_truefalse_qty = int(request.args.get('exercise_' + str(i) + '_truefalse_qty', -1))
|
||||||
|
exercise_paragraphmatch_qty = int(request.args.get('exercise_' + str(i) + '_paragraphmatch_qty', -1))
|
||||||
|
exercise_ideamatch_qty = int(request.args.get('exercise_' + str(i) + '_ideamatch_qty', -1))
|
||||||
|
|
||||||
if exercise_type == CustomLevelExerciseTypes.MULTIPLE_CHOICE_4.value:
|
if exercise_type == CustomLevelExerciseTypes.MULTIPLE_CHOICE_4.value:
|
||||||
response["exercises"]["exercise_" + str(i)] = {}
|
response["exercises"]["exercise_" + str(i)] = {}
|
||||||
@@ -1597,7 +1373,7 @@ def get_custom_level():
|
|||||||
|
|
||||||
response["exercises"]["exercise_" + str(i)]["questions"].extend(
|
response["exercises"]["exercise_" + str(i)]["questions"].extend(
|
||||||
generate_level_mc(exercise_id, qty,
|
generate_level_mc(exercise_id, qty,
|
||||||
response["exercises"]["exercise_" + str(i)]["questions"])["questions"])
|
response["exercises"]["exercise_" + str(i)]["questions"])["questions"])
|
||||||
exercise_id = exercise_id + qty
|
exercise_id = exercise_id + qty
|
||||||
exercise_qty = exercise_qty - qty
|
exercise_qty = exercise_qty - qty
|
||||||
|
|
||||||
@@ -1613,7 +1389,8 @@ def get_custom_level():
|
|||||||
|
|
||||||
response["exercises"]["exercise_" + str(i)]["questions"].extend(
|
response["exercises"]["exercise_" + str(i)]["questions"].extend(
|
||||||
gen_multiple_choice_blank_space_utas(qty, exercise_id,
|
gen_multiple_choice_blank_space_utas(qty, exercise_id,
|
||||||
response["exercises"]["exercise_" + str(i)]["questions"])["questions"])
|
response["exercises"]["exercise_" + str(i)]["questions"])[
|
||||||
|
"questions"])
|
||||||
exercise_id = exercise_id + qty
|
exercise_id = exercise_id + qty
|
||||||
exercise_qty = exercise_qty - qty
|
exercise_qty = exercise_qty - qty
|
||||||
|
|
||||||
@@ -1629,7 +1406,8 @@ def get_custom_level():
|
|||||||
|
|
||||||
response["exercises"]["exercise_" + str(i)]["questions"].extend(
|
response["exercises"]["exercise_" + str(i)]["questions"].extend(
|
||||||
gen_multiple_choice_underlined_utas(qty, exercise_id,
|
gen_multiple_choice_underlined_utas(qty, exercise_id,
|
||||||
response["exercises"]["exercise_" + str(i)]["questions"])["questions"])
|
response["exercises"]["exercise_" + str(i)]["questions"])[
|
||||||
|
"questions"])
|
||||||
exercise_id = exercise_id + qty
|
exercise_id = exercise_id + qty
|
||||||
exercise_qty = exercise_qty - qty
|
exercise_qty = exercise_qty - qty
|
||||||
|
|
||||||
@@ -1643,9 +1421,205 @@ def get_custom_level():
|
|||||||
exercise_mc_qty, exercise_topic)
|
exercise_mc_qty, exercise_topic)
|
||||||
response["exercises"]["exercise_" + str(i)]["type"] = "readingExercises"
|
response["exercises"]["exercise_" + str(i)]["type"] = "readingExercises"
|
||||||
exercise_id = exercise_id + exercise_qty
|
exercise_id = exercise_id + exercise_qty
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.WRITING_LETTER.value:
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_writing_task_1(exercise_topic, exercise_difficulty)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "writing"
|
||||||
|
exercise_id = exercise_id + 1
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.WRITING_2.value:
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_writing_task_2(exercise_topic, exercise_difficulty)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "writing"
|
||||||
|
exercise_id = exercise_id + 1
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.SPEAKING_1.value:
|
||||||
|
response["exercises"]["exercise_" + str(i)] = (
|
||||||
|
gen_speaking_part_1(exercise_topic, exercise_topic_2, exercise_difficulty))
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "interactiveSpeaking"
|
||||||
|
exercise_id = exercise_id + 1
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.SPEAKING_2.value:
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_speaking_part_2(exercise_topic, exercise_difficulty)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "speaking"
|
||||||
|
exercise_id = exercise_id + 1
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.SPEAKING_3.value:
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_speaking_part_3(exercise_topic, exercise_difficulty)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "interactiveSpeaking"
|
||||||
|
exercise_id = exercise_id + 1
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.READING_1.value:
|
||||||
|
exercises = []
|
||||||
|
exercise_qty_q = queue.Queue()
|
||||||
|
total_qty = 0
|
||||||
|
if exercise_fillblanks_qty != -1:
|
||||||
|
exercises.append('fillBlanks')
|
||||||
|
exercise_qty_q.put(exercise_fillblanks_qty)
|
||||||
|
total_qty = total_qty + exercise_fillblanks_qty
|
||||||
|
if exercise_writeblanks_qty != -1:
|
||||||
|
exercises.append('writeBlanks')
|
||||||
|
exercise_qty_q.put(exercise_writeblanks_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanks_qty
|
||||||
|
if exercise_truefalse_qty != -1:
|
||||||
|
exercises.append('trueFalse')
|
||||||
|
exercise_qty_q.put(exercise_truefalse_qty)
|
||||||
|
total_qty = total_qty + exercise_truefalse_qty
|
||||||
|
if exercise_paragraphmatch_qty != -1:
|
||||||
|
exercises.append('paragraphMatch')
|
||||||
|
exercise_qty_q.put(exercise_paragraphmatch_qty)
|
||||||
|
total_qty = total_qty + exercise_paragraphmatch_qty
|
||||||
|
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_reading_passage_1(exercise_topic, exercise_difficulty,
|
||||||
|
exercises, exercise_qty_q, exercise_id)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "reading"
|
||||||
|
|
||||||
|
exercise_id = exercise_id + total_qty
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.READING_2.value:
|
||||||
|
exercises = []
|
||||||
|
exercise_qty_q = queue.Queue()
|
||||||
|
total_qty = 0
|
||||||
|
if exercise_fillblanks_qty != -1:
|
||||||
|
exercises.append('fillBlanks')
|
||||||
|
exercise_qty_q.put(exercise_fillblanks_qty)
|
||||||
|
total_qty = total_qty + exercise_fillblanks_qty
|
||||||
|
if exercise_writeblanks_qty != -1:
|
||||||
|
exercises.append('writeBlanks')
|
||||||
|
exercise_qty_q.put(exercise_writeblanks_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanks_qty
|
||||||
|
if exercise_truefalse_qty != -1:
|
||||||
|
exercises.append('trueFalse')
|
||||||
|
exercise_qty_q.put(exercise_truefalse_qty)
|
||||||
|
total_qty = total_qty + exercise_truefalse_qty
|
||||||
|
if exercise_paragraphmatch_qty != -1:
|
||||||
|
exercises.append('paragraphMatch')
|
||||||
|
exercise_qty_q.put(exercise_paragraphmatch_qty)
|
||||||
|
total_qty = total_qty + exercise_paragraphmatch_qty
|
||||||
|
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_reading_passage_2(exercise_topic, exercise_difficulty,
|
||||||
|
exercises, exercise_qty_q, exercise_id)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "reading"
|
||||||
|
|
||||||
|
exercise_id = exercise_id + total_qty
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.READING_3.value:
|
||||||
|
exercises = []
|
||||||
|
exercise_qty_q = queue.Queue()
|
||||||
|
total_qty = 0
|
||||||
|
if exercise_fillblanks_qty != -1:
|
||||||
|
exercises.append('fillBlanks')
|
||||||
|
exercise_qty_q.put(exercise_fillblanks_qty)
|
||||||
|
total_qty = total_qty + exercise_fillblanks_qty
|
||||||
|
if exercise_writeblanks_qty != -1:
|
||||||
|
exercises.append('writeBlanks')
|
||||||
|
exercise_qty_q.put(exercise_writeblanks_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanks_qty
|
||||||
|
if exercise_truefalse_qty != -1:
|
||||||
|
exercises.append('trueFalse')
|
||||||
|
exercise_qty_q.put(exercise_truefalse_qty)
|
||||||
|
total_qty = total_qty + exercise_truefalse_qty
|
||||||
|
if exercise_paragraphmatch_qty != -1:
|
||||||
|
exercises.append('paragraphMatch')
|
||||||
|
exercise_qty_q.put(exercise_paragraphmatch_qty)
|
||||||
|
total_qty = total_qty + exercise_paragraphmatch_qty
|
||||||
|
if exercise_ideamatch_qty != -1:
|
||||||
|
exercises.append('ideaMatch')
|
||||||
|
exercise_qty_q.put(exercise_ideamatch_qty)
|
||||||
|
total_qty = total_qty + exercise_ideamatch_qty
|
||||||
|
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_reading_passage_3(exercise_topic, exercise_difficulty,
|
||||||
|
exercises, exercise_qty_q, exercise_id)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "reading"
|
||||||
|
|
||||||
|
exercise_id = exercise_id + total_qty
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.LISTENING_1.value:
|
||||||
|
exercises = []
|
||||||
|
exercise_qty_q = queue.Queue()
|
||||||
|
total_qty = 0
|
||||||
|
if exercise_mc_qty != -1:
|
||||||
|
exercises.append('multipleChoice')
|
||||||
|
exercise_qty_q.put(exercise_mc_qty)
|
||||||
|
total_qty = total_qty + exercise_mc_qty
|
||||||
|
if exercise_writeblanksquestions_qty != -1:
|
||||||
|
exercises.append('writeBlanksQuestions')
|
||||||
|
exercise_qty_q.put(exercise_writeblanksquestions_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanksquestions_qty
|
||||||
|
if exercise_writeblanksfill_qty != -1:
|
||||||
|
exercises.append('writeBlanksFill')
|
||||||
|
exercise_qty_q.put(exercise_writeblanksfill_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanksfill_qty
|
||||||
|
if exercise_writeblanksform_qty != -1:
|
||||||
|
exercises.append('writeBlanksForm')
|
||||||
|
exercise_qty_q.put(exercise_writeblanksform_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanksform_qty
|
||||||
|
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_listening_section_1(exercise_topic, exercise_difficulty,
|
||||||
|
exercises, exercise_qty_q,
|
||||||
|
exercise_id)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "listening"
|
||||||
|
|
||||||
|
exercise_id = exercise_id + total_qty
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.LISTENING_2.value:
|
||||||
|
exercises = []
|
||||||
|
exercise_qty_q = queue.Queue()
|
||||||
|
total_qty = 0
|
||||||
|
if exercise_mc_qty != -1:
|
||||||
|
exercises.append('multipleChoice')
|
||||||
|
exercise_qty_q.put(exercise_mc_qty)
|
||||||
|
total_qty = total_qty + exercise_mc_qty
|
||||||
|
if exercise_writeblanksquestions_qty != -1:
|
||||||
|
exercises.append('writeBlanksQuestions')
|
||||||
|
exercise_qty_q.put(exercise_writeblanksquestions_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanksquestions_qty
|
||||||
|
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_listening_section_2(exercise_topic, exercise_difficulty,
|
||||||
|
exercises, exercise_qty_q,
|
||||||
|
exercise_id)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "listening"
|
||||||
|
|
||||||
|
exercise_id = exercise_id + total_qty
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.LISTENING_3.value:
|
||||||
|
exercises = []
|
||||||
|
exercise_qty_q = queue.Queue()
|
||||||
|
total_qty = 0
|
||||||
|
if exercise_mc3_qty != -1:
|
||||||
|
exercises.append('multipleChoice3Options')
|
||||||
|
exercise_qty_q.put(exercise_mc3_qty)
|
||||||
|
total_qty = total_qty + exercise_mc3_qty
|
||||||
|
if exercise_writeblanksquestions_qty != -1:
|
||||||
|
exercises.append('writeBlanksQuestions')
|
||||||
|
exercise_qty_q.put(exercise_writeblanksquestions_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanksquestions_qty
|
||||||
|
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_listening_section_3(exercise_topic, exercise_difficulty,
|
||||||
|
exercises, exercise_qty_q,
|
||||||
|
exercise_id)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "listening"
|
||||||
|
|
||||||
|
exercise_id = exercise_id + total_qty
|
||||||
|
elif exercise_type == CustomLevelExerciseTypes.LISTENING_4.value:
|
||||||
|
exercises = []
|
||||||
|
exercise_qty_q = queue.Queue()
|
||||||
|
total_qty = 0
|
||||||
|
if exercise_mc_qty != -1:
|
||||||
|
exercises.append('multipleChoice')
|
||||||
|
exercise_qty_q.put(exercise_mc_qty)
|
||||||
|
total_qty = total_qty + exercise_mc_qty
|
||||||
|
if exercise_writeblanksquestions_qty != -1:
|
||||||
|
exercises.append('writeBlanksQuestions')
|
||||||
|
exercise_qty_q.put(exercise_writeblanksquestions_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanksquestions_qty
|
||||||
|
if exercise_writeblanksfill_qty != -1:
|
||||||
|
exercises.append('writeBlanksFill')
|
||||||
|
exercise_qty_q.put(exercise_writeblanksfill_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanksfill_qty
|
||||||
|
if exercise_writeblanksform_qty != -1:
|
||||||
|
exercises.append('writeBlanksForm')
|
||||||
|
exercise_qty_q.put(exercise_writeblanksform_qty)
|
||||||
|
total_qty = total_qty + exercise_writeblanksform_qty
|
||||||
|
|
||||||
|
response["exercises"]["exercise_" + str(i)] = gen_listening_section_4(exercise_topic, exercise_difficulty,
|
||||||
|
exercises, exercise_qty_q,
|
||||||
|
exercise_id)
|
||||||
|
response["exercises"]["exercise_" + str(i)]["type"] = "listening"
|
||||||
|
|
||||||
|
exercise_id = exercise_id + total_qty
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@app.route('/grade_short_answers', methods=['POST'])
|
@app.route('/grade_short_answers', methods=['POST'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def grade_short_answers():
|
def grade_short_answers():
|
||||||
@@ -1670,7 +1644,8 @@ def grade_short_answers():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": 'Grade these answers according to the text content and write a correct answer if they are wrong. Text, questions and answers:\n ' + str(data)
|
"content": 'Grade these answers according to the text content and write a correct answer if they are '
|
||||||
|
'wrong. Text, questions and answers:\n ' + str(data)
|
||||||
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1680,6 +1655,7 @@ def grade_short_answers():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/fetch_tips', methods=['POST'])
|
@app.route('/fetch_tips', methods=['POST'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def fetch_answer_tips():
|
def fetch_answer_tips():
|
||||||
|
|||||||
@@ -15,19 +15,19 @@ from helper.speech_to_text_helper import has_x_words
|
|||||||
nltk.download('words')
|
nltk.download('words')
|
||||||
|
|
||||||
|
|
||||||
def gen_reading_passage_1(topic, req_exercises, difficulty):
|
def gen_reading_passage_1(topic, difficulty, req_exercises, number_of_exercises_q=queue.Queue(), start_id=1):
|
||||||
if (len(req_exercises) == 0):
|
if (len(req_exercises) == 0):
|
||||||
req_exercises = random.sample(READING_EXERCISE_TYPES, 2)
|
req_exercises = random.sample(READING_EXERCISE_TYPES, 2)
|
||||||
|
|
||||||
number_of_exercises_q = divide_number_into_parts(TOTAL_READING_PASSAGE_1_EXERCISES, len(req_exercises))
|
if (number_of_exercises_q.empty()):
|
||||||
|
number_of_exercises_q = divide_number_into_parts(TOTAL_READING_PASSAGE_1_EXERCISES, len(req_exercises))
|
||||||
|
|
||||||
passage = generate_reading_passage_1_text(topic)
|
passage = generate_reading_passage_1_text(topic)
|
||||||
if passage == "":
|
if passage == "":
|
||||||
return gen_reading_passage_1(topic, req_exercises, difficulty)
|
return gen_reading_passage_1(topic, difficulty, req_exercises, number_of_exercises_q, start_id)
|
||||||
start_id = 1
|
|
||||||
exercises = generate_reading_exercises(passage["text"], req_exercises, number_of_exercises_q, start_id, difficulty)
|
exercises = generate_reading_exercises(passage["text"], req_exercises, number_of_exercises_q, start_id, difficulty)
|
||||||
if contains_empty_dict(exercises):
|
if contains_empty_dict(exercises):
|
||||||
return gen_reading_passage_1(topic, req_exercises, difficulty)
|
return gen_reading_passage_1(topic, difficulty, req_exercises, number_of_exercises_q, start_id)
|
||||||
return {
|
return {
|
||||||
"exercises": exercises,
|
"exercises": exercises,
|
||||||
"text": {
|
"text": {
|
||||||
@@ -38,19 +38,19 @@ def gen_reading_passage_1(topic, req_exercises, difficulty):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def gen_reading_passage_2(topic, req_exercises, difficulty):
|
def gen_reading_passage_2(topic, difficulty, req_exercises, number_of_exercises_q=queue.Queue(), start_id=14):
|
||||||
if (len(req_exercises) == 0):
|
if (len(req_exercises) == 0):
|
||||||
req_exercises = random.sample(READING_EXERCISE_TYPES, 2)
|
req_exercises = random.sample(READING_EXERCISE_TYPES, 2)
|
||||||
|
|
||||||
number_of_exercises_q = divide_number_into_parts(TOTAL_READING_PASSAGE_2_EXERCISES, len(req_exercises))
|
if (number_of_exercises_q.empty()):
|
||||||
|
number_of_exercises_q = divide_number_into_parts(TOTAL_READING_PASSAGE_2_EXERCISES, len(req_exercises))
|
||||||
|
|
||||||
passage = generate_reading_passage_2_text(topic)
|
passage = generate_reading_passage_2_text(topic)
|
||||||
if passage == "":
|
if passage == "":
|
||||||
return gen_reading_passage_2(topic, req_exercises, difficulty)
|
return gen_reading_passage_2(topic, difficulty, req_exercises, number_of_exercises_q, start_id)
|
||||||
start_id = 14
|
|
||||||
exercises = generate_reading_exercises(passage["text"], req_exercises, number_of_exercises_q, start_id, difficulty)
|
exercises = generate_reading_exercises(passage["text"], req_exercises, number_of_exercises_q, start_id, difficulty)
|
||||||
if contains_empty_dict(exercises):
|
if contains_empty_dict(exercises):
|
||||||
return gen_reading_passage_2(topic, req_exercises, difficulty)
|
return gen_reading_passage_2(topic, difficulty, req_exercises, number_of_exercises_q, start_id)
|
||||||
return {
|
return {
|
||||||
"exercises": exercises,
|
"exercises": exercises,
|
||||||
"text": {
|
"text": {
|
||||||
@@ -61,19 +61,19 @@ def gen_reading_passage_2(topic, req_exercises, difficulty):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def gen_reading_passage_3(topic, req_exercises, difficulty):
|
def gen_reading_passage_3(topic, difficulty, req_exercises, number_of_exercises_q=queue.Queue(), start_id=27):
|
||||||
if (len(req_exercises) == 0):
|
if (len(req_exercises) == 0):
|
||||||
req_exercises = random.sample(READING_EXERCISE_TYPES, 2)
|
req_exercises = random.sample(READING_EXERCISE_TYPES, 2)
|
||||||
|
|
||||||
number_of_exercises_q = divide_number_into_parts(TOTAL_READING_PASSAGE_3_EXERCISES, len(req_exercises))
|
if (number_of_exercises_q.empty()):
|
||||||
|
number_of_exercises_q = divide_number_into_parts(TOTAL_READING_PASSAGE_3_EXERCISES, len(req_exercises))
|
||||||
|
|
||||||
passage = generate_reading_passage_3_text(topic)
|
passage = generate_reading_passage_3_text(topic)
|
||||||
if passage == "":
|
if passage == "":
|
||||||
return gen_reading_passage_3(topic, req_exercises, difficulty)
|
return gen_reading_passage_3(topic, difficulty, req_exercises, number_of_exercises_q, start_id)
|
||||||
start_id = 27
|
|
||||||
exercises = generate_reading_exercises(passage["text"], req_exercises, number_of_exercises_q, start_id, difficulty)
|
exercises = generate_reading_exercises(passage["text"], req_exercises, number_of_exercises_q, start_id, difficulty)
|
||||||
if contains_empty_dict(exercises):
|
if contains_empty_dict(exercises):
|
||||||
return gen_reading_passage_3(topic, req_exercises, difficulty)
|
return gen_reading_passage_3(topic, difficulty, req_exercises, number_of_exercises_q, start_id)
|
||||||
return {
|
return {
|
||||||
"exercises": exercises,
|
"exercises": exercises,
|
||||||
"text": {
|
"text": {
|
||||||
@@ -865,7 +865,8 @@ def gen_idea_match_exercise(text: str, quantity: int, start_id):
|
|||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": (
|
"content": (
|
||||||
'From the text extract ' + str(quantity) + ' ideas, theories, opinions and who they are from. The text: ' + str(text))
|
'From the text extract ' + str(
|
||||||
|
quantity) + ' ideas, theories, opinions and who they are from. The text: ' + str(text))
|
||||||
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -882,6 +883,7 @@ def gen_idea_match_exercise(text: str, quantity: int, start_id):
|
|||||||
"type": "matchSentences"
|
"type": "matchSentences"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def build_options(ideas):
|
def build_options(ideas):
|
||||||
options = []
|
options = []
|
||||||
letters = iter(string.ascii_uppercase)
|
letters = iter(string.ascii_uppercase)
|
||||||
@@ -892,6 +894,7 @@ def build_options(ideas):
|
|||||||
})
|
})
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
|
||||||
def build_sentences(ideas, start_id):
|
def build_sentences(ideas, start_id):
|
||||||
sentences = []
|
sentences = []
|
||||||
letters = iter(string.ascii_uppercase)
|
letters = iter(string.ascii_uppercase)
|
||||||
@@ -906,6 +909,7 @@ def build_sentences(ideas, start_id):
|
|||||||
sentence["id"] = i
|
sentence["id"] = i
|
||||||
return sentences
|
return sentences
|
||||||
|
|
||||||
|
|
||||||
def assign_letters_to_paragraphs(paragraphs):
|
def assign_letters_to_paragraphs(paragraphs):
|
||||||
result = []
|
result = []
|
||||||
letters = iter(string.ascii_uppercase)
|
letters = iter(string.ascii_uppercase)
|
||||||
@@ -1272,7 +1276,8 @@ def replace_exercise_if_exists(all_exams, current_exercise, current_exam, seen_k
|
|||||||
current_exercise["options"])
|
current_exercise["options"])
|
||||||
for exercise in exercise_dict.get("exercises", [])[0]["questions"]
|
for exercise in exercise_dict.get("exercises", [])[0]["questions"]
|
||||||
):
|
):
|
||||||
return replace_exercise_if_exists(all_exams, generate_single_mc_level_question(), current_exam, seen_keys)
|
return replace_exercise_if_exists(all_exams, generate_single_mc_level_question(), current_exam,
|
||||||
|
seen_keys)
|
||||||
return current_exercise, seen_keys
|
return current_exercise, seen_keys
|
||||||
|
|
||||||
|
|
||||||
@@ -1302,7 +1307,8 @@ def replace_blank_space_exercise_if_exists_utas(all_exams, current_exercise, cur
|
|||||||
key = (current_exercise['prompt'], tuple(sorted(option['text'] for option in current_exercise['options'])))
|
key = (current_exercise['prompt'], tuple(sorted(option['text'] for option in current_exercise['options'])))
|
||||||
# Check if the key is in the set
|
# Check if the key is in the set
|
||||||
if key in seen_keys:
|
if key in seen_keys:
|
||||||
return replace_exercise_if_exists_utas(all_exams, generate_single_mc_blank_space_level_question(), current_exam, seen_keys)
|
return replace_exercise_if_exists_utas(all_exams, generate_single_mc_blank_space_level_question(), current_exam,
|
||||||
|
seen_keys)
|
||||||
else:
|
else:
|
||||||
seen_keys.add(key)
|
seen_keys.add(key)
|
||||||
|
|
||||||
@@ -1313,7 +1319,8 @@ def replace_blank_space_exercise_if_exists_utas(all_exams, current_exercise, cur
|
|||||||
current_exercise["options"])
|
current_exercise["options"])
|
||||||
for exercise in exam.get("questions", [])
|
for exercise in exam.get("questions", [])
|
||||||
):
|
):
|
||||||
return replace_exercise_if_exists_utas(all_exams, generate_single_mc_blank_space_level_question(), current_exam,
|
return replace_exercise_if_exists_utas(all_exams, generate_single_mc_blank_space_level_question(),
|
||||||
|
current_exam,
|
||||||
seen_keys)
|
seen_keys)
|
||||||
return current_exercise, seen_keys
|
return current_exercise, seen_keys
|
||||||
|
|
||||||
@@ -1323,7 +1330,8 @@ def replace_underlined_exercise_if_exists_utas(all_exams, current_exercise, curr
|
|||||||
key = (current_exercise['prompt'], tuple(sorted(option['text'] for option in current_exercise['options'])))
|
key = (current_exercise['prompt'], tuple(sorted(option['text'] for option in current_exercise['options'])))
|
||||||
# Check if the key is in the set
|
# Check if the key is in the set
|
||||||
if key in seen_keys:
|
if key in seen_keys:
|
||||||
return replace_exercise_if_exists_utas(all_exams, generate_single_mc_underlined_level_question(), current_exam, seen_keys)
|
return replace_exercise_if_exists_utas(all_exams, generate_single_mc_underlined_level_question(), current_exam,
|
||||||
|
seen_keys)
|
||||||
else:
|
else:
|
||||||
seen_keys.add(key)
|
seen_keys.add(key)
|
||||||
|
|
||||||
@@ -1334,7 +1342,8 @@ def replace_underlined_exercise_if_exists_utas(all_exams, current_exercise, curr
|
|||||||
current_exercise["options"])
|
current_exercise["options"])
|
||||||
for exercise in exam.get("questions", [])
|
for exercise in exam.get("questions", [])
|
||||||
):
|
):
|
||||||
return replace_exercise_if_exists_utas(all_exams, generate_single_mc_underlined_level_question(), current_exam,
|
return replace_exercise_if_exists_utas(all_exams, generate_single_mc_underlined_level_question(),
|
||||||
|
current_exam,
|
||||||
seen_keys)
|
seen_keys)
|
||||||
return current_exercise, seen_keys
|
return current_exercise, seen_keys
|
||||||
|
|
||||||
@@ -1376,8 +1385,8 @@ def generate_single_mc_blank_space_level_question():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": ('Generate 1 multiple choice blank space question of 4 options for an english level exam, it can be easy, '
|
"content": ('Generate 1 multiple choice blank space question of 4 options for an english level exam, '
|
||||||
'intermediate or advanced.')
|
'it can be easy, intermediate or advanced.')
|
||||||
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1401,8 +1410,8 @@ def generate_single_mc_underlined_level_question():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": ('Generate 1 multiple choice blank space question of 4 options for an english level exam, it can be easy, '
|
"content": ('Generate 1 multiple choice blank space question of 4 options for an english level exam, '
|
||||||
'intermediate or advanced.')
|
'it can be easy, intermediate or advanced.')
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1469,9 +1478,9 @@ def gen_multiple_choice_blank_space_utas(quantity: int, start_id: int, all_exams
|
|||||||
if all_exams is not None:
|
if all_exams is not None:
|
||||||
seen_keys = set()
|
seen_keys = set()
|
||||||
for i in range(len(question["questions"])):
|
for i in range(len(question["questions"])):
|
||||||
question["questions"][i], seen_keys = replace_blank_space_exercise_if_exists_utas(all_exams, question["questions"][i],
|
question["questions"][i], seen_keys = (
|
||||||
question,
|
replace_blank_space_exercise_if_exists_utas(all_exams, question["questions"][i], question,
|
||||||
seen_keys)
|
seen_keys))
|
||||||
response = fix_exercise_ids(question, start_id)
|
response = fix_exercise_ids(question, start_id)
|
||||||
response["questions"] = randomize_mc_options_order(response["questions"])
|
response["questions"] = randomize_mc_options_order(response["questions"])
|
||||||
return response
|
return response
|
||||||
@@ -1546,11 +1555,9 @@ def gen_multiple_choice_underlined_utas(quantity: int, start_id: int, all_exams=
|
|||||||
if all_exams is not None:
|
if all_exams is not None:
|
||||||
seen_keys = set()
|
seen_keys = set()
|
||||||
for i in range(len(question["questions"])):
|
for i in range(len(question["questions"])):
|
||||||
question["questions"][i], seen_keys = replace_underlined_exercise_if_exists_utas(all_exams,
|
question["questions"][i], seen_keys = (
|
||||||
question["questions"][
|
replace_underlined_exercise_if_exists_utas(all_exams, question["questions"][i], question,
|
||||||
i],
|
seen_keys))
|
||||||
question,
|
|
||||||
seen_keys)
|
|
||||||
response = fix_exercise_ids(question, start_id)
|
response = fix_exercise_ids(question, start_id)
|
||||||
response["questions"] = randomize_mc_options_order(response["questions"])
|
response["questions"] = randomize_mc_options_order(response["questions"])
|
||||||
return response
|
return response
|
||||||
@@ -1765,7 +1772,8 @@ def generate_level_mc(start_id: int, quantity: int, all_questions=None):
|
|||||||
if all_questions is not None:
|
if all_questions is not None:
|
||||||
seen_keys = set()
|
seen_keys = set()
|
||||||
for i in range(len(question["questions"])):
|
for i in range(len(question["questions"])):
|
||||||
question["questions"][i], seen_keys = replace_exercise_if_exists_utas(all_questions, question["questions"][i],
|
question["questions"][i], seen_keys = replace_exercise_if_exists_utas(all_questions,
|
||||||
|
question["questions"][i],
|
||||||
question,
|
question,
|
||||||
seen_keys)
|
seen_keys)
|
||||||
response = fix_exercise_ids(question, start_id)
|
response = fix_exercise_ids(question, start_id)
|
||||||
@@ -1791,3 +1799,293 @@ def randomize_mc_options_order(questions):
|
|||||||
question['solution'] = option['id']
|
question['solution'] = option['id']
|
||||||
|
|
||||||
return questions
|
return questions
|
||||||
|
|
||||||
|
|
||||||
|
def gen_writing_task_1(topic, difficulty):
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": ('You are a helpful assistant designed to output JSON on this format: '
|
||||||
|
'{"prompt": "prompt content"}')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": ('Craft a prompt for an IELTS Writing Task 1 General Training exercise that instructs the '
|
||||||
|
'student to compose a letter. The prompt should present a specific scenario or situation, '
|
||||||
|
'based on the topic of "' + topic + '", requiring the student to provide information, '
|
||||||
|
'advice, or instructions within the letter. '
|
||||||
|
'Make sure that the generated prompt is '
|
||||||
|
'of ' + difficulty + 'difficulty and does not contain '
|
||||||
|
'forbidden subjects in muslim '
|
||||||
|
'countries.')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": 'The prompt should end with "In the letter you should" followed by 3 bullet points of what '
|
||||||
|
'the answer should include.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
token_count = count_total_tokens(messages)
|
||||||
|
response = make_openai_call(GPT_3_5_TURBO, messages, token_count, "prompt",
|
||||||
|
GEN_QUESTION_TEMPERATURE)
|
||||||
|
return {
|
||||||
|
"question": add_newline_before_hyphen(response["prompt"].strip()),
|
||||||
|
"difficulty": difficulty,
|
||||||
|
"topic": topic
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def add_newline_before_hyphen(s):
|
||||||
|
return s.replace(" -", "\n-")
|
||||||
|
|
||||||
|
|
||||||
|
def gen_writing_task_2(topic, difficulty):
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": ('You are a helpful assistant designed to output JSON on this format: '
|
||||||
|
'{"prompt": "prompt content"}')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": (
|
||||||
|
'Craft a comprehensive question of ' + difficulty + 'difficulty like the ones for IELTS Writing '
|
||||||
|
'Task 2 General Training that directs the '
|
||||||
|
'candidate'
|
||||||
|
'to delve into an in-depth analysis of '
|
||||||
|
'contrasting perspectives on the topic '
|
||||||
|
'of "' + topic + '". The candidate should be '
|
||||||
|
'asked to discuss the '
|
||||||
|
'strengths and weaknesses of '
|
||||||
|
'both viewpoints.')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": 'The question should lead to an answer with either "theories", "complicated information" or '
|
||||||
|
'be "very descriptive" on the topic.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
token_count = count_total_tokens(messages)
|
||||||
|
response = make_openai_call(GPT_4_O, messages, token_count, "prompt", GEN_QUESTION_TEMPERATURE)
|
||||||
|
return {
|
||||||
|
"question": response["prompt"].strip(),
|
||||||
|
"difficulty": difficulty,
|
||||||
|
"topic": topic
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def gen_speaking_part_1(first_topic: str, second_topic: str, difficulty):
|
||||||
|
json_format = {
|
||||||
|
"first_topic": "topic 1",
|
||||||
|
"second_topic": "topic 2",
|
||||||
|
"questions": [
|
||||||
|
"Introductory question about the first topic, starting the topic with 'Let's talk about x' and then the "
|
||||||
|
"question.",
|
||||||
|
"Follow up question about the first topic",
|
||||||
|
"Follow up question about the first topic",
|
||||||
|
"Question about second topic",
|
||||||
|
"Follow up question about the second topic",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": (
|
||||||
|
'You are a helpful assistant designed to output JSON on this format: ' + str(json_format))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": (
|
||||||
|
'Craft 5 simple and single questions of easy difficulty for IELTS Speaking Part 1 '
|
||||||
|
'that encourages candidates to delve deeply into '
|
||||||
|
'personal experiences, preferences, or insights on the topic '
|
||||||
|
'of "' + first_topic + '" and the topic of "' + second_topic + '". '
|
||||||
|
'Make sure that the generated '
|
||||||
|
'question'
|
||||||
|
'does not contain forbidden '
|
||||||
|
'subjects in'
|
||||||
|
'muslim countries.')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": 'The questions should lead to the usage of 4 verb tenses (present perfect, present, '
|
||||||
|
'past and future).'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": 'They must be 1 single question each and not be double-barreled questions.'
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
token_count = count_total_tokens(messages)
|
||||||
|
response = make_openai_call(GPT_4_O, messages, token_count, ["first_topic"],
|
||||||
|
GEN_QUESTION_TEMPERATURE)
|
||||||
|
response["type"] = 1
|
||||||
|
response["difficulty"] = difficulty
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def gen_speaking_part_2(topic: str, difficulty):
|
||||||
|
json_format = {
|
||||||
|
"topic": "topic",
|
||||||
|
"question": "question",
|
||||||
|
"prompts": [
|
||||||
|
"prompt_1",
|
||||||
|
"prompt_2",
|
||||||
|
"prompt_3"
|
||||||
|
],
|
||||||
|
"suffix": "And explain why..."
|
||||||
|
}
|
||||||
|
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": 'You are a helpful assistant designed to output JSON on this format: ' + str(json_format)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": (
|
||||||
|
'Create a question of medium difficulty for IELTS Speaking Part 2 '
|
||||||
|
'that encourages candidates to narrate a '
|
||||||
|
'personal experience or story related to the topic '
|
||||||
|
'of "' + topic + '". Include 3 prompts that '
|
||||||
|
'guide the candidate to describe '
|
||||||
|
'specific aspects of the experience, '
|
||||||
|
'such as details about the situation, '
|
||||||
|
'their actions, and the reasons it left a '
|
||||||
|
'lasting impression. Make sure that the '
|
||||||
|
'generated question does not contain '
|
||||||
|
'forbidden subjects in muslim countries.')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": 'The prompts must not be questions. Also include a suffix like the ones in the IELTS exams '
|
||||||
|
'that start with "And explain why".'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
token_count = count_total_tokens(messages)
|
||||||
|
response = make_openai_call(GPT_4_O, messages, token_count, GEN_FIELDS, GEN_QUESTION_TEMPERATURE)
|
||||||
|
response["type"] = 2
|
||||||
|
response["difficulty"] = difficulty
|
||||||
|
response["topic"] = topic
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def gen_speaking_part_3(topic: str, difficulty):
|
||||||
|
json_format = {
|
||||||
|
"topic": "topic",
|
||||||
|
"questions": [
|
||||||
|
"Introductory question about the topic.",
|
||||||
|
"Follow up question about the topic",
|
||||||
|
"Follow up question about the topic",
|
||||||
|
"Follow up question about the topic",
|
||||||
|
"Follow up question about the topic"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": (
|
||||||
|
'You are a helpful assistant designed to output JSON on this format: ' + str(json_format))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": (
|
||||||
|
'Formulate a set of 5 single questions of hard difficulty for IELTS Speaking Part 3 that encourage candidates to engage in a '
|
||||||
|
'meaningful discussion on the topic of "' + topic + '". Provide inquiries, ensuring '
|
||||||
|
'they explore various aspects, perspectives, and implications related to the topic.'
|
||||||
|
'Make sure that the generated question does not contain forbidden subjects in muslim countries.')
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": 'They must be 1 single question each and not be double-barreled questions.'
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
token_count = count_total_tokens(messages)
|
||||||
|
response = make_openai_call(GPT_4_O, messages, token_count, GEN_FIELDS, GEN_QUESTION_TEMPERATURE)
|
||||||
|
# Remove the numbers from the questions only if the string starts with a number
|
||||||
|
response["questions"] = [re.sub(r"^\d+\.\s*", "", question) if re.match(r"^\d+\.", question) else question for
|
||||||
|
question in response["questions"]]
|
||||||
|
response["type"] = 3
|
||||||
|
response["difficulty"] = difficulty
|
||||||
|
response["topic"] = topic
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def gen_listening_section_1(topic, difficulty, req_exercises, number_of_exercises_q=queue.Queue(), start_id=1):
|
||||||
|
if (len(req_exercises) == 0):
|
||||||
|
req_exercises = random.sample(LISTENING_1_EXERCISE_TYPES, 1)
|
||||||
|
|
||||||
|
if (number_of_exercises_q.empty()):
|
||||||
|
number_of_exercises_q = divide_number_into_parts(TOTAL_LISTENING_SECTION_1_EXERCISES, len(req_exercises))
|
||||||
|
|
||||||
|
processed_conversation = generate_listening_1_conversation(topic)
|
||||||
|
|
||||||
|
exercises = generate_listening_conversation_exercises(parse_conversation(processed_conversation),
|
||||||
|
req_exercises,
|
||||||
|
number_of_exercises_q,
|
||||||
|
start_id, difficulty)
|
||||||
|
return {
|
||||||
|
"exercises": exercises,
|
||||||
|
"text": processed_conversation,
|
||||||
|
"difficulty": difficulty
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def gen_listening_section_2(topic, difficulty, req_exercises, number_of_exercises_q=queue.Queue(), start_id=11):
|
||||||
|
if (len(req_exercises) == 0):
|
||||||
|
req_exercises = random.sample(LISTENING_2_EXERCISE_TYPES, 2)
|
||||||
|
|
||||||
|
if (number_of_exercises_q.empty()):
|
||||||
|
number_of_exercises_q = divide_number_into_parts(TOTAL_LISTENING_SECTION_2_EXERCISES, len(req_exercises))
|
||||||
|
|
||||||
|
monologue = generate_listening_2_monologue(topic)
|
||||||
|
|
||||||
|
exercises = generate_listening_monologue_exercises(str(monologue), req_exercises, number_of_exercises_q,
|
||||||
|
start_id, difficulty)
|
||||||
|
return {
|
||||||
|
"exercises": exercises,
|
||||||
|
"text": monologue,
|
||||||
|
"difficulty": difficulty
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def gen_listening_section_3(topic, difficulty, req_exercises, number_of_exercises_q=queue.Queue(), start_id=21):
|
||||||
|
if (len(req_exercises) == 0):
|
||||||
|
req_exercises = random.sample(LISTENING_3_EXERCISE_TYPES, 1)
|
||||||
|
|
||||||
|
if (number_of_exercises_q.empty()):
|
||||||
|
number_of_exercises_q = divide_number_into_parts(TOTAL_LISTENING_SECTION_3_EXERCISES, len(req_exercises))
|
||||||
|
|
||||||
|
processed_conversation = generate_listening_3_conversation(topic)
|
||||||
|
|
||||||
|
exercises = generate_listening_conversation_exercises(parse_conversation(processed_conversation), req_exercises,
|
||||||
|
number_of_exercises_q,
|
||||||
|
start_id, difficulty)
|
||||||
|
return {
|
||||||
|
"exercises": exercises,
|
||||||
|
"text": processed_conversation,
|
||||||
|
"difficulty": difficulty
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def gen_listening_section_4(topic, difficulty, req_exercises, number_of_exercises_q=queue.Queue(), start_id=31):
|
||||||
|
if (len(req_exercises) == 0):
|
||||||
|
req_exercises = random.sample(LISTENING_EXERCISE_TYPES, 2)
|
||||||
|
|
||||||
|
if (number_of_exercises_q.empty()):
|
||||||
|
number_of_exercises_q = divide_number_into_parts(TOTAL_LISTENING_SECTION_4_EXERCISES, len(req_exercises))
|
||||||
|
|
||||||
|
monologue = generate_listening_4_monologue(topic)
|
||||||
|
|
||||||
|
exercises = generate_listening_monologue_exercises(str(monologue), req_exercises, number_of_exercises_q,
|
||||||
|
start_id, difficulty)
|
||||||
|
return {
|
||||||
|
"exercises": exercises,
|
||||||
|
"text": monologue,
|
||||||
|
"difficulty": difficulty
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
@@ -24,7 +25,8 @@ class TrainingContentService:
|
|||||||
self._logger = getLogger(__name__)
|
self._logger = getLogger(__name__)
|
||||||
self._llm = openai
|
self._llm = openai
|
||||||
|
|
||||||
def get_tips(self, stats):
|
def get_tips(self, training_content):
|
||||||
|
user, stats = training_content["userID"], training_content["stats"]
|
||||||
exam_data, exam_map = self._sort_out_solutions(stats)
|
exam_data, exam_map = self._sort_out_solutions(stats)
|
||||||
training_content = self._get_exam_details_and_tips(exam_data)
|
training_content = self._get_exam_details_and_tips(exam_data)
|
||||||
tips = self._query_kb(training_content.queries)
|
tips = self._query_kb(training_content.queries)
|
||||||
@@ -39,7 +41,8 @@ class TrainingContentService:
|
|||||||
'created_at': int(datetime.now().timestamp() * 1000),
|
'created_at': int(datetime.now().timestamp() * 1000),
|
||||||
**exam_map,
|
**exam_map,
|
||||||
**usefull_tips.dict(),
|
**usefull_tips.dict(),
|
||||||
**weak_areas
|
**weak_areas,
|
||||||
|
"user": user
|
||||||
}
|
}
|
||||||
doc_ref = self._db.collection('training').add(training_doc)
|
doc_ref = self._db.collection('training').add(training_doc)
|
||||||
return {
|
return {
|
||||||
@@ -70,7 +73,6 @@ class TrainingContentService:
|
|||||||
|
|
||||||
tips = {"tips": []}
|
tips = {"tips": []}
|
||||||
for query in queries:
|
for query in queries:
|
||||||
print(f"{query.category} {query.text}")
|
|
||||||
if query.category == "words":
|
if query.category == "words":
|
||||||
tips["tips"].extend(
|
tips["tips"].extend(
|
||||||
self._training_content_module.query_knowledge_base(query.text, "word_link")
|
self._training_content_module.query_knowledge_base(query.text, "word_link")
|
||||||
@@ -104,7 +106,16 @@ class TrainingContentService:
|
|||||||
' with sentence structure and punctuation.", the "queries" field is where you will write queries '
|
' with sentence structure and punctuation.", the "queries" field is where you will write queries '
|
||||||
'for tips that will be displayed to the student, the category attribute is a collection of '
|
'for tips that will be displayed to the student, the category attribute is a collection of '
|
||||||
'embeddings and the text will be the text used to query the knowledge base. The categories are '
|
'embeddings and the text will be the text used to query the knowledge base. The categories are '
|
||||||
f'the following [{", ".join(self.TOOLS)}].'
|
f'the following [{", ".join(self.TOOLS)}]. The exam data will be a json where the key of the field '
|
||||||
|
'"exams" is the exam id, an exam can be composed of multiple modules or single modules. The student'
|
||||||
|
' will see your response so refrain from using phrasing like "The student" did x, y and z. If the '
|
||||||
|
'field "answer" in a question is an empty array "[]", then the student didn\'t answer any question '
|
||||||
|
'and you must address that in your response. Also questions aren\'t modules, the only modules are: '
|
||||||
|
'level, speaking, writing, reading and listening. The details array needs to be tailored to the '
|
||||||
|
'exam attempt, even if you receive the same exam you must treat as different exams by their id.'
|
||||||
|
'Don\'t make references to an exam by it\'s id, the GUI will handle that so the student knows '
|
||||||
|
'which is the exam your comments and summary are referencing too. Even if the student hasn\'t '
|
||||||
|
'submitted no answers for an exam, you must still fill the details structure addressing that fact.'
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -150,42 +161,68 @@ class TrainingContentService:
|
|||||||
def _sort_out_solutions(self, stats):
|
def _sort_out_solutions(self, stats):
|
||||||
grouped_stats = {}
|
grouped_stats = {}
|
||||||
for stat in stats:
|
for stat in stats:
|
||||||
exam_id = stat["exam"]
|
session_key = f'{str(stat["date"])}-{stat["user"]}'
|
||||||
module = stat["module"]
|
module = stat["module"]
|
||||||
if module not in grouped_stats:
|
exam_id = stat["exam"]
|
||||||
grouped_stats[module] = {}
|
|
||||||
if exam_id not in grouped_stats[module]:
|
if session_key not in grouped_stats:
|
||||||
grouped_stats[module][exam_id] = []
|
grouped_stats[session_key] = {}
|
||||||
grouped_stats[module][exam_id].append(stat)
|
if module not in grouped_stats[session_key]:
|
||||||
|
grouped_stats[session_key][module] = {
|
||||||
|
"stats": [],
|
||||||
|
"exam_id": exam_id
|
||||||
|
}
|
||||||
|
grouped_stats[session_key][module]["stats"].append(stat)
|
||||||
|
|
||||||
exercises = {}
|
exercises = {}
|
||||||
exam_map = {}
|
exam_map = {}
|
||||||
for module, exams in grouped_stats.items():
|
for session_key, modules in grouped_stats.items():
|
||||||
exercises[module] = {}
|
exercises[session_key] = {}
|
||||||
for exam_id, stat_group in exams.items():
|
for module, module_stats in modules.items():
|
||||||
exam = self._get_doc_by_id(module, exam_id)
|
exercises[session_key][module] = {}
|
||||||
exercises[module][exam_id] = {"date": None, "exercises": [], "score": None}
|
|
||||||
|
exam_id = module_stats["exam_id"]
|
||||||
|
if exam_id not in exercises[session_key][module]:
|
||||||
|
exercises[session_key][module][exam_id] = {"date": None, "exercises": []}
|
||||||
|
|
||||||
exam_total_questions = 0
|
exam_total_questions = 0
|
||||||
exam_total_correct = 0
|
exam_total_correct = 0
|
||||||
for stat in stat_group:
|
|
||||||
|
for stat in module_stats["stats"]:
|
||||||
exam_total_questions += stat["score"]["total"]
|
exam_total_questions += stat["score"]["total"]
|
||||||
exam_total_correct += stat["score"]["correct"]
|
exam_total_correct += stat["score"]["correct"]
|
||||||
exercises[module][exam_id]["date"] = stat["date"]
|
exercises[session_key][module][exam_id]["date"] = stat["date"]
|
||||||
|
|
||||||
if exam_id not in exam_map:
|
if session_key not in exam_map:
|
||||||
exam_map[exam_id] = {"stat_ids": [], "score": 0}
|
exam_map[session_key] = {"stat_ids": [], "score": 0}
|
||||||
exam_map[exam_id]["stat_ids"].append(stat["id"])
|
exam_map[session_key]["stat_ids"].append(stat["id"])
|
||||||
|
|
||||||
|
exam = self._get_doc_by_id(module, exam_id)
|
||||||
if module == "listening":
|
if module == "listening":
|
||||||
exercises[module][exam_id]["exercises"].extend(self._get_listening_solutions(stat, exam))
|
exercises[session_key][module][exam_id]["exercises"].extend(
|
||||||
if module == "reading":
|
self._get_listening_solutions(stat, exam))
|
||||||
exercises[module][exam_id]["exercises"].extend(self._get_reading_solutions(stat, exam))
|
elif module == "reading":
|
||||||
if module == "writing":
|
exercises[session_key][module][exam_id]["exercises"].extend(
|
||||||
exercises[module][exam_id]["exercises"].extend(self._get_writing_prompts_and_answers(stat, exam))
|
self._get_reading_solutions(stat, exam))
|
||||||
|
elif module == "writing":
|
||||||
|
exercises[session_key][module][exam_id]["exercises"].extend(
|
||||||
|
self._get_writing_prompts_and_answers(stat, exam)
|
||||||
|
)
|
||||||
|
elif module == "speaking":
|
||||||
|
exercises[session_key][module][exam_id]["exercises"].extend(
|
||||||
|
self._get_speaking_solutions(stat, exam)
|
||||||
|
)
|
||||||
|
elif module == "level":
|
||||||
|
exercises[session_key][module][exam_id]["exercises"].extend(
|
||||||
|
self._get_level_solutions(stat, exam)
|
||||||
|
)
|
||||||
|
|
||||||
exam_map[exam_id]["score"] = round((exam_total_correct / exam_total_questions) * 100)
|
exam_map[session_key]["score"] = round((exam_total_correct / exam_total_questions) * 100)
|
||||||
exam_map[exam_id]["module"] = module
|
exam_map[session_key]["module"] = module
|
||||||
return exercises, exam_map
|
with open('exam_result.json', 'w') as file:
|
||||||
|
json.dump({"exams": exercises}, file, indent=4)
|
||||||
|
|
||||||
|
return {"exams": exercises}, exam_map
|
||||||
|
|
||||||
def _get_writing_prompts_and_answers(self, stat, exam):
|
def _get_writing_prompts_and_answers(self, stat, exam):
|
||||||
result = []
|
result = []
|
||||||
@@ -211,6 +248,54 @@ class TrainingContentService:
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_mc_question(exercise, stat):
|
||||||
|
shuffle_maps = stat.get("shuffleMaps", [])
|
||||||
|
answer = stat["solutions"] if len(shuffle_maps) == 0 else []
|
||||||
|
if len(shuffle_maps) != 0:
|
||||||
|
for solution in stat["solutions"]:
|
||||||
|
shuffle_map = [
|
||||||
|
item["map"] for item in shuffle_maps
|
||||||
|
if item["questionID"] == solution["question"]
|
||||||
|
]
|
||||||
|
answer.append({
|
||||||
|
"question": solution["question"],
|
||||||
|
"option": shuffle_map[solution["option"]]
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
"question": exercise["prompt"],
|
||||||
|
"exercise": exercise["questions"],
|
||||||
|
"answer": stat["solutions"]
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _swap_key_name(d, original_key, new_key):
|
||||||
|
d[new_key] = d.pop(original_key)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _get_level_solutions(self, stat, exam):
|
||||||
|
result = []
|
||||||
|
try:
|
||||||
|
for part in exam["parts"]:
|
||||||
|
for exercise in part["exercises"]:
|
||||||
|
if exercise["id"] == stat["exercise"]:
|
||||||
|
if stat["type"] == "fillBlanks":
|
||||||
|
result.append({
|
||||||
|
"prompt": exercise["prompt"],
|
||||||
|
"template": exercise["text"],
|
||||||
|
"words": exercise["words"],
|
||||||
|
"solutions": exercise["solutions"],
|
||||||
|
"answer": [
|
||||||
|
self._swap_key_name(item, 'solution', 'option')
|
||||||
|
for item in stat["solutions"]
|
||||||
|
]
|
||||||
|
})
|
||||||
|
elif stat["type"] == "multipleChoice":
|
||||||
|
result.append(self._get_mc_question(exercise, stat))
|
||||||
|
except KeyError as e:
|
||||||
|
self._logger.warning(f"Malformed stat object: {str(e)}")
|
||||||
|
return result
|
||||||
|
|
||||||
def _get_listening_solutions(self, stat, exam):
|
def _get_listening_solutions(self, stat, exam):
|
||||||
result = []
|
result = []
|
||||||
try:
|
try:
|
||||||
@@ -224,16 +309,54 @@ class TrainingContentService:
|
|||||||
"solution": exercise["solutions"],
|
"solution": exercise["solutions"],
|
||||||
"answer": stat["solutions"]
|
"answer": stat["solutions"]
|
||||||
})
|
})
|
||||||
if stat["type"] == "multipleChoice":
|
elif stat["type"] == "fillBlanks":
|
||||||
result.append({
|
result.append({
|
||||||
"question": exercise["prompt"],
|
"question": exercise["prompt"],
|
||||||
"exercise": exercise["questions"],
|
"template": exercise["text"],
|
||||||
|
"words": exercise["words"],
|
||||||
|
"solutions": exercise["solutions"],
|
||||||
"answer": stat["solutions"]
|
"answer": stat["solutions"]
|
||||||
})
|
})
|
||||||
|
elif stat["type"] == "multipleChoice":
|
||||||
|
result.append(self._get_mc_question(exercise, stat))
|
||||||
|
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
self._logger.warning(f"Malformed stat object: {str(e)}")
|
self._logger.warning(f"Malformed stat object: {str(e)}")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _find_shuffle_map(shuffle_maps, question_id):
|
||||||
|
return next((item["map"] for item in shuffle_maps if item["questionID"] == question_id), None)
|
||||||
|
|
||||||
|
def _get_speaking_solutions(self, stat, exam):
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
result = {
|
||||||
|
"comments": {
|
||||||
|
key: value['comment'] for key, value in stat['solutions'][0]['evaluation']['task_response'].items()}
|
||||||
|
,
|
||||||
|
"exercises": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for exercise in exam["exercises"]:
|
||||||
|
if exercise["id"] == stat["exercise"]:
|
||||||
|
if stat["type"] == "interactiveSpeaking":
|
||||||
|
for i in range(len(exercise["prompts"])):
|
||||||
|
result["exercises"][f"exercise_{i+1}"] = {
|
||||||
|
"question": exercise["prompts"][i]["text"]
|
||||||
|
}
|
||||||
|
for i in range(len(exercise["prompts"])):
|
||||||
|
answer = stat['solutions'][0]["evaluation"].get(f'transcript_{i+1}', '')
|
||||||
|
result["exercises"][f"exercise_{i+1}"]["answer"] = answer
|
||||||
|
elif stat["type"] == "speaking":
|
||||||
|
result["exercises"]["exercise_1"] = {
|
||||||
|
"question": exercise["text"],
|
||||||
|
"answer": stat['solutions'][0]["evaluation"].get(f'transcript', '')
|
||||||
|
}
|
||||||
|
except KeyError as e:
|
||||||
|
self._logger.warning(f"Malformed stat object: {str(e)}")
|
||||||
|
return [result]
|
||||||
|
|
||||||
def _get_reading_solutions(self, stat, exam):
|
def _get_reading_solutions(self, stat, exam):
|
||||||
result = []
|
result = []
|
||||||
try:
|
try:
|
||||||
@@ -258,8 +381,13 @@ class TrainingContentService:
|
|||||||
"solutions": exercise["solutions"],
|
"solutions": exercise["solutions"],
|
||||||
"answer": stat["solutions"]
|
"answer": stat["solutions"]
|
||||||
})
|
})
|
||||||
else:
|
elif stat["type"] == "trueFalse":
|
||||||
# match_sentences
|
result.append({
|
||||||
|
"text": text,
|
||||||
|
"questions": exercise["questions"],
|
||||||
|
"answer": stat["solutions"]
|
||||||
|
})
|
||||||
|
elif stat["type"] == "matchSentences":
|
||||||
result.append({
|
result.append({
|
||||||
"text": text,
|
"text": text,
|
||||||
"question": exercise["prompt"],
|
"question": exercise["prompt"],
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class UploadLevelService:
|
|||||||
FileHelper.remove_directory(f'./tmp/{path_id}')
|
FileHelper.remove_directory(f'./tmp/{path_id}')
|
||||||
|
|
||||||
if response:
|
if response:
|
||||||
return response.dict(exclude_none=True)
|
return self.fix_ids(response.dict(exclude_none=True))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -378,3 +378,18 @@ class UploadLevelService:
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fix_ids(response):
|
||||||
|
counter = 1
|
||||||
|
for part in response["parts"]:
|
||||||
|
for exercise in part["exercises"]:
|
||||||
|
if exercise["type"] == "multipleChoice":
|
||||||
|
for question in exercise["questions"]:
|
||||||
|
question["id"] = counter
|
||||||
|
counter += 1
|
||||||
|
if exercise["type"] == "fillBlanks":
|
||||||
|
for i in range(len(exercise["words"])):
|
||||||
|
exercise["words"][i]["id"] = counter
|
||||||
|
exercise["solutions"][i]["id"] = counter
|
||||||
|
counter += 1
|
||||||
|
return response
|
||||||
Reference in New Issue
Block a user