Spaces:
Sleeping
Sleeping
| # modules/mcq_generator.py | |
| """Enhanced MCQ Quiz Generator Module""" | |
| import random | |
| from typing import Dict, List, Tuple | |
| from modules.api_utils import ( | |
| fetch_wikipedia_summary, | |
| search_wikipedia, | |
| fetch_related_topics, | |
| fetch_wikipedia_categories, | |
| ) | |
| def generate_smart_distractors( | |
| correct_answer: str, topic: str, context: str | |
| ) -> List[str]: | |
| """Generate intelligent distractor options""" | |
| distractors = set() | |
| # Get related topics | |
| related = fetch_related_topics(topic, 10) | |
| distractors.update(related) | |
| # Get categories and use them for distractors | |
| categories = fetch_wikipedia_categories(topic) | |
| if categories: | |
| # Search for other items in the same categories | |
| for category in categories[:2]: | |
| similar_items = search_wikipedia(category, 5) | |
| distractors.update(similar_items) | |
| # Remove the correct answer and topic | |
| distractors.discard(correct_answer) | |
| distractors.discard(topic) | |
| # Convert to list and shuffle | |
| distractor_list = list(distractors) | |
| random.shuffle(distractor_list) | |
| # If not enough distractors, add generic ones | |
| if len(distractor_list) < 3: | |
| generic_distractors = [ | |
| "Scientific Theory", | |
| "Historical Event", | |
| "Mathematical Concept", | |
| "Geographical Location", | |
| "Literary Work", | |
| "Technological Innovation", | |
| "Cultural Phenomenon", | |
| "Economic System", | |
| "Political Movement", | |
| ] | |
| distractor_list.extend(generic_distractors) | |
| return distractor_list[:3] | |
| def generate_question_types(topic: str, summary_data: Dict, difficulty: str) -> Dict: | |
| """Generate different types of questions based on difficulty""" | |
| title = summary_data.get("title", topic) | |
| extract = summary_data.get("extract", "") | |
| description = summary_data.get("description", "") | |
| question_templates = { | |
| "Easy": [ | |
| f"What is {title}?", | |
| f"Which of the following best describes {title}?", | |
| f"What category does {title} belong to?", | |
| ], | |
| "Medium": [ | |
| f"What is the primary characteristic of {title}?", | |
| f"How is {title} commonly defined?", | |
| f"Which statement about {title} is most accurate?", | |
| ], | |
| "Hard": [ | |
| f"What distinguishes {title} from related concepts?", | |
| f"In what context is {title} most significant?", | |
| f"What is the key principle underlying {title}?", | |
| ], | |
| } | |
| # Select appropriate question | |
| questions = question_templates.get(difficulty, question_templates["Easy"]) | |
| question = random.choice(questions) | |
| # For harder difficulties, extract a more specific answer from the text | |
| if difficulty == "Easy": | |
| correct_answer = title | |
| elif difficulty == "Medium": | |
| # Try to find a defining characteristic | |
| sentences = extract.split(".") | |
| if len(sentences) > 1: | |
| correct_answer = description if description else title | |
| else: | |
| correct_answer = title | |
| else: # Hard | |
| # Use a more complex answer | |
| correct_answer = description if description else title | |
| return {"question": question, "correct_answer": correct_answer, "context": extract} | |
| def generate_mcq(topic: str, difficulty: str) -> Dict: | |
| """Generate an enhanced multiple choice question""" | |
| summary_data = fetch_wikipedia_summary(topic) | |
| if not summary_data: | |
| # Try searching for the topic | |
| search_results = search_wikipedia(topic, 3) | |
| if search_results: | |
| # Try the first search result | |
| topic = search_results[0] | |
| summary_data = fetch_wikipedia_summary(topic) | |
| if not summary_data: | |
| return { | |
| "error": "Topic not found on Wikipedia. Try a different topic or check spelling.", | |
| "status": False, | |
| "suggestions": search_results if search_results else [], | |
| } | |
| # Generate question based on difficulty | |
| question_data = generate_question_types(topic, summary_data, difficulty) | |
| # Generate smart distractors | |
| distractors = generate_smart_distractors( | |
| question_data["correct_answer"], topic, question_data["context"] | |
| ) | |
| # Create options | |
| options = [question_data["correct_answer"]] + distractors[:3] | |
| random.shuffle(options) | |
| # Create explanation | |
| extract = summary_data.get("extract", "") | |
| explanation = extract[:300] + "..." if len(extract) > 300 else extract | |
| return { | |
| "question": question_data["question"], | |
| "options": options, | |
| "correct_answer": question_data["correct_answer"], | |
| "explanation": explanation, | |
| "topic": summary_data.get("title", topic), | |
| "difficulty": difficulty, | |
| "status": True, | |
| } | |
| def generate_quiz_set( | |
| topic: str, difficulty: str, num_questions: int = 5 | |
| ) -> List[Dict]: | |
| """Generate a set of questions for a complete quiz""" | |
| questions = [] | |
| used_topics = set() | |
| # Get related topics for variety | |
| related_topics = [topic] + fetch_related_topics(topic, 10) | |
| for i in range(num_questions): | |
| # Try to use different related topics | |
| for related_topic in related_topics: | |
| if related_topic not in used_topics: | |
| question = generate_mcq(related_topic, difficulty) | |
| if question.get("status"): | |
| questions.append(question) | |
| used_topics.add(related_topic) | |
| break | |
| # If we couldn't get enough questions, try the main topic again | |
| if len(questions) <= i: | |
| question = generate_mcq(topic, difficulty) | |
| if question.get("status"): | |
| questions.append(question) | |
| return questions | |