jujutechnology commited on
Commit
9b78dcf
Β·
verified Β·
1 Parent(s): 62900c0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -8
app.py CHANGED
@@ -4,8 +4,9 @@ import os
4
  import json
5
  import base64
6
  from dotenv import load_dotenv
7
- # Correct import for the local storage library
8
  from streamlit_local_storage import LocalStorage
 
 
9
 
10
  # --- PAGE CONFIGURATION ---
11
  st.set_page_config(
@@ -32,6 +33,58 @@ def convert_role_for_gemini(role):
32
  return "model"
33
  return role # "user" stays the same
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  # --- API KEY & MODEL CONFIGURATION ---
36
  load_dotenv()
37
  api_key = None
@@ -43,12 +96,20 @@ except (KeyError, FileNotFoundError):
43
 
44
  if api_key:
45
  genai.configure(api_key=api_key)
 
 
46
  model = genai.GenerativeModel(
47
  model_name="gemini-2.5-flash-lite",
48
  system_instruction="""
49
  You are "Math Jegna", an AI specializing exclusively in mathematics.
50
  Your one and only function is to solve and explain math problems.
51
- You are an AI math tutor that primarily uses the Professor B methodology developed by Everard Barrett. Use the best method for the situation. Create images, infographics to help whenever possible. This methodology is designed to activate children's natural learning capacities and present mathematics as a contextual, developmental story that makes sense.
 
 
 
 
 
 
52
  Core Philosophy and Principles
53
  1. Contextual Learning Approach
54
  Present math as a story: Every mathematical concept should be taught as part of a continuing narrative that builds connections between ideas
@@ -144,7 +205,6 @@ if "chats" not in st.session_state:
144
  else:
145
  raise ValueError("No shared chat")
146
  except (TypeError, ValueError, Exception):
147
- # Use the correct method: localS.getItem()
148
  saved_data_json = localS.getItem("math_mentor_chats")
149
  if saved_data_json:
150
  saved_data = json.loads(saved_data_json)
@@ -230,11 +290,14 @@ for chat_key in list(st.session_state.chats.keys()):
230
  active_chat = st.session_state.chats[st.session_state.active_chat_key]
231
 
232
  st.title(f"Math Mentor: {st.session_state.active_chat_key} 🧠")
233
- st.write("Stuck on a math problem? Just type it below, and I'll walk you through it step-by-step!")
234
 
235
  for message in active_chat:
236
  with st.chat_message(name=message["role"], avatar="πŸ§‘β€πŸ’»" if message["role"] == "user" else "🧠"):
237
  st.markdown(message["content"])
 
 
 
238
 
239
  if user_prompt := st.chat_input():
240
  active_chat.append({"role": "user", "content": user_prompt})
@@ -244,14 +307,31 @@ if user_prompt := st.chat_input():
244
  with st.chat_message("assistant", avatar="🧠"):
245
  with st.spinner("Math Mentor is thinking... πŸ€”"):
246
  try:
 
247
  chat_session = model.start_chat(history=[
248
  {'role': convert_role_for_gemini(msg['role']), 'parts': [msg['content']]}
249
- for msg in active_chat[:-1]
250
  ])
251
  response = chat_session.send_message(user_prompt)
252
  ai_response_text = response.text
253
  st.markdown(ai_response_text)
254
- active_chat.append({"role": "assistant", "content": ai_response_text})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
  except Exception as e:
257
  error_message = f"Sorry, something went wrong. Math Mentor is taking a break! πŸ€–\n\n**Error:** {e}"
@@ -259,9 +339,17 @@ if user_prompt := st.chat_input():
259
  active_chat.append({"role": "assistant", "content": error_message})
260
 
261
  # --- SAVE DATA TO LOCAL STORAGE ---
 
 
 
 
 
 
 
 
 
262
  data_to_save = {
263
- "chats": st.session_state.chats,
264
  "active_chat_key": st.session_state.active_chat_key
265
  }
266
- # Use the correct method: localS.setItem()
267
  localS.setItem("math_mentor_chats", json.dumps(data_to_save))
 
4
  import json
5
  import base64
6
  from dotenv import load_dotenv
 
7
  from streamlit_local_storage import LocalStorage
8
+ from PIL import Image
9
+ from io import BytesIO
10
 
11
  # --- PAGE CONFIGURATION ---
12
  st.set_page_config(
 
33
  return "model"
34
  return role # "user" stays the same
35
 
36
+ def should_generate_visual(user_prompt, ai_response):
37
+ """Determine if a visual aid would be helpful based on the content"""
38
+ visual_keywords = [
39
+ 'graph', 'plot', 'diagram', 'chart', 'visual', 'picture', 'illustration',
40
+ 'geometry', 'triangle', 'circle', 'rectangle', 'square', 'polygon',
41
+ 'coordinate', 'axis', 'function', 'parabola', 'line', 'slope',
42
+ 'fraction', 'percentage', 'ratio', 'proportion', 'angles',
43
+ 'number line', 'timeline', 'distribution', 'probability',
44
+ 'pattern', 'sequence', 'series', 'matrix', 'vector'
45
+ ]
46
+
47
+ combined_text = (user_prompt + " " + ai_response).lower()
48
+ return any(keyword in combined_text for keyword in visual_keywords)
49
+
50
+ def generate_math_visual(user_prompt, ai_response):
51
+ """Generate a math visual using Gemini's image generation capabilities"""
52
+ try:
53
+ # Create a focused prompt for mathematical illustration
54
+ visual_prompt = f"""Create a clear, educational math diagram to illustrate this concept: {user_prompt}
55
+
56
+ Style: Clean, minimalist educational diagram with:
57
+ - White or light background
58
+ - Clear labels and text
59
+ - Professional textbook style
60
+ - High contrast for readability
61
+ - Mathematical accuracy
62
+ - Simple, focused design
63
+
64
+ Make it suitable for a math student to understand the concept better."""
65
+
66
+ # Configure the image generation model
67
+ image_model = genai.GenerativeModel("gemini-2.5-flash-image-preview")
68
+
69
+ response = image_model.generate_content(
70
+ visual_prompt,
71
+ generation_config=genai.GenerationConfig(
72
+ response_modalities=["TEXT", "IMAGE"]
73
+ )
74
+ )
75
+
76
+ # Extract image from response
77
+ for part in response.candidates[0].content.parts:
78
+ if part.inline_data is not None:
79
+ image = Image.open(BytesIO(part.inline_data.data))
80
+ return image
81
+
82
+ return None
83
+
84
+ except Exception as e:
85
+ st.error(f"Could not generate visual: {e}")
86
+ return None
87
+
88
  # --- API KEY & MODEL CONFIGURATION ---
89
  load_dotenv()
90
  api_key = None
 
96
 
97
  if api_key:
98
  genai.configure(api_key=api_key)
99
+
100
+ # Main text model
101
  model = genai.GenerativeModel(
102
  model_name="gemini-2.5-flash-lite",
103
  system_instruction="""
104
  You are "Math Jegna", an AI specializing exclusively in mathematics.
105
  Your one and only function is to solve and explain math problems.
106
+ You are an AI math tutor that primarily uses the Professor B methodology developed by Everard Barrett. Use the best method for the situation. This methodology is designed to activate children's natural learning capacities and present mathematics as a contextual, developmental story that makes sense.
107
+
108
+ IMPORTANT: When explaining mathematical concepts that would benefit from visual aids, explicitly mention that a visual diagram will be provided to help illustrate the concept. Use phrases like:
109
+ - "Let me show you this with a diagram..."
110
+ - "A visual representation will help clarify this..."
111
+ - "I'll create an illustration to demonstrate..."
112
+
113
  Core Philosophy and Principles
114
  1. Contextual Learning Approach
115
  Present math as a story: Every mathematical concept should be taught as part of a continuing narrative that builds connections between ideas
 
205
  else:
206
  raise ValueError("No shared chat")
207
  except (TypeError, ValueError, Exception):
 
208
  saved_data_json = localS.getItem("math_mentor_chats")
209
  if saved_data_json:
210
  saved_data = json.loads(saved_data_json)
 
290
  active_chat = st.session_state.chats[st.session_state.active_chat_key]
291
 
292
  st.title(f"Math Mentor: {st.session_state.active_chat_key} 🧠")
293
+ st.write("Stuck on a math problem? Just type it below, and I'll walk you through it step-by-step with visual aids when helpful!")
294
 
295
  for message in active_chat:
296
  with st.chat_message(name=message["role"], avatar="πŸ§‘β€πŸ’»" if message["role"] == "user" else "🧠"):
297
  st.markdown(message["content"])
298
+ # Display stored images if they exist
299
+ if "image" in message:
300
+ st.image(message["image"], caption="Math Concept Illustration", use_column_width=True)
301
 
302
  if user_prompt := st.chat_input():
303
  active_chat.append({"role": "user", "content": user_prompt})
 
307
  with st.chat_message("assistant", avatar="🧠"):
308
  with st.spinner("Math Mentor is thinking... πŸ€”"):
309
  try:
310
+ # Generate text response first
311
  chat_session = model.start_chat(history=[
312
  {'role': convert_role_for_gemini(msg['role']), 'parts': [msg['content']]}
313
+ for msg in active_chat[:-1] if 'content' in msg
314
  ])
315
  response = chat_session.send_message(user_prompt)
316
  ai_response_text = response.text
317
  st.markdown(ai_response_text)
318
+
319
+ # Store the text response
320
+ message_data = {"role": "assistant", "content": ai_response_text}
321
+
322
+ # Check if we should generate a visual aid
323
+ if should_generate_visual(user_prompt, ai_response_text):
324
+ with st.spinner("Creating visual aid... 🎨"):
325
+ visual_image = generate_math_visual(user_prompt, ai_response_text)
326
+ if visual_image:
327
+ st.image(visual_image, caption="Math Concept Illustration", use_column_width=True)
328
+ # Convert image to bytes for storage
329
+ img_buffer = BytesIO()
330
+ visual_image.save(img_buffer, format="PNG")
331
+ img_bytes = img_buffer.getvalue()
332
+ message_data["image"] = img_bytes
333
+
334
+ active_chat.append(message_data)
335
 
336
  except Exception as e:
337
  error_message = f"Sorry, something went wrong. Math Mentor is taking a break! πŸ€–\n\n**Error:** {e}"
 
339
  active_chat.append({"role": "assistant", "content": error_message})
340
 
341
  # --- SAVE DATA TO LOCAL STORAGE ---
342
+ # Note: We'll only save text content to local storage, not images (too large)
343
+ simplified_chats = {}
344
+ for chat_key, messages in st.session_state.chats.items():
345
+ simplified_chats[chat_key] = []
346
+ for message in messages:
347
+ simplified_message = {"role": message["role"], "content": message["content"]}
348
+ # Don't save image data to local storage
349
+ simplified_chats[chat_key].append(simplified_message)
350
+
351
  data_to_save = {
352
+ "chats": simplified_chats,
353
  "active_chat_key": st.session_state.active_chat_key
354
  }
 
355
  localS.setItem("math_mentor_chats", json.dumps(data_to_save))