Spaces:
Running
Running
File size: 8,173 Bytes
18fc9c1 257c34d 18fc9c1 bec29d2 257c34d bec29d2 257c34d bec29d2 257c34d bec29d2 257c34d 1279145 bec29d2 257c34d bec29d2 257c34d bec29d2 257c34d bec29d2 257c34d bec29d2 257c34d bec29d2 257c34d bec29d2 257c34d bec29d2 257c34d 01cbd3a bec29d2 257c34d c1f6444 257c34d bec29d2 257c34d eced281 257c34d 1279145 257c34d 1279145 257c34d 1279145 257c34d 1279145 257c34d 1279145 257c34d 1279145 257c34d 1279145 257c34d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
import gradio as gr
import pandas as pd
from mcq_generator import ImprovedMCQGenerator, is_suitable_for_students
import io
import tempfile # <-- Import tempfile
import traceback # <-- Optional: for better error logging
# Initialize MCQ Generator (Keep this outside the function for efficiency)
try:
mcq_generator = ImprovedMCQGenerator()
print("β
MCQ Generator Initialized Successfully")
except Exception as e:
print(f"β Failed to initialize MCQ Generator: {e}")
# You might want to stop the app or handle this more gracefully
mcq_generator = None
def generate_mcqs_ui(paragraph, num_questions):
# Check if generator initialized properly
if mcq_generator is None:
return None, None, None, "β Error: MCQ Generator failed to initialize. Check server logs."
# --- Input Validation ---
if not paragraph or not paragraph.strip():
return None, None, None, "β οΈ Please enter a valid paragraph."
print("\n--- Checking Suitability ---") # Add logging
if not is_suitable_for_students(paragraph):
print("β Paragraph deemed unsuitable.") # Add logging
# Return None for HTML and both file paths, plus the status message
return None, None, None, "β The paragraph is not suitable for MCQ generation (due to bias/toxicity/short length)."
print("β
Paragraph suitable.") # Add logging
try:
print(f"--- Generating {num_questions} MCQs ---") # Add logging
# Generate MCQs using the generator
mcqs = mcq_generator.generate_mcqs(paragraph, num_questions)
if not mcqs:
print("β οΈ No MCQs generated (potentially issue in generator logic).") # Add logging
return None, None, None, "β οΈ Could not generate MCQs for this text. Try different content or fewer questions."
print(f"β
Generated {len(mcqs)} MCQs successfully.") # Add logging
# --- Create Pretty HTML Output ---
pretty_mcqs_html = ""
for idx, mcq in enumerate(mcqs):
options = ""
# Ensure options exist and handle potential errors
mcq_options = mcq.get('options', [])
answer_index = mcq.get('answer_index', -1)
question_text = mcq.get('question', '[No Question Text]')
for opt_idx, option in enumerate(mcq_options):
options += f"<b>{chr(65+opt_idx)}.</b> {option}<br>"
question_html = f"<div style='margin-bottom:20px; padding:10px; border:1px solid #ccc; border-radius:10px; background:#f9f9f9;'>"
question_html += f"<b>Q{idx+1}:</b> {question_text}<br><br>{options}"
if 0 <= answer_index < len(mcq_options):
question_html += f"<i><b>Answer:</b> {chr(65+answer_index)}</i>"
else:
question_html += f"<i><b>Answer:</b> [Invalid Answer Index]</i>"
question_html += "</div>"
pretty_mcqs_html += question_html
# --- Prepare Text Output and CSV Data ---
txt_output = ""
csv_data = []
for idx, mcq in enumerate(mcqs):
mcq_options = mcq.get('options', [])
answer_index = mcq.get('answer_index', -1)
question_text = mcq.get('question', '[No Question Text]')
txt_output += f"Q{idx+1}: {question_text}\n"
for opt_idx, option in enumerate(mcq_options):
txt_output += f" {chr(65+opt_idx)}. {option}\n"
if 0 <= answer_index < len(mcq_options):
txt_output += f"Answer: {chr(65+answer_index)}\n\n"
else:
txt_output += f"Answer: [Invalid Answer Index]\n\n"
# Ensure 4 options for CSV, padding if necessary
options_padded = mcq_options + [''] * (4 - len(mcq_options))
csv_row = {
'Question': question_text,
'Option A': options_padded[0],
'Option B': options_padded[1],
'Option C': options_padded[2],
'Option D': options_padded[3],
'Answer': chr(65+answer_index) if 0 <= answer_index < len(mcq_options) else '[Invalid]'
}
csv_data.append(csv_row)
# --- Create In-Memory Buffers (Still useful for structuring data) ---
txt_buffer = io.StringIO()
txt_buffer.write(txt_output)
txt_buffer.seek(0)
csv_buffer = io.StringIO()
pd.DataFrame(csv_data).to_csv(csv_buffer, index=False)
csv_buffer.seek(0)
# --- Create Temporary Files and Get Paths ---
print("--- Creating temporary files ---") # Add logging
# Use delete=False so Gradio can access the file after the 'with' block closes it.
# Gradio should handle the cleanup of these temporary files.
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False, encoding='utf-8') as temp_txt:
temp_txt.write(txt_buffer.getvalue())
txt_filepath = temp_txt.name
print(f"Created TXT temp file: {txt_filepath}") # Add logging
with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False, encoding='utf-8') as temp_csv:
temp_csv.write(csv_buffer.getvalue())
csv_filepath = temp_csv.name
print(f"Created CSV temp file: {csv_filepath}") # Add logging
# --- Return HTML, File Paths, and Status ---
# Return order must match the `outputs` list in demo.launch()
return pretty_mcqs_html, txt_filepath, csv_filepath, "β
MCQs generated successfully!"
except Exception as e:
print(f"β Error during MCQ generation process: {e}") # Add logging
print(traceback.format_exc()) # Print detailed traceback for debugging
# Return None for HTML and both file paths, plus the error message
return None, None, None, f"β Error generating MCQs: {str(e)}"
# --- Define Gradio Interface ---
with gr.Blocks(theme=gr.themes.Soft()) as demo: # Added a theme for aesthetics
gr.Markdown("<h1 style='text-align:center;'>π Smart MCQ Generator</h1>")
gr.Markdown("Enter a paragraph of study material, choose the number of questions, and get MCQs instantly!") # Added description
with gr.Row():
paragraph_input = gr.Textbox(
lines=10, # Increased lines
label="Enter Paragraph for MCQs",
placeholder="Paste your study material here (ideally 50-500 words)...",
elem_id="paragraph-input" # Added elem_id for potential CSS styling
)
with gr.Row():
num_questions_slider = gr.Slider(
minimum=1, # Explicit minimum
maximum=10, # Explicit maximum
step=1,
value=5,
label="Number of Questions to Generate",
elem_id="num-questions-slider"
)
with gr.Row():
generate_btn = gr.Button("π Generate MCQs", variant="primary") # Made button primary
# Status box
status = gr.Textbox(label="Status", interactive=False, placeholder="Generation status will appear here...", elem_id="status-box")
# Use Accordion for tidier output section
with gr.Accordion("Generated MCQs & Downloads", open=True): # Default to open
# MCQ HTML output
mcq_output = gr.HTML(label="Generated MCQs")
# Download links - SEPARATED
with gr.Row():
download_txt = gr.File(label="Download MCQs (.txt)")
download_csv = gr.File(label="Download MCQs (.csv)")
# Set up the button click event
generate_btn.click(
fn=generate_mcqs_ui,
inputs=[paragraph_input, num_questions_slider],
# Outputs must match the return order of generate_mcqs_ui
outputs=[mcq_output, download_txt, download_csv, status],
api_name="generate_mcqs" # Added api_name for potential API usage
)
# --- Launch the app ---
# share=True generates a public link (useful for HF Spaces)
# server_name="0.0.0.0" makes it accessible within the container network
# server_port=7860 is the standard Gradio port for Spaces
print("--- Launching Gradio App ---")
demo.launch(share=True, server_name="0.0.0.0", server_port=7860) |