Spaces:
Sleeping
Sleeping
Jeff Myers II
Replaced Gemma for OpenAI API and commented out visualize_quiz_answers (seems to be breaking the script).
54e639b
| # %% | |
| import random | |
| import gradio as gr | |
| from News import News | |
| from Gemma import GemmaLLM | |
| # import matplotlib.pyplot as plt | |
| # %% | |
| class Cooldown: | |
| ... | |
| cooldown = Cooldown() ################################## News fetching cooldown in seconds | |
| news = News() ########################################## Initialize the News object | |
| model = GemmaLLM() ##################################### Initialize the Gemma model | |
| # %% | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# Reading & Quiz Application") | |
| ###### | |
| ###### State Variables and Components Initialization | |
| ###### | |
| init = ( ########################################### Initialize the Gradio interface with components and state variables | |
| gr.Markdown("## Read Articles"), | |
| ## State variables for news articles and quiz, | |
| gr.State({}), gr.State([]), gr.State({}), | |
| gr.Slider(label="Number of Articles", minimum=1, maximum=10, value=10, step=1), | |
| gr.Radio(label="Category (optional)", choices=news.__CATEGORIES__), | |
| gr.Button("Get Articles"), | |
| gr.Radio(visible=False), | |
| gr.Textbox(visible=False), | |
| gr.Button(visible=False), | |
| gr.Checkbox(visible=False), | |
| gr.Textbox(visible=False), | |
| gr.Button(visible=False), | |
| ## State variables for quiz | |
| gr.State([]), gr.State([]), gr.State(), | |
| [gr.Radio(visible=False) for _ in range(10)], | |
| gr.Button(visible=False), | |
| gr.Textbox(visible=False), | |
| gr.Button(visible=False), | |
| ) | |
| ( ################################################## State variables and components for news articles and quiz | |
| heading, | |
| ## Components for news articles | |
| article, articles, descriptions, | |
| num_headlines, category, get, | |
| headline, description, show, | |
| summarize, content, ready, | |
| ## Components for quiz | |
| answers, response, results, | |
| quiz, submit, | |
| evaluation, read, | |
| ) = init | |
| def hide_news(): ################################### Hide news-related components | |
| num_headlines = gr.Slider(visible=False) | |
| category = gr.Radio(visible=False) | |
| get = gr.Button(visible=False) | |
| headline = gr.Radio(visible=False) | |
| description = gr.Textbox(visible=False) | |
| show = gr.Button(visible=False) | |
| summarize = gr.Checkbox(visible=False) | |
| content = gr.Textbox(visible=False) | |
| ready = gr.Button(visible=False) | |
| return num_headlines, category, get, headline, description, show, summarize, content, ready | |
| def show_news(): ################################### Show news-related components | |
| num_headlines = gr.Slider(label="Number of Articles", minimum=1, maximum=10, value=10, step=1, visible=True) | |
| category = gr.Radio(label="Category (optional)", choices=news.__CATEGORIES__, visible=True) | |
| get = gr.Button("Get Articles", visible=True) | |
| return num_headlines, category, get | |
| def show_headline(headlines, descriptions): ######## Show news headlines and descriptions | |
| headline = gr.Radio(label="Select an Article", choices=headlines, value=headlines[0], interactive=True, visible=True) | |
| description = gr.Textbox(label="Article Description", value=descriptions[0], visible=True) | |
| show = gr.Button("Show Content", visible=True) | |
| return headline, description, show | |
| def show_content(content): ######################### Show article content and summary | |
| summarize = gr.Checkbox(label="Show Summary?", value=False, interactive=True, visible=True) | |
| content = gr.Textbox(label="Content", value=content, visible=True) | |
| ready = gr.Button("Begin Quiz", visible=True) | |
| return summarize, content, ready | |
| def format_mcq(mcq): ############################### Format multiple choice question for quiz | |
| if not mcq or not isinstance(mcq, dict): | |
| print(f"Multiple choice question object is a {type(mcq)} but should be {type(dict())}.") | |
| return "Invalid multiple choice question.", None | |
| question = mcq.get('question', 'No question provided.') | |
| answer = mcq.get('correct_answer', 'No correct answer provided.') | |
| false_answers = mcq.get('false_answers', []) | |
| if not isinstance(false_answers, list): | |
| print(f"False answers is a {type(false_answers)} but should be {type(list())}.") | |
| return "Invalid false answers format.", None | |
| options = random.shuffle([answer] + false_answers) | |
| return question, options, answer | |
| def hide_quiz(): ################################### Hide quiz-related components | |
| quiz = [gr.Radio(visible=False) for _ in range(10)] | |
| submit = gr.Button(visible=False) | |
| evaluation = gr.Textbox(visible=False) | |
| read = gr.Button(visible=False) | |
| return read, evaluation, submit, *quiz | |
| def show_quiz(mcqs): ############################### Show quiz-related components | |
| quiz = [(mcq["question"], mcq["false_answers"], mcq["correct_answer"]) for mcq in mcqs] | |
| quiz = [(question, random.sample(distractors + [answer], 4), answer) for question, distractors, answer in quiz] | |
| questions, options, answers = zip(*quiz) if quiz else ([], [], []) | |
| quiz = [gr.Radio(label=f"{i + 1}: {questions[i]}", choices=options[i], visible=True) for i in range(len(mcqs))] | |
| quiz += [gr.Radio(visible=False) for _ in range(10 - len(mcqs))] | |
| submit = gr.Button("Submit Answers", interactive=bool(answers), visible=True) | |
| return submit, list(answers), *quiz | |
| def show_eval(eva): ################################ Show evaluation of user's response to the quiz | |
| evaluation = gr.Textbox(label="Evaluation", value=eva, visible=True) | |
| read = gr.Button("Read Articles", visible=True) | |
| return evaluation, read | |
| ###### | |
| ###### Get and Display News Articles | |
| ###### | |
| def get_headline(category, num_headlines): ######### Get news headlines based on selected category and number | |
| articles = news.get_top_headlines(category=category, num_headlines=num_headlines) | |
| headlines, descriptions = zip(*[(article['title'], article.get('description', 'No description available.')) for article in articles]) | |
| show = show_headline(headlines, descriptions) | |
| descriptions = {h: d for h, d in zip(headlines, descriptions)} | |
| return articles, descriptions, *show | |
| get.click(get_headline, inputs=[category, num_headlines], outputs=[articles, descriptions, headline, description, show]) | |
| def get_description(descriptions, headline): ####### Get description for the selected headline | |
| description = "No description available." | |
| if not descriptions: print("Descriptions are empty.") | |
| elif not headline: print("Headline is empty.") | |
| elif not isinstance(descriptions, dict): print(f"Descriptions is a {type(descriptions)} but should be {type(dict())}.") | |
| else: description = descriptions.get(headline, description) | |
| return description | |
| headline.change(get_description, inputs=[descriptions, headline], outputs=[description]) | |
| def get_article(articles, headline): ############### Get article for the selected headline | |
| headlines = [a['title'] for a in articles] | |
| if headline not in headlines: return {} | |
| return articles[headlines.index(headline)] | |
| show.click(get_article, inputs=[articles, headline], outputs=[article]) | |
| def get_content(article): ########################## Get content for the selected article | |
| return article, *show_content(article.get("content", "Content not available.")) | |
| article.change(get_content, inputs=[article], outputs=[article, summarize, content, ready]) | |
| def toggle_summary(articles, article, summarize): ## Toggle between showing summary and full content | |
| if not article: print("Selected article is empty.") | |
| elif not isinstance(article, dict): print(f"Selected article is a {type(article)} but should be {type(dict())}.") | |
| elif not summarize: return article.get("content", "Content not available.") | |
| elif "summary" not in article: | |
| idx = articles.index(article) | |
| articles[idx]["summary"] = model.get_summary(article, 1) | |
| article = articles[idx] | |
| return article.get("summary", "Summary not available.") | |
| summarize.change(toggle_summary, inputs=[articles, article, summarize], outputs=[content]) | |
| ###### | |
| ###### Quiz Generation and Evaluation | |
| ###### | |
| def get_quiz(content): ############################# Generate quiz questions from the article content | |
| multichoicequests = [] | |
| if not content: mcqs = multichoicequests | |
| else: mcqs = model.get_questions(content, 3, "Moderate") | |
| if not isinstance(mcqs, list): print(f"Multiple choice questions object is a {type(mcqs)} but should be {type(list())}.") | |
| elif len(mcqs) == 0: print("Content is empty or no multiple choice questions generated.") | |
| for mcq in mcqs: | |
| missing = set() | |
| if not isinstance(mcq, dict): print(f"Multiple choice question object is {type(mcq)} but should be {type(dict())}.") | |
| else: missing = set(['question', 'correct_answer', 'false_answers']) - set(mcq.keys()) | |
| if missing: print(f"Multiple choice question object is missing keys: {missing}.") | |
| else: multichoicequests.append(mcq) | |
| return gr.Markdown("## Quiz"), *hide_news(), *show_quiz(multichoicequests) | |
| ready.click(get_quiz, inputs=[content], outputs=[ | |
| heading, num_headlines, category, get, headline, description, show, summarize, content, ready, submit, answers, *quiz]) | |
| def get_evaluation(answers, *quiz): ################ Evaluate the user's responses to the quiz | |
| results, response, evaluation = 0, list(quiz), "" | |
| if not answers: return "Answers are empty." | |
| elif not quiz: return "Quiz is empty." | |
| elif not isinstance(answers, list): return f"Answers is a {type(answers)} but should be {type(list())}." | |
| for i, (ans, resp) in enumerate(zip(answers, response)): | |
| if ans == resp: | |
| results += 1 | |
| evaluation += f"\n\t{i + 1}: Correct!" | |
| else: evaluation += f"\n\t{i + 1}: Incorrect." | |
| evaluation = f"You got {results} out of {len(answers)} correct.\n" + evaluation | |
| results /= len(answers) | |
| if 0.9 <= results <= 1.0: evaluation = f"Excellent! " + evaluation | |
| elif 0.8 <= results < 0.9: evaluation = f"Great job! " + evaluation | |
| elif 0.7 <= results < 0.8: evaluation = f"Good effort! " + evaluation | |
| elif 0.6 <= results < 0.7: evaluation = f"Keep practicing! " + evaluation | |
| elif 0.5 <= results < 0.6: evaluation = f"You can do better! " + evaluation | |
| else: evaluation = f"Keep trying! " + evaluation | |
| return show_eval(evaluation) | |
| submit.click(get_evaluation, inputs=[answers, *quiz], outputs=[evaluation, read]) | |
| def read_articles(): ############################### Reset the interface to read articles again | |
| return gr.Markdown("## News Articles"), *show_news(), *hide_quiz() | |
| read.click(read_articles, outputs=[heading, num_headlines, category, get, read, evaluation, submit, *quiz]) | |
| demo.launch() | |
| # def visualize_quiz_answers(answers, *quiz_items): | |
| # """ | |
| # Visualization of correct/incorrect answers from the quiz | |
| # """ | |
| # if not answers: | |
| # return None | |
| # correct = 0 | |
| # for user_ans, question in zip(answers, quiz_items): | |
| # if user_ans == question["correct_answer"]: | |
| # correct += 1 | |
| # incorrect = len(answers) - correct | |
| # fig, ax = plt.subplots() | |
| # ax.bar(["Correct", "Incorrect"], [correct, incorrect]) | |
| # ax.set_ylabel("Questions") | |
| # ax.set_title("Quiz Score Summary") | |
| # return fig | |