import streamlit as st import os from dotenv import load_dotenv import hashlib import json from huggingface_hub import InferenceClient load_dotenv() st.set_page_config(page_title="Quiz Generator", layout="centered") # Initialize Hugging Face Inference Client client = InferenceClient( provider="novita", api_key=os.environ["HF_TOKEN"], ) st.title("Quiz Generator with Hugging Face using Qwen3-Coder") st.markdown( """ This app generates a quiz based on your provided context/content and topic. """ ) def get_quiz_hash(quiz_text): """Generate a hash for the quiz text to track uniqueness.""" return hashlib.sha256(quiz_text.encode("utf-8")).hexdigest() def generate_quiz_direct(context, query, num_questions, previous_quizzes=None): # Add instructions to avoid repeating previous quizzes/options previous_quizzes = previous_quizzes or [] previous_quizzes_text = "\n\n".join(previous_quizzes) uniqueness_instruction = "" if previous_quizzes: uniqueness_instruction = ( "\n\nIMPORTANT: Do NOT repeat any questions, options, or explanations from the previous quizzes below. " "Create new, improved, and more creative questions and options. Make sure the quiz is different and better than before.\n" "Previous quizzes:\n" "-----\n" f"{previous_quizzes_text}\n" "-----\n" ) prompt_template = f""" You are a helpful assistant tasked with generating a quiz. Use the following context/content for quiz generation: ----- {context} ----- Topic or query for the quiz: {query} Follow this quiz format for each question: Question 1: Which of the following tasks is not part of the Data Cleaning phase? Options: - Handling missing values - Standardizing formats - Removing duplicate entries - One-hot encoding categorical variables Correct answer: One-hot encoding categorical variables Explanation: One-hot encoding is a feature engineering step that belongs to the Data Transformation phase, not the Data Cleaning phase. Why are other options not correct? - Handling missing values: This is explicitly listed as part of the data cleaning phase. - Standardizing formats: This refers to making data consistent, which is a cleaning task. - Removing duplicate entries: This is a standard part of data cleaning to ensure data quality. Question 2: Which of the following steps are undertaken during the model deployment stage of a project? Options: - Cross-validation of models - Creating a Flask API - Hyperparameter tuning with grid search - Aggregating transaction data by customer Correct answer: Creating a Flask API Explanation: During deployment, the model was wrapped in a Flask API and deployed on a cloud VM or container for real-time usage. Why are other options not correct? - Cross-validation of models: This was done during model evaluation in the training phase. - Hyperparameter tuning with grid search: This occurred before deployment, during model selection. - Aggregating transaction data by customer: This was part of data transformation and feature engineering, not deployment. Question 3: In the CI Pipeline, after a data scientist pushes new model logic to the code repository, several automated processes are triggered, including running unit tests and validating the schema. What is one of the primary outputs that indicates the success of the CI Pipeline operations following these changes? Options: - New version model for users - Staging environment deployment - Tested and versioned model along with code - User interface updates Correct Answer: Tested and versioned model along with code Option - Explanation: Tested and versioned model along with code. Once the new model logic is pushed and undergoes validation and testing, the CI Pipeline produces a thoroughly tested and versioned model along with any associated code. This output ensures that the model is ready for further stages in the delivery pipeline. Why are other options not correct? - The new version model for users is a result of the CD Pipeline, which is focused on finalizing and deploying user-ready products, not a direct output of the CI Pipeline. - Staging environment deployment occurs after the CI Pipeline has successfully completed its processes and is not an output of the CI directly. - User interface updates involve front-end changes, which may not be directly managed in the CI Pipeline focused on backend processes, such as model validation and testing. --- Now, based only on the above context/content, generate a new quiz on the given topic/query. Create exactly {num_questions} questions. For each question, follow the above format exactly: - State the question. - List 4 options. - Clearly indicate the correct answer. - Provide a concise explanation for the correct answer. - For each incorrect option, explain why it is not correct. - Do not include nouns in the options and explanations. - Do not use terms like lecture, class and also do not stick with context - Do not include options such as "All of the above" and "None of the above" {uniqueness_instruction} Return only the quiz in the specified format. """ # Use Hugging Face chat completion API completion = client.chat.completions.create( model="Qwen/Qwen3-Coder-480B-A35B-Instruct", messages=[ { "role": "user", "content": prompt_template } ], ) # The response is in completion.choices[0].message.content return completion.choices[0].message.content # Session state to store previous quizzes for uniqueness if "previous_quiz_hashes" not in st.session_state: st.session_state.previous_quiz_hashes = set() if "previous_quizzes" not in st.session_state: st.session_state.previous_quizzes = [] if "last_context" not in st.session_state: st.session_state.last_context = "" if "last_query" not in st.session_state: st.session_state.last_query = "" if "last_num_questions" not in st.session_state: st.session_state.last_num_questions = 0 if "last_quiz" not in st.session_state: st.session_state.last_quiz = "" with st.form("quiz_form"): context_text = st.text_area( "Paste the context/content to use for quiz generation:", height=200, help="Provide the source material for the quiz." ) user_query = st.text_input( "Provide the topic or query for the quiz:", help="E.g., 'Data Cleaning', 'Generative AI', etc." ) num_questions = st.number_input( "How many quiz questions do you want to create?", min_value=1, max_value=20, value=3, step=1 ) submitted = st.form_submit_button("Generate Quiz") regenerate = st.form_submit_button("Regenerate Better Quiz") def handle_quiz_generation(context_text, user_query, num_questions, regenerate=False): # If context/query/num_questions changed, reset previous quizzes if ( context_text != st.session_state.last_context or user_query != st.session_state.last_query or num_questions != st.session_state.last_num_questions ): st.session_state.previous_quiz_hashes = set() st.session_state.previous_quizzes = [] st.session_state.last_quiz = "" # Generate quiz, ensuring uniqueness if regenerating previous_quizzes = st.session_state.previous_quizzes if regenerate else [] with st.spinner("Generating quiz..."): quiz = generate_quiz_direct(context_text, user_query, num_questions, previous_quizzes) quiz_hash = get_quiz_hash(quiz) # If quiz is duplicate, try again (up to 3 times) attempts = 0 while quiz_hash in st.session_state.previous_quiz_hashes and attempts < 3: previous_quizzes = st.session_state.previous_quizzes + [quiz] quiz = generate_quiz_direct(context_text, user_query, num_questions, previous_quizzes) quiz_hash = get_quiz_hash(quiz) attempts += 1 # Store quiz and hashes st.session_state.previous_quiz_hashes.add(quiz_hash) st.session_state.previous_quizzes.append(quiz) st.session_state.last_context = context_text st.session_state.last_query = user_query st.session_state.last_num_questions = num_questions st.session_state.last_quiz = quiz return quiz if submitted or regenerate: if not context_text.strip(): st.error("Please provide the context/content for quiz generation.") elif not user_query.strip(): st.error("Please provide a topic or query for the quiz.") else: quiz = handle_quiz_generation(context_text, user_query, num_questions, regenerate=regenerate) st.subheader("Generated Quiz") st.code(quiz, language="markdown") if st.session_state.previous_quizzes and not regenerate: st.info("If you didn't like this quiz, click 'Regenerate Better Quiz' to get a new, improved, and different quiz.")