from flask import Flask, request, render_template, jsonify, send_from_directory from PIL import Image import io import os import re import matplotlib.pyplot as plt import tempfile from gradio_client import Client, handle_file from dataclasses import dataclass from typing import List, Optional import logging from google import genai from google.genai import types # Logging configuration logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class MathSolver: def __init__(self): plt.switch_backend('Agg') # Non-interactive backend def query_gemini(self, image_path: str, prompt: str) -> str: try: img = Image.open(image_path) buffered = io.BytesIO() img.save(buffered, format="PNG") img_byte_arr = buffered.getvalue() response = client.models.generate_content( model="gemini-2.0-flash-thinking-exp-01-21", config={'thinking_config': {'include_thoughts': True}, 'temperature': 1, 'max_output_tokens': 8192}, contents=[ {'parts': [{'text': prompt}, {'inline_data': {'mime_type': 'image/png', 'data': img_byte_arr}}]} ] ) full_response = "" for candidate in response.candidates: for part in candidate.content.parts: if part.thought: full_response += f"
Thought:
{part.text}
" else: full_response += f"
Answer:
{part.text}
" return full_response except Exception as e: logger.error(f"Gemini Error: {str(e)}") raise @staticmethod def query_qwen2(image_path: str, question: str) -> str: try: client = Client("Qwen/Qwen2.5-Math-Demo") return client.predict( image=handle_file(image_path), sketchpad=None, question=question, api_name="/math_chat_bot" ) except Exception as e: logger.error(f"Qwen2 Error: {str(e)}") raise @staticmethod def extract_and_execute_python_code(text: str) -> Optional[List[str]]: code_blocks = re.findall(r'```python\n(.*?)```', text, re.DOTALL) if not code_blocks: return None image_paths = [] for code in code_blocks: try: code = "import numpy as np\n" + code code = code.replace("\\", "\\\\") with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmpfile: plt.figure() exec(code) plt.savefig(tmpfile.name) plt.close() relative_path = os.path.basename(tmpfile.name) image_paths.append(relative_path) except Exception as e: logger.error(f"Error generating graph: {str(e)}") continue return image_paths if image_paths else None # Application configuration app = Flask(__name__) GOOGLE_API_KEY = os.environ.get("TOKEN") client = genai.Client( api_key=GOOGLE_API_KEY, http_options={'api_version': 'v1alpha'}, ) math_solver = MathSolver() @app.route('/') def index(): return render_template('math.html') @app.route('/upload', methods=['POST']) def upload_image(): if 'image' not in request.files: return jsonify({'error': 'No image provided'}), 400 file = request.files['image'] if not file.filename: return jsonify({'error': 'No file selected'}), 400 model_choice = request.form.get('model_choice', 'gemini') custom_instruction = request.form.get('custom_instruction', '') prompt = f"Solve this math problem. Provide a complete solution with rendering LaTeX. {custom_instruction}" try: with tempfile.NamedTemporaryFile(delete=False) as temp_file: file.save(temp_file.name) result = ( math_solver.query_gemini(temp_file.name, prompt) if model_choice == "mariam's" else math_solver.query_qwen2(temp_file.name, prompt) ) image_paths = math_solver.extract_and_execute_python_code(result) os.unlink(temp_file.name) return jsonify({ 'result': result, 'model': model_choice, 'image_paths': image_paths, 'temp_dir': tempfile.gettempdir() }) except Exception as e: logger.error(f"Error processing: {str(e)}") return jsonify({'error': str(e)}), 500 @app.route('/temp/') def serve_temp_image(filename): try: return send_from_directory(tempfile.gettempdir(), filename) except Exception as e: logger.error(f"Error sending image: {str(e)}") return jsonify({'error': 'Image not found'}), 404 if __name__ == '__main__': app.run(debug=True)