|
|
import gradio as gr |
|
|
import requests |
|
|
import json |
|
|
import os |
|
|
import re |
|
|
|
|
|
|
|
|
GROQ_API_KEY = os.environ.get("GROQ_API_KEY", "") |
|
|
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "") |
|
|
|
|
|
|
|
|
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""" |
|
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
|
padding: 30px; border-radius: 15px; color: white; font-family: 'Segoe UI', sans-serif;"> |
|
|
<div style="background: rgba(255,255,255,0.15); backdrop-filter: blur(10px); |
|
|
padding: 25px; border-radius: 12px; margin-bottom: 20px;"> |
|
|
<pre style="color: white; font-size: 16px; line-height: 1.8; white-space: pre-wrap; font-family: inherit;"> |
|
|
{text} |
|
|
</pre> |
|
|
</div> |
|
|
<div style="text-align: center; margin-top: 15px; color: rgba(255,255,255,0.8); font-size: 14px;"> |
|
|
โจ Scroll down to see the solution! โจ |
|
|
</div> |
|
|
</div> |
|
|
""" |
|
|
return html |
|
|
|
|
|
def format_solution_html(text: str): |
|
|
"""Format solution in nice HTML""" |
|
|
html = f""" |
|
|
<div style="background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%); |
|
|
padding: 30px; border-radius: 15px; color: white; font-family: 'Segoe UI', sans-serif;"> |
|
|
<div style="background: rgba(255,255,255,0.15); backdrop-filter: blur(10px); |
|
|
padding: 25px; border-radius: 12px;"> |
|
|
<h2 style="margin-top: 0; color: white;">๐ Step-by-Step Solution</h2> |
|
|
<div style="color: white; font-size: 15px; line-height: 1.8;"> |
|
|
{text.replace(chr(10), '<br>')} |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
""" |
|
|
return html |
|
|
|
|
|
|
|
|
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(): |
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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* |
|
|
""") |
|
|
|
|
|
|
|
|
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() |