Docfile's picture
Update app.py
3f35d09 verified
raw
history blame
4.53 kB
from flask import Flask, request, render_template, send_from_directory
import google.generativeai as genai
import os
from PIL import Image
import subprocess
import uuid
import re
import tempfile
from pathlib import Path
app = Flask(__name__)
# Configuration constants
UPLOAD_FOLDER = Path('uploads')
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
# Create uploads directory if it doesn't exist
UPLOAD_FOLDER.mkdir(exist_ok=True)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
# Gemini API configuration
def configure_gemini():
token = os.environ.get("TOKEN")
if not token:
raise ValueError("Environment variable TOKEN must be set.")
genai.configure(api_key=token)
generation_config = {
"temperature": 1,
"top_p": 0.95,
"top_k": 64,
"max_output_tokens": 8192,
}
safety_settings = [
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
]
return genai.GenerativeModel(
model_name="gemini-1.5-pro",
generation_config=generation_config,
safety_settings=safety_settings,
)
PROMPT_TEMPLATE = """
Résous cet exercice. Tu répondras en détaillant au maximum ton procédé de calcul.
Réponse attendue uniquement en LaTeX
"""
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def generate_svg_from_chemfig(chemfig_code, tmpdirname):
unique_id = str(uuid.uuid4())
tex_filename = Path(tmpdirname) / f"chem_{unique_id}.tex"
pdf_filename = Path(tmpdirname) / f"chem_{unique_id}.pdf"
svg_filename = f"chem_{unique_id}.svg"
tex_content = f"""\\documentclass[margin=10pt]{{standalone}}
\\usepackage{{chemfig}}
\\begin{{document}}
\\chemfig{{{chemfig_code}}}
\\end{{document}}"""
tex_filename.write_text(tex_content)
try:
subprocess.run(["pdflatex", "-interaction=nonstopmode", str(tex_filename)],
check=True, cwd=tmpdirname)
subprocess.run(["pdf2svg", str(pdf_filename),
str(UPLOAD_FOLDER / svg_filename)], check=True)
return svg_filename
except subprocess.CalledProcessError as e:
raise Exception(f"LaTeX compilation or SVG conversion error: {e}")
@app.route("/", methods=["GET", "POST"])
def index():
if request.method != "POST":
return render_template("index.html", e="")
if "image" not in request.files:
return render_template("index.html", e="No image selected.")
image_file = request.files["image"]
if not image_file or not allowed_file(image_file.filename):
return render_template("index.html", e="Invalid file type. Please upload PNG or JPG.")
try:
model = configure_gemini()
with tempfile.NamedTemporaryFile(delete=False) as temp_img:
image_file.save(temp_img.name)
image = Image.open(temp_img.name)
response = model.generate_content([PROMPT_TEMPLATE, image])
latex_code = response.text
os.unlink(temp_img.name)
# Handle chemfig diagrams
match = re.search(r"\\chemfig\{(.*?)\}", latex_code, re.DOTALL)
if match:
chemfig_code = match.group(1)
with tempfile.TemporaryDirectory() as tmpdirname:
svg_filename = generate_svg_from_chemfig(chemfig_code, tmpdirname)
return render_template("index.html",
e=f'<img src="/uploads/{svg_filename}" alt="Chemical structure">')
# Block potentially unsafe content
if any(keyword in latex_code.lower() for keyword in
['.pdf', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg']):
return render_template("index.html",
e="Sorry, images and PDFs are not yet supported in the response.")
return render_template("index.html", e=latex_code)
except Exception as error:
return render_template("index.html", e=f"Error processing request: {str(error)}")
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
if __name__ == "__main__":
app.run(debug=True)