import streamlit as st import requests from pipelines import generate_quiz import shelve from dataclasses import dataclass from typing import Literal import streamlit.components.v1 as components st.title(":red[DEV] *the Quizbot* 🤖") st.subheader("Hey there! I'm **Dev** the QuizBot! Ready to flaunt your smarts in a topic of your choice?", divider='grey') @st.experimental_dialog("Invalid Choice", width="small") def warn(): st.write("Please choose from the given options.") @dataclass class Message: origin: Literal["human", "ai"] message: str def load_css(): with open("static/styles.css", "r") as f: st.markdown(f"", unsafe_allow_html=True) def initialize_session_state(): defaults = { "quiz": None, "current_question_index": 0, "responses": [], "interactions": [], "quiz_completed": False, "topic": None, "messages": load_chat_history() } for key, value in defaults.items(): if key not in st.session_state: st.session_state[key] = value def load_chat_history(): with shelve.open("chat_history") as db: return db.get("messages", []) def save_chat_history(messages): with shelve.open("chat_history") as db: db["messages"] = messages from urllib.parse import quote def fetch_wikipedia_link(topic: str) -> str | None: try: encoded_topic = quote(topic) api_url = f"https://en.wikipedia.org/api/rest_v1/page/summary/{encoded_topic}" headers = { "User-Agent": "QuizBot/1.0 (https://huggingface.co/your-space) Python/3.x" } response = requests.get(api_url, headers=headers, timeout=5) if response.status_code != 200: st.error(f"Failed to fetch Wikipedia content for '{topic}' (status {response.status_code})") return None data = response.json() return data.get("content_urls", {}).get("desktop", {}).get("page") except requests.RequestException as e: st.error(f"Network error: {e}") return None load_css() initialize_session_state() placeholder = st.container() if st.session_state.quiz is None: st.session_state.interactions = [] with st.form("generate_quiz_form"): st.markdown('**Enter a Topic:**') cols = st.columns((4, 1)) topic = cols[0].text_input("Topic:", label_visibility="collapsed") generate_button = cols[1].form_submit_button("Generate Quiz") if generate_button: if topic: link = fetch_wikipedia_link(topic) if link: for _ in range(2): try: quiz = generate_quiz(link) if quiz: st.session_state.quiz = quiz st.session_state.current_question_index = 0 st.session_state.responses = [] st.session_state.quiz_completed = False st.rerun() except Exception as e: st.error(f"Failed to generate quiz: {e}") else: st.error("Please enter a topic.") else: with st.form("quiz_form"): if st.session_state.quiz_completed: st.markdown("## Results") score = sum(1 for interaction in st.session_state.interactions if interaction["is_correct"]) if score > len(st.session_state.quiz['questions']): score = len(st.session_state.quiz['questions']) st.markdown(f"Your score: {score} out of {len(st.session_state.quiz['questions'])}") try_again_button = st.form_submit_button("Try Again") if try_again_button: for key in ["quiz", "current_question_index", "responses", "interactions", "quiz_completed", "topic"]: st.session_state[key] = None if key == "quiz" else 0 if key == "current_question_index" else [] st.cache_data.clear() st.rerun() else: current_question_index = st.session_state.current_question_index if current_question_index < len(st.session_state.quiz["questions"]): question = st.session_state.quiz["questions"][current_question_index] question_text = question.get('question', question.get('statement', question.get('prompt', ''))) options = question.get("options", []) st.markdown(f"**Question {current_question_index + 1}:** {question_text}") if options: st.markdown("Choices:") for option in options: st.markdown(option) user_response = st.text_input("Your answer:", key=f"input_{current_question_index}") submit_button = st.form_submit_button("Submit Answer") if submit_button: st.session_state[f"answer_{current_question_index}"] = user_response correct_answer = question.get("right_option", question.get("answer")) if options and options[0].lower() in ['true', 'false']: invalid_option = user_response.lower() not in ["true", "false"] else: valid_options = [opt[0].lower() for opt in options] invalid_option = user_response.lower() not in valid_options and question.get("statement") is None is_correct = user_response.lower() == correct_answer.lower() st.session_state.responses.append(user_response) st.session_state.interactions.append({ "question": question_text, "user_response": user_response, "correct_answer": correct_answer, "is_correct": is_correct, "invalid_option": invalid_option, "options": options }) if not invalid_option: st.session_state.current_question_index += 1 if st.session_state.current_question_index >= len(st.session_state.quiz["questions"]): st.session_state.quiz_completed = True st.rerun() else: warn() with placeholder.container(): if st.session_state.interactions: i = 0 for idx, interaction in enumerate(st.session_state.interactions): if interaction['invalid_option']: continue options_html = "
".join(interaction['options']) question_html = f"Question {i + 1}: {interaction['question']}
Choices:
{options_html}" div = f"""
{question_html}
""" st.markdown(div, unsafe_allow_html=True) user_response_html = f"Your answer: {interaction['user_response']}" div = f"""
{user_response_html}
""" st.markdown(div, unsafe_allow_html=True) feedback_html = f"Correct! The correct answer is: {interaction['correct_answer']}" if interaction['is_correct'] else f"Wrong. The correct answer is: {interaction['correct_answer']}" div = f"""
{feedback_html}
""" if idx == len(st.session_state.interactions) - 1: div = f'
{div}
' st.markdown(div, unsafe_allow_html=True) i += 1 save_chat_history(st.session_state.messages) components.html(""" """, height=0, width=0)