louiecerv's picture
save
f3e6155
raw
history blame
6.51 kB
import streamlit as st
import os
import google.generativeai as genai
import json
from PIL import Image
import re
import json
import tempfile
# Define constants
TEXT_PROMPT = """Use the provided document. Read the list of quadratic equations.
Return your response as a JSON list. Do not include any extra text, explanations, or backslashes.
Example JSON output:
[
"x^2 - 5x + 6 = 0",
"2x^2 + 3x - 1 = 0",
"x^2 - 9 = 0",
"3x^2 - 2x + 4 = 0",
"x^2 + 8x + 15 = 0"
]
"""
MODEL_ID = "gemini-2.0-flash-exp" # Keep the model ID as is
try:
api_key = os.getenv("GEMINI_API_KEY")
model_id = MODEL_ID
genai.configure(api_key=api_key)
except Exception as e:
st.error(f"Error: {e}")
st.stop()
model = genai.GenerativeModel(MODEL_ID)
chat = model.start_chat()
def get_local_file_path(img_file="problem1.png"):
"""
Returns the path to the local PDF file.
"""
try:
file_path = os.path.join("problems", img_file)
if not os.path.exists(file_path):
raise FileNotFoundError(f"{file_path} does not exist.")
return file_path
except Exception as e:
st.error(f"Failed to find the local file: {e}")
st.stop() # Stop if the file is not found
# Initialize conversation history in Streamlit session state
if "conversation_history" not in st.session_state:
st.session_state.conversation_history = []
if "uploaded_file_part" not in st.session_state: # Store the file *part*
st.session_state.uploaded_file_part = None
if "uploaded_pdf_path" not in st.session_state:
st.session_state.uploaded_pdf_path = get_local_file_path()
def multimodal_prompt(pdf_path, text_prompt, file_type="PDF"):
"""
Sends a multimodal prompt to Gemini, handling file uploads efficiently.
Args:
pdf_path: The path to the file (PDF or image).
text_prompt: The text prompt for the model.
file_type: "PDF" or "image" to specify the file type.
Returns:
The model's response as a string, or an error message.
"""
try:
if file_type == "PDF":
mime_type = "application/pdf"
elif file_type == "image":
import mimetypes
mime_type, _ = mimetypes.guess_type(pdf_path)
if mime_type is None:
return "Could not determine MIME type for image. Please check the file path or type."
else:
return "Invalid file_type. Must be 'PDF' or 'image'."
if st.session_state.get("uploaded_file_part") is None: # First time, upload
pdf_part = genai.upload_file(pdf_path, mime_type=mime_type)
st.session_state.uploaded_file_part = pdf_part
prompt = [text_prompt, pdf_part] # First turn includes the actual file
else: # Subsequent turns, reference the file
prompt = [text_prompt, st.session_state.uploaded_file_part] # Subsequent turns include the file reference
response = chat.send_message(prompt)
# Update conversation history
st.session_state.conversation_history.append({"role": "user", "content": text_prompt, "has_file": True})
st.session_state.conversation_history.append({"role": "assistant", "content": response.text})
return response.text
except Exception as e:
return f"An error occurred: {e}"
def get_equation(response):
# Remove the ```json and ``` and extra spaces.
try:
json_string = response.replace('```json', '').replace('```', '').strip()
# Parse the JSON string into a Python list.
problems_list = json.loads(json_string)
# return the first item found
return problems_list[0]
except json.JSONDecodeError:
st.error("Invalid JSON format in the response.")
return None
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
return None
if "problem_step" not in st.session_state:
st.session_state.problem_step = 0
# --- Main Page ---
st.title("📚❓Problem Solving Tutor")
about = """
**How to use this App**
Replace this placeholder with the actual text.
"""
with st.spinner("Loading the problem..."):
if st.session_state.get("uploaded_pdf_path") is None:
st.session_state.uploaded_pdf_path = get_local_file_path("problem1.png")
filepath = st.session_state.uploaded_pdf_path
response = multimodal_prompt(filepath, TEXT_PROMPT, file_type="image")
# --- Display the image ---
st.image(filepath, caption="Problem Image", use_container_width=True)
equation = get_equation(response)
st.write(f"**Equation:** {equation}")
problem_step = st.session_state.problem_step
if problem_step == 0:
#Show instructions to submit the answer
st.write("Please write down your answer in a piece of paper. Take a picture of the paper and submit it in the next step.")
st.write("Click the button below to proceed.")
img_file_buffer = st.camera_input("Take a picture of your answer.")
if img_file_buffer is not None:
# process the answer
st.write("Processing your answer...")
# Save the image to a temporary file
with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file:
temp_file.write(img_file_buffer.read())
image_path = temp_file.name
st.write("Image saved to:", image_path)
# create the text prompt
text_prompt = "Use the provided image. The image shoqs, a student's answer to the problem. Evaluate the answer and provide a correct solution. Provide feedback how can the student improve their answer."
if st.button("Ask Tutor for Feedback"):
if text_prompt:
with st.spinner("AI is thinking..."):
response = multimodal_prompt(image_path, text_prompt, file_type="image")
st.markdown(response)
if st.button("Next"):
# Evaluate the response
if "Correct" in response:
st.write("Correct! 🎉")
st.session_state.problem_step = 1
else:
st.write("Incorrect. 😞")
st.session_state.problem_step = 0
else:
st.write("Please take a picture of your answer.")
st.markdown("Visit our Hugging Face Space!")
st.markdown("© 2025 WVSU AI Dev Team 🤖 ✨")