diff --git a/app.py b/app.py index 5fec16a..cabe2aa 100644 --- a/app.py +++ b/app.py @@ -1,25 +1,23 @@ +import random + from flask import Flask, request from flask_jwt_extended import JWTManager, jwt_required from functools import reduce -import firebase_admin -from firebase_admin import credentials, firestore -from helper.api_messages import QuestionType, get_grading_messages, get_question_gen_messages, get_question_tips, \ - get_speaking_grading_messages +from helper.api_messages import * +from helper.constants import * +from helper.exercises import * from helper.file_helper import delete_files_older_than_one_day -from helper.firebase_helper import download_firebase_file, upload_file_firebase, upload_file_firebase_get_url, \ - save_to_db +from helper.firebase_helper import * from helper.heygen_api import create_video -from helper.speech_to_text_helper import speech_to_text, text_to_speech, has_words, has_10_words +from helper.speech_to_text_helper import * from helper.token_counter import count_tokens -from helper.openai_interface import make_openai_call +from helper.openai_interface import make_openai_call, make_openai_instruct_call import os -import uuid import re from dotenv import load_dotenv -from templates.question_templates import getListening1Template, getListening2Template, getSpeaking1Template, \ - getSpeaking2Template, getSpeaking3Template +from templates.question_templates import * load_dotenv() @@ -32,22 +30,6 @@ jwt = JWTManager(app) cred = credentials.Certificate(os.getenv("GOOGLE_APPLICATION_CREDENTIALS")) firebase_admin.initialize_app(cred) -GRADING_TEMPERATURE = 0.1 -TIPS_TEMPERATURE = 0.2 -GEN_QUESTION_TEMPERATURE = 0.9 -GPT_3_5_TURBO = "gpt-3.5-turbo" -GPT_3_5_TURBO_16K = "gpt-3.5-turbo-16k" -GRADING_FIELDS = ['comment', 'overall', 'task_response'] -GEN_FIELDS = ['question'] -LISTENING_GEN_FIELDS = ['transcript', 'exercise'] - -FIREBASE_BUCKET = 'mti-ielts.appspot.com' -AUDIO_FILES_PATH = 'download-audio/' -FIREBASE_LISTENING_AUDIO_FILES_PATH = 'listening_recordings/' - -VIDEO_FILES_PATH = 'download-video/' -FIREBASE_SPEAKING_VIDEO_FILES_PATH = 'speaking_videos/' - @app.route('/listening_section_1', methods=['GET']) @jwt_required() def get_listening_section_1_question(): @@ -61,6 +43,7 @@ def get_listening_section_1_question(): except Exception as e: return str(e) + @app.route('/save_listening_section_1', methods=['POST']) @jwt_required() def save_listening_section_1_question(): @@ -97,6 +80,7 @@ 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(): @@ -132,6 +116,7 @@ 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(): @@ -167,6 +152,7 @@ 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(): @@ -216,6 +202,24 @@ def grade_writing_task_1(): except Exception as e: return str(e) + +@app.route('/writing_task1_general', methods=['GET']) +@jwt_required() +def get_writing_task_1_general_question(): + try: + gen_wt1_question = "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, " \ + "requiring the student to provide information, advice, or instructions within the letter." + token_count = count_tokens(gen_wt1_question)["n_tokens"] + response = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_wt1_question, token_count, None, + GEN_QUESTION_TEMPERATURE) + return { + "question": response.strip() + } + except Exception as e: + return str(e) + + @app.route('/save_writing_task_1', methods=['POST']) @jwt_required() def save_writing_task_1_question(): @@ -259,18 +263,26 @@ def grade_writing_task_2(): except Exception as e: return str(e) -@app.route('/writing_task2', methods=['GET']) + +@app.route('/writing_task2_general', methods=['GET']) @jwt_required() -def get_writing_task_2_question(): +def get_writing_task_2_general_question(): try: - messages = get_question_gen_messages(QuestionType.WRITING_TASK_2) - 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) - response = make_openai_call(GPT_3_5_TURBO, messages, token_count, GEN_FIELDS, GEN_QUESTION_TEMPERATURE) - return response + gen_wt2_question = "Craft a comprehensive question for IELTS Writing Task 2 General Training that directs the candidate " \ + "to delve into an in-depth analysis of contrasting perspectives on a specific topic. The candidate " \ + "should be asked to discuss the strengths and weaknesses of both viewpoints, provide evidence or " \ + "examples, and present a well-rounded argument before concluding with their personal opinion on the " \ + "subject." + token_count = count_tokens(gen_wt2_question)["n_tokens"] + response = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_wt2_question, token_count, None, + GEN_QUESTION_TEMPERATURE) + return { + "question": response.strip() + } except Exception as e: return str(e) + @app.route('/save_writing_task_2', methods=['POST']) @jwt_required() def save_writing_task_2_question(): @@ -325,14 +337,19 @@ def grade_speaking_task_1(): @jwt_required() def get_speaking_task_1_question(): try: - messages = get_question_gen_messages(QuestionType.SPEAKING_1) - 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) - response = make_openai_call(GPT_3_5_TURBO, messages, token_count, GEN_FIELDS, GEN_QUESTION_TEMPERATURE) + gen_sp1_question = "Craft a thought-provoking question for IELTS Speaking Part 1 that encourages candidates to delve deeply " \ + "into personal experiences, preferences, or insights on diverse topics. Instruct the candidate to offer " \ + "not only detailed descriptions but also provide nuanced explanations, examples, or anecdotes to enrich " \ + "their response." \ + "Provide your response in this json format: {'topic': 'topic','question': 'question'}" + 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, + GEN_QUESTION_TEMPERATURE) return response except Exception as e: return str(e) + @app.route('/save_speaking_task_1', methods=['POST']) @jwt_required() def save_speaking_task_1_question(): @@ -380,6 +397,7 @@ def save_speaking_task_1_question(): except Exception as e: return str(e) + @app.route('/speaking_task_2', methods=['POST']) @jwt_required() def grade_speaking_task_2(): @@ -419,14 +437,20 @@ def grade_speaking_task_2(): @jwt_required() def get_speaking_task_2_question(): try: - messages = get_question_gen_messages(QuestionType.SPEAKING_2) - 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) - response = make_openai_call(GPT_3_5_TURBO, messages, token_count, GEN_FIELDS, GEN_QUESTION_TEMPERATURE) + gen_sp2_question = "Create a question for IELTS Speaking Part 2 that encourages candidates to narrate a personal experience " \ + "or story related to a randomly selected 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." \ + "Provide your response in this json format: {'topic': 'topic','question': 'question', " \ + "'prompts': ['prompt_1', 'prompt_2', 'prompt_3']}" + 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, + GEN_QUESTION_TEMPERATURE) return response except Exception as e: return str(e) + @app.route('/save_speaking_task_2', methods=['POST']) @jwt_required() def save_speaking_task_2_question(): @@ -474,6 +498,27 @@ def save_speaking_task_2_question(): except Exception as e: return str(e) + +@app.route('/speaking_task_3', methods=['GET']) +@jwt_required() +def get_speaking_task_3_question(): + try: + gen_sp3_question = "Formulate a set of 3 questions for IELTS Speaking Part 3 that encourage candidates to engage in a " \ + "meaningful discussion on a particular topic. Provide inquiries, ensuring " \ + "they explore various aspects, perspectives, and implications related to the topic." \ + "Provide your response in this json format: {'topic': 'topic','questions': ['question', " \ + "'question', 'question']}" + token_count = count_tokens(gen_sp3_question)["n_tokens"] + response = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_sp3_question, 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"]] + return response + except Exception as e: + return str(e) + + @app.route('/speaking_task_3', methods=['POST']) @jwt_required() def grade_speaking_task_3(): @@ -508,6 +553,7 @@ def grade_speaking_task_3(): except Exception as e: return str(e), 400 + @app.route('/save_speaking_task_3', methods=['POST']) @jwt_required() def save_speaking_task_3_question(): @@ -555,6 +601,61 @@ def save_speaking_task_3_question(): except Exception as e: return str(e) + +@app.route('/reading_passage_1', methods=['GET']) +@jwt_required() +def get_reading_passage_1_question(): + try: + TOTAL_EXERCISES = 13 + + # Extract parameters from the URL query string + topic = request.args.get('topic', default=random.choice(topics)) + req_exercises = request.args.getlist('exercises') + + number_of_exercises_q = divide_number_into_parts(TOTAL_EXERCISES, len(req_exercises)) + + passage = generate_reading_passage(QuestionType.READING_PASSAGE_1, topic) + exercises = [] + + for req_exercise in req_exercises: + if (req_exercise == "multiple_choice"): + mc_question = gen_multiple_choice_exercise(passage["text"], number_of_exercises_q.get()) + exercises.append(mc_question) + + exercises = fix_exercise_ids(exercises) + return { + "exercises": exercises, + "text": { + "content": passage["text"], + "title": passage["title"] + }, + } + except Exception as e: + return str(e) + + +@app.route('/reading_passage_1', methods=['POST']) +@jwt_required() +def save_reading_passage_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('/fetch_tips', methods=['POST']) @jwt_required() def fetch_answer_tips(): @@ -576,5 +677,6 @@ def fetch_answer_tips(): except Exception as e: return str(e) + if __name__ == '__main__': app.run() diff --git a/generate_base_questions.py b/generate_base_questions.py index 40c221a..74a5220 100644 --- a/generate_base_questions.py +++ b/generate_base_questions.py @@ -2033,7 +2033,7 @@ new_reading_to_insert_1 = { ], "prompt": "Which of the following sources is NOT mentioned as a renewable energy source?", "solution": "B", - "variant": "text", + "variant": "text" }, { "id": "11", @@ -2963,7 +2963,8 @@ new_reading_to_insert_2 = { "solutions": [ { "id": "24", - "solution": ["Task switching", "Attention management", "Inhibition of distractions", "Cognitive flexibility"] + "solution": ["Task switching", "Attention management", "Inhibition of distractions", + "Cognitive flexibility"] }, { "id": "25", @@ -3081,7 +3082,8 @@ new_reading_to_insert_2 = { "imperative to strike a balance between the benefits and {{34}} posed by social media " "in contemporary society.", "type": "fillBlanks", - "words": ["cyberbullying", "internet", "trade", "Privacy", "addictive", "resilience", "connectivity", "echo", + "words": ["cyberbullying", "internet", "trade", "Privacy", "addictive", "resilience", + "connectivity", "echo", "challenges", "adaptability", "digital", "Social", "harsh"] }, { @@ -3638,7 +3640,8 @@ new_reading_to_insert_3 = { "solutions": [ { "id": "24", - "solution": ["Task switching", "Attention management", "Inhibition of distractions", "Cognitive flexibility"] + "solution": ["Task switching", "Attention management", "Inhibition of distractions", + "Cognitive flexibility"] }, { "id": "25", @@ -3756,7 +3759,8 @@ new_reading_to_insert_3 = { "imperative to strike a balance between the benefits and {{34}} posed by social media " "in contemporary society.", "type": "fillBlanks", - "words": ["cyberbullying", "internet", "trade", "Privacy", "addictive", "resilience", "connectivity", "echo", + "words": ["cyberbullying", "internet", "trade", "Privacy", "addictive", "resilience", + "connectivity", "echo", "challenges", "adaptability", "digital", "Social", "harsh"] }, { @@ -5423,6 +5427,657 @@ new_listening_to_insert_2 = { "minTimer": 30, "module": "listening" } +new_listening_to_insert_3 = { + "parts": [ + { + "audio": { + "repeatableTimes": 3, + "source": "https://firebasestorage.googleapis.com/v0/b/mti-ielts.appspot.com/o/listening_recordings%2Ftoms_auto_repairs.mp3?alt=media&token=d88b9e6c-8ff3-4a62-9026-283202c1ba85" + }, + "exercises": [ + { + "id": str(uuid.uuid4()), + "maxWords": 4, + "prompt": "You will hear a conversation between a woman and a mechanic. Answer the questions " + "below using no more than four words or a number.", + "solutions": [ + { + "id": "1", + "solution": ["Tom's Auto Repair"] + }, + { + "id": "2", + "solution": ["Sarah", "Sara"] + }, + { + "id": "3", + "solution": ["clicking"] + }, + { + "id": "4", + "solution": ["engine"] + }, + { + "id": "5", + "solution": ["Honda Civic"] + }, + { + "id": "6", + "solution": ["2016"] + }, + { + "id": "7", + "solution": ["Thursday"] + }, + { + "id": "8", + "solution": ["3PM", "3 PM", "3:00 PM"] + }, + { + "id": "9", + "solution": ["No"] + }, + { + "id": "10", + "solution": ["Car Keys and Documents"] + }, + ], + "text": "Auto Repair Shop Name: {{1}}\\n" + "Client Name: {{2}}\\n" + "Type of noise: {{3}}\\n" + "Lights On: {{4}}\\n" + "Car: {{5}}\\n" + "Year of Manufacturing: {{6}}\\n" + "Appointment Day Of Week: {{7}}\\n" + "Time of appointment: {{8}}\\n" + "Has warranties? {{9}}\\n" + "Should bring: {{10}}\\n", + "type": "writeBlanks" + } + ] + }, + { + "audio": { + "repeatableTimes": 3, + "source": "https://firebasestorage.googleapis.com/v0/b/mti-ielts.appspot.com/o/listening_recordings%2Ffirst_day_school.mp3?alt=media&token=318ccb58-42fb-465c-b2d7-becd9cb360ee" + }, + "exercises": [ + { + "id": str(uuid.uuid4()), + "prompt": "After listening to the monologue, select the appropriate options.", + "questions": [ + { + "id": "11", + "options": [ + { + "id": "A", + "text": "To introduce school rules and regulations." + }, + { + "id": "B", + "text": "To welcome students to a new school year." + }, + { + "id": "C", + "text": "To discuss the importance of technology in education." + }, + { + "id": "D", + "text": "To explain the structure of extracurricular clubs." + } + ], + "prompt": "What is the primary purpose of the monologue?", + "solution": "B", + "variant": "text" + }, + { + "id": "12", + "options": [ + { + "id": "A", + "text": "It solely focuses on mathematics and science." + }, + { + "id": "B", + "text": "It promotes critical thinking, creativity, and problem-solving." + }, + { + "id": "C", + "text": "It discourages students from asking questions." + }, + { + "id": "D", + "text": "It limits students' involvement in extracurricular activities." + } + ], + "prompt": "In the monologue, what does the speaker emphasize about the school's curriculum?", + "solution": "B", + "variant": "text" + }, + { + "id": "13", + "options": [ + { + "id": "A", + "text": "Drama club." + }, + { + "id": "B", + "text": "Astronomy club." + }, + { + "id": "C", + "text": "Robotics club." + }, + { + "id": "D", + "text": "Literature club." + } + ], + "prompt": "Which of the following is NOT mentioned as an extracurricular activity in the monologue?", + "solution": "D", + "variant": "text" + }, + { + "id": "14", + "options": [ + { + "id": "A", + "text": "To restrict students' individuality." + }, + { + "id": "B", + "text": "To create a sense of unity and belonging." + }, + { + "id": "C", + "text": "To make students look sharp at all times." + }, + { + "id": "D", + "text": "To discourage students from attending extracurricular activities." + } + ], + "prompt": "According to the monologue, why does the school have a dress code and uniform?", + "solution": "B", + "variant": "text" + }, + { + "id": "15", + "options": [ + { + "id": "A", + "text": "Families are not supportive of students' education." + }, + { + "id": "B", + "text": "Families should not be involved in students' school life." + }, + { + "id": "C", + "text": "Families are important in guiding and supporting students." + }, + { + "id": "D", + "text": "Families hinder students' ability to make friends." + } + ], + "prompt": "What does the monologue suggest about the role of family in a student's life?", + "solution": "C", + "variant": "text" + }, + { + "id": "16", + "options": [ + { + "id": "A", + "text": "Seeking knowledge, asking questions, and embracing diversity." + }, + { + "id": "B", + "text": "Following strict rules without question." + }, + { + "id": "C", + "text": "Focusing solely on academic achievements." + }, + { + "id": "D", + "text": "Avoiding extracurricular activities to prioritize academics." + } + ], + "prompt": "According to the monologue, what does the school encourage in students?", + "solution": "A", + "variant": "text" + }, + { + "id": "17", + "options": [ + { + "id": "A", + "text": "Students should focus on academic studies only." + }, + { + "id": "B", + "text": "Participation in clubs and activities is discouraged." + }, + { + "id": "C", + "text": "Students have a range of opportunities to pursue their passions." + }, + { + "id": "D", + "text": "Clubs are only for those interested in music and drama." + } + ], + "prompt": "What is the primary message in the section about clubs and extracurricular activities?", + "solution": "C", + "variant": "text" + }, + { + "id": "18", + "options": [ + { + "id": "A", + "text": "They are essential for exploring the digital world and developing skills." + }, + { + "id": "B", + "text": "They are mainly used for playing games." + }, + { + "id": "C", + "text": "They help students avoid human interaction." + }, + { + "id": "D", + "text": "They limit students' creativity." + } + ], + "prompt": "According to the monologue, what is the importance of the school's technology resources?", + "solution": "A", + "variant": "text" + }, + { + "id": "19", + "options": [ + { + "id": "A", + "text": "Bullying is encouraged to toughen up students." + }, + { + "id": "B", + "text": "Bullying is not mentioned in the monologue." + }, + { + "id": "C", + "text": "Bullying is strictly prohibited with a zero-tolerance policy." + }, + { + "id": "D", + "text": "Bullying is seen as a natural part of school life." + } + ], + "prompt": "In the monologue, how is the school's approach to bullying described?", + "solution": "C", + "variant": "text" + }, + { + "id": "20", + "options": [ + { + "id": "A", + "text": "Students should avoid making friends and focus solely on academics." + }, + { + "id": "B", + "text": "Students should embrace a well-rounded education, involvement in clubs, and respect for one another." + }, + { + "id": "C", + "text": "Students should never ask questions and follow rules blindly." + }, + { + "id": "D", + "text": "Students should avoid participating in extracurricular activities to prioritize academics." + } + ], + "prompt": "What is the speaker's main message to students throughout the monologue?", + "solution": "B", + "variant": "text" + } + ], + "type": "multipleChoice", + } + ] + }, + { + "audio": { + "repeatableTimes": 3, + "source": "https://firebasestorage.googleapis.com/v0/b/mti-ielts.appspot.com/o/listening_recordings%2Fgym_training_conversation.mp3?alt=media&token=169757de-dbd9-4aeb-9bd6-3a470898cd34" + }, + "exercises": [ + { + "id": str(uuid.uuid4()), + "prompt": "After listening to the conversation, select the appropriate options.", + "questions": [ + { + "id": "21", + "options": [ + { + "id": "A", + "text": "Upper body strength." + }, + { + "id": "B", + "text": "Cardiovascular endurance." + }, + { + "id": "C", + "text": "Flexibility." + }, + { + "id": "D", + "text": "Core stability." + } + ], + "prompt": "What aspect of his fitness is Alex primarily looking to improve?", + "solution": "C", + "variant": "text" + }, + { + "id": "22", + "options": [ + { + "id": "A", + "text": "By doing only weightlifting." + }, + { + "id": "B", + "text": "With a mix of cardio and flexibility training." + }, + { + "id": "C", + "text": "By following a strict diet without exercise." + }, + { + "id": "D", + "text": "With exclusively long-distance running." + } + ], + "prompt": "How is Linda preparing for her 10K run?", + "solution": "B", + "variant": "text" + }, + { + "id": "23", + "options": [ + { + "id": "A", + "text": "Yoga." + }, + { + "id": "B", + "text": "Pilates." + }, + { + "id": "C", + "text": "HIIT workouts." + }, + { + "id": "D", + "text": "Swimming." + } + ], + "prompt": "What type of training is Mark incorporating into his routine?", + "solution": "C", + "variant": "text" + }, + { + "id": "24", + "options": [ + { + "id": "A", + "text": "Bench presses and rows." + }, + { + "id": "B", + "text": "Leg curls and lunges." + }, + { + "id": "C", + "text": "Bicep curls and tricep dips." + }, + { + "id": "D", + "text": "Planks and push-ups." + } + ], + "prompt": "What specific strength training exercises is Alex focusing on?", + "solution": "A", + "variant": "text" + }, + { + "id": "25", + "options": [ + { + "id": "A", + "text": "Finishing under 1 hour." + }, + { + "id": "B", + "text": "Completing in under 45 minutes." + }, + { + "id": "C", + "text": "Finishing under 50 minutes." + }, + { + "id": "D", + "text": "Setting a personal best time." + } + ], + "prompt": "What is Linda's specific time goal for her upcoming 10K run?", + "solution": "C", + "variant": "text" + }, + { + "id": "26", + "options": [ + { + "id": "A", + "text": "Gaining muscle mass." + }, + { + "id": "B", + "text": "Increasing flexibility." + }, + { + "id": "C", + "text": "Losing weight and achieving more defined abs and arms." + }, + { + "id": "D", + "text": "Improving running endurance." + } + ], + "prompt": "Mark's fitness goal includes:", + "solution": "C", + "variant": "text" + }, + { + "id": "27", + "options": [ + { + "id": "A", + "text": "Short-term training plans." + }, + { + "id": "B", + "text": "Quick fixes and shortcuts." + }, + { + "id": "C", + "text": "Consistency and hard work." + }, + { + "id": "D", + "text": "Frequent changes in workout routines." + } + ], + "prompt": "What does the trainer emphasize as a key to success in reaching fitness goals?", + "solution": "C", + "variant": "text" + }, + { + "id": "28", + "options": [ + { + "id": "A", + "text": "Increase caloric intake." + }, + { + "id": "B", + "text": "Focus on strength training only." + }, + { + "id": "C", + "text": "Create a calorie deficit and introduce core-focused workouts." + }, + { + "id": "D", + "text": "Avoid exercise altogether." + } + ], + "prompt": "What does the trainer suggest for Mark to help him shed pounds?", + "solution": "C", + "variant": "text" + }, + { + "id": "29", + "options": [ + { + "id": "A", + "text": "It doesn't emphasize the importance of goal setting." + }, + { + "id": "B", + "text": "The conversation shows that setting specific goals is crucial for tracking progress." + }, + { + "id": "C", + "text": "It implies that goals are only necessary for professional athletes." + }, + { + "id": "D", + "text": "The trainer discourages goal setting for a balanced fitness routine." + } + ], + "prompt": "How does the conversation highlight the importance of setting goals?", + "solution": "B", + "variant": "text" + }, + { + "id": "30", + "options": [ + { + "id": "A", + "text": "Promoting quick fixes for weight loss." + }, + { + "id": "B", + "text": "Highlighting the need for exclusive weightlifting." + }, + { + "id": "C", + "text": "Providing personalized advice to help individuals reach their fitness goals." + }, + { + "id": "D", + "text": "Discouraging cardio exercises." + } + ], + "prompt": "In the conversation, what is the primary focus of the trainer's guidance?", + "solution": "C", + "variant": "text" + } + ], + "type": "multipleChoice", + } + ] + }, + { + "audio": { + "repeatableTimes": 3, + "source": "https://firebasestorage.googleapis.com/v0/b/mti-ielts.appspot.com/o/listening_recordings%2Fcultural_appropriation.mp3?alt=media&token=1f298ad9-6c3e-4c49-9337-12f772ae2121" + }, + "exercises": [ + { + "id": str(uuid.uuid4()), + "maxWords": 3, + "prompt": "You will hear a lecture about international finance. Complete the notes bellow. Write no more " + "than 3 words or numbers for each answer.", + "solutions": [ + { + "id": "31", + "solution": ["culture"] + }, + { + "id": "32", + "solution": ["dominant "] + }, + { + "id": "33", + "solution": ["diversity"] + }, + { + "id": "34", + "solution": ["borrowing"] + }, + { + "id": "35", + "solution": ["Power"] + }, + { + "id": "36", + "solution": ["stereotypes"] + }, + { + "id": "37", + "solution": ["loss"] + }, + { + "id": "38", + "solution": ["understanding"] + }, + { + "id": "39", + "solution": ["sensitivity"] + }, + { + "id": "40", + "solution": ["respectful "] + }, + ], + "text": "Cultural appropriation is a controversial topic because it involves the adoption or use of elements from another {{31}}.\\n" + "Cultural appropriation becomes problematic when elements are borrowed from a marginalized culture by those from a {{32}} culture.\\n" + "Cultural exchange is essential for cultural {{33}}, but appropriation raises concerns about respect and understanding.\\n" + "Cultural appropriation is more than just cultural {{34}}; it has far-reaching social and ethical implications.\\n" + "{{35}} dynamics play a crucial role in cultural appropriation, as the appropriator often hails from a dominant culture.\\n" + "When cultural elements are commodified without acknowledging their significance, they risk perpetuating {{36}}.\\n" + "Erasure of marginalized cultures is a significant concern because it can lead to the {{37}} of cultural identity.\\n" + "The line between cultural appropriation and appreciation is not always clear-cut and depends on intent, context and {{38}}.\\n" + "The ongoing debate on cultural appropriation reflects broader conversations on cultural {{39}}.\\n" + "Fostering a deeper understanding of cultural appropriation is essential for promoting {{40}} cross-cultural interactions\\n", + "type": "writeBlanks" + } + ] + }, + ], + "isDiagnostic": False, + "minTimer": 30, + "module": "listening" +} # Falta section 3 e 4 do listening # writing task 1 com imagens ... @@ -5435,5 +6090,5 @@ db = firestore.client() # Add the JSON data to Firestore collection_ref = db.collection('listening') -document_ref = collection_ref.add(new_listening_to_insert_2) +document_ref = collection_ref.add(new_listening_to_insert_3) print(f"Document added with ID: {document_ref}") diff --git a/helper/api_messages.py b/helper/api_messages.py index 881fc74..40c8c95 100644 --- a/helper/api_messages.py +++ b/helper/api_messages.py @@ -12,6 +12,12 @@ class QuestionType(Enum): WRITING_TASK_2 = "Writing Task 2" SPEAKING_1 = "Speaking Task Part 1" SPEAKING_2 = "Speaking Task Part 2" + READING_PASSAGE_1 = "Reading Passage 1" + READING_PASSAGE_2 = "Reading Passage 2" + READING_PASSAGE_3 = "Reading Passage 3" + +class ExerciseType(Enum): + MULTIPLE_CHOICE = "multiple choice" def get_grading_messages(question_type: QuestionType, question: str, answer: str, context: str = None): diff --git a/helper/constants.py b/helper/constants.py new file mode 100644 index 0000000..2eec3fb --- /dev/null +++ b/helper/constants.py @@ -0,0 +1,120 @@ +GRADING_TEMPERATURE = 0.1 +TIPS_TEMPERATURE = 0.2 +GEN_QUESTION_TEMPERATURE = 0.7 +GPT_3_5_TURBO = "gpt-3.5-turbo" +GPT_3_5_TURBO_16K = "gpt-3.5-turbo-16k" +GPT_3_5_TURBO_INSTRUCT = "gpt-3.5-turbo-instruct" +GRADING_FIELDS = ['comment', 'overall', 'task_response'] +GEN_FIELDS = ['topic'] +GEN_TEXT_FIELDS = ['title'] +LISTENING_GEN_FIELDS = ['transcript', 'exercise'] + +FIREBASE_BUCKET = 'mti-ielts.appspot.com' +AUDIO_FILES_PATH = 'download-audio/' +FIREBASE_LISTENING_AUDIO_FILES_PATH = 'listening_recordings/' + +VIDEO_FILES_PATH = 'download-video/' +FIREBASE_SPEAKING_VIDEO_FILES_PATH = 'speaking_videos/' + +topics = [ + "Art and Creativity", + "History of Ancient Civilizations", + "Environmental Conservation", + "Space Exploration", + "Artificial Intelligence", + "Climate Change", + "World Religions", + "The Human Brain", + "Renewable Energy", + "Cultural Diversity", + "Modern Technology Trends", + "Women's Rights", + "Sustainable Agriculture", + "Globalization", + "Natural Disasters", + "Cybersecurity", + "Philosophy of Ethics", + "Robotics", + "Health and Wellness", + "Literature and Classics", + "World Geography", + "Music and Its Influence", + "Human Rights", + "Social Media Impact", + "Food Sustainability", + "Economics and Markets", + "Human Evolution", + "Political Systems", + "Mental Health Awareness", + "Quantum Physics", + "Biodiversity", + "Education Reform", + "Animal Rights", + "The Industrial Revolution", + "Future of Work", + "Film and Cinema", + "Genetic Engineering", + "Ancient Mythology", + "Climate Policy", + "Space Travel", + "Renewable Energy Sources", + "Cultural Heritage Preservation", + "Modern Art Movements", + "Immigration Issues", + "Sustainable Transportation", + "The History of Medicine", + "Artificial Neural Networks", + "Climate Adaptation", + "Philosophy of Existence", + "Augmented Reality", + "Yoga and Meditation", + "Literary Genres", + "World Oceans", + "Gender Equality", + "Social Networking", + "Sustainable Fashion", + "International Trade", + "Prehistoric Era", + "Democracy and Governance", + "Postcolonial Literature", + "Geopolitics", + "Psychology and Behavior", + "Nanotechnology", + "Endangered Species", + "Education Technology", + "Renaissance Art", + "Renewable Energy Policy", + "Cultural Festivals", + "Modern Architecture", + "Climate Resilience", + "Artificial Life", + "Fitness and Nutrition", + "Classic Literature Adaptations", + "World History Wars", + "Ethical Dilemmas", + "Internet of Things (IoT)", + "Meditation Practices", + "Literary Symbolism", + "Marine Conservation", + "Social Justice Movements", + "Sustainable Tourism", + "International Finance", + "Ancient Philosophy", + "Cold War Era", + "Behavioral Economics", + "Space Colonization", + "Clean Energy Initiatives", + "Cultural Exchange", + "Modern Sculpture", + "Climate Mitigation", + "Artificial Intelligence Ethics", + "Mindfulness", + "Literary Criticism", + "Wildlife Conservation", + "Political Activism", + "Renewable Energy Innovations", + "History of Mathematics", + "Human-Computer Interaction", + "Global Health", + "Cultural Appropriation" +] \ No newline at end of file diff --git a/helper/exercises.py b/helper/exercises.py new file mode 100644 index 0000000..e0364cc --- /dev/null +++ b/helper/exercises.py @@ -0,0 +1,72 @@ +import queue + +from helper.api_messages import QuestionType +from helper.openai_interface import make_openai_instruct_call +from helper.token_counter import count_tokens +from helper.constants import * + +def divide_number_into_parts(number, parts): + if number < parts: + return None + + part_size = number // parts + remaining = number % parts + + q = queue.Queue() + + for i in range(parts): + if i < remaining: + q.put(part_size + 1) + else: + q.put(part_size) + + return q + +def fix_exercise_ids(exercises): + # Initialize the starting ID for the first exercise + current_id = 1 + + # Iterate through exercises + for exercise in exercises: + questions = exercise["questions"] + + # Iterate through questions and update the "id" value + for question in questions: + question["id"] = str(current_id) + current_id += 1 + + return exercises + + +def generate_reading_passage(type: QuestionType, topic: str): + gen_reading_passage_1 = "Generate an extensive text for IELTS " + type.READING_PASSAGE_1.value + ", of at least 1500 words, on the topic " \ + "of " + topic + ". The passage should offer a substantial amount of " \ + "information, analysis, or narrative " \ + "relevant to the chosen subject matter. This text passage aims to serve as the primary reading " \ + "section of an IELTS test, providing an in-depth and comprehensive exploration of the topic." \ + "Provide your response in this json format: {'title': 'title of the text', 'text': 'generated text'}" + token_count = count_tokens(gen_reading_passage_1)["n_tokens"] + return make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_reading_passage_1, token_count, GEN_TEXT_FIELDS, + GEN_QUESTION_TEMPERATURE) + +def gen_multiple_choice_exercise(text: str, quantity: int): + gen_multiple_choice_for_text = "Generate" + str(quantity) + "multiple choice questions for this text: " \ + "'" + text + "'\n" \ + "Use this format: 'questions': [{'id': '9', 'options': [{'id': 'A', 'text': " \ + "'Economic benefits'}, {'id': 'B', 'text': 'Government regulations'}, {'id': 'C', 'text': " \ + "'Concerns about climate change'}, {'id': 'D', 'text': 'Technological advancement'}], " \ + "'prompt': 'What is the main reason for the shift towards renewable energy sources?', " \ + "'solution': 'C', 'variant': 'text'}]" + token_count = count_tokens(gen_multiple_choice_for_text)["n_tokens"] + mc_questions = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_multiple_choice_for_text, token_count, + None, + GEN_QUESTION_TEMPERATURE) + parse_mc_questions = "Parse this '" + mc_questions + "' into this json format: 'questions': [{'id': '9', 'options': [{'id': 'A', 'text': " \ + "'Economic benefits'}, {'id': 'B', 'text': 'Government regulations'}, {'id': 'C', 'text': " \ + "'Concerns about climate change'}, {'id': 'D', 'text': 'Technological advancement'}], " \ + "'prompt': 'What is the main reason for the shift towards renewable energy sources?', " \ + "'solution': 'C', 'variant': 'text'}]" + token_count = count_tokens(parse_mc_questions)["n_tokens"] + return make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, parse_mc_questions, token_count, + ["questions"], + GEN_QUESTION_TEMPERATURE) \ No newline at end of file diff --git a/helper/openai_interface.py b/helper/openai_interface.py index d5a4b57..e5213ed 100644 --- a/helper/openai_interface.py +++ b/helper/openai_interface.py @@ -8,7 +8,6 @@ from dotenv import load_dotenv load_dotenv() openai.api_key = os.getenv("OPENAI_API_KEY") - MAX_TOKENS = 4097 TOP_P = 0.9 FREQUENCY_PENALTY = 0.5 @@ -16,6 +15,7 @@ FREQUENCY_PENALTY = 0.5 TRY_LIMIT = 1 try_count = 0 + def process_response(input_string, quotation_check_field): if '{' in input_string: try: @@ -24,25 +24,42 @@ def process_response(input_string, quotation_check_field): # Extract everything after the first '{' (inclusive) result = input_string[index:] if re.search(r"'" + quotation_check_field + "':\s*'(.*?)'", result, re.DOTALL | re.MULTILINE): - parsed_string = result.replace("\"", "\\\"") - pattern = r"(?= TRY_LIMIT: + try_count = 0 + return remove_special_chars_and_escapes(response) + else: + try_count = 0 + return processed_response diff --git a/wt1_playground.py b/wt1_playground.py index 0d4a4fc..dafe761 100644 --- a/wt1_playground.py +++ b/wt1_playground.py @@ -13,6 +13,8 @@ from helper.token_counter import count_tokens load_dotenv() openai.api_key = os.getenv("OPENAI_API_KEY") +# https://chat.openai.com/share/195c4549-f67c-4353-be44-65c4d5ad5b05 + question = "The average standard of people's health is likely to be lower in the future than it is now. To what extent do " \ "you agree or disagree with this statement?" answer = "I completely disagree with the written statement. I believe that most of the people in the world have more information " \ @@ -32,14 +34,38 @@ answer = "I completely disagree with the written statement. I believe that most # map(lambda x: x["content"], filter(lambda x: "content" in x, messages)), 0) # response = make_openai_call("gpt-4", messages, token_count, GRADING_FIELDS, GRADING_TEMPERATURE) -grade_wt2_message = "You are a IELTS examiner. " \ - "The question you have to grade is of type Writing Task 2 and is the following:" + question + \ - "Assess this answer according to the IELTS grading system. It is mandatory for you to provide your response" \ - " with the overall grade and breakdown grades, with just the following json format: {'comment': 'Comment about " \ - "answer quality will go here', 'overall': 7.0, 'task_response': {'Task Achievement': 8.0, " \ - "'Coherence and Cohesion': 6.5, 'Lexical Resource': 7.5, 'Grammatical Range and Accuracy': 6.0}} " \ - "Evaluate this answer according to ielts grading system: " + answer +gen_wt1_question = "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, requiring the student " \ + "to provide information, advice, or instructions within the letter." +gen_wt2_question = "Craft a comprehensive question for IELTS Writing Task 2 General Training that directs the candidate " \ + "to delve into an in-depth analysis of contrasting perspectives on a specific topic. The candidate " \ + "should be asked to discuss the strengths and weaknesses of both viewpoints, provide evidence or " \ + "examples, and present a well-rounded argument before concluding with their personal opinion on the " \ + "subject." +gen_sp1_question = "Craft a thought-provoking question for IELTS Speaking Part 1 that encourages candidates to delve deeply " \ + "into personal experiences, preferences, or insights on diverse topics. Instruct the candidate to offer " \ + "not only detailed descriptions but also provide nuanced explanations, examples, or anecdotes to enrich " \ + "their response." \ + "Provide your response in this json format: {'topic': 'topic','question': 'question'}" +gen_sp2_question = "Create a question for IELTS Speaking Part 2 that encourages candidates to narrate a personal experience " \ + "or story related to a randomly selected 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." \ + "Provide your response in this json format: {'topic': 'topic','question': 'question', " \ + "'prompts': ['prompt_1', 'prompt_2', 'prompt_3']}" +gen_sp3_question = "Formulate a set of 3 questions for IELTS Speaking Part 3 that encourage candidates to engage in a " \ + "meaningful discussion on a particular topic. Provide inquiries, ensuring " \ + "they explore various aspects, perspectives, and implications related to the topic." \ + "Provide your response in this json format: {'topic': 'topic','questions': ['question_1', " \ + "'question_2', 'question_3']}" +grade_wt2_message = "You are a IELTS examiner. " \ + "The question you have to grade is of type Writing Task 2 and is the following:" + question + \ + "Assess this answer according to the IELTS grading system. It is mandatory for you to provide your response" \ + " with the overall grade and breakdown grades, with just the following json format: {'comment': 'Comment about " \ + "answer quality will go here', 'overall': 7.0, 'task_response': {'Task Achievement': 8.0, " \ + "'Coherence and Cohesion': 6.5, 'Lexical Resource': 7.5, 'Grammatical Range and Accuracy': 6.0}} " \ + "Evaluate this answer according to ielts grading system: " + answer topics = [ "Art and Creativity", @@ -145,30 +171,87 @@ topics = [ ] gen_listening2_message = "You are an IELTS program designed to assist with language learning. Your task is to provide a detailed " \ - "transcript of a monologue on the subject of " + random.choice(topics) + ". Ensure that the transcript is comprehensive " \ - "and covers the topic " \ - "thoroughly.After the transcript, you should generate a fill in the blanks " \ - "exercise with six statements related to the content of the monologue. The blank spaces in the exercise should " \ - "be identified by {{number}}. Finally, provide the answers for the exercise." \ - "Response Format (JSON): { 'transcript': 'Transcript of the monologue on a specific subject with a minimum of 500 words.', 'exercise': {" \ - "'statements': { '1': 'Statement 1 with a blank space to fill.', '2': 'Statement 2 with a blank space to fill.'," \ - "'3': 'Statement 3 with a blank space to fill.', '4': 'Statement 4 with a blank space to fill.', " \ - "'5': 'Statement 5 with a blank space to fill.', '6': 'Statement 6 with a blank space to fill.' }, " \ - "'answers': { '1': 'Answer to fill the blank space in statement 1.', " \ - "'2': 'Answer to fill the blank space in statement 2.', '3': 'Answer to fill the blank space in statement 3.'," \ - "'4': 'Answer to fill the blank space in statement 4.', '5': 'Answer to fill the blank space in statement 5.'," \ - "'6': 'Answer to fill the blank space in statement 6.' } } }" + "transcript of a monologue on the subject of " + random.choice( + topics) + ". Ensure that the transcript is comprehensive " \ + "and covers the topic " \ + "thoroughly.After the transcript, you should generate a fill in the blanks " \ + "exercise with six statements related to the content of the monologue. The blank spaces in the exercise should " \ + "be identified by {{number}}. Finally, provide the answers for the exercise." \ + "Response Format (JSON): { 'transcript': 'Transcript of the monologue on a specific subject with a minimum of 500 words.', 'exercise': {" \ + "'statements': { '1': 'Statement 1 with a blank space to fill.', '2': 'Statement 2 with a blank space to fill.'," \ + "'3': 'Statement 3 with a blank space to fill.', '4': 'Statement 4 with a blank space to fill.', " \ + "'5': 'Statement 5 with a blank space to fill.', '6': 'Statement 6 with a blank space to fill.' }, " \ + "'answers': { '1': 'Answer to fill the blank space in statement 1.', " \ + "'2': 'Answer to fill the blank space in statement 2.', '3': 'Answer to fill the blank space in statement 3.'," \ + "'4': 'Answer to fill the blank space in statement 4.', '5': 'Answer to fill the blank space in statement 5.'," \ + "'6': 'Answer to fill the blank space in statement 6.' } } }" +gen_reading_passage_1 = "Generate an extensive text for IELTS Reading Passage 1, of at least 1500 words, on the topic " \ + "of " + random.choice(topics) + ". The passage should offer a substantial amount of " \ + "information, analysis, or narrative " \ + "relevant to the chosen subject matter. This text passage aims to serve as the primary reading " \ + "section of an IELTS test, providing an in-depth and comprehensive exploration of the topic." \ + "Provide your response in this json format: {'title': 'title of the text', 'text': 'generated text'}" +gen_reading_passage_2 = "Generate an extensive text for IELTS Reading Passage 2, of at least 1500 words, on the topic " \ + "of " + random.choice(topics) + ". The passage should offer a substantial amount of " \ + "information, analysis, or narrative " \ + "relevant to the chosen subject matter. This text passage aims to serve as the primary reading " \ + "section of an IELTS test, providing an in-depth and comprehensive exploration of the topic." \ + "Provide your response in this json format: {'title': 'title of the text', 'text': 'generated text'}" +gen_reading_passage_3 = "Generate an extensive text for IELTS Reading Passage 2, of at least 1500 words, on the topic " \ + "of " + random.choice(topics) + ". The passage should offer a substantial amount of " \ + "information, analysis, or narrative " \ + "relevant to the chosen subject matter. This text passage aims to serve as the primary reading " \ + "section of an IELTS test, providing an in-depth and comprehensive exploration of the topic." \ + "Provide your response in this json format: {'title': 'title of the text', 'text': 'generated text'}" -token_count = count_tokens(gen_listening2_message)["n_tokens"] +sample_text = "In recent years, there has been a significant shift towards renewable energy sources as societies " \ + "strive to reduce their dependence on fossil fuels and combat the effects of climate change. Renewable " \ + "energy, derived from sources such as sunlight, wind, and water, offers a promising alternative to " \ + "traditional energy generation methods.\\nSolar power, harnessed from the sun's rays, has gained immense " \ + "popularity. Photovoltaic cells, commonly known as solar panels, capture sunlight and convert it into " \ + "electricity. This technology has become more efficient and affordable, contributing to a growing number " \ + "of solar installations on rooftops and solar farms. Solar energy not only reduces greenhouse gas " \ + "emissions but also grants individuals and businesses the ability to generate their own power.\\nSimilarly, " \ + "wind energy has emerged as a reliable and clean source of electricity. Wind turbines, often found in " \ + "wind farms, harness the kinetic energy of moving air to turn blades and generate electricity. These " \ + "structures are strategically placed in areas with consistent wind patterns, contributing to the overall " \ + "energy grid. Wind power has the advantage of scalability, with both small and large installations being " \ + "feasible options.\\nHydropower, generated from flowing water in rivers and dams, is another vital renewable " \ + "energy source. The force of water is used to turn turbines, which then produce electricity. While hydropower " \ + "has a long history, advancements in technology have led to more efficient and environmentally friendly " \ + "designs. However, the construction of dams for hydropower can have significant ecological and social " \ + "impacts, requiring careful consideration.\\nGeothermal energy, originating from the Earth's heat, is " \ + "also gaining attention. This energy source is harnessed through underground steam and hot water reservoirs, " \ + "which are tapped for electricity generation and heating. Geothermal power plants have a relatively small " \ + "environmental footprint and provide a consistent source of energy, making them a viable option in regions " \ + "with suitable geological conditions.\\nIn conclusion, the transition to renewable energy sources marks a " \ + "pivotal step towards sustainable and environmentally conscious energy generation. Solar, wind, hydropower, " \ + "and geothermal energy offer diverse options that can collectively contribute to reducing carbon emissions " \ + "and combating climate change. As technology continues to evolve and economies adapt, the potential for " \ + "widespread adoption of renewable energy remains promising." +gen_multiple_choice_for_text = "Generate 10 multiple choice questions for this text: '" + sample_text + "'\n" \ + "Parse those questions to this format: 'questions': [{'id': '9', 'options': [{'id': 'A', 'text': " \ + "'Economic benefits'}, {'id': 'B', 'text': 'Government regulations'}, {'id': 'C', 'text': " \ + "'Concerns about climate change'}, {'id': 'D', 'text': 'Technological advancement'}], " \ + "'prompt': 'What is the main reason for the shift towards renewable energy sources?', " \ + "'solution': 'C', 'variant': 'text'}]" + +mc_questions = "questions: 1. What is the main reason for the shift towards renewable energy sources? - A. Economic benefits - B. Government regulations - C. Concerns about climate change - D. Technological advancement 2. Which of the following is NOT a renewable energy source mentioned in the text? - A. Solar power - B. Coal - C. Wind energy - D. Hydropower 3. What is the term used to describe the conversion of sunlight into electricity? - A. Solar power - B. Photovoltaic cells - C. Wind turbines - D. Hydropower 4. Which of the following is a benefit of solar energy? - A. Reduced greenhouse gas emissions - B. Increased dependence on fossil fuels - C. Higher energy costs - D. Limited availability 5. How do wind turbines generate electricity? - A. By harnessing the sun's rays - B. By using the force of water - C. By capturing wind - D. By tapping into underground reservoirs 6. What is the advantage of wind power over other renewable energy sources? - A. It is more affordable - B. It is more scalable - C. It has a smaller environmental footprint - D. It is easier to construct 7. Which renewable energy source has a long history but has recently seen advancements in technology? - A. Solar energy - B. Hydropower - C. Wind energy - D. Geothermal energy 8. What is the main drawback of constructing dams for hydropower? - A. Limited availability of suitable locations - B. High cost of construction - C. Negative impacts on the environment - D. Technological limitations 9. What is the source of geothermal energy? - A. The sun's rays - B. Moving air - C. Flowing water - D. The Earth's heat 10. How does geothermal energy differ from other renewable energy sources mentioned in the text? - A. It has a smaller environmental footprint - B. It is more expensive to harness - C. It is not affected by geographical conditions - D. It provides a consistent source of energy." +parse_mc_questions = "Parse this '" + mc_questions + "' into this json format: 'questions': [{'id': '9', 'options': [{'id': 'A', 'text': " \ + "'Economic benefits'}, {'id': 'B', 'text': 'Government regulations'}, {'id': 'C', 'text': " \ + "'Concerns about climate change'}, {'id': 'D', 'text': 'Technological advancement'}], " \ + "'prompt': 'What is the main reason for the shift towards renewable energy sources?', " \ + "'solution': 'C', 'variant': 'text'}]" + +token_count = count_tokens(parse_mc_questions)["n_tokens"] response = openai.Completion.create( - model="gpt-3.5-turbo-instruct", - prompt=gen_listening2_message, - max_tokens=int(4097 - token_count - 300), - temperature=0.7 -)["choices"][0]["text"] + model="gpt-3.5-turbo-instruct", + prompt=parse_mc_questions, + max_tokens=int(4097 - token_count - 300), + temperature=0.7 +) # processed = process_response(response, "comment") -processed = process_response(response, "transcript") +processed = process_response(response["choices"][0]["text"], "transcript") print(processed) -