Merge branch 'develop' of bitbucket.org:ecropdev/ielts-be into develop
This commit is contained in:
160
app.py
160
app.py
@@ -53,7 +53,7 @@ def get_listening_section_1_question():
|
||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||
|
||||
if (len(req_exercises) == 0):
|
||||
req_exercises = random.sample(LISTENING_EXERCISE_TYPES, 1)
|
||||
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))
|
||||
|
||||
@@ -62,7 +62,8 @@ def get_listening_section_1_question():
|
||||
app.logger.info("Generated conversation: " + str(processed_conversation))
|
||||
|
||||
start_id = 1
|
||||
exercises = generate_listening_conversation_exercises(parse_conversation(processed_conversation), req_exercises,
|
||||
exercises = generate_listening_conversation_exercises(parse_conversation(processed_conversation),
|
||||
req_exercises,
|
||||
number_of_exercises_q,
|
||||
start_id, difficulty)
|
||||
return {
|
||||
@@ -85,7 +86,7 @@ def get_listening_section_2_question():
|
||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||
|
||||
if (len(req_exercises) == 0):
|
||||
req_exercises = random.sample(LISTENING_EXERCISE_TYPES, 2)
|
||||
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))
|
||||
|
||||
@@ -115,7 +116,7 @@ def get_listening_section_3_question():
|
||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||
|
||||
if (len(req_exercises) == 0):
|
||||
req_exercises = random.sample(LISTENING_EXERCISE_TYPES, 1)
|
||||
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))
|
||||
|
||||
@@ -351,12 +352,12 @@ def grade_writing_task_2():
|
||||
{
|
||||
"role": "user",
|
||||
"content": (
|
||||
'Evaluate the given Writing Task 2 response based on the IELTS grading system, ensuring a '
|
||||
'strict assessment that penalizes errors. Deduct points for deviations from the task, and '
|
||||
'assign a score of 0 if the response fails to address the question. Additionally, provide an '
|
||||
'exemplary answer with a minimum of 250 words, along with a detailed commentary highlighting '
|
||||
'both strengths and weaknesses in the response.'
|
||||
'\n Question: "' + question + '" \n Answer: "' + answer + '"')
|
||||
'Evaluate the given Writing Task 2 response based on the IELTS grading system, ensuring a '
|
||||
'strict assessment that penalizes errors. Deduct points for deviations from the task, and '
|
||||
'assign a score of 0 if the response fails to address the question. Additionally, provide an '
|
||||
'exemplary answer with a minimum of 250 words, along with a detailed commentary highlighting '
|
||||
'both strengths and weaknesses in the response.'
|
||||
'\n Question: "' + question + '" \n Answer: "' + answer + '"')
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
@@ -591,7 +592,7 @@ def grade_speaking_task_1():
|
||||
@app.route('/speaking_task_1', methods=['GET'])
|
||||
@jwt_required()
|
||||
def get_speaking_task_1_question():
|
||||
difficulty = request.args.get("difficulty", default=random.choice(difficulties))
|
||||
difficulty = request.args.get("difficulty", default="easy")
|
||||
first_topic = request.args.get("first_topic", default=random.choice(mti_topics))
|
||||
second_topic = request.args.get("second_topic", default=random.choice(mti_topics))
|
||||
|
||||
@@ -599,7 +600,7 @@ def get_speaking_task_1_question():
|
||||
"first_topic": "topic 1",
|
||||
"second_topic": "topic 2",
|
||||
"questions": [
|
||||
"Introductory question, should start with a greeting and introduce a question about the first topic.",
|
||||
"Introductory question, should start with a greeting and introduce a 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",
|
||||
@@ -617,7 +618,7 @@ def get_speaking_task_1_question():
|
||||
{
|
||||
"role": "user",
|
||||
"content": (
|
||||
'Craft 5 thought-provoking questions of ' + difficulty + ' difficulty for IELTS Speaking Part 1 '
|
||||
'Craft 5 simple 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 + '". Instruct the candidate '
|
||||
@@ -813,7 +814,7 @@ def get_speaking_task_2_question():
|
||||
'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 "' + random.choice(mti_topics) + '". Include 3 prompts that '
|
||||
'of "' + topic + '". Include 3 prompts that '
|
||||
'guide the candidate to describe '
|
||||
'specific aspects of the experience, '
|
||||
'such as details about the situation, '
|
||||
@@ -847,7 +848,7 @@ def get_speaking_task_3_question():
|
||||
json_format = {
|
||||
"topic": "topic",
|
||||
"questions": [
|
||||
"Introductory question, should start with a greeting and introduce a question about the topic.",
|
||||
"Introductory question about the topic.",
|
||||
"Follow up question about the topic",
|
||||
"Follow up question about the topic",
|
||||
"Follow up question about the topic",
|
||||
@@ -865,8 +866,7 @@ def get_speaking_task_3_question():
|
||||
"role": "user",
|
||||
"content": (
|
||||
'Formulate a set of 5 questions of hard difficulty for IELTS Speaking Part 3 that encourage candidates to engage in a '
|
||||
'meaningful discussion on the topic of "' + random.choice(
|
||||
mti_topics) + '". Provide inquiries, ensuring '
|
||||
'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.')
|
||||
|
||||
@@ -1080,21 +1080,93 @@ def save_speaking():
|
||||
return str(e)
|
||||
|
||||
|
||||
@app.route("/speaking/generate_speaking_video", methods=['POST'])
|
||||
@app.route("/speaking/generate_video_1", methods=['POST'])
|
||||
@jwt_required()
|
||||
def generate_speaking_video():
|
||||
def generate_video_1():
|
||||
try:
|
||||
data = request.get_json()
|
||||
sp3_questions = []
|
||||
avatar = data.get("avatar", random.choice(list(AvatarEnum)).value)
|
||||
|
||||
request_id = str(uuid.uuid4())
|
||||
logging.info("POST - generate_video_1 - Received request to generate video 1. "
|
||||
"Use this id to track the logs: " + str(request_id) + " - Request data: " + str(
|
||||
request.get_json()))
|
||||
|
||||
logging.info("POST - generate_video_1 - " + str(request_id) + " - Creating videos for speaking part 1.")
|
||||
for question in data["questions"]:
|
||||
logging.info("POST - generate_video_1 - " + str(request_id) + " - Creating video for question: " + question)
|
||||
result = create_video(question, avatar)
|
||||
logging.info("POST - generate_video_1 - " + str(request_id) + " - Video created: " + result)
|
||||
if result is not None:
|
||||
sound_file_path = VIDEO_FILES_PATH + result
|
||||
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + result
|
||||
logging.info(
|
||||
"POST - generate_video_1 - " + str(
|
||||
request_id) + " - Uploading video to firebase: " + firebase_file_path)
|
||||
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
||||
logging.info(
|
||||
"POST - generate_video_1 - " + str(
|
||||
request_id) + " - Uploaded video to firebase: " + url)
|
||||
video = {
|
||||
"text": question,
|
||||
"video_path": firebase_file_path,
|
||||
"video_url": url
|
||||
}
|
||||
sp3_questions.append(video)
|
||||
else:
|
||||
logging.error("POST - generate_video_1 - " + str(
|
||||
request_id) + " - Failed to create video for part 1 question: " + question)
|
||||
|
||||
response = {
|
||||
"prompts": sp3_questions,
|
||||
"first_title": data["first_topic"],
|
||||
"second_title": data["second_topic"],
|
||||
"type": "interactiveSpeaking",
|
||||
"id": uuid.uuid4()
|
||||
}
|
||||
logging.info(
|
||||
"POST - generate_video_1 - " + str(
|
||||
request_id) + " - Finished creating videos for speaking part 1: " + str(response))
|
||||
return response
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
@app.route("/speaking/generate_video_2", methods=['POST'])
|
||||
@jwt_required()
|
||||
def generate_video_2():
|
||||
try:
|
||||
data = request.get_json()
|
||||
avatar = data.get("avatar", random.choice(list(AvatarEnum)).value)
|
||||
prompts = data.get("prompts", [])
|
||||
question = data.get("question")
|
||||
if len(prompts) > 0:
|
||||
question = question + " In your answer you should consider: " + " ".join(prompts)
|
||||
sp1_result = create_video(question, avatar)
|
||||
if sp1_result is not None:
|
||||
sound_file_path = VIDEO_FILES_PATH + sp1_result
|
||||
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp1_result
|
||||
suffix = data.get("suffix", "")
|
||||
|
||||
# Removed as the examiner should not say what is on the card.
|
||||
# question = question + " In your answer you should consider: " + " ".join(prompts) + suffix
|
||||
question = question + "\nYou have 1 minute to take notes."
|
||||
|
||||
request_id = str(uuid.uuid4())
|
||||
logging.info("POST - generate_video_2 - Received request to generate video 2. "
|
||||
"Use this id to track the logs: " + str(request_id) + " - Request data: " + str(
|
||||
request.get_json()))
|
||||
|
||||
logging.info("POST - generate_video_2 - " + str(request_id) + " - Creating video for speaking part 2.")
|
||||
logging.info("POST - generate_video_2 - " + str(request_id) + " - Creating video for question: " + question)
|
||||
result = create_video(question, avatar)
|
||||
logging.info("POST - generate_video_2 - " + str(request_id) + " - Video created: " + result)
|
||||
|
||||
if result is not None:
|
||||
sound_file_path = VIDEO_FILES_PATH + result
|
||||
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + result
|
||||
logging.info(
|
||||
"POST - generate_video_2 - " + str(
|
||||
request_id) + " - Uploading video to firebase: " + firebase_file_path)
|
||||
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
||||
logging.info(
|
||||
"POST - generate_video_2 - " + str(
|
||||
request_id) + " - Uploaded video to firebase: " + url)
|
||||
sp1_video_path = firebase_file_path
|
||||
sp1_video_url = url
|
||||
|
||||
@@ -1105,31 +1177,47 @@ def generate_speaking_video():
|
||||
"video_url": sp1_video_url,
|
||||
"video_path": sp1_video_path,
|
||||
"type": "speaking",
|
||||
"id": uuid.uuid4()
|
||||
"id": uuid.uuid4(),
|
||||
"suffix": suffix
|
||||
}
|
||||
else:
|
||||
app.logger.error("Failed to create video for part 1 question: " + data["question"])
|
||||
return str("Failed to create video for part 1 question: " + data["question"])
|
||||
logging.error("POST - generate_video_2 - " + str(
|
||||
request_id) + " - Failed to create video for part 2 question: " + question)
|
||||
return str("Failed to create video for part 2 question: " + data["question"])
|
||||
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
@app.route("/speaking/generate_interactive_video", methods=['POST'])
|
||||
@app.route("/speaking/generate_video_3", methods=['POST'])
|
||||
@jwt_required()
|
||||
def generate_interactive_video():
|
||||
def generate_video_3():
|
||||
try:
|
||||
data = request.get_json()
|
||||
sp3_questions = []
|
||||
avatar = data.get("avatar", random.choice(list(AvatarEnum)).value)
|
||||
|
||||
app.logger.info('Creating videos for speaking part 3')
|
||||
request_id = str(uuid.uuid4())
|
||||
logging.info("POST - generate_video_3 - Received request to generate video 3. "
|
||||
"Use this id to track the logs: " + str(request_id) + " - Request data: " + str(
|
||||
request.get_json()))
|
||||
|
||||
logging.info("POST - generate_video_3 - " + str(request_id) + " - Creating videos for speaking part 3.")
|
||||
for question in data["questions"]:
|
||||
logging.info("POST - generate_video_3 - " + str(request_id) + " - Creating video for question: " + question)
|
||||
result = create_video(question, avatar)
|
||||
logging.info("POST - generate_video_3 - " + str(request_id) + " - Video created: " + result)
|
||||
|
||||
if result is not None:
|
||||
sound_file_path = VIDEO_FILES_PATH + result
|
||||
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + result
|
||||
logging.info(
|
||||
"POST - generate_video_3 - " + str(
|
||||
request_id) + " - Uploading video to firebase: " + firebase_file_path)
|
||||
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
||||
logging.info(
|
||||
"POST - generate_video_3 - " + str(
|
||||
request_id) + " - Uploaded video to firebase: " + url)
|
||||
video = {
|
||||
"text": question,
|
||||
"video_path": firebase_file_path,
|
||||
@@ -1137,14 +1225,19 @@ def generate_interactive_video():
|
||||
}
|
||||
sp3_questions.append(video)
|
||||
else:
|
||||
app.app.logger.error("Failed to create video for part 3 question: " + question)
|
||||
logging.error("POST - generate_video_3 - " + str(
|
||||
request_id) + " - Failed to create video for part 3 question: " + question)
|
||||
|
||||
return {
|
||||
response = {
|
||||
"prompts": sp3_questions,
|
||||
"title": data["topic"],
|
||||
"type": "interactiveSpeaking",
|
||||
"id": uuid.uuid4()
|
||||
}
|
||||
logging.info(
|
||||
"POST - generate_video_3 - " + str(
|
||||
request_id) + " - Finished creating videos for speaking part 3: " + str(response))
|
||||
return response
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
@@ -1203,6 +1296,7 @@ def get_level_exam():
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
@app.route('/level_utas', methods=['GET'])
|
||||
@jwt_required()
|
||||
def get_level_utas():
|
||||
|
||||
@@ -19,6 +19,11 @@ GEN_TEXT_FIELDS = ['title']
|
||||
LISTENING_GEN_FIELDS = ['transcript', 'exercise']
|
||||
READING_EXERCISE_TYPES = ['fillBlanks', 'writeBlanks', 'trueFalse', 'paragraphMatch']
|
||||
LISTENING_EXERCISE_TYPES = ['multipleChoice', 'writeBlanksQuestions', 'writeBlanksFill', 'writeBlanksForm']
|
||||
LISTENING_1_EXERCISE_TYPES = ['multipleChoice', 'writeBlanksQuestions', 'writeBlanksFill', 'writeBlanksFill',
|
||||
'writeBlanksForm', 'writeBlanksForm', 'writeBlanksForm', 'writeBlanksForm']
|
||||
LISTENING_2_EXERCISE_TYPES = ['multipleChoice', 'writeBlanksQuestions']
|
||||
LISTENING_3_EXERCISE_TYPES = ['multipleChoice3Options', 'writeBlanksQuestions']
|
||||
LISTENING_4_EXERCISE_TYPES = ['multipleChoice', 'writeBlanksQuestions', 'writeBlanksFill', 'writeBlanksForm']
|
||||
|
||||
TOTAL_READING_PASSAGE_1_EXERCISES = 13
|
||||
TOTAL_READING_PASSAGE_2_EXERCISES = 13
|
||||
|
||||
@@ -283,6 +283,16 @@ def generate_listening_1_conversation(topic: str):
|
||||
'Make sure that the generated conversation does not contain forbidden subjects in '
|
||||
'muslim countries.')
|
||||
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": 'Try to have misleading discourse (refer multiple dates, multiple colors and etc).'
|
||||
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": 'Try to have spelling of names (cities, people, etc)'
|
||||
|
||||
}
|
||||
]
|
||||
token_count = count_total_tokens(messages)
|
||||
@@ -400,7 +410,7 @@ def generate_listening_4_monologue(topic: str):
|
||||
{
|
||||
"role": "user",
|
||||
"content": (
|
||||
'Generate a comprehensive monologue on the academic subject '
|
||||
'Generate a comprehensive and complex monologue on the academic subject '
|
||||
'of: "' + topic + '". Make sure that the generated monologue does not contain forbidden subjects in '
|
||||
'muslim countries.')
|
||||
|
||||
@@ -467,7 +477,12 @@ def generate_listening_conversation_exercises(conversation: str, req_exercises:
|
||||
|
||||
if req_exercise == "multipleChoice":
|
||||
question = gen_multiple_choice_exercise_listening_conversation(conversation, number_of_exercises, start_id,
|
||||
difficulty)
|
||||
difficulty, 4)
|
||||
exercises.append(question)
|
||||
print("Added multiple choice: " + str(question))
|
||||
elif req_exercise == "multipleChoice3Options":
|
||||
question = gen_multiple_choice_exercise_listening_conversation(conversation, number_of_exercises, start_id,
|
||||
difficulty, 3)
|
||||
exercises.append(question)
|
||||
print("Added multiple choice: " + str(question))
|
||||
elif req_exercise == "writeBlanksQuestions":
|
||||
@@ -723,7 +738,7 @@ def assign_letters_to_paragraphs(paragraphs):
|
||||
return result
|
||||
|
||||
|
||||
def gen_multiple_choice_exercise_listening_conversation(text: str, quantity: int, start_id, difficulty):
|
||||
def gen_multiple_choice_exercise_listening_conversation(text: str, quantity: int, start_id, difficulty, n_options=4):
|
||||
messages = [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -737,7 +752,7 @@ def gen_multiple_choice_exercise_listening_conversation(text: str, quantity: int
|
||||
{
|
||||
"role": "user",
|
||||
"content": (
|
||||
'Generate ' + str(quantity) + ' ' + difficulty + ' difficulty multiple choice questions of 4 options '
|
||||
'Generate ' + str(quantity) + ' ' + difficulty + ' difficulty multiple choice questions of ' + str(n_options) + ' options '
|
||||
'of for this conversation:\n"' + text + '"')
|
||||
|
||||
}
|
||||
@@ -753,7 +768,7 @@ def gen_multiple_choice_exercise_listening_conversation(text: str, quantity: int
|
||||
}
|
||||
|
||||
|
||||
def gen_multiple_choice_exercise_listening_monologue(text: str, quantity: int, start_id, difficulty):
|
||||
def gen_multiple_choice_exercise_listening_monologue(text: str, quantity: int, start_id, difficulty, n_options=4):
|
||||
messages = [
|
||||
{
|
||||
"role": "system",
|
||||
@@ -768,7 +783,7 @@ def gen_multiple_choice_exercise_listening_monologue(text: str, quantity: int, s
|
||||
"role": "user",
|
||||
"content": (
|
||||
'Generate ' + str(
|
||||
quantity) + ' ' + difficulty + ' difficulty multiple choice questions of 4 options '
|
||||
quantity) + ' ' + difficulty + ' difficulty multiple choice questions of ' + str(n_options) + ' options '
|
||||
'of for this monologue:\n"' + text + '"')
|
||||
|
||||
}
|
||||
@@ -951,13 +966,19 @@ def gen_write_blanks_form_exercise_listening_conversation(text: str, quantity: i
|
||||
"role": "system",
|
||||
"content": (
|
||||
'You are a helpful assistant designed to output JSON on this format: '
|
||||
'{"form": ["key: value", "key2: value"]}')
|
||||
'{"form": ["key": "value", "key2": "value"]}')
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": (
|
||||
'Generate a form with ' + str(
|
||||
quantity) + ' ' + difficulty + ' difficulty key-value pairs about this conversation:\n"' + text + '"')
|
||||
quantity) + ' entries with information about this conversation:\n"' + text + '"')
|
||||
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": 'It must be a form and not questions. '
|
||||
'Example: {"form": ["Color of car": "blue", "Brand of car": "toyota"]}'
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user