File size: 3,658 Bytes
1c7ddd9
c09fe54
 
b9e41b9
d58419a
c09fe54
b9e41b9
c09fe54
 
 
 
 
 
b9e41b9
c09fe54
 
 
 
 
 
 
 
b9e41b9
c09fe54
 
 
b9e41b9
c09fe54
 
 
 
 
 
 
 
 
483a0e0
d58419a
 
 
 
b9e41b9
c09fe54
d58419a
 
 
 
 
 
483a0e0
d58419a
 
 
 
 
b9e41b9
d58419a
 
2d32051
d58419a
 
2d32051
d58419a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f93c15f
1c7ddd9
d58419a
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
import os
import gradio as gr
import google.generativeai as genai

# Configure Gemini API (key must be set in Hugging Face Space secrets)
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))

# ---------- PROMPTS ----------
TRANSCRIPTION_PROMPT = """
Persona:
You are an expert transcriptionist specializing in scientific and mathematical documents. 
Your primary goal is to convert handwritten mathematical work into a perfectly formatted, 
machine-readable Markdown document using LaTeX for all mathematical notation.

Rules:
- Transcribe exactly what is written, do not correct errors.
- Use $...$ for inline math, $$...$$ for block math.
- Ignore struck-through text.
- Preserve structure: bold for Q numbers (**1.**), step-by-step math with \\begin{align*}.
- If a symbol is ambiguous, mark as [x?].
Output must be a clean Markdown string.
"""

GRADING_PROMPT = """
You are an official examiner. Grade the student transcription using the question paper 
and the official marking scheme.

Rules:
1. Apply marks exactly as per the markscheme (M1, A1, etc.).
2. M marks must be earned before A marks.
3. Justify each awarded or withheld mark with clear reasoning.
4. Classify all errors as Conceptual Error, Silly Mistake, or None.
5. Follow dependency between M and A strictly.
6. Do not give marks outside the markscheme.
Output must be a structured grading report with reasoning.
"""

# ---------- STEP 1: TRANSCRIPTION ----------
def transcribe(ans_file):
    try:
        ans_uploaded = genai.upload_file(path=ans_file.name, display_name="Answer Sheet")

        model = genai.GenerativeModel("gemini-2.5-pro", generation_config={"temperature": 0})
        resp = model.generate_content([TRANSCRIPTION_PROMPT, ans_uploaded])

        transcription = getattr(resp, "text", None) or resp.candidates[0].content.parts[0].text
        return transcription
    except Exception as e:
        return f"❌ Error during transcription: {e}"

# ---------- STEP 2: GRADING ----------
def grade(qp_file, ms_file, transcription):
    try:
        qp_uploaded = genai.upload_file(path=qp_file.name, display_name="Question Paper")
        ms_uploaded = genai.upload_file(path=ms_file.name, display_name="Marking Scheme")

        model = genai.GenerativeModel("gemini-2.5-pro", generation_config={"temperature": 0})
        resp = model.generate_content([GRADING_PROMPT, qp_uploaded, ms_uploaded, transcription])

        grading = getattr(resp, "text", None) or resp.candidates[0].content.parts[0].text
        return grading
    except Exception as e:
        return f"❌ Error during grading: {e}"

# ---------- GRADIO APP ----------
with gr.Blocks(title="πŸ“˜ AI Teacher Assistant") as demo:
    gr.Markdown("## πŸ“˜ AI Teacher Assistant\nUpload exam documents to transcribe and grade student answers step by step.")

    with gr.Row():
        qp_file = gr.File(label="Upload Question Paper (PDF)", type="filepath")
        ms_file = gr.File(label="Upload Mark Scheme (PDF)", type="filepath")
        ans_file = gr.File(label="Upload Student Answer Sheet (PDF)", type="filepath")

    # Step 1: Transcription
    transcribe_btn = gr.Button("Step 1: Transcribe Answer Sheet")
    transcription_out = gr.Markdown(label="πŸ“„ Student Transcription")

    # Step 2: Grading
    grade_btn = gr.Button("Step 2: Grade the Student")
    grading_out = gr.Textbox(label="βœ… Grading Report (Step-by-Step)", lines=20)

    # Button Logic
    transcribe_btn.click(fn=transcribe, inputs=[ans_file], outputs=[transcription_out])
    grade_btn.click(fn=grade, inputs=[qp_file, ms_file, transcription_out], outputs=[grading_out])

if __name__ == "__main__":
    demo.launch()