Spaces:
Sleeping
Sleeping
| 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" | |
| 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'." | |
| pdf_part = genai.upload_file(pdf_path, mime_type=mime_type) | |
| prompt = [text_prompt, pdf_part] # First turn includes the actual file | |
| 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 shows, | |
| my answer to the problem. If the image is not clear ask for another image and do not perform | |
| any of the following instructions. If the image is clear, evaluate the answer as either | |
| correct or incorrect. If the answer is incorrect, do not provide the correct answer. | |
| Provide feedback how can the student improve their answer. | |
| If the answer is correct, provide feedback that the answer is correct and discuss the solution. | |
| If the student used the factoring method, ask the student to try again and next time use the | |
| quadratic formula method. The goal is to solve the problem using the quadratic formula method do not | |
| ask the student to use the factoring method. | |
| """ | |
| 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 🤖 ✨") |