diff --git a/helper/constants.py b/helper/constants.py index 7557ee9..2692aef 100644 --- a/helper/constants.py +++ b/helper/constants.py @@ -10,6 +10,7 @@ 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" +GPT_4_PREVIEW = "gpt-4-turbo-preview" GRADING_FIELDS = ['comment', 'overall', 'task_response'] GEN_FIELDS = ['topic'] diff --git a/helper/exercises.py b/helper/exercises.py index 7b58abc..63f8c24 100644 --- a/helper/exercises.py +++ b/helper/exercises.py @@ -6,7 +6,7 @@ import uuid from helper.api_messages import QuestionType from helper.firebase_helper import get_all -from helper.openai_interface import make_openai_instruct_call +from helper.openai_interface import make_openai_instruct_call, make_openai_call from helper.token_counter import count_tokens from helper.constants import * from wonderwords import RandomWord @@ -682,47 +682,58 @@ def gen_multiple_choice_level(quantity: int, start_id=1): "questions and some advanced questions. Ensure that the questions cover a range of topics such as " \ "verb tense, subject-verb agreement, pronoun usage, sentence structure, and punctuation. Make sure " \ "every question only has 1 correct answer." + + messages = [{ + "role": "user", + "content": gen_multiple_choice_for_text + }] + token_count = count_tokens(gen_multiple_choice_for_text)["n_tokens"] - 300 - mc_questions = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, gen_multiple_choice_for_text, token_count, + mc_questions = make_openai_call(GPT_4_PREVIEW, messages, token_count, None, GEN_QUESTION_TEMPERATURE) - split_mc_questions = mc_questions.split('13') + if not '25' in mc_questions: + return gen_multiple_choice_level(quantity, start_id) + else: + split_mc_questions = mc_questions.split('13') - parse_mc_questions = ('Parse the questions into this json format: {"questions": [{"id": "9", "options": ' - '[{"id": "A", "text": ' - '"And"}, {"id": "B", "text": "Cat"}, {"id": "C", "text": ' - '"Happy"}, {"id": "D", "text": "Jump"}], ' - '"prompt": "Which of the following is a conjunction?", ' - '"solution": "A", "variant": "text"}]}. ' - '\nThe questions: "' + split_mc_questions[0] + '"') - token_count = count_tokens(parse_mc_questions, model_name=GPT_3_5_TURBO_INSTRUCT)["n_tokens"] - question = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, parse_mc_questions, token_count, - ["questions"], - GEN_QUESTION_TEMPERATURE) - parse_mc_questions = ('Parse the questions into this json format: {"questions": [{"id": "9", "options": ' - '[{"id": "A", "text": ' - '"And"}, {"id": "B", "text": "Cat"}, {"id": "C", "text": ' - '"Happy"}, {"id": "D", "text": "Jump"}], ' - '"prompt": "Which of the following is a conjunction?", ' - '"solution": "A", "variant": "text"}]}. ' - '\nThe questions: "' + '13' + split_mc_questions[1] + '"') - token_count = count_tokens(parse_mc_questions, model_name=GPT_3_5_TURBO_INSTRUCT)["n_tokens"] - question_2 = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, parse_mc_questions, token_count, - ["questions"], - GEN_QUESTION_TEMPERATURE) - question["questions"].extend(question_2["questions"]) + parse_mc_questions = ('Parse the questions into this json format: \n\'{"questions": [{"id": "9", "options": ' + '[{"id": "A", "text": ' + '"And"}, {"id": "B", "text": "Cat"}, {"id": "C", "text": ' + '"Happy"}, {"id": "D", "text": "Jump"}], ' + '"prompt": "Which of the following is a conjunction?", ' + '"solution": "A", "variant": "text"}]}\'\n ' + '\nThe questions: "' + split_mc_questions[0] + '"') + token_count = count_tokens(parse_mc_questions, model_name=GPT_3_5_TURBO_INSTRUCT)["n_tokens"] + question = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, parse_mc_questions, token_count, + ["questions"], + GEN_QUESTION_TEMPERATURE) + print(question) + parse_mc_questions = ('Parse the questions into this json format: \n\'{"questions": [{"id": "9", "options": ' + '[{"id": "A", "text": ' + '"And"}, {"id": "B", "text": "Cat"}, {"id": "C", "text": ' + '"Happy"}, {"id": "D", "text": "Jump"}], ' + '"prompt": "Which of the following is a conjunction?", ' + '"solution": "A", "variant": "text"}]}\'\n ' + '\nThe questions: "' + '13' + split_mc_questions[1] + '"') + token_count = count_tokens(parse_mc_questions, model_name=GPT_3_5_TURBO_INSTRUCT)["n_tokens"] + question_2 = make_openai_instruct_call(GPT_3_5_TURBO_INSTRUCT, parse_mc_questions, token_count, + ["questions"], + GEN_QUESTION_TEMPERATURE) + print(question_2) + question["questions"].extend(question_2["questions"]) - all_exams = get_all("level") - seen_keys = set() - for i in range(len(question["questions"])): - question["questions"][i], seen_keys = replace_exercise_if_exists(all_exams, question["questions"][i], question, - seen_keys) - return { - "id": str(uuid.uuid4()), - "prompt": "Select the appropriate option.", - "questions": fix_exercise_ids(question, start_id)["questions"], - "type": "multipleChoice", - } + all_exams = get_all("level") + seen_keys = set() + for i in range(len(question["questions"])): + question["questions"][i], seen_keys = replace_exercise_if_exists(all_exams, question["questions"][i], question, + seen_keys) + return { + "id": str(uuid.uuid4()), + "prompt": "Select the appropriate option.", + "questions": fix_exercise_ids(question, start_id)["questions"], + "type": "multipleChoice", + } def replace_exercise_if_exists(all_exams, current_exercise, current_exam, seen_keys): diff --git a/helper/openai_interface.py b/helper/openai_interface.py index 3bd86af..902e511 100644 --- a/helper/openai_interface.py +++ b/helper/openai_interface.py @@ -140,19 +140,25 @@ def make_openai_call(model, messages, token_count, fields_to_check, temperature) top_p=float(TOP_P), frequency_penalty=float(FREQUENCY_PENALTY), messages=messages - ) + )["choices"][0]["message"]["content"] + + if has_blacklisted_words(result) and try_count < TRY_LIMIT: + try_count = try_count + 1 + return make_openai_call(model, messages, token_count, fields_to_check, temperature) + elif has_blacklisted_words(result) and try_count >= TRY_LIMIT: + return "" if fields_to_check is None: - return result["choices"][0]["message"]["content"] + return result.replace("\n\n", " ").strip() - processed_response = process_response(result["choices"][0]["message"]["content"], fields_to_check[0]) + processed_response = process_response(result, fields_to_check[0]) if check_fields(processed_response, fields_to_check) is False and try_count < TRY_LIMIT: try_count = try_count + 1 return make_openai_call(model, messages, token_count, fields_to_check, temperature) elif try_count >= TRY_LIMIT: try_count = 0 - return result["choices"][0]["message"]["content"] + return result else: try_count = 0 return processed_response @@ -176,13 +182,22 @@ def make_openai_instruct_call(model, message: str, token_count, fields_to_check, if fields_to_check is None: return response.replace("\n\n", " ").strip() - processed_response = process_response(response, fields_to_check[0]) - if check_fields(processed_response, fields_to_check) is False and try_count < TRY_LIMIT: - try_count = try_count + 1 + response = remove_special_characters_from_beginning(response) + if response[0] != "{" and response[0] != '"': + response = "{\"" + response + if not response.endswith("}"): + response = response + "}" + try: + processed_response = process_response(response, fields_to_check[0]) + + if check_fields(processed_response, fields_to_check) is False and try_count < TRY_LIMIT: + try_count = try_count + 1 + return make_openai_instruct_call(model, message, token_count, fields_to_check, temperature) + else: + try_count = 0 + return processed_response + except Exception as e: return make_openai_instruct_call(model, message, token_count, fields_to_check, temperature) - else: - try_count = 0 - return processed_response # GRADING SUMMARY @@ -275,3 +290,13 @@ def get_speaking_corrections(text): def has_blacklisted_words(text: str): text_lower = text.lower() return any(word in text_lower for word in BLACKLISTED_WORDS) + + +def remove_special_characters_from_beginning(string): + cleaned_string = string.lstrip('\n') + if string.startswith("'") or string.startswith('"'): + cleaned_string = string[1:] + if cleaned_string.endswith('"'): + return cleaned_string[:-1] + else: + return cleaned_string