atz21 commited on
Commit
b24f07c
Β·
verified Β·
1 Parent(s): 2d4bf5b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -72
app.py CHANGED
@@ -1,10 +1,34 @@
1
  import gradio as gr
2
- import PyPDF2
3
- import json
4
- from some_llm_api import call_gemini_llm # replace with actual API call
5
 
6
- # Predefined topic list (abbreviated for brevity; include all topics in practice)
7
- TOPICS = [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  "SL 1.1 - Operations with numbers in the form a Γ— 10k where 1 < a < 10 and k is an integer.",
9
  "SL 1.2 - Arithmetic sequences and series. Use of the formulae for the nth term and the sum of the first n terms of the sequence. Use of sigma notation for sums of arithmetic sequences. Applications. Analysis, interpretation and prediction where a model is not perfectly arithmetic in real life.",
10
  "SL 1.3 - Geometric sequences and series. Use of the formulae for the n th term and the sum of the first n terms of the sequence. Use of sigma notation for the sums of geometric sequences. Applications.",
@@ -89,72 +113,56 @@ TOPICS = [
89
  "AHL 5.18 - First order differential equations. Numerical solution of dy/dx = f(x, y) using Euler's method. Variables separable. Homogeneous differential equation. Solution of y' + P(x)y = Q(x), using the integrating factor.",
90
  "AHL 5.19 - Maclaurin series to obtain expansions for eΛ£, sinx, cosx, ln(1+x), (1+x)α΅–, p∈Q. Use of simple substitution, products, integration and differentiation to obtain other series. Maclaurin series developed from differential equations"
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  ]
93
 
94
- def extract_pdf_text(pdf_file):
95
- reader = PyPDF2.PdfReader(pdf_file)
96
- text = ""
97
- for page in reader.pages:
98
- text += page.extract_text() + "\n"
99
- return text
100
-
101
- def process_qp_and_graded(qp_file, graded_file):
102
- # Step 1: Extract text
103
- qp_text = extract_pdf_text(qp_file)
104
- graded_text = extract_pdf_text(graded_file)
105
-
106
- # Step 2: Call Gemini LLM to identify topics for each question
107
- llm_prompt = f"""
108
- You are a math expert. Identify the topic for each question in the following question paper
109
- from this list: {', '.join(TOPICS)}.
110
- Return JSON in the following format:
111
- [
112
- {{
113
- "question_number": 1,
114
- "topic": "SL 1.1",
115
- "content": "The question text"
116
- }},
117
- ...
118
- ]
119
- Question paper text:
120
- {qp_text}
121
- """
122
- identified_questions = call_gemini_llm(llm_prompt)
123
-
124
- # Step 3: Generate new 8-question test based on student's graded answers
125
- # Prompt LLM to generate new test using the recommended composition
126
- llm_test_prompt = f"""
127
- You are a math teacher. Based on the graded answers below:
128
- {graded_text}
129
-
130
- And the following questions with topics:
131
- {identified_questions}
132
-
133
- Create a new 8-question test with the following composition:
134
- - 4 remediation items based on wrong answers (2 near-transfer, 2 far-transfer)
135
- - 2 retention items on topics the student got right
136
- - 1 synthesis / higher-order item combining multiple concepts
137
- - 1 confidence/metacognition item
138
-
139
- Return JSON with question_number, topic, and content.
140
- """
141
- new_test = call_gemini_llm(llm_test_prompt)
142
-
143
- return json.dumps(identified_questions, indent=2), json.dumps(new_test, indent=2)
144
-
145
- # Gradio interface
146
- iface = gr.Interface(
147
- fn=process_qp_and_graded,
148
- inputs=[
149
- gr.File(label="Question Paper PDF"),
150
- gr.File(label="Graded Answers PDF")
151
- ],
152
- outputs=[
153
- gr.Textbox(label="Questions with Topics", lines=20),
154
- gr.Textbox(label="Generated 8-Question Test", lines=20)
155
- ],
156
- title="Math Question Topic Identifier & Test Generator",
157
- description="Upload the student's question paper and graded answers PDFs. This app identifies question topics and generates a new targeted test."
158
- )
159
-
160
- iface.launch()
 
1
  import gradio as gr
2
+ import os
3
+ from PIL import Image
4
+ import google.generativeai as genai
5
 
6
+ # Configure Gemini API
7
+ genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
8
+
9
+ def create_model():
10
+ try:
11
+ return genai.GenerativeModel("gemini-2.5-pro", generation_config={"temperature": 0})
12
+ except:
13
+ return genai.GenerativeModel("gemini-2.5-flash", generation_config={"temperature": 0})
14
+
15
+ def gemini_generate_content(model, prompt_text, file_upload_obj=None):
16
+ inputs = [prompt_text]
17
+ if file_upload_obj:
18
+ inputs.append(file_upload_obj)
19
+ response = model.generate_content(inputs)
20
+ raw_text = getattr(response, "text", None)
21
+ if not raw_text and getattr(response, "candidates", None):
22
+ raw_text = response.candidates[0].content.parts[0].text
23
+ if not raw_text:
24
+ raw_text = str(response)
25
+ return raw_text
26
+
27
+ # Load merged_gemini_output.txt reference
28
+ with open("merged_gemini_output.txt", "r", encoding="utf-8") as f:
29
+ merged_questions_ref = f.read()
30
+
31
+ TOPIC_LIST = """
32
  "SL 1.1 - Operations with numbers in the form a Γ— 10k where 1 < a < 10 and k is an integer.",
33
  "SL 1.2 - Arithmetic sequences and series. Use of the formulae for the nth term and the sum of the first n terms of the sequence. Use of sigma notation for sums of arithmetic sequences. Applications. Analysis, interpretation and prediction where a model is not perfectly arithmetic in real life.",
34
  "SL 1.3 - Geometric sequences and series. Use of the formulae for the n th term and the sum of the first n terms of the sequence. Use of sigma notation for the sums of geometric sequences. Applications.",
 
113
  "AHL 5.18 - First order differential equations. Numerical solution of dy/dx = f(x, y) using Euler's method. Variables separable. Homogeneous differential equation. Solution of y' + P(x)y = Q(x), using the integrating factor.",
114
  "AHL 5.19 - Maclaurin series to obtain expansions for eΛ£, sinx, cosx, ln(1+x), (1+x)α΅–, p∈Q. Use of simple substitution, products, integration and differentiation to obtain other series. Maclaurin series developed from differential equations"
115
 
116
+ """
117
+
118
+ def identify_topics_and_generate_test(qp_file_obj, graded_as_file_obj):
119
+ model = create_model()
120
+ qp_path = qp_file_obj.name
121
+ as_path = graded_as_file_obj.name
122
+
123
+ prompt = f"""
124
+ You are an experienced math examiner and curriculum expert.
125
+
126
+ INPUT:
127
+ - Question Paper PDF: {qp_path}
128
+ - Graded Answer Sheet PDF: {as_path}
129
+
130
+ TASK 1: Identify the topic of each question in the Question Paper from this list:
131
+ {TOPIC_LIST}
132
+
133
+ Refer to previous questions and topics provided here:
134
+ {merged_questions_ref}
135
+
136
+ OUTPUT 1: Provide a JSON array of questions in the following format:
137
+ [
138
+ {{"question_number": 1, "topic": "SL 1.2", "content": "..."}},
139
+ ...
140
  ]
141
 
142
+ TASK 2: Based on the student's performance in the graded answer sheet, generate a new **8-question remedial test** following these rules:
143
+ 1. 4 remediation items: concepts the student got wrong (2 near-transfer, 2 far-transfer)
144
+ 2. 2 retention items: concepts the student got right
145
+ 3. 1 synthesis/higher-order item: combines multiple concepts
146
+ 4. 1 confidence/metacognition item: student reflects on confidence or explains an answer
147
+
148
+ OUTPUT 2: Provide a JSON array of the 8 remedial questions with question number, topic, and content.
149
+ """
150
+
151
+ result = gemini_generate_content(model, prompt_text=prompt)
152
+ return result
153
+
154
+ with gr.Blocks(title="AI Topic Identifier & Remedial Test Generator") as demo:
155
+ gr.Markdown("## πŸ“˜ Topic Identification & Remedial Test Generator")
156
+
157
+ with gr.Row():
158
+ qp_file = gr.File(label="πŸ“„ Upload Question Paper (PDF)")
159
+ graded_as_file = gr.File(label="πŸ“ Upload Graded Answer Sheet (PDF)")
160
+
161
+ run_button = gr.Button("πŸš€ Identify Topics & Generate Test")
162
+
163
+ output_box = gr.Textbox(label="πŸ“ Gemini Output (JSON)", lines=20)
164
+
165
+ run_button.click(fn=identify_topics_and_generate_test, inputs=[qp_file, graded_as_file], outputs=[output_box])
166
+
167
+ if __name__ == "__main__":
168
+ demo.launch()