atz21 commited on
Commit
f923772
·
verified ·
1 Parent(s): d5a9c21

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -15
app.py CHANGED
@@ -1,4 +1,5 @@
1
  import os
 
2
  import gradio as gr
3
  import google.generativeai as genai
4
  from markdown_pdf import MarkdownPdf, Section
@@ -173,7 +174,58 @@ def create_model():
173
  except Exception:
174
  return genai.GenerativeModel("gemini-2.5-flash", generation_config={"temperature": 0})
175
 
176
- # ---------- PIPELINE: ALIGN + GRADE ----------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  def align_and_grade(qp_file, ms_file, ans_file):
178
  try:
179
  # Step 0: Compress if needed
@@ -188,40 +240,44 @@ def align_and_grade(qp_file, ms_file, ans_file):
188
 
189
  model = create_model()
190
 
191
- # Step 2: Alignment
192
  resp = model.generate_content([
193
  PROMPTS["ALIGNMENT_PROMPT"]["content"],
194
  qp_uploaded,
195
  ms_uploaded,
196
  ans_uploaded
197
  ])
198
- aligned_text = getattr(resp, "text", None)
199
- if not aligned_text and resp.candidates:
200
- aligned_text = resp.candidates[0].content.parts[0].text
201
 
202
- aligned_pdf_path = save_as_pdf(aligned_text, "aligned_qp_ms_as.pdf")
 
 
203
 
204
- # Step 3: Grading
205
  response = model.generate_content([
206
  PROMPTS["GRADING_PROMPT"]["content"],
207
- aligned_text
208
  ])
209
- grading = getattr(response, "text", None)
210
- if not grading and response.candidates:
211
- grading = response.candidates[0].content.parts[0].text
212
 
213
- # Save grading report with student's answer filename
 
214
  base_name = os.path.splitext(os.path.basename(ans_file))[0]
215
- grading_pdf_path = save_as_pdf(grading, f"{base_name}_graded.pdf")
216
 
217
- return aligned_text, aligned_pdf_path, grading, grading_pdf_path
 
218
 
219
  except Exception as e:
220
  return f"❌ Error: {e}", None, None, None
221
 
222
  # ---------- GRADIO APP ----------
223
  with gr.Blocks(title="LeadIB AI Grading (Alignment + Auto-Grading)") as demo:
224
- gr.Markdown("## LeadIB AI Grading\nUpload Question Paper, Markscheme, and Student Answer Sheet.\nThe system will align and grade automatically.")
225
 
226
  with gr.Row():
227
  qp_file = gr.File(label="Upload Question Paper (PDF)", type="filepath")
 
1
  import os
2
+ import re
3
  import gradio as gr
4
  import google.generativeai as genai
5
  from markdown_pdf import MarkdownPdf, Section
 
174
  except Exception:
175
  return genai.GenerativeModel("gemini-2.5-flash", generation_config={"temperature": 0})
176
 
177
+ # ---------- NEW: Pretty math conversion ----------
178
+ _SUPER_MAP = {
179
+ "0": "⁰", "1": "¹", "2": "²", "3": "³", "4": "⁴",
180
+ "5": "⁵", "6": "⁶", "7": "⁷", "8": "⁸", "9": "⁹",
181
+ "+": "⁺", "-": "⁻", "(": "⁽", ")": "⁾",
182
+ "n": "ⁿ", "i": "ⁱ", "a": "ᵃ", "b": "ᵇ", "c": "ᶜ", "d": "ᵈ", "e": "ᵉ",
183
+ "o": "ᵒ", "r": "ʳ", "t": "ᵗ", "u": "ᵘ", "v": "ᵛ", "w": "ʷ", "x": "ˣ", "y": "ʸ"
184
+ }
185
+
186
+ def _to_superscript(s: str) -> str:
187
+ """Map characters to available Unicode superscripts; fallback to original char if unavailable."""
188
+ out = []
189
+ for ch in s:
190
+ out.append(_SUPER_MAP.get(ch, _SUPER_MAP.get(ch.lower(), ch)))
191
+ return "".join(out)
192
+
193
+ def pretty_math(text: str) -> str:
194
+ """
195
+ Convert caret-notation exponents to Unicode superscripts.
196
+
197
+ Handles:
198
+ x^2, x^{12}, x^(12), 10^4, (3x10^4)^3, and similar patterns.
199
+ Only characters with known superscripts are converted (digits, +-(), some letters).
200
+ """
201
+
202
+ if not text:
203
+ return text
204
+
205
+ new = text
206
+
207
+ # Convert instances like ^{...}
208
+ new = re.sub(r'\^\{\s*([^}]+)\s*\}', lambda m: _to_superscript(m.group(1)), new)
209
+
210
+ # Convert instances like ^(...)
211
+ new = re.sub(r'\^\(\s*([^\)]+)\s*\)', lambda m: _to_superscript(m.group(1)), new)
212
+
213
+ # Convert caret followed by a simple integer (e.g., ^12)
214
+ new = re.sub(r'\^([+-]?\d+)', lambda m: _to_superscript(m.group(1)), new)
215
+
216
+ # Convert caret followed by single non-space token (e.g., x^n)
217
+ new = re.sub(r'\^([A-Za-z0-9\+\-\(\)]+)', lambda m: _to_superscript(m.group(1)), new)
218
+
219
+ # Replace common scientific notation '3x10^4' -> '3×10⁴' when 'x' is used as multiplication
220
+ # Only apply when the 'x' sits between digits and '10' (heuristic)
221
+ new = re.sub(r'(\d)\s*[xX]\s*(10)', r'\1×\2', new)
222
+
223
+ # Also compact spaced forms: '3 x 10^4' -> '3×10⁴' (keeps previously superscripted exponent)
224
+ new = re.sub(r'(\d)\s*×\s*(10)', r'\1×\2', new)
225
+
226
+ return new
227
+
228
+ # -------------------- PIPELINE: ALIGN + GRADE --------------------
229
  def align_and_grade(qp_file, ms_file, ans_file):
230
  try:
231
  # Step 0: Compress if needed
 
240
 
241
  model = create_model()
242
 
243
+ # Step 2: Alignment (raw)
244
  resp = model.generate_content([
245
  PROMPTS["ALIGNMENT_PROMPT"]["content"],
246
  qp_uploaded,
247
  ms_uploaded,
248
  ans_uploaded
249
  ])
250
+ aligned_text_raw = getattr(resp, "text", None)
251
+ if not aligned_text_raw and getattr(resp, "candidates", None):
252
+ aligned_text_raw = resp.candidates[0].content.parts[0].text
253
 
254
+ # Pretty version for display/PDF (does NOT affect the raw text used for grading)
255
+ aligned_text_pretty = pretty_math(aligned_text_raw) if aligned_text_raw else aligned_text_raw
256
+ aligned_pdf_path = save_as_pdf(aligned_text_pretty or "[No aligned text produced]", "aligned_qp_ms_as.pdf")
257
 
258
+ # Step 3: Grading (use raw aligned text as input to grader)
259
  response = model.generate_content([
260
  PROMPTS["GRADING_PROMPT"]["content"],
261
+ aligned_text_raw or "[No aligned text produced]"
262
  ])
263
+ grading_raw = getattr(response, "text", None)
264
+ if not grading_raw and getattr(response, "candidates", None):
265
+ grading_raw = response.candidates[0].content.parts[0].text
266
 
267
+ # Pretty version of grading output for display/PDF
268
+ grading_pretty = pretty_math(grading_raw) if grading_raw else grading_raw
269
  base_name = os.path.splitext(os.path.basename(ans_file))[0]
270
+ grading_pdf_path = save_as_pdf(grading_pretty or "[No grading produced]", f"{base_name}_graded.pdf")
271
 
272
+ # Return pretty/display versions (raws remain unmodified for internal processing)
273
+ return aligned_text_pretty or "", aligned_pdf_path, grading_pretty or "", grading_pdf_path
274
 
275
  except Exception as e:
276
  return f"❌ Error: {e}", None, None, None
277
 
278
  # ---------- GRADIO APP ----------
279
  with gr.Blocks(title="LeadIB AI Grading (Alignment + Auto-Grading)") as demo:
280
+ gr.Markdown("## LeadIB AI Grading\nUpload Question Paper, Markscheme, and Student Answer Sheet.\nThe system will align and grade automatically. Mathematical exponents (e.g. `x^2`) will be converted to Unicode superscripts (e.g. `x²`) in the displayed text and PDFs.")
281
 
282
  with gr.Row():
283
  qp_file = gr.File(label="Upload Question Paper (PDF)", type="filepath")