import os import torch import gradio as gr from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig from peft import PeftModel import re # Model configuration BASE_MODEL = "deepseek-ai/deepseek-math-7b-instruct" REPO_ID = "danxh/math-mcq-generator-v1" # Global variables for model and tokenizer model = None tokenizer = None def load_model(): """Load the fine-tuned model with error handling""" global model, tokenizer try: print("🔄 Loading model and tokenizer...") # Simplified loading for Hugging Face Spaces bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_use_double_quant=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.float16 # Changed to float16 for better compatibility ) # Load base model base_model = AutoModelForCausalLM.from_pretrained( BASE_MODEL, quantization_config=bnb_config, device_map="auto", torch_dtype=torch.float16, trust_remote_code=True ) # Load LoRA adapter model = PeftModel.from_pretrained(base_model, REPO_ID) # Load tokenizer tokenizer = AutoTokenizer.from_pretrained(REPO_ID) if tokenizer.pad_token is None: tokenizer.pad_token = tokenizer.eos_token print("✅ Model loaded successfully!") return True except Exception as e: print(f"❌ Error loading model: {str(e)}") return False def generate_mcq(chapter, topics, difficulty="medium", cognitive_skill="direct_application"): """Generate MCQ using the fine-tuned model""" if model is None or tokenizer is None: return "❌ Model not loaded. Please wait for initialization." try: input_text = f"chapter: {chapter}\ntopics: {topics}\nDifficulty: {difficulty}\nCognitive Skill: {cognitive_skill}" prompt = f"""### Instruction: Generate a math MCQ similar in style to the provided examples. ### Input: {input_text} ### Response: """ inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512) inputs = {k: v.to(model.device) for k, v in inputs.items()} with torch.no_grad(): outputs = model.generate( **inputs, max_new_tokens=300, temperature=0.7, do_sample=True, pad_token_id=tokenizer.eos_token_id, eos_token_id=tokenizer.eos_token_id, repetition_penalty=1.1 ) generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True) response_start = generated_text.find("### Response:") + len("### Response:") response = generated_text[response_start:].strip() return response except Exception as e: return f"❌ Error generating MCQ: {str(e)}" def parse_mcq_response(response): """Parse the model response""" try: question_match = re.search(r'Question:\s*(.*?)(?=\nOptions:|Options:)', response, re.DOTALL) question = question_match.group(1).strip() if question_match else "Question not found" options_match = re.search(r'Options:\s*(.*?)(?=\nAnswer:|Answer:)', response, re.DOTALL) if options_match: options_text = options_match.group(1).strip() option_pattern = r'\([A-D]\)\s*([^(]*?)(?=\s*\([A-D]\)|$)' options = [] for match in re.finditer(option_pattern, options_text): option_text = match.group(1).strip() if option_text: options.append(option_text) else: options = ["Options not found"] answer_match = re.search(r'Answer:\s*([A-D])', response) answer = answer_match.group(1) if answer_match else "Answer not found" return { "question": question, "options": options, "correct_answer": answer } except Exception as e: return { "question": "Parsing error", "options": ["Error parsing options"], "correct_answer": "N/A", "error": str(e) } def generate_mcq_web(chapter, topics_text, difficulty, cognitive_skill, num_questions=1): """Web interface wrapper for MCQ generation""" if model is None or tokenizer is None: return """

⏳ Model Loading

The model is still loading. Please wait a moment and try again.

""" try: # Parse topics topics_list = [t.strip() for t in topics_text.split(',') if t.strip()] if not topics_list: topics_list = ["General"] results = [] for i in range(min(num_questions, 3)): # Limit to 3 questions max # Generate MCQ raw_response = generate_mcq(chapter, topics_list, difficulty, cognitive_skill) parsed = parse_mcq_response(raw_response) if "error" not in parsed: # Format for web display question_html = f"""

📚 Question {i+1}

{parsed['question']}

Options:

✅ Correct Answer: {parsed['correct_answer']}
""" results.append(question_html) else: error_html = f"""

❌ Error generating question {i+1}

{parsed.get('error', 'Unknown error occurred')}

""" results.append(error_html) return "".join(results) except Exception as e: return f"""

❌ System Error

Error: {str(e)}

""" # Create the interface interface = gr.Interface( fn=generate_mcq_web, inputs=[ gr.Textbox( label="📚 Chapter", placeholder="e.g., Applications of Trigonometry, Conic Sections", value="Applications of Trigonometry", info="Enter the mathematics chapter or topic area" ), gr.Textbox( label="📝 Topics (comma-separated)", placeholder="e.g., Heights and Distances, Circle, Tangents", value="Heights and Distances", info="Enter specific topics within the chapter, separated by commas" ), gr.Dropdown( choices=["easy", "medium", "hard"], label="⚡ Difficulty Level", value="medium", info="Select the difficulty level for the questions" ), gr.Dropdown( choices=["recall", "direct_application", "pattern_recognition", "strategic_reasoning", "trap_aware"], label="🧠 Cognitive Skill", value="direct_application", info="Select the type of thinking skill required" ), gr.Slider( minimum=1, maximum=3, step=1, label="🔢 Number of Questions", value=1, info="How many questions to generate (max 3)" ) ], outputs=gr.HTML(label="Generated MCQ(s)"), title="🧮 Mathematics MCQ Generator", description=""" Generate high-quality mathematics multiple choice questions using AI. This model has been fine-tuned specifically for educational content creation. **Note**: Model loading may take a few minutes on first startup. """, article=""" ### 🔬 About This Model This MCQ generator is powered by a fine-tuned version of DeepSeek-Math-7B, specifically adapted for mathematics education. ### 💡 Tips for Best Results: - Be specific with chapter and topic names - Try different cognitive skill levels for variety - Start with 1 question to test, then generate more ### 🤝 Collaboration This is part of a collaborative project to create specialized educational AI tools. """, theme=gr.themes.Soft(primary_hue="blue", secondary_hue="purple"), examples=[ ["Applications of Trigonometry", "Heights and Distances", "easy", "recall", 1], ["Conic Sections", "Circle", "medium", "pattern_recognition", 1], ["Applications of Trigonometry", "Angle of Elevation and Depression", "hard", "strategic_reasoning", 1] ] ) # Initialize model loading print("🚀 Starting model loading...") model_loaded = load_model() if model_loaded: print("✅ Ready to generate MCQs!") else: print("❌ Model loading failed. The interface may not work properly.") # Launch the interface if __name__ == "__main__": interface.launch()