import os import gradio as gr import requests def clamp(x, minimum, maximum): return max(minimum, min(x, maximum)) ################################################################################################################################################# # API calls ################################################################################################################################################# # read secret api key API_KEY = os.getenv('ApiKey') base_url = "https://skapi.polyglot-edu.com/" levels = ["Pre K", "Primary", "Middle School", "High School", "Academic"] def get_level_mapping(level): return { "Academic": 0, "Pre K": 1, "Primary": 2, "Middle School": 3, "High School": 4, }[level] def generate_fill_gaps(original_text, level, number_of_words, number_of_gaps, number_of_distractors, temperature): """ Generate a fill-gaps question from a given text. Parameters ---------- original_text : str The original text from which to generate the fill-gaps question. number_of_words : int The number of words of the generated text. number_of_gaps : int The number of gaps to generate. number_of_distractors : int The number of distractors to generate for each gap. temperature : float The temperature for the generation. Returns ------- str The fill-gaps question. """ match number_of_words: case "≈ 150 Words": number_of_words = 150 case "≈ 250 Words": number_of_words = 250 case "≈ 350 Words": number_of_words = 350 response = requests.post( base_url + "FillTheGaps/generateexercise", headers={ "ApiKey": API_KEY }, json={ "text": original_text, "level": get_level_mapping(level), "n_o_w": int(number_of_words), "n_o_g": int(number_of_gaps), "n_o_d": int(number_of_distractors), "temperature": int(temperature) * 0.2 }, timeout=20 ) if response.status_code == 200: return response.text raise Exception(f"API call failed with status code {response.status_code} and message {response.text}") def generate_open_question(original_text, level, temperature): """ Generate an open question from a given text. Parameters ---------- original_text : str The original text from which to generate the open question. temperature : float The temperature for the generation. Returns ------- str The open question. """ response = requests.post( base_url + "QuestionExercise/generateexercise", headers={ "ApiKey": API_KEY }, json={ "text": original_text, "level": get_level_mapping(level), "temperature": int(temperature) * 0.2 }, timeout=20 ) if response.status_code == 200: return response.text raise Exception(f"API call failed with status code {response.status_code} and message {response.text}") def generate_multiplechoice(original_text, level, number_of_options, number_of_easy_distractors, number_of_distractors, temperature): """ Generate a multiple-choice question from a given text. Parameters ---------- original_text : str The original text from which to generate the multiple-choice question. number_of_options : int The number of options to generate. number_of_easy_distractors : int The number of easy distractors to generate for each option. number_of_distractors : int The number of distractors to generate for each option. temperature : float The temperature for the generation. Returns ------- str The multiple-choice question. """ response = requests.post( base_url + "QuizExercise/generateexercise", headers={ "ApiKey": API_KEY }, json={ "text": original_text, "type": True, "level": get_level_mapping(level), "n_o_d": int(number_of_distractors), "nedd": int(number_of_easy_distractors), "temperature": int(temperature) * 0.2 }, timeout=20 ) if response.status_code == 200: return response.text raise Exception(f"API call failed with status code {response.status_code} and message {response.text}") ################################################################################################################################################# # Interface building ################################################################################################################################################# flag_link = "https://www.google.com" comment_link = "https://www.google.com" def build_fill_gaps_interface(): """ Build the fill-gaps interface. """ with gr.Blocks(title="Fill-gaps") as demo: with gr.Row(): with gr.Column(scale=5): input_field = gr.TextArea(lines=10, max_lines=10, label="Input text (can be a text or a url)") submit_btn = gr.Button(value="Submit") with gr.Column(scale=4): output_text_length = gr.Radio(["≈ 150 Words", "≈ 250 Words", "≈ 350 Words"], label="Output text length", value="≈ 150 Words") level = gr.Radio(levels, label="Level", value="Primary") with gr.Row(): blanks = gr.Number(value=5, minimum=4, maximum=8, step=1, label="Number of blanks") distractors = gr.Number(value=5, minimum=4, maximum=8, step=1, label="Number of distractors") temperature = gr.Checkbox(value=False, label="Increase creativity (decreases preciseness)") def update_numeric(output_text_length, blanks, distractors): if output_text_length == "≈ 150 Words": min_, max_ = 4, 8 elif output_text_length == "≈ 250 Words": min_, max_ = 6, 10 elif output_text_length == "≈ 350 Words": min_, max_ = 8, 12 return ( gr.Number(value=clamp(blanks, min_, max_), minimum=min_, maximum=max_, label="Number of blanks"), gr.Number(value=clamp(distractors, 0, blanks), minimum=0, maximum=blanks, label="Number of distractors") ) def update_blanks(blanks, distractors): return gr.Number(value=clamp(distractors, 0, blanks), minimum=0, maximum=blanks, label="Number of distractors") blanks.change(update_blanks, [blanks, distractors], [distractors]) output_text_length.change(update_numeric, [output_text_length, blanks, distractors], [blanks, distractors]) with gr.Row(): output = gr.TextArea(placeholder="Generated text", label="Output") with gr.Row() as button_row: upvote_btn = gr.Button(value="👍 Upvote") downvote_btn = gr.Button(value="👎 Downvote") comment_btn = gr.Button(value="💬 Comment", link=comment_link) flag_btn = gr.Button(value="⚠️ Flag", link=flag_link) submit_btn.click(generate_fill_gaps, [input_field, level, output_text_length, blanks, distractors, temperature], [output]) return demo def build_multiplechoice_interface(): """ Build the open question interface. """ with gr.Blocks(title="Open Question") as demo: with gr.Row(): with gr.Column(scale=5): input_field = gr.TextArea(lines=10, max_lines=10, label="Input text (can be a text or a url)") submit_btn = gr.Button(value="Submit") with gr.Column(scale=4): level = gr.Radio(levels, label="Level", value="Primary") with gr.Row(): options = gr.Number(value=4, minimum=2, maximum=8, step=1, label="Number of blanks", interactive=False) easy_distractors = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of easy distractors") distractors = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of distractors") temperature = gr.Checkbox(value=False, label="Increase creativity (decreases preciseness)") def update_options(options, easy_distractors, distractors): distractors = clamp(distractors, 0, options) easy_distractors = clamp(easy_distractors, 0, distractors) return ( gr.Number(value=easy_distractors, minimum=0, maximum=distractors, label="Number of easy distractors"), gr.Number(value=distractors, minimum=0, maximum=options, label="Number of distractors") ) def update_distractors(easy_distractors, distractors): easy_distractors = clamp(easy_distractors, 0, distractors) return gr.Number(value=easy_distractors, minimum=0, maximum=distractors, label="Number of easy distractors") options.change(update_options, [options, easy_distractors, distractors], [easy_distractors, distractors]) distractors.change(update_distractors, [easy_distractors, distractors], [easy_distractors]) with gr.Row(): output = gr.TextArea(placeholder="Generated text", label="Output") with gr.Row() as button_row: upvote_btn = gr.Button(value="👍 Upvote") downvote_btn = gr.Button(value="👎 Downvote") comment_btn = gr.Button(value="💬 Comment", link=comment_link) flag_btn = gr.Button(value="⚠️ Flag", link=flag_link) submit_btn.click(generate_multiplechoice, [input_field, level, options, easy_distractors, distractors, temperature], [output]) return demo def build_open_question_interface(): """ Build the multiple-choice interface. """ with gr.Blocks(title="Multiple choice") as demo: with gr.Row(): with gr.Column(scale=5): input_field = gr.TextArea(lines=10, max_lines=10, label="Input text (can be a text or a url)") submit_btn = gr.Button(value="Submit") with gr.Column(scale=4): level = gr.Radio(levels, label="Level", value="Primary") with gr.Row(): pass temperature = gr.Checkbox(value=False, label="Increase creativity (decreases preciseness)") with gr.Row(): output = gr.TextArea(placeholder="Generated text", label="Output") with gr.Row() as button_row: upvote_btn = gr.Button(value="👍 Upvote") downvote_btn = gr.Button(value="👎 Downvote") comment_btn = gr.Button(value="💬 Comment", link=comment_link) flag_btn = gr.Button(value="⚠️ Flag", link=flag_link) submit_btn.click(generate_open_question, [input_field, level, temperature], [output]) return demo def build_demo(): return gr.TabbedInterface( [build_fill_gaps_interface(), build_open_question_interface(), build_multiplechoice_interface()], ["Fill-gaps", "Open question", "Multiple-choice"], title="Education AI" ) if __name__ == "__main__": build_demo().launch(share=False)