Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -178,6 +178,9 @@ def create_number_line(start, end, points, title="Number Line"):
|
|
| 178 |
"""(NEW & Dynamic) Creates a simple number line SVG."""
|
| 179 |
width = 600
|
| 180 |
padding = 30
|
|
|
|
|
|
|
|
|
|
| 181 |
scale = (width - 2 * padding) / (end - start)
|
| 182 |
def to_x(n): return padding + (n - start) * scale
|
| 183 |
ticks_html = "".join([f'<g transform="translate({to_x(i)}, 50)"><line y2="10" stroke="#aaa"/><text y="30" text-anchor="middle" fill="#555">{i}</text></g>' for i in range(start, end + 1)])
|
|
@@ -186,12 +189,68 @@ def create_number_line(start, end, points, title="Number Line"):
|
|
| 186 |
return html
|
| 187 |
|
| 188 |
def create_place_value_blocks(number):
|
| 189 |
-
"""(Dynamic) Create place value blocks for understanding numbers."""
|
| 190 |
hundreds, tens, ones = number // 100, (number % 100) // 10, number % 10
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
return html
|
| 196 |
|
| 197 |
def create_shape_explorer():
|
|
@@ -206,10 +265,6 @@ def create_money_counter():
|
|
| 206 |
|
| 207 |
# --- [The rest of your application code remains the same] ---
|
| 208 |
# --- API KEY & MODEL CONFIGURATION, SESSION STATE, DIALOGS, etc. ---
|
| 209 |
-
# ... (Paste the rest of your original app.py code from the "API KEY" section onwards here) ...
|
| 210 |
-
|
| 211 |
-
# NOTE: For brevity, I am not repeating the entire second half of your app.
|
| 212 |
-
# The code below is identical to your original file.
|
| 213 |
|
| 214 |
# --- API KEY & MODEL CONFIGURATION ---
|
| 215 |
load_dotenv()
|
|
@@ -225,7 +280,7 @@ if api_key:
|
|
| 225 |
|
| 226 |
# Main text model
|
| 227 |
model = genai.GenerativeModel(
|
| 228 |
-
model_name="gemini-
|
| 229 |
system_instruction="""
|
| 230 |
You are "Math Jegna", an AI specializing exclusively in K-12 mathematics.
|
| 231 |
Your one and only function is to solve and explain math problems for children.
|
|
@@ -239,7 +294,6 @@ if api_key:
|
|
| 239 |
Focus on concepts appropriate for K-12 students:
|
| 240 |
- Basic counting and number recognition
|
| 241 |
- Simple addition and subtraction (using manipulatives)
|
| 242 |
-
- Fractions as parts of wholes (pizza slices, etc.)
|
| 243 |
- Multiplication as arrays or groups
|
| 244 |
- Basic shapes and geometry
|
| 245 |
- Place value with hundreds, tens, ones
|
|
@@ -392,9 +446,11 @@ with st.sidebar:
|
|
| 392 |
if st.button("π Share Chat", use_container_width=True):
|
| 393 |
chat_json = json.dumps(st.session_state.chats[st.session_state.active_chat_key])
|
| 394 |
chat_b64 = base64.urlsafe_b64encode(chat_json.encode()).decode()
|
| 395 |
-
|
|
|
|
| 396 |
st.code(share_url)
|
| 397 |
-
st.info("Copy the URL above to share this specific chat!")
|
|
|
|
| 398 |
|
| 399 |
st.header(f"Chatting with Math Jegna: _{st.session_state.active_chat_key}_")
|
| 400 |
|
|
@@ -402,6 +458,9 @@ st.header(f"Chatting with Math Jegna: _{st.session_state.active_chat_key}_")
|
|
| 402 |
for message in st.session_state.chats[st.session_state.active_chat_key]:
|
| 403 |
with st.chat_message(message["role"]):
|
| 404 |
st.markdown(message["content"])
|
|
|
|
|
|
|
|
|
|
| 405 |
|
| 406 |
# User input
|
| 407 |
if prompt := st.chat_input("Ask a K-8 math question..."):
|
|
@@ -430,18 +489,24 @@ if prompt := st.chat_input("Ask a K-8 math question..."):
|
|
| 430 |
response_container.markdown(full_response + " β")
|
| 431 |
response_container.markdown(full_response)
|
| 432 |
|
| 433 |
-
# After generating text, decide if a visual is needed
|
|
|
|
| 434 |
if should_generate_visual(prompt, full_response):
|
| 435 |
-
|
| 436 |
-
if
|
| 437 |
-
|
| 438 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
|
| 440 |
-
# Add AI response to session state
|
| 441 |
-
st.session_state.chats[st.session_state.active_chat_key].append({"role": "assistant", "content": full_response})
|
| 442 |
|
| 443 |
except genai.types.generation_types.BlockedPromptException as e:
|
| 444 |
-
|
| 445 |
-
st.
|
|
|
|
| 446 |
except Exception as e:
|
| 447 |
st.error(f"An error occurred: {e}")
|
|
|
|
| 178 |
"""(NEW & Dynamic) Creates a simple number line SVG."""
|
| 179 |
width = 600
|
| 180 |
padding = 30
|
| 181 |
+
# Handle the edge case where start equals end
|
| 182 |
+
if start >= end:
|
| 183 |
+
end = start + 1
|
| 184 |
scale = (width - 2 * padding) / (end - start)
|
| 185 |
def to_x(n): return padding + (n - start) * scale
|
| 186 |
ticks_html = "".join([f'<g transform="translate({to_x(i)}, 50)"><line y2="10" stroke="#aaa"/><text y="30" text-anchor="middle" fill="#555">{i}</text></g>' for i in range(start, end + 1)])
|
|
|
|
| 189 |
return html
|
| 190 |
|
| 191 |
def create_place_value_blocks(number):
|
| 192 |
+
"""(FIXED & Dynamic) Create place value blocks for understanding numbers."""
|
| 193 |
hundreds, tens, ones = number // 100, (number % 100) // 10, number % 10
|
| 194 |
+
|
| 195 |
+
# --- Hundreds Block HTML ---
|
| 196 |
+
h_block_html = ""
|
| 197 |
+
if hundreds > 0:
|
| 198 |
+
hundreds_grid = "".join(["<div style='background:#F5A6A6'></div>"] * 100)
|
| 199 |
+
hundreds_squares = "".join([f"""
|
| 200 |
+
<div style="width: 100px; height: 100px; background: #FF6B6B; border: 2px solid #D63031; display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px; padding: 2px;">
|
| 201 |
+
{hundreds_grid}
|
| 202 |
+
</div>
|
| 203 |
+
""" for _ in range(hundreds)])
|
| 204 |
+
h_block_html = f"""
|
| 205 |
+
<div style="text-align: center;">
|
| 206 |
+
<h4>Hundreds: {hundreds}</h4>
|
| 207 |
+
<div style="display: flex; gap: 5px;">{hundreds_squares}</div>
|
| 208 |
+
</div>
|
| 209 |
+
"""
|
| 210 |
+
|
| 211 |
+
# --- Tens Block HTML ---
|
| 212 |
+
t_block_html = ""
|
| 213 |
+
if tens > 0:
|
| 214 |
+
tens_grid = "".join(["<div style='background:#A2E8E4'></div>"] * 10)
|
| 215 |
+
tens_sticks = "".join([f"""
|
| 216 |
+
<div style="width: 10px; height: 100px; background: #4ECDC4; border: 2px solid #00B894; display: grid; grid-template-rows: repeat(10, 1fr); gap: 2px; padding: 2px;">
|
| 217 |
+
{tens_grid}
|
| 218 |
+
</div>
|
| 219 |
+
""" for _ in range(tens)])
|
| 220 |
+
t_block_html = f"""
|
| 221 |
+
<div style="text-align: center;">
|
| 222 |
+
<h4>Tens: {tens}</h4>
|
| 223 |
+
<div style="display: flex; gap: 5px; align-items: flex-end;">{tens_sticks}</div>
|
| 224 |
+
</div>
|
| 225 |
+
"""
|
| 226 |
+
|
| 227 |
+
# --- Ones Block HTML ---
|
| 228 |
+
o_block_html = ""
|
| 229 |
+
if ones > 0:
|
| 230 |
+
ones_cubes = "".join(['<div style="width: 10px; height: 10px; background: #FFE066; border: 2px solid #FDCB6E;"></div>' for _ in range(ones)])
|
| 231 |
+
o_block_html = f"""
|
| 232 |
+
<div style="text-align: center;">
|
| 233 |
+
<h4>Ones: {ones}</h4>
|
| 234 |
+
<div style="display: flex; gap: 5px; align-items: flex-end; flex-wrap: wrap; width: 50px; justify-content: center;">{ones_cubes}</div>
|
| 235 |
+
</div>
|
| 236 |
+
"""
|
| 237 |
+
|
| 238 |
+
# --- Final Assembly ---
|
| 239 |
+
html = f"""
|
| 240 |
+
<div style="padding: 20px; background: linear-gradient(135deg, #dfe6e9 0%, #b2bec3 100%); border-radius: 15px; margin: 10px 0;">
|
| 241 |
+
<h3 style="color: #333; text-align: center;">Place Value Blocks for {number}</h3>
|
| 242 |
+
<div style="display: flex; justify-content: center; align-items: flex-end; gap: 20px; flex-wrap: wrap; padding: 20px 0; min-height: 150px;">
|
| 243 |
+
{h_block_html}
|
| 244 |
+
{t_block_html}
|
| 245 |
+
{o_block_html}
|
| 246 |
+
</div>
|
| 247 |
+
<div style="text-align: center; margin-top: 15px; padding: 10px; background: rgba(0,0,0,0.1); border-radius: 10px;">
|
| 248 |
+
<h4 style="color: #333; margin:0;">
|
| 249 |
+
{hundreds} Hundreds + {tens} Tens + {ones} Ones = {number}
|
| 250 |
+
</h4>
|
| 251 |
+
</div>
|
| 252 |
+
</div>
|
| 253 |
+
"""
|
| 254 |
return html
|
| 255 |
|
| 256 |
def create_shape_explorer():
|
|
|
|
| 265 |
|
| 266 |
# --- [The rest of your application code remains the same] ---
|
| 267 |
# --- API KEY & MODEL CONFIGURATION, SESSION STATE, DIALOGS, etc. ---
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
|
| 269 |
# --- API KEY & MODEL CONFIGURATION ---
|
| 270 |
load_dotenv()
|
|
|
|
| 280 |
|
| 281 |
# Main text model
|
| 282 |
model = genai.GenerativeModel(
|
| 283 |
+
model_name="gemini-1.5-flash",
|
| 284 |
system_instruction="""
|
| 285 |
You are "Math Jegna", an AI specializing exclusively in K-12 mathematics.
|
| 286 |
Your one and only function is to solve and explain math problems for children.
|
|
|
|
| 294 |
Focus on concepts appropriate for K-12 students:
|
| 295 |
- Basic counting and number recognition
|
| 296 |
- Simple addition and subtraction (using manipulatives)
|
|
|
|
| 297 |
- Multiplication as arrays or groups
|
| 298 |
- Basic shapes and geometry
|
| 299 |
- Place value with hundreds, tens, ones
|
|
|
|
| 446 |
if st.button("π Share Chat", use_container_width=True):
|
| 447 |
chat_json = json.dumps(st.session_state.chats[st.session_state.active_chat_key])
|
| 448 |
chat_b64 = base64.urlsafe_b64encode(chat_json.encode()).decode()
|
| 449 |
+
# This part might need adjustment depending on how Streamlit Community Cloud handles base URLs
|
| 450 |
+
share_url = f"https://huggingface.co/spaces/YOUR_SPACE_HERE?shared_chat={chat_b64}" # Placeholder
|
| 451 |
st.code(share_url)
|
| 452 |
+
st.info("Copy the URL above to share this specific chat! (You might need to update the base URL)")
|
| 453 |
+
|
| 454 |
|
| 455 |
st.header(f"Chatting with Math Jegna: _{st.session_state.active_chat_key}_")
|
| 456 |
|
|
|
|
| 458 |
for message in st.session_state.chats[st.session_state.active_chat_key]:
|
| 459 |
with st.chat_message(message["role"]):
|
| 460 |
st.markdown(message["content"])
|
| 461 |
+
# If a visual was generated and saved with the message, display it
|
| 462 |
+
if "visual_html" in message and message["visual_html"]:
|
| 463 |
+
components.html(message["visual_html"], height=400, scrolling=True)
|
| 464 |
|
| 465 |
# User input
|
| 466 |
if prompt := st.chat_input("Ask a K-8 math question..."):
|
|
|
|
| 489 |
response_container.markdown(full_response + " β")
|
| 490 |
response_container.markdown(full_response)
|
| 491 |
|
| 492 |
+
# After generating text, decide if a visual is needed and generate it
|
| 493 |
+
visual_html_content = None
|
| 494 |
if should_generate_visual(prompt, full_response):
|
| 495 |
+
visual_html_content = create_visual_manipulative(prompt, full_response)
|
| 496 |
+
if visual_html_content:
|
| 497 |
+
components.html(visual_html_content, height=400, scrolling=True)
|
| 498 |
+
|
| 499 |
+
# Add AI response and visual to session state
|
| 500 |
+
st.session_state.chats[st.session_state.active_chat_key].append({
|
| 501 |
+
"role": "assistant",
|
| 502 |
+
"content": full_response,
|
| 503 |
+
"visual_html": visual_html_content # Store the visual with the message
|
| 504 |
+
})
|
| 505 |
|
|
|
|
|
|
|
| 506 |
|
| 507 |
except genai.types.generation_types.BlockedPromptException as e:
|
| 508 |
+
error_message = "I can only answer math questions for students. Please ask me about numbers, shapes, or other math topics!"
|
| 509 |
+
st.error(error_message)
|
| 510 |
+
st.session_state.chats[st.session_state.active_chat_key].append({"role": "assistant", "content": error_message, "visual_html": None})
|
| 511 |
except Exception as e:
|
| 512 |
st.error(f"An error occurred: {e}")
|