From 680ec00885fc7f1aafc8f081837ae99407ee223a Mon Sep 17 00:00:00 2001 From: Cristiano Ferreira Date: Wed, 6 Sep 2023 22:19:42 +0100 Subject: [PATCH] Fix mistake on grade speaking task 1. --- app.py | 123 +++++++- helper/firebase_helper.py | 20 ++ templates/question_templates.py | 483 ++++++++++++++++++++++++++++++++ 3 files changed, 624 insertions(+), 2 deletions(-) create mode 100644 templates/question_templates.py diff --git a/app.py b/app.py index c9c95dd..fef1f0b 100644 --- a/app.py +++ b/app.py @@ -5,7 +5,8 @@ import firebase_admin from firebase_admin import credentials from helper.api_messages import QuestionType, get_grading_messages, get_question_gen_messages, get_question_tips from helper.file_helper import delete_files_older_than_one_day -from helper.firebase_helper import download_firebase_file, upload_file_firebase +from helper.firebase_helper import download_firebase_file, upload_file_firebase, upload_file_firebase_get_url, \ + save_to_db from helper.speech_to_text_helper import speech_to_text, text_to_speech, has_words from helper.token_counter import count_tokens from helper.openai_interface import make_openai_call @@ -15,6 +16,8 @@ import re from dotenv import load_dotenv +from templates.question_templates import getListening1Template, getListening2Template + load_dotenv() app = Flask(__name__) @@ -49,10 +52,37 @@ def get_listening_section_1_question(): map(lambda x: x["content"], filter(lambda x: "content" in x, messages)), 0) response = make_openai_call(GPT_3_5_TURBO_16K, messages, token_count, LISTENING_GEN_FIELDS, GEN_QUESTION_TEMPERATURE) + # file_name = str(uuid.uuid4()) + ".mp3" + # sound_file_path = AUDIO_FILES_PATH + file_name + # firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name + # text_to_speech(response["transcript"], sound_file_path) + # upload_file_firebase(FIREBASE_BUCKET, firebase_file_path, sound_file_path) + # response["audio_file"] = firebase_file_path return response except Exception as e: return str(e) +@app.route('/save_listening_section_1', methods=['POST']) +@jwt_required() +def save_listening_section_1_question(): + try: + # data = request.get_json() + # question = data.get('question') + question = getListening1Template() + file_name = str(uuid.uuid4()) + ".mp3" + sound_file_path = AUDIO_FILES_PATH + file_name + firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name + # TODO it's the conversation audio, still work to do on text-to-speech + text_to_speech(question["audio"]["conversation"], sound_file_path) + file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path) + question["audio"]["source"] = file_url + if save_to_db("listening", question): + return question + else: + raise Exception("Failed to save question: " + question) + except Exception as e: + return str(e) + @app.route('/listening_section_2', methods=['GET']) @jwt_required() @@ -75,6 +105,26 @@ def get_listening_section_2_question(): except Exception as e: return str(e) +@app.route('/save_listening_section_2', methods=['POST']) +@jwt_required() +def save_listening_section_2_question(): + try: + # data = request.get_json() + # question = data.get('question') + question = getListening2Template() + file_name = str(uuid.uuid4()) + ".mp3" + sound_file_path = AUDIO_FILES_PATH + file_name + firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name + text_to_speech(question["audio"]["text"], sound_file_path) + file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path) + question["audio"]["source"] = file_url + if save_to_db("listening", question): + return question + else: + raise Exception("Failed to save question: " + question) + except Exception as e: + return str(e) + @app.route('/listening_section_3', methods=['GET']) @jwt_required() @@ -97,6 +147,26 @@ def get_listening_section_3_question(): except Exception as e: return str(e) +@app.route('/save_listening_section_3', methods=['POST']) +@jwt_required() +def save_listening_section_3_question(): + try: + # data = request.get_json() + # question = data.get('question') + question = getListening2Template() + file_name = str(uuid.uuid4()) + ".mp3" + sound_file_path = AUDIO_FILES_PATH + file_name + firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name + text_to_speech(question["audio"]["text"], sound_file_path) + file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path) + question["audio"]["source"] = file_url + if save_to_db("listening", question): + return question + else: + raise Exception("Failed to save question: " + question) + except Exception as e: + return str(e) + @app.route('/listening_section_4', methods=['GET']) @jwt_required() @@ -119,6 +189,26 @@ def get_listening_section_4_question(): except Exception as e: return str(e) +@app.route('/save_listening_section_4', methods=['POST']) +@jwt_required() +def save_listening_section_4_question(): + try: + # data = request.get_json() + # question = data.get('question') + question = getListening2Template() + file_name = str(uuid.uuid4()) + ".mp3" + sound_file_path = AUDIO_FILES_PATH + file_name + firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name + text_to_speech(question["audio"]["text"], sound_file_path) + file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path) + question["audio"]["source"] = file_url + if save_to_db("listening", question): + return question + else: + raise Exception("Failed to save question: " + question) + except Exception as e: + return str(e) + @app.route('/writing_task1', methods=['POST']) @jwt_required() @@ -148,6 +238,21 @@ def grade_writing_task_1(): except Exception as e: return str(e) +@app.route('/save_writing_task_1', methods=['POST']) +@jwt_required() +def save_writing_task_1_question(): + try: + # data = request.get_json() + # question = data.get('question') + # TODO ADD SAVE IMAGE TO DB + question = getListening2Template() + if save_to_db("writing", question): + return question + else: + raise Exception("Failed to save question: " + question) + except Exception as e: + return str(e) + @app.route('/writing_task2', methods=['POST']) @jwt_required() @@ -211,6 +316,20 @@ def get_writing_task_2_question(): except Exception as e: return str(e) +@app.route('/save_writing_task_2', methods=['POST']) +@jwt_required() +def save_writing_task_2_question(): + try: + # data = request.get_json() + # question = data.get('question') + question = getListening2Template() + if save_to_db("writing", question): + return question + else: + raise Exception("Failed to save question: " + question) + except Exception as e: + return str(e) + @app.route('/speaking_task_1', methods=['POST']) @jwt_required() @@ -224,7 +343,7 @@ def grade_speaking_task_1(): download_firebase_file(FIREBASE_BUCKET, answer_firebase_path, sound_file_name) answer = speech_to_text(sound_file_name) - if has_words("ajajajajd"): + if has_words(answer): messages = get_grading_messages(QuestionType.SPEAKING_1, question, answer) token_count = reduce(lambda count, item: count + count_tokens(item)['n_tokens'], map(lambda x: x["content"], filter(lambda x: "content" in x, messages)), 0) diff --git a/helper/firebase_helper.py b/helper/firebase_helper.py index 0b60382..8e39e3f 100644 --- a/helper/firebase_helper.py +++ b/helper/firebase_helper.py @@ -1,4 +1,11 @@ from google.cloud import storage +import os +import uuid + +import firebase_admin +from firebase_admin import credentials, firestore + +from dotenv import load_dotenv def download_firebase_file(bucket_name, source_blob_name, destination_file_name): # Downloads a file from Firebase Storage. @@ -41,5 +48,18 @@ def upload_file_firebase_get_url(bucket_name, destination_blob_name, source_file print("Error uploading file to Google Cloud Storage:", e) return None +def save_to_db(collection: str, item): + # Initialize Firebase Admin SDK + cred = credentials.Certificate(os.getenv("GOOGLE_APPLICATION_CREDENTIALS")) + firebase_admin.initialize_app(cred) + db = firestore.client() + collection_ref = db.collection(collection) + document_ref = collection_ref.add(item) + if document_ref: + print(f"Document added with ID: {document_ref}") + return True + else: + return False + diff --git a/templates/question_templates.py b/templates/question_templates.py new file mode 100644 index 0000000..189b822 --- /dev/null +++ b/templates/question_templates.py @@ -0,0 +1,483 @@ +import uuid + + +def getListening1Template(): + return { + "audio": { + "repeatableTimes": 3, + "source": "https://firebasestorage.googleapis.com/v0/b/mti-ielts.appspot.com/o/listening_recordings%2Fhotel_reservation.mp3?alt=media&token=7c6a88f9-b71a-41f4-8581-d9a0574f4d44", + "conversation": [ + { + "voice": "male", + "text": "voice line 1" + }, + { + "voice": "female", + "text": "voice line 2" + }, + { + "voice": "male", + "text": "voice line 3" + } + ] + }, + "exercises": [ + { + "id": str(uuid.uuid4()), + "maxWords": 3, + "prompt": "You will hear a conversation between a customer and a receptionist at a hotel. Complete the form " + "below using no more than three words or a number.", + "solutions": [ + { + "id": "1", + "solution": ["Johnson", "Mr. Johnson"] + }, + { + "id": "2", + "solution": ["15th of September", "fifteenth of September"] + }, + { + "id": "3", + "solution": ["Deluxe double room"] + }, + { + "id": "4", + "solution": ["Three nights", "3 nights"] + }, + ], + "text": "Name of Customer:{{1}}\\nDate of Arrival:{{2}}\\nType of Room:{{3}}\\nNumber of Nights:{{4}}", + "type": "writeBlanks" + } + ], + "isDiagnostic": True, + "minTimer": 7, + "module": "listening", + "section": 1 + } + + +def getListening2Template(): + return { + "audio": { + "repeatableTimes": 3, + "source": "https://firebasestorage.googleapis.com/v0/b/mti-ielts.appspot.com/o/listening_recordings%2Fmuseum_guide.mp3?alt=media&token=bfb9aea9-4006-4e11-af9a-1594232b4c20", + "text": "Listening section 2 text." + }, + "exercises": [ + { + "id": str(uuid.uuid4()), + "maxWords": 3, + "prompt": "You will hear a guide giving information about a museum exhibition. Complete the sentences using no more than three words or a number.", + "solutions": [ + { + "id": "1", + "options": ["Art and Culture"] + }, + { + "id": "2", + "options": ["10 AM"] + }, + { + "id": "3", + "options": ["ID", "Card", "student ID", "senior citizen card"] + }, + { + "id": "4", + "options": ["day"] + }, + { + "id": "5", + "options": ["45"] + } + ], + "text": "The exhibition is titled \"Exploring the History of {{1}}.\"\\nThe museum opens at {{2}} on weekdays." + "\\nVisitors can get a discount with a valid {{3}}.\\nThe museum offers a guided tour every {{4}}." + "\\nThe guided tour lasts approximately {{5}} minutes.", + "type": "writeBlanks" + } + ], + "isDiagnostic": True, + "minTimer": 7, + "module": "listening", + "section": 2 + } + + +def getReading1Template(): + return { + "exercises": [ + { + "id": str(uuid.uuid4()), + "prompt": "Do the following statements agree with the information given in Reading Passage 1?", + "questions": [ + { + "id": "1", + "prompt": "Bees are solely responsible for the pollination of all flowering plants mentioned in the passage.", + "solution": False + }, + { + "id": "2", + "prompt": "Bee populations have been declining due to factors such as habitat loss, pesticide exposure, and climate changes.", + "solution": True + }, + { + "id": "3", + "prompt": "The decline in bee populations has no impact on the agricultural industry or food prices.", + "solution": False + } + ], + "type": "trueFalse" + }, + { + "id": str(uuid.uuid4()), + "prompt": "Select the appropriate option.", + "questions": [ + { + "id": 1, + "options": [ + { + "id": "A", + "text": "Providing shade to plants" + }, + { + "id": "B", + "text": "Controlling pest populations" + }, + { + "id": "C", + "text": "Attracting other pollinators" + }, + { + "id": "D", + "text": "Creating intricate webs" + } + ], + "prompt": "What is the primary role of bees in ecosystems according to the passage?", + "solution": "B", + "variant": "text", + }, + { + "id": 2, + "options": [ + { + "id": "A", + "text": "30%" + }, + { + "id": "B", + "text": "50%" + }, + { + "id": "C", + "text": "80%" + }, + { + "id": "D", + "text": "100%" + } + ], + "prompt": "Approximately how much of flowering plants rely on animal pollinators like bees for fertilization?", + "solution": "C", + "variant": "text", + }, + { + "id": 3, + "options": [ + { + "id": "A", + "text": "It leads to lower food prices" + }, + { + "id": "B", + "text": "It ensures larger crop sizes" + }, + { + "id": "C", + "text": "It provides diverse and nutritious diets" + }, + { + "id": "D", + "text": "It reduces the need for pesticides" + } + ], + "prompt": "Why is the role of bees in enhancing crop productivity beneficial for consumers?", + "solution": "C", + "variant": "text", + } + ], + "type": "multipleChoice", + } + ], + "isDiagnostic": True, + "minTimer": 20, + "text": { + "content": "Bees, often regarded as unassuming insects, play a pivotal role in the intricate web of ecosystems " + "around the world. Beyond their humble appearance, these industrious creatures contribute substantially " + "to the health and diversity of both natural environments and human communities.\\nAt the heart of their " + "significance lies their role as pollinators. Bees facilitate the reproduction of various plants by " + "transferring pollen between flowers as they collect nectar. This seemingly simple act has profound " + "consequences for the propagation of plant species. In fact, it's estimated that approximately 80% of " + "flowering plants rely on animal pollinators like bees for fertilization.\\nThe value of bee-mediated " + "pollination extends well beyond the plant kingdom. A significant portion of the global food supply " + "hinges on the pollination services that bees provide. Crops such as apples, blueberries, almonds, " + "and cucumbers owe their successful yields to the diligent work of bees. Their role in enhancing crop " + "productivity is not only beneficial for farmers but also for consumers who enjoy diverse and nutritious " + "diets.\\nHowever, the bee populations worldwide have been facing challenges and declines in recent " + "years. Multiple factors, including habitat loss, pesticide exposure, and climate changes, have " + "contributed to this decline. The consequences of dwindling bee populations reverberate throughout " + "ecosystems. Reduced pollination can lead to decreased plant diversity, affecting animals that rely " + "on these plants for food and habitat.\\nThe decline in bee populations also has economic implications. " + "The agricultural industry heavily relies on pollination, and the absence of sufficient bee populations " + "can result in lower crop yields and increased production costs. This, in turn, can impact food prices " + "and livelihoods.\\nEfforts to address the decline in bee populations encompass various strategies. " + "Conservation initiatives involve creating and preserving bee-friendly habitats, reducing pesticide " + "usage, and raising awareness about the importance of bees in ecosystems. Furthermore, researchers " + "are investigating bee biology and behavior to better understand their needs and vulnerabilities." + "\\nIn conclusion, bees, often underestimated in their significance, are integral components of ecosystems. " + "Their role as pollinators contributes to the survival of numerous plant species and the stability of " + "the food chain. Acknowledging their importance and taking steps to protect their populations are " + "vital for maintaining healthy ecosystems and ensuring sustainable food production for generations " + "to come.", + "title": "The Importance of Bees in Ecosystems" + }, + "type": "academic" + } + + +def getReading2Template(): + return { + "exercises": [ + { + "id": str(uuid.uuid4()), + "prompt": "Do the following statements agree with the information given in Reading Passage 2?", + "questions": [ + { + "id": "1", + "prompt": "Human rights are considered essential for social harmony and justice.", + "solution": "true" + }, + { + "id": "2", + "prompt": "Human rights encompass civil, political, economic, social, and cultural aspects.", + "solution": "true" + }, + { + "id": "3", + "prompt": "Economic, social, and cultural rights aim to address social inequalities.", + "solution": "true" + }, + { + "id": "4", + "prompt": "Respecting human rights is associated with stable and just societies.", + "solution": "true" + }, + { + "id": "5", + "prompt": "The digital age has not affected human rights concerns.", + "solution": "false" + } + ], + "type": "trueFalse" + }, + { + "id": str(uuid.uuid4()), + "prompt": "Select the appropriate option.", + "questions": [ + { + "id": 1, + "options": [ + { + "id": "A", + "text": "Enhancing economic growth" + }, + { + "id": "B", + "text": "Ensuring cultural diversity" + }, + { + "id": "C", + "text": "Safeguarding individual dignity and worth" + }, + { + "id": "D", + "text": "Promoting political ideologies" + } + ], + "prompt": "What is the central purpose of human rights, according to the passage?", + "solution": "C", + "variant": "text", + }, + { + "id": 2, + "options": [ + { + "id": "A", + "text": "Economic rights" + }, + { + "id": "B", + "text": "Political rights" + }, + { + "id": "C", + "text": "Social rights" + }, + { + "id": "D", + "text": "Cultural rights" + } + ], + "prompt": "Which rights enable citizens to participate in governance and express opinions freely?", + "solution": "B", + "variant": "text", + }, + { + "id": 3, + "options": [ + { + "id": "A", + "text": "Ignoring human rights abuses" + }, + { + "id": "B", + "text": "Upholding human rights and preventing abuses" + }, + { + "id": "C", + "text": "Encouraging social unrest" + }, + { + "id": "D", + "text": "Perpetrating human rights violations" + } + ], + "prompt": "What role do international organizations and treaties play in relation to human rights?", + "solution": "B", + "variant": "text", + }, + { + "id": 4, + "options": [ + { + "id": "A", + "text": "Promoting social unrest" + }, + { + "id": "B", + "text": "Leading to instability" + }, + { + "id": "C", + "text": "Causing conflicts" + }, + { + "id": "D", + "text": "Fostering stability and justice" + } + ], + "prompt": "What impact does respecting human rights have on societies, as mentioned in the passage?", + "solution": "D", + "variant": "text", + } + ], + "type": "multipleChoice", + } + ], + "isDiagnostic": True, + "minTimer": 20, + "text": { + "content": "Human rights, the fundamental principles that safeguard the inherent dignity and worth of every individual, " + "form the cornerstone of just and equitable societies. These rights are universally acknowledged and " + "are considered essential for maintaining social harmony, justice, and the well-being of humanity." + "\\nAt the heart of the concept of human rights is the recognition that every person is entitled to " + "certain inalienable rights, regardless of their nationality, ethnicity, gender, or any other characteristic. " + "These rights encompass civil, political, economic, social, and cultural dimensions, aiming to ensure that " + "individuals can lead a life of dignity, freedom, and opportunity.\\nCivil and political rights encompass " + "the rights to life, liberty, and personal security. They protect individuals from arbitrary arrests, " + "torture, and discrimination. These rights also include the freedom of expression, assembly, and association, " + "enabling citizens to participate in their governance and voice their opinions without fear of reprisal." + "\\nEconomic, social, and cultural rights focus on ensuring that all individuals have access to essential " + "resources for a decent standard of living. This includes the right to education, health care, housing, " + "and work. These rights are particularly critical for addressing social inequalities and providing opportunities " + "for marginalized groups.\\nThe importance of human rights is underscored by their role in promoting " + "peace and preventing conflicts. When human rights are respected, societies are more likely to be stable " + "and just. Conversely, the violation of human rights often leads to social unrest, tensions, and " + "even violence. International organizations and treaties play a crucial role in upholding human rights " + "globally, aiming to prevent human rights abuses and hold accountable those who perpetrate them.\\nDespite " + "the significant progress made in advancing human rights, challenges persist. Discrimination, gender " + "inequality, and the violation of the rights of minorities and vulnerable groups remain prevalent in " + "many parts of the world. Moreover, the digital age has introduced new dimensions to human rights concerns, " + "with issues such as online privacy and cyberbullying warranting attention.\\nIn conclusion, the " + "importance of human rights cannot be overstated. These rights provide a moral compass for societies " + "and governments, guiding them toward justice, equality, and respect for every individual. The continued " + "efforts to protect and uphold human rights are essential for fostering inclusive and harmonious " + "communities on both local and global scales.", + "title": "The Importance of Human Rights" + }, + "type": "academic" + } + + +def getSpeaking1Template(): + return { + "exercises": [ + { + "id": str(uuid.uuid4()), + "prompts": [], + "text": "Do you enjoy traveling?\\nWhat was the last place you visited for a holiday?\\nDo you prefer traveling " + "by car or by plane?\\nWhat type of places do you like to visit when you travel?", + "title": "Travel", + "type": "speaking" + } + ], + "isDiagnostic": False, + "minTimer": 5, + "module": "speaking" + } + + +def getSpeaking2Template(): + return { + "exercises": [ + { + "id": str(uuid.uuid4()), + "prompts": [ + "Explain the circumstances that led to your need to adapt to a new environment.", + "What were the major changes or differences in this new environment?", + "How did you handle the process of adapting to these changes?", + "Reflect on the impact this experience had on your adaptability and personal growth." + ], + "text": "Describe an occasion when you had to adapt to a new environment.", + "title": "New Environment", + "type": "speaking" + } + ], + "isDiagnostic": False, + "minTimer": 5, + "module": "speaking" + } + + +def getWriting2Template(): + return { + "exercises": [ + { + "id": str(uuid.uuid4()), + "prefix": "You should spend about 40 minutes on this task.\nPresent a written argument or case to an educated " + "reader with no specialist knowledge of the following topic:", + "prompt": "In many countries, the levels of pollution and waste are increasing. What are the main causes of " + "this increase, and what measures could be taken to address these problems?", + "suffix": "You should write at least 250 words.\nUse your own ideas, knowledge and experience and support " + "your arguments with examples and relevant evidence.", + "type": "writing", + "wordCounter": { + "limit": 250, + "type": "min" + } + } + ], + "isDiagnostic": True, + "minTimer": 40, + "module": "writing", + "task": "2" + }