Add mini test compatibility.

This commit is contained in:
Cristiano Ferreira
2024-01-22 17:10:22 +00:00
parent 1591f8d9fb
commit 6c03e3590c
5 changed files with 141 additions and 86 deletions

91
app.py
View File

@@ -3,6 +3,8 @@ import threading
from flask import Flask, request from flask import Flask, request
from flask_jwt_extended import JWTManager, jwt_required from flask_jwt_extended import JWTManager, jwt_required
from functools import reduce from functools import reduce
from helper.ExamVariant import ExamVariant
from helper.api_messages import * from helper.api_messages import *
from helper.exercises import * from helper.exercises import *
from helper.file_helper import delete_files_older_than_one_day from helper.file_helper import delete_files_older_than_one_day
@@ -161,6 +163,7 @@ def save_listening():
try: try:
data = request.get_json() data = request.get_json()
parts = data.get('parts') parts = data.get('parts')
minTimer = data.get('minTimer', LISTENING_MIN_TIMER_DEFAULT)
template = getListeningTemplate() template = getListeningTemplate()
id = str(uuid.uuid4()) id = str(uuid.uuid4())
for i, part in enumerate(parts, start=0): for i, part in enumerate(parts, start=0):
@@ -175,6 +178,12 @@ def save_listening():
template["parts"][i]["audio"]["source"] = file_url template["parts"][i]["audio"]["source"] = file_url
template["parts"][i]["exercises"] = part["exercises"] template["parts"][i]["exercises"] = part["exercises"]
if minTimer != LISTENING_MIN_TIMER_DEFAULT:
template["minTimer"] = minTimer
template["variant"] = ExamVariant.PARTIAL.value
else:
template["variant"] = ExamVariant.FULL.value
(result, id) = save_to_db_with_id("listening", template, id) (result, id) = save_to_db_with_id("listening", template, id)
if result: if result:
return {**template, "id": id} return {**template, "id": id}
@@ -293,25 +302,25 @@ def get_writing_task_2_general_question():
except Exception as e: except Exception as e:
return str(e) return str(e)
# THE SAVING OF WRITING IS DONE WITHOUT THE API ON THE FRONTEND
@app.route('/writing', methods=['POST']) # @app.route('/writing', methods=['POST'])
@jwt_required() # @jwt_required()
def save_writing_task(): # def save_writing_task():
try: # try:
data = request.get_json() # data = request.get_json()
exercises = data.get('exercises') # exercises = data.get('exercises')
template = getWritingTemplate() # template = getWritingTemplate()
id = str(uuid.uuid4()) # id = str(uuid.uuid4())
for i, exercise in enumerate(exercises, start=0): # for i, exercise in enumerate(exercises, start=0):
template["exercises"][i]["prompt"] = exercise # template["exercises"][i]["prompt"] = exercise
#
(result, id) = save_to_db_with_id("writing", template, id) # (result, id) = save_to_db_with_id("writing", template, id)
if result: # if result:
return {**template, "id": id} # return {**template, "id": id}
else: # else:
raise Exception("Failed to save writing: " + template) # raise Exception("Failed to save writing: " + template)
except Exception as e: # except Exception as e:
return str(e) # return str(e)
@app.route('/speaking_task_1', methods=['POST']) @app.route('/speaking_task_1', methods=['POST'])
@@ -377,6 +386,7 @@ def get_speaking_task_1_question():
token_count = count_tokens(gen_sp1_question)["n_tokens"] token_count = count_tokens(gen_sp1_question)["n_tokens"]
response = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_sp1_question, token_count, GEN_FIELDS, response = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_sp1_question, token_count, GEN_FIELDS,
GEN_QUESTION_TEMPERATURE) GEN_QUESTION_TEMPERATURE)
response["type"] = 1
return response return response
except Exception as e: except Exception as e:
return str(e) return str(e)
@@ -446,6 +456,7 @@ def get_speaking_task_2_question():
token_count = count_tokens(gen_sp2_question)["n_tokens"] token_count = count_tokens(gen_sp2_question)["n_tokens"]
response = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_sp2_question, token_count, GEN_FIELDS, response = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_sp2_question, token_count, GEN_FIELDS,
GEN_QUESTION_TEMPERATURE) GEN_QUESTION_TEMPERATURE)
response["type"] = 2
return response return response
except Exception as e: except Exception as e:
return str(e) return str(e)
@@ -466,6 +477,7 @@ def get_speaking_task_3_question():
# Remove the numbers from the questions only if the string starts with a number # 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 response["questions"] = [re.sub(r"^\d+\.\s*", "", question) if re.match(r"^\d+\.", question) else question for
question in response["questions"]] question in response["questions"]]
response["type"] = 3
return response return response
except Exception as e: except Exception as e:
return str(e) return str(e)
@@ -544,7 +556,15 @@ def save_speaking():
try: try:
data = request.get_json() data = request.get_json()
exercises = data.get('exercises') exercises = data.get('exercises')
minTimer = data.get('minTimer', SPEAKING_MIN_TIMER_DEFAULT)
template = getSpeakingTemplate() template = getSpeakingTemplate()
if minTimer != SPEAKING_MIN_TIMER_DEFAULT:
template["minTimer"] = minTimer
template["variant"] = ExamVariant.PARTIAL.value
else:
template["variant"] = ExamVariant.FULL.value
id = str(uuid.uuid4()) id = str(uuid.uuid4())
app.logger.info('Received request to save speaking with id: ' + id) app.logger.info('Received request to save speaking with id: ' + id)
thread_event.set() thread_event.set()
@@ -646,22 +666,23 @@ def get_reading_passage_3_question():
return str(e) return str(e)
@app.route('/reading', methods=['POST']) # THE SAVING OF READING IS DONE WITHOUT THE API ON THE FRONTEND
@jwt_required() # @app.route('/reading', methods=['POST'])
def save_reading_passage(): # @jwt_required()
try: # def save_reading_passage():
data = request.get_json() # try:
parts = data.get('parts') # data = request.get_json()
template = getReadingTemplate() # parts = data.get('parts')
template["parts"] = parts # template = getReadingTemplate()
id = str(uuid.uuid4()) # template["parts"] = parts
(result, id) = save_to_db_with_id("reading", template, id) # id = str(uuid.uuid4())
if result: # (result, id) = save_to_db_with_id("reading", template, id)
return {**template, "id": id} # if result:
else: # return {**template, "id": id}
raise Exception("Failed to save reading: " + template) # else:
except Exception as e: # raise Exception("Failed to save reading: " + template)
return str(e) # except Exception as e:
# return str(e)
@app.route('/level', methods=['GET']) @app.route('/level', methods=['GET'])

6
helper/ExamVariant.py Normal file
View File

@@ -0,0 +1,6 @@
from enum import Enum
class ExamVariant(Enum):
FULL = "full"
PARTIAL = "partial"

View File

@@ -27,6 +27,10 @@ TOTAL_LISTENING_SECTION_2_EXERCISES = 10
TOTAL_LISTENING_SECTION_3_EXERCISES = 10 TOTAL_LISTENING_SECTION_3_EXERCISES = 10
TOTAL_LISTENING_SECTION_4_EXERCISES = 10 TOTAL_LISTENING_SECTION_4_EXERCISES = 10
LISTENING_MIN_TIMER_DEFAULT = 30
WRITING_MIN_TIMER_DEFAULT = 60
SPEAKING_MIN_TIMER_DEFAULT = 14
EN_US_VOICES = [ EN_US_VOICES = [
{'Gender': 'Female', 'Id': 'Salli', 'LanguageCode': 'en-US', 'LanguageName': 'US English', 'Name': 'Salli', {'Gender': 'Female', 'Id': 'Salli', 'LanguageCode': 'en-US', 'LanguageName': 'US English', 'Name': 'Salli',
'SupportedEngines': ['neural', 'standard']}, 'SupportedEngines': ['neural', 'standard']},

View File

@@ -38,58 +38,80 @@ TYLER_CHRISTOPHER = "03c796f8ed274bb38f19e893bcbc6121"
def create_videos_and_save_to_db(exercises, template, id): def create_videos_and_save_to_db(exercises, template, id):
# Speaking 1 # Speaking 1
app.app.logger.info('Creating video for speaking part 1') # Using list comprehension to find the element with the desired value in the 'type' field
sp1_result = create_video(exercises[0]["question"], random.choice(list(AvatarEnum))) found_exercises_1 = [element for element in exercises if element.get('type') == 1]
if sp1_result is not None: # Check if any elements were found
sound_file_path = VIDEO_FILES_PATH + sp1_result if found_exercises_1:
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp1_result exercise_1 = found_exercises_1[0]
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path) app.app.logger.info('Creating video for speaking part 1')
sp1_video_path = firebase_file_path sp1_result = create_video(exercise_1["question"], random.choice(list(AvatarEnum)))
sp1_video_url = url if sp1_result is not None:
template["exercises"][0]["text"] = exercises[0]["question"] sound_file_path = VIDEO_FILES_PATH + sp1_result
template["exercises"][0]["title"] = exercises[0]["topic"] firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp1_result
template["exercises"][0]["video_url"] = sp1_video_url url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
template["exercises"][0]["video_path"] = sp1_video_path sp1_video_path = firebase_file_path
else: sp1_video_url = url
app.app.logger.error("Failed to create video for part 1 question: " + exercises[0]["question"]) template["exercises"][0]["text"] = exercise_1["question"]
template["exercises"][0]["title"] = exercise_1["topic"]
template["exercises"][0]["video_url"] = sp1_video_url
template["exercises"][0]["video_path"] = sp1_video_path
else:
app.app.logger.error("Failed to create video for part 1 question: " + exercise_1["question"])
# Speaking 2 # Speaking 2
app.app.logger.info('Creating video for speaking part 2') # Using list comprehension to find the element with the desired value in the 'type' field
sp2_result = create_video(exercises[1]["question"], random.choice(list(AvatarEnum))) found_exercises_2 = [element for element in exercises if element.get('type') == 2]
if sp2_result is not None: # Check if any elements were found
sound_file_path = VIDEO_FILES_PATH + sp2_result if found_exercises_2:
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp2_result exercise_2 = found_exercises_2[0]
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path) app.app.logger.info('Creating video for speaking part 2')
sp2_video_path = firebase_file_path sp2_result = create_video(exercise_2["question"], random.choice(list(AvatarEnum)))
sp2_video_url = url if sp2_result is not None:
template["exercises"][1]["prompts"] = exercises[1]["prompts"] sound_file_path = VIDEO_FILES_PATH + sp2_result
template["exercises"][1]["text"] = exercises[1]["question"] firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp2_result
template["exercises"][1]["title"] = exercises[1]["topic"] url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
template["exercises"][1]["video_url"] = sp2_video_url sp2_video_path = firebase_file_path
template["exercises"][1]["video_path"] = sp2_video_path sp2_video_url = url
else: template["exercises"][1]["prompts"] = exercise_2["prompts"]
app.app.logger.error("Failed to create video for part 2 question: " + exercises[1]["question"]) template["exercises"][1]["text"] = exercise_2["question"]
template["exercises"][1]["title"] = exercise_2["topic"]
template["exercises"][1]["video_url"] = sp2_video_url
template["exercises"][1]["video_path"] = sp2_video_path
else:
app.app.logger.error("Failed to create video for part 2 question: " + exercise_2["question"])
# Speaking 3 # Speaking 3
sp3_questions = [] # Using list comprehension to find the element with the desired value in the 'type' field
avatar = random.choice(list(AvatarEnum)) found_exercises_3 = [element for element in exercises if element.get('type') == 3]
app.app.logger.info('Creating videos for speaking part 3') # Check if any elements were found
for question in exercises[2]["questions"]: if found_exercises_3:
result = create_video(question, avatar) exercise_3 = found_exercises_3[0]
if result is not None: sp3_questions = []
sound_file_path = VIDEO_FILES_PATH + result avatar = random.choice(list(AvatarEnum))
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + result app.app.logger.info('Creating videos for speaking part 3')
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path) for question in exercise_3["questions"]:
video = { result = create_video(question, avatar)
"text": question, if result is not None:
"video_path": firebase_file_path, sound_file_path = VIDEO_FILES_PATH + result
"video_url": url firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + result
} url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
sp3_questions.append(video) video = {
else: "text": question,
app.app.logger.error("Failed to create video for part 3 question: " + question) "video_path": firebase_file_path,
template["exercises"][2]["prompts"] = sp3_questions "video_url": url
template["exercises"][2]["title"] = exercises[2]["topic"] }
sp3_questions.append(video)
else:
app.app.logger.error("Failed to create video for part 3 question: " + question)
template["exercises"][2]["prompts"] = sp3_questions
template["exercises"][2]["title"] = exercise_3["topic"]
if not found_exercises_3:
template["exercises"].pop(2)
if not found_exercises_2:
template["exercises"].pop(1)
if not found_exercises_1:
template["exercises"].pop(0)
save_to_db_with_id("speaking", template, id) save_to_db_with_id("speaking", template, id)
app.app.logger.info('Saved speaking to DB with id ' + id + " : " + str(template)) app.app.logger.info('Saved speaking to DB with id ' + id + " : " + str(template))

View File

@@ -1,5 +1,7 @@
import uuid import uuid
from helper.constants import *
def getListeningTemplate(): def getListeningTemplate():
return { return {
@@ -34,7 +36,7 @@ def getListeningTemplate():
}, },
], ],
"isDiagnostic": False, "isDiagnostic": False,
"minTimer": 30, "minTimer": LISTENING_MIN_TIMER_DEFAULT,
"module": "listening" "module": "listening"
} }
@@ -1180,7 +1182,7 @@ def getSpeakingTemplate():
} }
], ],
"isDiagnostic": False, "isDiagnostic": False,
"minTimer": 14, "minTimer": SPEAKING_MIN_TIMER_DEFAULT,
"module": "speaking" "module": "speaking"
} }
@@ -1242,7 +1244,7 @@ def getWritingTemplate():
} }
], ],
"isDiagnostic": False, "isDiagnostic": False,
"minTimer": 60, "minTimer": WRITING_MIN_TIMER_DEFAULT,
"module": "writing", "module": "writing",
"type": "general" "type": "general"
} }