BeastGokul commited on
Commit
ae67c79
·
verified ·
1 Parent(s): 8bb00f8

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +376 -0
app.py ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import numpy as np
4
+ import random
5
+ import pandas as pd
6
+ import matplotlib.pyplot as plt
7
+ from transformers import AutoTokenizer, AutoModelForCausalLM
8
+ import time
9
+
10
+ # Load model and tokenizer
11
+ model_name = "/kaggle/input/nika-1.5b/transformers/default/1/nika-7b"
12
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
13
+ model = AutoModelForCausalLM.from_pretrained(model_name)
14
+
15
+ # Sample problems database (you would expand this)
16
+ sample_problems = {
17
+ "algebra": [
18
+ {
19
+ "problem": "Find all positive integers n such that n^2 + 20 is divisible by n + 5.",
20
+ "difficulty": "medium",
21
+ "solution": "Let's denote n^2 + 20 = k(n + 5) for some integer k.\nThis gives us n^2 + 20 = kn + 5k\nn^2 - kn - 5k + 20 = 0\nn^2 - kn = 5k - 20\nWe need to find values of n such that n^2 - kn = 5k - 20 has solutions.\nRearranging, we get n(n - k) = 5k - 20\nFor n > 0 and n + 5 to divide n^2 + 20, we need to check possible values.\nTrying n = 4: 4^2 + 20 = 36, 4 + 5 = 9, and 36 is divisible by 9. So n = 4 works.\nTrying n = 15: 15^2 + 20 = 245, 15 + 5 = 20, and 245 is not divisible by 20.\nAfter checking more values systematically, we find that n = 4 is the only positive integer solution."
22
+ },
23
+ {
24
+ "problem": "Determine all real values of x such that log_(x-1)(x^2 - 5x + 7) = 2.",
25
+ "difficulty": "hard",
26
+ "solution": "For log_(x-1)(x^2 - 5x + 7) = 2 to be defined, we need:\n1) x - 1 > 0, so x > 1\n2) x - 1 ≠ 1, so x ≠ 2\n3) x^2 - 5x + 7 > 0\n\nNow, log_(x-1)(x^2 - 5x + 7) = 2 means (x^2 - 5x + 7) = (x-1)^2\n\nExpanding (x-1)^2 = (x-1)(x-1) = x^2 - 2x + 1\n\nSo we need to solve x^2 - 5x + 7 = x^2 - 2x + 1\n-5x + 7 = -2x + 1\n-3x = -6\nx = 2\n\nBut we already established x ≠ 2, so there are no solutions."
27
+ }
28
+ ],
29
+ "geometry": [
30
+ {
31
+ "problem": "Points A, B, C, and D lie on a circle in that order. If AB = BC = CD and angle BAC = 30°, what is the measure of angle ADC in degrees?",
32
+ "difficulty": "medium",
33
+ "solution": "Since AB = BC = CD, we know that B divides arc AC into two equal parts, and C divides arc BD into two equal parts.\n\nLet's denote the center of the circle as O.\nSince AB = BC, triangles AOB and BOC are isosceles.\nThis means angle AOB = angle BOA and angle BOC = angle COB.\n\nWe know angle BAC = 30°.\nBy the inscribed angle theorem, angle BAC = (1/2) × (arc BC).\nSo arc BC = 60°.\n\nSince AB = BC = CD, arcs AB, BC, and CD all have the same length.\nThis means arc AB = arc BC = arc CD = 60°.\n\nBy the inscribed angle theorem, angle ADC = (1/2) × (arc AC).\nArc AC = arc AB + arc BC = 60° + 60° = 120°.\nTherefore, angle ADC = (1/2) × 120° = 60°."
34
+ }
35
+ ],
36
+ "number_theory": [
37
+ {
38
+ "problem": "Find the sum of all positive integers n such that n^2 + n + 1 is divisible by 7.",
39
+ "difficulty": "hard",
40
+ "solution": "Let's consider n mod 7 and check when n^2 + n + 1 ≡ 0 (mod 7).\n\nFor n ≡ 0 (mod 7): 0^2 + 0 + 1 = 1 ≡ 1 (mod 7) ❌\nFor n ≡ 1 (mod 7): 1^2 + 1 + 1 = 3 ≡ 3 (mod 7) ❌\nFor n ≡ 2 (mod 7): 2^2 + 2 + 1 = 7 ≡ 0 (mod 7) ✓\nFor n ≡ 3 (mod 7): 3^2 + 3 + 1 = 13 ≡ 6 (mod 7) ❌\nFor n ≡ 4 (mod 7): 4^2 + 4 + 1 = 21 ≡ 0 (mod 7) ✓\nFor n ≡ 5 (mod 7): 5^2 + 5 + 1 = 31 ≡ 3 (mod 7) ❌\nFor n ≡ 6 (mod 7): 6^2 + 6 + 1 = 43 ≡ 1 (mod 7) ❌\n\nSo n^2 + n + 1 is divisible by 7 when n ≡ 2 (mod 7) or n ≡ 4 (mod 7).\n\nFor n ≤ 100, the positive integers that satisfy this are:\n2, 4, 9, 11, 16, 18, 23, 25, 30, 32, 37, 39, 44, 46, 51, 53, 58, 60, 65, 67, 72, 74, 79, 81, 86, 88, 93, 95, 100\n\nThe sum of these numbers is 1501."
41
+ }
42
+ ],
43
+ "combinatorics": [
44
+ {
45
+ "problem": "How many different 4-digit numbers can be formed using the digits 1, 2, 3, 4, 5 without repetition?",
46
+ "difficulty": "easy",
47
+ "solution": "We need to create 4-digit numbers using 5 distinct digits without repetition.\n\nFor the first position, we have 5 choices (1, 2, 3, 4, or 5).\nFor the second position, we have 4 remaining choices.\nFor the third position, we have 3 remaining choices.\nFor the fourth position, we have 2 remaining choices.\n\nBy the multiplication principle, the total number of possible 4-digit numbers is:\n5 × 4 × 3 × 2 = 120"
48
+ }
49
+ ]
50
+ }
51
+
52
+ # Function to generate problem based on filters
53
+ def generate_problem(topic, difficulty):
54
+ filtered_problems = [p for p in sample_problems.get(topic, []) if p["difficulty"] == difficulty]
55
+ if filtered_problems:
56
+ return random.choice(filtered_problems)["problem"]
57
+ return "No problem found matching the criteria. Try a different combination."
58
+
59
+ # Function to solve problem using AI model
60
+ def solve_problem(problem_text):
61
+ if not problem_text.strip():
62
+ return "Please enter a problem first."
63
+
64
+ prompt = f"Solve this math olympiad problem step by step:\n\n{problem_text}\n\nSolution:"
65
+
66
+ # Add a small delay to simulate AI thinking (remove in production)
67
+ time.sleep(2)
68
+
69
+ inputs = tokenizer(prompt, return_tensors="pt")
70
+
71
+ # In a real system, you would use your AI model here
72
+ # outputs = model.generate(inputs["input_ids"], max_length=1024, temperature=0.7)
73
+ # solution = tokenizer.decode(outputs[0], skip_special_tokens=True).split("Solution:")[1].strip()
74
+
75
+ # For demo purposes, we'll provide a placeholder solution
76
+ for topic in sample_problems:
77
+ for problem in sample_problems[topic]:
78
+ if problem["problem"] == problem_text:
79
+ return problem["solution"]
80
+
81
+ return "I'll solve this step-by-step:\n\n1. First, let's understand what the problem is asking...\n\n(This is a placeholder. In the actual implementation, the AI model would generate a detailed solution.)"
82
+
83
+ # Function to analyze student solution
84
+ def analyze_solution(problem, student_solution, ai_solution):
85
+ if not student_solution.strip():
86
+ return "Please enter your solution first."
87
+
88
+ # In a real system, you would compare the solutions more intelligently
89
+ # For demo purposes, we'll provide a placeholder analysis
90
+
91
+ feedback = "Solution Analysis:\n\n"
92
+
93
+ # Simple keyword checking (very basic, would be much more sophisticated in reality)
94
+ ai_keywords = set([word.lower() for word in ai_solution.split() if len(word) > 4])
95
+ student_keywords = set([word.lower() for word in student_solution.split() if len(word) > 4])
96
+
97
+ common_keywords = ai_keywords.intersection(student_keywords)
98
+
99
+ if len(common_keywords) / max(1, len(ai_keywords)) > 0.4:
100
+ feedback += "✓ Your approach seems correct and contains many of the key concepts needed.\n\n"
101
+ else:
102
+ feedback += "⚠ Your approach may be missing some key concepts or taking a different direction.\n\n"
103
+
104
+ # Check for solution steps
105
+ if student_solution.count("\n") < 3:
106
+ feedback += "⚠ Your solution could benefit from showing more steps and reasoning.\n\n"
107
+ else:
108
+ feedback += "✓ Good job showing your work step by step!\n\n"
109
+
110
+ # Give general encouragement
111
+ feedback += "Areas to focus on:\n"
112
+ feedback += "- Consider whether you've addressed all constraints in the problem\n"
113
+ feedback += "- Check if your solution is logically complete\n"
114
+ feedback += "- Verify any algebraic manipulations\n\n"
115
+
116
+ return feedback
117
+
118
+ # Function to generate practice schedule
119
+ def generate_schedule(topics, difficulty_level, hours_per_week, weeks):
120
+ if not topics or not difficulty_level or not hours_per_week or not weeks:
121
+ return "Please fill in all fields."
122
+
123
+ # Create a DataFrame for the schedule
124
+ schedule = []
125
+ days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
126
+
127
+ # Distribute topics across the schedule
128
+ topics_cycle = topics.copy()
129
+ random.shuffle(topics_cycle)
130
+
131
+ # Calculate hours per day (simple distribution)
132
+ hours_per_day = [hours_per_week // 5 if d in ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'] else
133
+ hours_per_week // 10 for d in days]
134
+
135
+ # Ensure the total equals hours per week
136
+ while sum(hours_per_day) < hours_per_week:
137
+ idx = random.randint(0, len(days)-1)
138
+ hours_per_day[idx] += 1
139
+
140
+ for week in range(1, weeks+1):
141
+ for day_idx, day in enumerate(days):
142
+ if hours_per_day[day_idx] > 0:
143
+ topic = topics_cycle[week % len(topics_cycle)]
144
+ schedule.append({
145
+ 'Week': week,
146
+ 'Day': day,
147
+ 'Topic': topic,
148
+ 'Hours': hours_per_day[day_idx],
149
+ 'Difficulty': difficulty_level
150
+ })
151
+
152
+ df = pd.DataFrame(schedule)
153
+
154
+ # Create a visualization
155
+ fig, ax = plt.subplots(figsize=(10, 6))
156
+ topic_hours = df.groupby('Topic')['Hours'].sum().reset_index()
157
+ ax.bar(topic_hours['Topic'], topic_hours['Hours'])
158
+ ax.set_title('Hours by Topic in Training Schedule')
159
+ ax.set_xlabel('Topic')
160
+ ax.set_ylabel('Total Hours')
161
+ plt.xticks(rotation=45)
162
+ plt.tight_layout()
163
+
164
+ # Convert to HTML for display
165
+ schedule_html = df.to_html(index=False)
166
+
167
+ return fig, schedule_html
168
+
169
+ # Function to track progress
170
+ def update_progress(topic, correct, incorrect):
171
+ # This would connect to a database in a real implementation
172
+ # For now, we just return a visualization
173
+ topics = ['Algebra', 'Geometry', 'Number Theory', 'Combinatorics', 'Calculus']
174
+ correct_counts = [0, 0, 0, 0, 0]
175
+ incorrect_counts = [0, 0, 0, 0, 0]
176
+
177
+ # Update the counts based on input
178
+ try:
179
+ topic_idx = topics.index(topic)
180
+ correct_counts[topic_idx] = int(correct)
181
+ incorrect_counts[topic_idx] = int(incorrect)
182
+ except:
183
+ pass
184
+
185
+ # Create the progress chart
186
+ fig, ax = plt.subplots(figsize=(10, 6))
187
+
188
+ x = np.arange(len(topics))
189
+ width = 0.35
190
+
191
+ ax.bar(x - width/2, correct_counts, width, label='Correct')
192
+ ax.bar(x + width/2, incorrect_counts, width, label='Incorrect')
193
+
194
+ # Add labels and legend
195
+ ax.set_ylabel('Number of Problems')
196
+ ax.set_title('Progress by Topic')
197
+ ax.set_xticks(x)
198
+ ax.set_xticklabels(topics)
199
+ ax.legend()
200
+
201
+ plt.tight_layout()
202
+
203
+ # Calculate accuracy
204
+ total = sum(correct_counts) + sum(incorrect_counts)
205
+ accuracy = sum(correct_counts) / max(1, total) * 100
206
+
207
+ return fig, f"Overall Accuracy: {accuracy:.1f}%"
208
+
209
+ # Function for the competition simulator
210
+ def simulate_competition(num_problems, difficulty, time_limit):
211
+ if not num_problems or not difficulty or not time_limit:
212
+ return "Please fill in all fields."
213
+
214
+ # Generate a set of problems for the competition
215
+ competition_problems = []
216
+ for topic in sample_problems:
217
+ filtered = [p for p in sample_problems[topic] if p["difficulty"] == difficulty]
218
+ if filtered:
219
+ competition_problems.extend(filtered[:min(2, len(filtered))])
220
+
221
+ if len(competition_problems) > num_problems:
222
+ competition_problems = random.sample(competition_problems, num_problems)
223
+
224
+ # Format the problems
225
+ formatted_problems = ""
226
+ for i, p in enumerate(competition_problems, 1):
227
+ formatted_problems += f"Problem {i}: {p['problem']}\n\n"
228
+
229
+ # Calculate expected time per problem
230
+ time_per_problem = time_limit / max(1, len(competition_problems))
231
+
232
+ return f"Competition Simulation\n\nDifficulty: {difficulty}\nTime Limit: {time_limit} minutes\nRecommended time per problem: {time_per_problem:.1f} minutes\n\n{formatted_problems}"
233
+
234
+ # Create the Gradio interface
235
+ with gr.Blocks(title="AI Math Olympiad Trainer") as demo:
236
+ gr.Markdown("# AI Math Olympiad Trainer System")
237
+
238
+ with gr.Tab("Problem Generator"):
239
+ gr.Markdown("### Generate and Solve Math Olympiad Problems")
240
+
241
+ with gr.Row():
242
+ with gr.Column():
243
+ topic_dropdown = gr.Dropdown(
244
+ choices=["algebra", "geometry", "number_theory", "combinatorics"],
245
+ label="Topic"
246
+ )
247
+ difficulty_dropdown = gr.Dropdown(
248
+ choices=["easy", "medium", "hard"],
249
+ label="Difficulty"
250
+ )
251
+ generate_btn = gr.Button("Generate Problem")
252
+
253
+ with gr.Column():
254
+ problem_output = gr.Textbox(label="Problem", lines=5)
255
+
256
+ with gr.Row():
257
+ with gr.Column():
258
+ solution_input = gr.Textbox(label="Your Solution", lines=10)
259
+ analyze_btn = gr.Button("Analyze My Solution")
260
+
261
+ with gr.Column():
262
+ ai_solution_btn = gr.Button("Get AI Solution")
263
+ ai_solution_output = gr.Textbox(label="AI Solution", lines=10)
264
+ analysis_output = gr.Textbox(label="Analysis", lines=8)
265
+
266
+ with gr.Tab("Training Schedule"):
267
+ gr.Markdown("### Create a Personalized Training Schedule")
268
+
269
+ with gr.Row():
270
+ with gr.Column():
271
+ topics_multiselect = gr.CheckboxGroup(
272
+ choices=["Algebra", "Geometry", "Number Theory", "Combinatorics", "Calculus"],
273
+ label="Select Topics"
274
+ )
275
+ difficulty_radio = gr.Radio(
276
+ choices=["easy", "medium", "hard", "mixed"],
277
+ label="Difficulty Level"
278
+ )
279
+ hours_slider = gr.Slider(
280
+ minimum=1, maximum=30, value=10, step=1,
281
+ label="Hours per Week"
282
+ )
283
+ weeks_slider = gr.Slider(
284
+ minimum=1, maximum=12, value=4, step=1,
285
+ label="Number of Weeks"
286
+ )
287
+ schedule_btn = gr.Button("Generate Schedule")
288
+
289
+ with gr.Column():
290
+ schedule_plot = gr.Plot(label="Hours Distribution")
291
+ schedule_output = gr.HTML(label="Your Schedule")
292
+
293
+ with gr.Tab("Progress Tracker"):
294
+ gr.Markdown("### Track Your Progress")
295
+
296
+ with gr.Row():
297
+ with gr.Column():
298
+ progress_topic = gr.Dropdown(
299
+ choices=["Algebra", "Geometry", "Number Theory", "Combinatorics", "Calculus"],
300
+ label="Topic"
301
+ )
302
+ correct_slider = gr.Slider(
303
+ minimum=0, maximum=50, value=0, step=1,
304
+ label="Correct Solutions"
305
+ )
306
+ incorrect_slider = gr.Slider(
307
+ minimum=0, maximum=50, value=0, step=1,
308
+ label="Incorrect Solutions"
309
+ )
310
+ update_btn = gr.Button("Update Progress")
311
+
312
+ with gr.Column():
313
+ progress_plot = gr.Plot(label="Progress Chart")
314
+ accuracy_output = gr.Textbox(label="Accuracy")
315
+
316
+ with gr.Tab("Competition Simulator"):
317
+ gr.Markdown("### Simulate a Math Competition")
318
+
319
+ with gr.Row():
320
+ with gr.Column():
321
+ problems_slider = gr.Slider(
322
+ minimum=1, maximum=10, value=3, step=1,
323
+ label="Number of Problems"
324
+ )
325
+ comp_difficulty = gr.Radio(
326
+ choices=["easy", "medium", "hard"],
327
+ label="Difficulty"
328
+ )
329
+ time_slider = gr.Slider(
330
+ minimum=15, maximum=180, value=60, step=15,
331
+ label="Time Limit (minutes)"
332
+ )
333
+ simulate_btn = gr.Button("Start Simulation")
334
+
335
+ with gr.Column():
336
+ simulation_output = gr.Textbox(label="Competition Problems", lines=15)
337
+
338
+ # Connect the functions
339
+ generate_btn.click(
340
+ generate_problem,
341
+ inputs=[topic_dropdown, difficulty_dropdown],
342
+ outputs=problem_output
343
+ )
344
+
345
+ ai_solution_btn.click(
346
+ solve_problem,
347
+ inputs=[problem_output],
348
+ outputs=ai_solution_output
349
+ )
350
+
351
+ analyze_btn.click(
352
+ analyze_solution,
353
+ inputs=[problem_output, solution_input, ai_solution_output],
354
+ outputs=analysis_output
355
+ )
356
+
357
+ schedule_btn.click(
358
+ generate_schedule,
359
+ inputs=[topics_multiselect, difficulty_radio, hours_slider, weeks_slider],
360
+ outputs=[schedule_plot, schedule_output]
361
+ )
362
+
363
+ update_btn.click(
364
+ update_progress,
365
+ inputs=[progress_topic, correct_slider, incorrect_slider],
366
+ outputs=[progress_plot, accuracy_output]
367
+ )
368
+
369
+ simulate_btn.click(
370
+ simulate_competition,
371
+ inputs=[problems_slider, comp_difficulty, time_slider],
372
+ outputs=simulation_output
373
+ )
374
+
375
+ # Launch the app
376
+ demo.launch()