import gradio as gr import requests import json import os import re # API Configuration GROQ_API_KEY = os.environ.get("GROQ_API_KEY", "") GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "") # Problem themes and topics THEMES = { "🎮 Gaming": ["video games", "esports", "streaming", "game development"], "⚽ Sports": ["soccer", "basketball", "olympics", "skateboarding"], "🚀 Space": ["astronauts", "planets", "rockets", "aliens"], "🍕 Food": ["pizza party", "baking", "restaurant", "food truck"], "🎵 Music": ["concert", "band", "playlist", "music festival"], "🐾 Animals": ["zoo", "pets", "wildlife", "ocean creatures"], "💻 Tech": ["coding", "robots", "apps", "social media"], "🎨 Art": ["painting", "museum", "crafts", "design"], } GRADE_LEVELS = { "Elementary (1-5)": "simple addition, subtraction, multiplication, division", "Middle School (6-8)": "fractions, decimals, percentages, basic algebra", "High School (9-12)": "algebra, geometry, trigonometry, basic calculus", "College+": "advanced calculus, linear algebra, differential equations" } def call_groq_api(prompt: str): """Call Groq API""" if not GROQ_API_KEY: return None url = "https://api.groq.com/openai/v1/chat/completions" headers = { "Authorization": f"Bearer {GROQ_API_KEY}", "Content-Type": "application/json" } payload = { "model": "llama-3.3-70b-versatile", "messages": [{"role": "user", "content": prompt}], "temperature": 0.7, "max_tokens": 1500 } try: response = requests.post(url, headers=headers, json=payload, timeout=30) response.raise_for_status() return response.json()["choices"][0]["message"]["content"] except Exception as e: print(f"Groq error: {e}") return None def call_gemini_api(prompt: str): """Fallback to Gemini""" if not GEMINI_API_KEY: return None url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key={GEMINI_API_KEY}" payload = { "contents": [{"parts": [{"text": prompt}]}], "generationConfig": {"temperature": 0.7, "maxOutputTokens": 1500} } try: response = requests.post(url, json=payload, timeout=30) response.raise_for_status() return response.json()["candidates"][0]["content"]["parts"][0]["text"] except Exception as e: print(f"Gemini error: {e}") return None def generate_problem(theme: str, grade: str, custom_topic: str = ""): """Generate a story problem""" topic = custom_topic if custom_topic else THEMES.get(theme, ["general math"])[0] math_level = GRADE_LEVELS.get(grade, "basic arithmetic") prompt = f"""Create an engaging math story problem for {grade} students. Theme: {topic} Math concepts: {math_level} Requirements: 1. Write a fun, relatable story (2-3 sentences) 2. Include specific numbers that make sense 3. Ask 2-3 questions of increasing difficulty 4. Make it realistic and age-appropriate 5. Use emojis to make it engaging Format your response as: TITLE: [Catchy title with emoji] STORY: [The scenario] QUESTIONS: 1. [Question 1 - easiest] 2. [Question 2 - medium] 3. [Question 3 - hardest] Example for reference: TITLE: 🎮 The Streaming Marathon STORY: Alex is streaming a gaming marathon to raise money for charity. They stream for 6 hours on Saturday and 4 hours on Sunday. Their average viewership is 250 people per hour, and each viewer donates $0.50 per hour watched. QUESTIONS: 1. How many total hours did Alex stream? 2. How many total viewer-hours did they get? 3. How much money did they raise for charity?""" response = call_groq_api(prompt) or call_gemini_api(prompt) if not response: return "❌ **Error**: Please add GROQ_API_KEY or GEMINI_API_KEY in Space settings.", "" return format_problem_html(response), response def solve_problem(problem_text: str): """Solve a given problem with step-by-step explanation""" prompt = f"""Solve this math problem with detailed step-by-step explanations. Problem: {problem_text} Provide: 1. A clear breakdown of what's being asked 2. Step-by-step solution for each question 3. Visual aids (use ASCII art, diagrams if helpful) 4. Final answers clearly marked 5. A "Check your work" tip Format with markdown for readability. Use emojis to make it engaging.""" response = call_groq_api(prompt) or call_gemini_api(prompt) if not response: return "❌ **Error**: Please add API key in Space settings." return format_solution_html(response) def format_problem_html(text: str): """Format problem in nice HTML""" html = f"""
{text}
            
✨ Scroll down to see the solution! ✨
""" return html def format_solution_html(text: str): """Format solution in nice HTML""" html = f"""

📝 Step-by-Step Solution

{text.replace(chr(10), '
')}
""" return html # Gradio Interface with gr.Blocks( theme=gr.themes.Soft(), css=""" .gradio-container {max-width: 900px !important;} .generate-btn {background: linear-gradient(90deg, #667eea, #764ba2) !important; color: white !important; font-weight: 600 !important; border: none !important;} .solve-btn {background: linear-gradient(90deg, #11998e, #38ef7d) !important; color: white !important; font-weight: 600 !important; border: none !important;} """, title="🧮 Math Story Problem Generator" ) as demo: gr.Markdown(""" # 🧮 Math Story Problem Generator & Solver ### Transform boring math into exciting stories! 🎉 **Generate** personalized word problems based on your interests, or **paste** any problem to get a detailed solution. """) with gr.Tabs(): # GENERATE TAB with gr.Tab("✨ Generate Problem"): with gr.Row(): with gr.Column(): theme_choice = gr.Dropdown( choices=list(THEMES.keys()), value="🎮 Gaming", label="📚 Choose Theme", info="Pick what interests you!" ) grade_choice = gr.Dropdown( choices=list(GRADE_LEVELS.keys()), value="Middle School (6-8)", label="🎓 Grade Level" ) custom_topic = gr.Textbox( label="🎯 Custom Topic (Optional)", placeholder="e.g., 'TikTok followers', 'Minecraft building', 'sneaker collection'", lines=1 ) generate_btn = gr.Button( "🚀 Generate Story Problem", variant="primary", size="lg", elem_classes="generate-btn" ) problem_output = gr.HTML(label="Generated Problem") problem_text_state = gr.State() with gr.Row(): show_solution_btn = gr.Button( "📝 Show Solution", variant="secondary", size="lg", elem_classes="solve-btn" ) solution_output = gr.HTML(label="Solution", visible=False) # SOLVE TAB with gr.Tab("🔍 Solve Problem"): gr.Markdown(""" ### Paste any math problem and get a detailed solution! Works with story problems, equations, geometry, algebra, and more. """) paste_problem = gr.Textbox( label="📋 Paste Your Math Problem", placeholder="Example: A train leaves Chicago at 60 mph. Another train leaves NYC (800 miles away) at 40 mph. When do they meet?", lines=5 ) solve_btn = gr.Button( "🧠 Solve It!", variant="primary", size="lg", elem_classes="solve-btn" ) solve_output = gr.HTML(label="Solution") gr.Markdown(""" --- ## 🎯 Features - ✅ **Personalized**: Choose themes you love - ✅ **Adaptive**: Problems match your grade level - ✅ **Step-by-Step**: Detailed solutions with explanations - ✅ **Visual**: ASCII art and diagrams when helpful - ✅ **Free**: Powered by free AI APIs! ## 🔑 Setup Add **GROQ_API_KEY** (from console.groq.com) as a HuggingFace Secret to enable generation. Gemini API also supported as fallback! ## 💡 Tips - Try custom topics that match your interests - Generate multiple problems to practice - Challenge yourself with harder grade levels - Use the solver to check your own work --- *Built with ❤️ for math learners everywhere* """) # Event handlers def generate_and_show(theme, grade, custom): html, text = generate_problem(theme, grade, custom) return html, text, gr.update(visible=False) def show_solution_for_problem(problem_text): if not problem_text: return gr.update(visible=False) solution = solve_problem(problem_text) return gr.update(value=solution, visible=True) generate_btn.click( fn=generate_and_show, inputs=[theme_choice, grade_choice, custom_topic], outputs=[problem_output, problem_text_state, solution_output] ) show_solution_btn.click( fn=show_solution_for_problem, inputs=[problem_text_state], outputs=[solution_output] ) solve_btn.click( fn=solve_problem, inputs=[paste_problem], outputs=[solve_output] ) if __name__ == "__main__": demo.launch()