CoolFace
Apppublic

BeastGokul/AI-Math-Olympiad-Trainer

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
app.py377 linesDownload Raw Back to root
1import gradio as gr2import torch3import numpy as np4import random5import pandas as pd6import matplotlib.pyplot as plt7import time8from peft import PeftModel9from transformers import AutoModelForCausalLM, AutoTokenizer10 11model_name = "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B"12model = AutoModelForCausalLM.from_pretrained(model_name)13tokenizer = AutoTokenizer.from_pretrained(model_name)14 15 16# Sample problems database (you would expand this)17sample_problems = {18    "algebra": [19        {20            "problem": "Find all positive integers n such that n^2 + 20 is divisible by n + 5.",21            "difficulty": "medium",22            "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."23        },24        {25            "problem": "Determine all real values of x such that log_(x-1)(x^2 - 5x + 7) = 2.",26            "difficulty": "hard",27            "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."28        }29    ],30    "geometry": [31        {32            "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?",33            "difficulty": "medium",34            "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°."35        }36    ],37    "number_theory": [38        {39            "problem": "Find the sum of all positive integers n such that n^2 + n + 1 is divisible by 7.",40            "difficulty": "hard",41            "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."42        }43    ],44    "combinatorics": [45        {46            "problem": "How many different 4-digit numbers can be formed using the digits 1, 2, 3, 4, 5 without repetition?",47            "difficulty": "easy",48            "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"49        }50    ]51}52 53# Function to generate problem based on filters54def generate_problem(topic, difficulty):55    filtered_problems = [p for p in sample_problems.get(topic, []) if p["difficulty"] == difficulty]56    if filtered_problems:57        return random.choice(filtered_problems)["problem"]58    return "No problem found matching the criteria. Try a different combination."59 60# Function to solve problem using AI model61def solve_problem(problem_text):62    if not problem_text.strip():63        return "Please enter a problem first."64    65    prompt = f"Solve this math olympiad problem step by step:\n\n{problem_text}\n\nSolution:"66    67    # Add a small delay to simulate AI thinking (remove in production)68    time.sleep(2)69    70    inputs = tokenizer(prompt, return_tensors="pt")71    72    # In a real system, you would use your AI model here73    # outputs = model.generate(inputs["input_ids"], max_length=1024, temperature=0.7)74    # solution = tokenizer.decode(outputs[0], skip_special_tokens=True).split("Solution:")[1].strip()75    76    # For demo purposes, we'll provide a placeholder solution77    for topic in sample_problems:78        for problem in sample_problems[topic]:79            if problem["problem"] == problem_text:80                return problem["solution"]81    82    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.)"83 84# Function to analyze student solution85def analyze_solution(problem, student_solution, ai_solution):86    if not student_solution.strip():87        return "Please enter your solution first."88    89    # In a real system, you would compare the solutions more intelligently90    # For demo purposes, we'll provide a placeholder analysis91    92    feedback = "Solution Analysis:\n\n"93    94    # Simple keyword checking (very basic, would be much more sophisticated in reality)95    ai_keywords = set([word.lower() for word in ai_solution.split() if len(word) > 4])96    student_keywords = set([word.lower() for word in student_solution.split() if len(word) > 4])97    98    common_keywords = ai_keywords.intersection(student_keywords)99    100    if len(common_keywords) / max(1, len(ai_keywords)) > 0.4:101        feedback += "✓ Your approach seems correct and contains many of the key concepts needed.\n\n"102    else:103        feedback += "⚠ Your approach may be missing some key concepts or taking a different direction.\n\n"104    105    # Check for solution steps106    if student_solution.count("\n") < 3:107        feedback += "⚠ Your solution could benefit from showing more steps and reasoning.\n\n"108    else:109        feedback += "✓ Good job showing your work step by step!\n\n"110    111    # Give general encouragement112    feedback += "Areas to focus on:\n"113    feedback += "- Consider whether you've addressed all constraints in the problem\n"114    feedback += "- Check if your solution is logically complete\n"115    feedback += "- Verify any algebraic manipulations\n\n"116    117    return feedback118 119# Function to generate practice schedule120def generate_schedule(topics, difficulty_level, hours_per_week, weeks):121    if not topics or not difficulty_level or not hours_per_week or not weeks:122        return "Please fill in all fields."123    124    # Create a DataFrame for the schedule125    schedule = []126    days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']127    128    # Distribute topics across the schedule129    topics_cycle = topics.copy()130    random.shuffle(topics_cycle)131    132    # Calculate hours per day (simple distribution)133    hours_per_day = [hours_per_week // 5 if d in ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'] else 134                     hours_per_week // 10 for d in days]135    136    # Ensure the total equals hours per week137    while sum(hours_per_day) < hours_per_week:138        idx = random.randint(0, len(days)-1)139        hours_per_day[idx] += 1140    141    for week in range(1, weeks+1):142        for day_idx, day in enumerate(days):143            if hours_per_day[day_idx] > 0:144                topic = topics_cycle[week % len(topics_cycle)]145                schedule.append({146                    'Week': week,147                    'Day': day,148                    'Topic': topic,149                    'Hours': hours_per_day[day_idx],150                    'Difficulty': difficulty_level151                })152    153    df = pd.DataFrame(schedule)154    155    # Create a visualization156    fig, ax = plt.subplots(figsize=(10, 6))157    topic_hours = df.groupby('Topic')['Hours'].sum().reset_index()158    ax.bar(topic_hours['Topic'], topic_hours['Hours'])159    ax.set_title('Hours by Topic in Training Schedule')160    ax.set_xlabel('Topic')161    ax.set_ylabel('Total Hours')162    plt.xticks(rotation=45)163    plt.tight_layout()164    165    # Convert to HTML for display166    schedule_html = df.to_html(index=False)167    168    return fig, schedule_html169 170# Function to track progress171def update_progress(topic, correct, incorrect):172    # This would connect to a database in a real implementation173    # For now, we just return a visualization174    topics = ['Algebra', 'Geometry', 'Number Theory', 'Combinatorics', 'Calculus']175    correct_counts = [0, 0, 0, 0, 0]176    incorrect_counts = [0, 0, 0, 0, 0]177    178    # Update the counts based on input179    try:180        topic_idx = topics.index(topic)181        correct_counts[topic_idx] = int(correct)182        incorrect_counts[topic_idx] = int(incorrect)183    except:184        pass185    186    # Create the progress chart187    fig, ax = plt.subplots(figsize=(10, 6))188    189    x = np.arange(len(topics))190    width = 0.35191    192    ax.bar(x - width/2, correct_counts, width, label='Correct')193    ax.bar(x + width/2, incorrect_counts, width, label='Incorrect')194    195    # Add labels and legend196    ax.set_ylabel('Number of Problems')197    ax.set_title('Progress by Topic')198    ax.set_xticks(x)199    ax.set_xticklabels(topics)200    ax.legend()201    202    plt.tight_layout()203    204    # Calculate accuracy205    total = sum(correct_counts) + sum(incorrect_counts)206    accuracy = sum(correct_counts) / max(1, total) * 100207    208    return fig, f"Overall Accuracy: {accuracy:.1f}%"209 210# Function for the competition simulator211def simulate_competition(num_problems, difficulty, time_limit):212    if not num_problems or not difficulty or not time_limit:213        return "Please fill in all fields."214    215    # Generate a set of problems for the competition216    competition_problems = []217    for topic in sample_problems:218        filtered = [p for p in sample_problems[topic] if p["difficulty"] == difficulty]219        if filtered:220            competition_problems.extend(filtered[:min(2, len(filtered))])221    222    if len(competition_problems) > num_problems:223        competition_problems = random.sample(competition_problems, num_problems)224    225    # Format the problems226    formatted_problems = ""227    for i, p in enumerate(competition_problems, 1):228        formatted_problems += f"Problem {i}: {p['problem']}\n\n"229    230    # Calculate expected time per problem231    time_per_problem = time_limit / max(1, len(competition_problems))232    233    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}"234 235# Create the Gradio interface236with gr.Blocks(title="AI Math Olympiad Trainer") as demo:237    gr.Markdown("# AI Math Olympiad Trainer System")238    239    with gr.Tab("Problem Generator"):240        gr.Markdown("### Generate and Solve Math Olympiad Problems")241        242        with gr.Row():243            with gr.Column():244                topic_dropdown = gr.Dropdown(245                    choices=["algebra", "geometry", "number_theory", "combinatorics"], 246                    label="Topic"247                )248                difficulty_dropdown = gr.Dropdown(249                    choices=["easy", "medium", "hard"], 250                    label="Difficulty"251                )252                generate_btn = gr.Button("Generate Problem")253            254            with gr.Column():255                problem_output = gr.Textbox(label="Problem", lines=5)256        257        with gr.Row():258            with gr.Column():259                solution_input = gr.Textbox(label="Your Solution", lines=10)260                analyze_btn = gr.Button("Analyze My Solution")261            262            with gr.Column():263                ai_solution_btn = gr.Button("Get AI Solution")264                ai_solution_output = gr.Textbox(label="AI Solution", lines=10)265                analysis_output = gr.Textbox(label="Analysis", lines=8)266    267    with gr.Tab("Training Schedule"):268        gr.Markdown("### Create a Personalized Training Schedule")269        270        with gr.Row():271            with gr.Column():272                topics_multiselect = gr.CheckboxGroup(273                    choices=["Algebra", "Geometry", "Number Theory", "Combinatorics", "Calculus"],274                    label="Select Topics"275                )276                difficulty_radio = gr.Radio(277                    choices=["easy", "medium", "hard", "mixed"],278                    label="Difficulty Level"279                )280                hours_slider = gr.Slider(281                    minimum=1, maximum=30, value=10, step=1,282                    label="Hours per Week"283                )284                weeks_slider = gr.Slider(285                    minimum=1, maximum=12, value=4, step=1,286                    label="Number of Weeks"287                )288                schedule_btn = gr.Button("Generate Schedule")289            290            with gr.Column():291                schedule_plot = gr.Plot(label="Hours Distribution")292                schedule_output = gr.HTML(label="Your Schedule")293    294    with gr.Tab("Progress Tracker"):295        gr.Markdown("### Track Your Progress")296        297        with gr.Row():298            with gr.Column():299                progress_topic = gr.Dropdown(300                    choices=["Algebra", "Geometry", "Number Theory", "Combinatorics", "Calculus"],301                    label="Topic"302                )303                correct_slider = gr.Slider(304                    minimum=0, maximum=50, value=0, step=1,305                    label="Correct Solutions"306                )307                incorrect_slider = gr.Slider(308                    minimum=0, maximum=50, value=0, step=1,309                    label="Incorrect Solutions"310                )311                update_btn = gr.Button("Update Progress")312            313            with gr.Column():314                progress_plot = gr.Plot(label="Progress Chart")315                accuracy_output = gr.Textbox(label="Accuracy")316    317    with gr.Tab("Competition Simulator"):318        gr.Markdown("### Simulate a Math Competition")319        320        with gr.Row():321            with gr.Column():322                problems_slider = gr.Slider(323                    minimum=1, maximum=10, value=3, step=1,324                    label="Number of Problems"325                )326                comp_difficulty = gr.Radio(327                    choices=["easy", "medium", "hard"],328                    label="Difficulty"329                )330                time_slider = gr.Slider(331                    minimum=15, maximum=180, value=60, step=15,332                    label="Time Limit (minutes)"333                )334                simulate_btn = gr.Button("Start Simulation")335            336            with gr.Column():337                simulation_output = gr.Textbox(label="Competition Problems", lines=15)338    339    # Connect the functions340    generate_btn.click(341        generate_problem, 342        inputs=[topic_dropdown, difficulty_dropdown], 343        outputs=problem_output344    )345    346    ai_solution_btn.click(347        solve_problem,348        inputs=[problem_output],349        outputs=ai_solution_output350    )351    352    analyze_btn.click(353        analyze_solution,354        inputs=[problem_output, solution_input, ai_solution_output],355        outputs=analysis_output356    )357    358    schedule_btn.click(359        generate_schedule,360        inputs=[topics_multiselect, difficulty_radio, hours_slider, weeks_slider],361        outputs=[schedule_plot, schedule_output]362    )363    364    update_btn.click(365        update_progress,366        inputs=[progress_topic, correct_slider, incorrect_slider],367        outputs=[progress_plot, accuracy_output]368    )369    370    simulate_btn.click(371        simulate_competition,372        inputs=[problems_slider, comp_difficulty, time_slider],373        outputs=simulation_output374    )375 376# Launch the app377demo.launch()