ManthaBhuvana commited on
Commit
257c34d
·
verified ·
1 Parent(s): 1279145

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -54
app.py CHANGED
@@ -2,102 +2,195 @@ import gradio as gr
2
  import pandas as pd
3
  from mcq_generator import ImprovedMCQGenerator, is_suitable_for_students
4
  import io
5
-
6
- # Initialize MCQ Generator
7
- mcq_generator = ImprovedMCQGenerator()
 
 
 
 
 
 
 
 
8
 
9
  def generate_mcqs_ui(paragraph, num_questions):
10
- if not paragraph.strip():
11
- return None, None, "⚠️ Please enter a valid paragraph."
 
 
 
 
 
12
 
 
13
  if not is_suitable_for_students(paragraph):
14
- return None, None, "❌ The paragraph is not suitable for MCQ generation (due to bias/toxicity/short length)."
 
 
 
15
 
16
  try:
 
17
  # Generate MCQs using the generator
18
  mcqs = mcq_generator.generate_mcqs(paragraph, num_questions)
19
 
20
- # Create pretty formatted MCQ list
21
- pretty_mcqs = []
 
 
 
 
 
 
22
  for idx, mcq in enumerate(mcqs):
23
  options = ""
24
- for opt_idx, option in enumerate(mcq['options']):
 
 
 
 
 
25
  options += f"<b>{chr(65+opt_idx)}.</b> {option}<br>"
 
26
  question_html = f"<div style='margin-bottom:20px; padding:10px; border:1px solid #ccc; border-radius:10px; background:#f9f9f9;'>"
27
- question_html += f"<b>Q{idx+1}:</b> {mcq['question']}<br><br>{options}"
28
- question_html += f"<i><b>Answer:</b> {chr(65+mcq['answer_index'])}</i>"
 
 
 
29
  question_html += "</div>"
30
- pretty_mcqs.append(question_html)
31
 
32
- # Prepare text output and CSV data
33
  txt_output = ""
34
  csv_data = []
35
 
36
  for idx, mcq in enumerate(mcqs):
37
- txt_output += f"Q{idx+1}: {mcq['question']}\n"
38
- for opt_idx, option in enumerate(mcq['options']):
 
 
 
 
39
  txt_output += f" {chr(65+opt_idx)}. {option}\n"
40
- txt_output += f"Answer: {chr(65+mcq['answer_index'])}\n\n"
41
-
42
- csv_data.append({
43
- 'Question': mcq['question'],
44
- 'Option A': mcq['options'][0],
45
- 'Option B': mcq['options'][1],
46
- 'Option C': mcq['options'][2],
47
- 'Option D': mcq['options'][3],
48
- 'Answer': chr(65+mcq['answer_index'])
49
- })
50
-
51
- # Create in-memory text file
 
 
 
 
 
 
 
52
  txt_buffer = io.StringIO()
53
  txt_buffer.write(txt_output)
54
  txt_buffer.seek(0)
55
 
56
- # Create in-memory CSV file
57
  csv_buffer = io.StringIO()
58
  pd.DataFrame(csv_data).to_csv(csv_buffer, index=False)
59
  csv_buffer.seek(0)
60
 
61
- # Return Gradio-compatible downloadable files
62
- txt_file = gr.File(value=txt_buffer, file_name="mcqs.txt", file_type="text/plain")
63
- csv_file = gr.File(value=csv_buffer, file_name="mcqs.csv", file_type="text/csv")
 
 
 
 
 
64
 
65
- return pretty_mcqs, [txt_file, csv_file], "✅ MCQs generated successfully!"
 
 
 
 
 
 
 
66
 
67
  except Exception as e:
68
- return None, None, f"❌ Error generating MCQs: {str(e)}"
 
 
 
69
 
70
 
71
- # Define Gradio interface
72
- with gr.Blocks() as demo:
73
  gr.Markdown("<h1 style='text-align:center;'>📚 Smart MCQ Generator</h1>")
74
-
75
- # Input for the paragraph and number of questions
76
- with gr.Row():
77
- paragraph_input = gr.Textbox(lines=8, label="Enter Paragraph for MCQs", placeholder="Paste your study material here...")
78
- with gr.Row():
79
- num_questions_slider = gr.Slider(1, 10, step=1, value=5, label="Number of Questions")
80
-
81
- # Generate Button
82
  with gr.Row():
83
- generate_btn = gr.Button("🚀 Generate MCQs")
84
-
85
- # Status box to show the message (success/error)
86
- status = gr.Textbox(label="Status", interactive=False)
 
 
87
 
88
- # MCQ output and download links
89
  with gr.Row():
90
- mcq_output = gr.HTML()
 
 
 
 
 
 
 
91
 
92
  with gr.Row():
93
- download_output = gr.File(label="Download MCQs (TXT/CSV)")
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- # Set up the button to trigger MCQ generation
96
  generate_btn.click(
97
  fn=generate_mcqs_ui,
98
  inputs=[paragraph_input, num_questions_slider],
99
- outputs=[mcq_output, download_output, status]
 
 
100
  )
101
 
102
- # Launch the app
103
- demo.launch(share=True, server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import pandas as pd
3
  from mcq_generator import ImprovedMCQGenerator, is_suitable_for_students
4
  import io
5
+ import tempfile # <-- Import tempfile
6
+ import traceback # <-- Optional: for better error logging
7
+
8
+ # Initialize MCQ Generator (Keep this outside the function for efficiency)
9
+ try:
10
+ mcq_generator = ImprovedMCQGenerator()
11
+ print("✅ MCQ Generator Initialized Successfully")
12
+ except Exception as e:
13
+ print(f"❌ Failed to initialize MCQ Generator: {e}")
14
+ # You might want to stop the app or handle this more gracefully
15
+ mcq_generator = None
16
 
17
  def generate_mcqs_ui(paragraph, num_questions):
18
+ # Check if generator initialized properly
19
+ if mcq_generator is None:
20
+ return None, None, None, "❌ Error: MCQ Generator failed to initialize. Check server logs."
21
+
22
+ # --- Input Validation ---
23
+ if not paragraph or not paragraph.strip():
24
+ return None, None, None, "⚠️ Please enter a valid paragraph."
25
 
26
+ print("\n--- Checking Suitability ---") # Add logging
27
  if not is_suitable_for_students(paragraph):
28
+ print("❌ Paragraph deemed unsuitable.") # Add logging
29
+ # Return None for HTML and both file paths, plus the status message
30
+ return None, None, None, "❌ The paragraph is not suitable for MCQ generation (due to bias/toxicity/short length)."
31
+ print("✅ Paragraph suitable.") # Add logging
32
 
33
  try:
34
+ print(f"--- Generating {num_questions} MCQs ---") # Add logging
35
  # Generate MCQs using the generator
36
  mcqs = mcq_generator.generate_mcqs(paragraph, num_questions)
37
 
38
+ if not mcqs:
39
+ print("⚠️ No MCQs generated (potentially issue in generator logic).") # Add logging
40
+ return None, None, None, "⚠️ Could not generate MCQs for this text. Try different content or fewer questions."
41
+
42
+ print(f"✅ Generated {len(mcqs)} MCQs successfully.") # Add logging
43
+
44
+ # --- Create Pretty HTML Output ---
45
+ pretty_mcqs_html = ""
46
  for idx, mcq in enumerate(mcqs):
47
  options = ""
48
+ # Ensure options exist and handle potential errors
49
+ mcq_options = mcq.get('options', [])
50
+ answer_index = mcq.get('answer_index', -1)
51
+ question_text = mcq.get('question', '[No Question Text]')
52
+
53
+ for opt_idx, option in enumerate(mcq_options):
54
  options += f"<b>{chr(65+opt_idx)}.</b> {option}<br>"
55
+
56
  question_html = f"<div style='margin-bottom:20px; padding:10px; border:1px solid #ccc; border-radius:10px; background:#f9f9f9;'>"
57
+ question_html += f"<b>Q{idx+1}:</b> {question_text}<br><br>{options}"
58
+ if 0 <= answer_index < len(mcq_options):
59
+ question_html += f"<i><b>Answer:</b> {chr(65+answer_index)}</i>"
60
+ else:
61
+ question_html += f"<i><b>Answer:</b> [Invalid Answer Index]</i>"
62
  question_html += "</div>"
63
+ pretty_mcqs_html += question_html
64
 
65
+ # --- Prepare Text Output and CSV Data ---
66
  txt_output = ""
67
  csv_data = []
68
 
69
  for idx, mcq in enumerate(mcqs):
70
+ mcq_options = mcq.get('options', [])
71
+ answer_index = mcq.get('answer_index', -1)
72
+ question_text = mcq.get('question', '[No Question Text]')
73
+
74
+ txt_output += f"Q{idx+1}: {question_text}\n"
75
+ for opt_idx, option in enumerate(mcq_options):
76
  txt_output += f" {chr(65+opt_idx)}. {option}\n"
77
+
78
+ if 0 <= answer_index < len(mcq_options):
79
+ txt_output += f"Answer: {chr(65+answer_index)}\n\n"
80
+ else:
81
+ txt_output += f"Answer: [Invalid Answer Index]\n\n"
82
+
83
+ # Ensure 4 options for CSV, padding if necessary
84
+ options_padded = mcq_options + [''] * (4 - len(mcq_options))
85
+ csv_row = {
86
+ 'Question': question_text,
87
+ 'Option A': options_padded[0],
88
+ 'Option B': options_padded[1],
89
+ 'Option C': options_padded[2],
90
+ 'Option D': options_padded[3],
91
+ 'Answer': chr(65+answer_index) if 0 <= answer_index < len(mcq_options) else '[Invalid]'
92
+ }
93
+ csv_data.append(csv_row)
94
+
95
+ # --- Create In-Memory Buffers (Still useful for structuring data) ---
96
  txt_buffer = io.StringIO()
97
  txt_buffer.write(txt_output)
98
  txt_buffer.seek(0)
99
 
 
100
  csv_buffer = io.StringIO()
101
  pd.DataFrame(csv_data).to_csv(csv_buffer, index=False)
102
  csv_buffer.seek(0)
103
 
104
+ # --- Create Temporary Files and Get Paths ---
105
+ print("--- Creating temporary files ---") # Add logging
106
+ # Use delete=False so Gradio can access the file after the 'with' block closes it.
107
+ # Gradio should handle the cleanup of these temporary files.
108
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False, encoding='utf-8') as temp_txt:
109
+ temp_txt.write(txt_buffer.getvalue())
110
+ txt_filepath = temp_txt.name
111
+ print(f"Created TXT temp file: {txt_filepath}") # Add logging
112
 
113
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False, encoding='utf-8') as temp_csv:
114
+ temp_csv.write(csv_buffer.getvalue())
115
+ csv_filepath = temp_csv.name
116
+ print(f"Created CSV temp file: {csv_filepath}") # Add logging
117
+
118
+ # --- Return HTML, File Paths, and Status ---
119
+ # Return order must match the `outputs` list in demo.launch()
120
+ return pretty_mcqs_html, txt_filepath, csv_filepath, "✅ MCQs generated successfully!"
121
 
122
  except Exception as e:
123
+ print(f"❌ Error during MCQ generation process: {e}") # Add logging
124
+ print(traceback.format_exc()) # Print detailed traceback for debugging
125
+ # Return None for HTML and both file paths, plus the error message
126
+ return None, None, None, f"❌ Error generating MCQs: {str(e)}"
127
 
128
 
129
+ # --- Define Gradio Interface ---
130
+ with gr.Blocks(theme=gr.themes.Soft()) as demo: # Added a theme for aesthetics
131
  gr.Markdown("<h1 style='text-align:center;'>📚 Smart MCQ Generator</h1>")
132
+ gr.Markdown("Enter a paragraph of study material, choose the number of questions, and get MCQs instantly!") # Added description
133
+
 
 
 
 
 
 
134
  with gr.Row():
135
+ paragraph_input = gr.Textbox(
136
+ lines=10, # Increased lines
137
+ label="Enter Paragraph for MCQs",
138
+ placeholder="Paste your study material here (ideally 50-500 words)...",
139
+ elem_id="paragraph-input" # Added elem_id for potential CSS styling
140
+ )
141
 
 
142
  with gr.Row():
143
+ num_questions_slider = gr.Slider(
144
+ minimum=1, # Explicit minimum
145
+ maximum=10, # Explicit maximum
146
+ step=1,
147
+ value=5,
148
+ label="Number of Questions to Generate",
149
+ elem_id="num-questions-slider"
150
+ )
151
 
152
  with gr.Row():
153
+ generate_btn = gr.Button("🚀 Generate MCQs", variant="primary") # Made button primary
154
+
155
+ # Status box
156
+ status = gr.Textbox(label="Status", interactive=False, placeholder="Generation status will appear here...", elem_id="status-box")
157
+
158
+ # Use Accordion for tidier output section
159
+ with gr.Accordion("Generated MCQs & Downloads", open=True): # Default to open
160
+ # MCQ HTML output
161
+ mcq_output = gr.HTML(label="Generated MCQs")
162
+
163
+ # Download links - SEPARATED
164
+ with gr.Row():
165
+ download_txt = gr.File(label="Download MCQs (.txt)")
166
+ download_csv = gr.File(label="Download MCQs (.csv)")
167
 
168
+ # Set up the button click event
169
  generate_btn.click(
170
  fn=generate_mcqs_ui,
171
  inputs=[paragraph_input, num_questions_slider],
172
+ # Outputs must match the return order of generate_mcqs_ui
173
+ outputs=[mcq_output, download_txt, download_csv, status],
174
+ api_name="generate_mcqs" # Added api_name for potential API usage
175
  )
176
 
177
+ # Add Examples
178
+ gr.Examples(
179
+ examples=[
180
+ ["The cell is the basic structural and functional unit of all living organisms. Cells can be classified into two main types: prokaryotic and eukaryotic. Prokaryotic cells, found in bacteria and archaea, lack a defined nucleus and membrane-bound organelles. In contrast, eukaryotic cells, which make up plants, animals, fungi, and protists, contain a nucleus that houses the cell’s DNA, as well as various organelles like mitochondria and the endoplasmic reticulum.", 3],
181
+ ["The Industrial Revolution began in Great Britain in the late 18th century. It marked a shift from manual labor to machine-based manufacturing. Key innovations included the steam engine, improved by James Watt, and mechanized looms in the textile industry. This led to increased productivity, urbanization, and the rise of new social classes.", 4],
182
+ ["Photosynthesis is the process used by plants, algae, and cyanobacteria to convert light energy into chemical energy, through a process that uses sunlight, water and carbon dioxide. This chemical energy is stored in carbohydrate molecules, such as sugars and starches, which are synthesized from carbon dioxide and water – hence the name photosynthesis, from the Greek φῶς, phos, 'light', and σύνθεσις, synthesis, 'putting together'. In most cases, oxygen is also released as a waste product.", 5]
183
+ ],
184
+ inputs=[paragraph_input, num_questions_slider],
185
+ outputs=[mcq_output, download_txt, download_csv, status], # Ensure outputs match here too
186
+ fn=generate_mcqs_ui,
187
+ cache_examples=False # Maybe disable caching during debugging
188
+ )
189
+
190
+
191
+ # --- Launch the app ---
192
+ # share=True generates a public link (useful for HF Spaces)
193
+ # server_name="0.0.0.0" makes it accessible within the container network
194
+ # server_port=7860 is the standard Gradio port for Spaces
195
+ print("--- Launching Gradio App ---")
196
+ demo.launch(share=True, server_name="0.0.0.0", server_port=7860)