Docfile commited on
Commit
3f35d09
·
verified ·
1 Parent(s): 110c1ff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -78
app.py CHANGED
@@ -2,90 +2,62 @@ from flask import Flask, request, render_template, send_from_directory
2
  import google.generativeai as genai
3
  import os
4
  from PIL import Image
5
- import io
6
  import subprocess
7
  import uuid
8
  import re
9
  import tempfile
 
10
 
11
  app = Flask(__name__)
12
- app.config['UPLOAD_FOLDER'] = 'uploads'
13
- os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
14
-
15
- # Configuration de l'API Gemini
16
- token = os.environ.get("TOKEN")
17
- if not token:
18
- raise ValueError("La variable d'environnement TOKEN doit être définie.")
19
-
20
- genai.configure(api_key=token)
21
-
22
- generation_config = {
23
- "temperature": 1,
24
- "top_p": 0.95,
25
- "top_k": 64,
26
- "max_output_tokens": 8192,
27
- }
28
-
29
- safety_settings = [
30
- {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
31
- {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
32
- {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
33
- {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
34
- ]
35
-
36
- mm = """resous cet exercice. tu répondras en détaillant au maximum ton procédé de calcul. réponse attendue uniquement en Latex
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  """
39
- model = genai.GenerativeModel(
40
- model_name="gemini-1.5-pro",
41
- generation_config=generation_config,
42
- safety_settings=safety_settings,
43
- )
44
-
45
-
46
-
47
- @app.route("/", methods=["GET", "POST"])
48
- def index():
49
- e = ""
50
- if request.method == "POST":
51
- if "image" not in request.files:
52
- e = "Aucune image sélectionnée."
53
- else:
54
- image_file = request.files["image"]
55
- try:
56
- with tempfile.NamedTemporaryFile(delete=False) as temp_img:
57
- image_file.save(temp_img.name)
58
- image = Image.open(temp_img.name)
59
-
60
- response = model.generate_content([mm, image])
61
- latex_code = response.text
62
- os.remove(temp_img.name)
63
-
64
- match = re.search(r"\\chemfig\{(.*?)\}", latex_code, re.DOTALL)
65
- if match:
66
- chemfig_code = match.group(1)
67
- try:
68
- with tempfile.TemporaryDirectory() as tmpdirname:
69
- svg_filename = generate_svg_from_chemfig(chemfig_code, tmpdirname)
70
- e = f'<img src="/uploads/{svg_filename}" alt="Structure chimique">'
71
- except Exception as svg_error:
72
- e = f"Erreur lors de la génération de l'image SVG : {str(svg_error)}"
73
- elif any(keyword in latex_code.lower() for keyword in ['.pdf', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg']):
74
- e = "Désolé, les images et les PDF ne sont pas encore pris en charge dans la réponse."
75
- else:
76
- e = latex_code
77
-
78
-
79
- except Exception as img_err:
80
- e = f"Erreur lors du traitement de l'image: {str(img_err)}"
81
-
82
- return render_template("index.html", e=e)
83
 
 
 
84
 
85
  def generate_svg_from_chemfig(chemfig_code, tmpdirname):
86
  unique_id = str(uuid.uuid4())
87
- tex_filename = os.path.join(tmpdirname, f"chem_{unique_id}.tex")
88
- pdf_filename = os.path.join(tmpdirname, f"chem_{unique_id}.pdf")
89
  svg_filename = f"chem_{unique_id}.svg"
90
 
91
  tex_content = f"""\\documentclass[margin=10pt]{{standalone}}
@@ -94,21 +66,63 @@ def generate_svg_from_chemfig(chemfig_code, tmpdirname):
94
  \\chemfig{{{chemfig_code}}}
95
  \\end{{document}}"""
96
 
97
- with open(tex_filename, "w") as tex_file:
98
- tex_file.write(tex_content)
99
 
100
  try:
101
- subprocess.run(["pdflatex", "-interaction=nonstopmode", tex_filename], check=True, cwd=tmpdirname)
102
- subprocess.run(["pdf2svg", pdf_filename, os.path.join(app.config['UPLOAD_FOLDER'], svg_filename)], check=True)
 
 
103
  return svg_filename
104
  except subprocess.CalledProcessError as e:
105
- raise Exception(f"Erreur lors de la compilation LaTeX ou de la conversion en SVG : {e}")
 
 
 
 
 
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
  @app.route('/uploads/<filename>')
109
  def uploaded_file(filename):
110
  return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
111
 
112
-
113
  if __name__ == "__main__":
114
  app.run(debug=True)
 
2
  import google.generativeai as genai
3
  import os
4
  from PIL import Image
 
5
  import subprocess
6
  import uuid
7
  import re
8
  import tempfile
9
+ from pathlib import Path
10
 
11
  app = Flask(__name__)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ # Configuration constants
14
+ UPLOAD_FOLDER = Path('uploads')
15
+ ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
16
+
17
+ # Create uploads directory if it doesn't exist
18
+ UPLOAD_FOLDER.mkdir(exist_ok=True)
19
+ app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
20
+
21
+ # Gemini API configuration
22
+ def configure_gemini():
23
+ token = os.environ.get("TOKEN")
24
+ if not token:
25
+ raise ValueError("Environment variable TOKEN must be set.")
26
+
27
+ genai.configure(api_key=token)
28
+
29
+ generation_config = {
30
+ "temperature": 1,
31
+ "top_p": 0.95,
32
+ "top_k": 64,
33
+ "max_output_tokens": 8192,
34
+ }
35
+
36
+ safety_settings = [
37
+ {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
38
+ {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
39
+ {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
40
+ {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
41
+ ]
42
+
43
+ return genai.GenerativeModel(
44
+ model_name="gemini-1.5-pro",
45
+ generation_config=generation_config,
46
+ safety_settings=safety_settings,
47
+ )
48
+
49
+ PROMPT_TEMPLATE = """
50
+ Résous cet exercice. Tu répondras en détaillant au maximum ton procédé de calcul.
51
+ Réponse attendue uniquement en LaTeX
52
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
+ def allowed_file(filename):
55
+ return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
56
 
57
  def generate_svg_from_chemfig(chemfig_code, tmpdirname):
58
  unique_id = str(uuid.uuid4())
59
+ tex_filename = Path(tmpdirname) / f"chem_{unique_id}.tex"
60
+ pdf_filename = Path(tmpdirname) / f"chem_{unique_id}.pdf"
61
  svg_filename = f"chem_{unique_id}.svg"
62
 
63
  tex_content = f"""\\documentclass[margin=10pt]{{standalone}}
 
66
  \\chemfig{{{chemfig_code}}}
67
  \\end{{document}}"""
68
 
69
+ tex_filename.write_text(tex_content)
 
70
 
71
  try:
72
+ subprocess.run(["pdflatex", "-interaction=nonstopmode", str(tex_filename)],
73
+ check=True, cwd=tmpdirname)
74
+ subprocess.run(["pdf2svg", str(pdf_filename),
75
+ str(UPLOAD_FOLDER / svg_filename)], check=True)
76
  return svg_filename
77
  except subprocess.CalledProcessError as e:
78
+ raise Exception(f"LaTeX compilation or SVG conversion error: {e}")
79
+
80
+ @app.route("/", methods=["GET", "POST"])
81
+ def index():
82
+ if request.method != "POST":
83
+ return render_template("index.html", e="")
84
 
85
+ if "image" not in request.files:
86
+ return render_template("index.html", e="No image selected.")
87
+
88
+ image_file = request.files["image"]
89
+ if not image_file or not allowed_file(image_file.filename):
90
+ return render_template("index.html", e="Invalid file type. Please upload PNG or JPG.")
91
+
92
+ try:
93
+ model = configure_gemini()
94
+
95
+ with tempfile.NamedTemporaryFile(delete=False) as temp_img:
96
+ image_file.save(temp_img.name)
97
+ image = Image.open(temp_img.name)
98
+
99
+ response = model.generate_content([PROMPT_TEMPLATE, image])
100
+ latex_code = response.text
101
+ os.unlink(temp_img.name)
102
+
103
+ # Handle chemfig diagrams
104
+ match = re.search(r"\\chemfig\{(.*?)\}", latex_code, re.DOTALL)
105
+ if match:
106
+ chemfig_code = match.group(1)
107
+ with tempfile.TemporaryDirectory() as tmpdirname:
108
+ svg_filename = generate_svg_from_chemfig(chemfig_code, tmpdirname)
109
+ return render_template("index.html",
110
+ e=f'<img src="/uploads/{svg_filename}" alt="Chemical structure">')
111
+
112
+ # Block potentially unsafe content
113
+ if any(keyword in latex_code.lower() for keyword in
114
+ ['.pdf', '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg']):
115
+ return render_template("index.html",
116
+ e="Sorry, images and PDFs are not yet supported in the response.")
117
+
118
+ return render_template("index.html", e=latex_code)
119
+
120
+ except Exception as error:
121
+ return render_template("index.html", e=f"Error processing request: {str(error)}")
122
 
123
  @app.route('/uploads/<filename>')
124
  def uploaded_file(filename):
125
  return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
126
 
 
127
  if __name__ == "__main__":
128
  app.run(debug=True)