Docfile commited on
Commit
b30ad3b
·
verified ·
1 Parent(s): 905c884

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -118
app.py CHANGED
@@ -1,128 +1,102 @@
1
- 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 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}}
64
- \\usepackage{{chemfig}}
65
- \\begin{{document}}
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)
 
1
+ from flask import Flask, render_template, request, send_file
2
  import google.generativeai as genai
3
  import os
 
 
 
4
  import re
5
+ from rdkit.Chem import MolFromSmiles, MolToImage
6
+ from rdkit.Chem.Draw import rdMolDraw2D
7
  import tempfile
8
+ import uuid
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ # Configuration de l'API Gemini
11
+ token = os.environ.get("TOKEN")
12
+ genai.configure(api_key=token)
13
+ generation_config = {
14
+ "temperature": 1,
15
+ "top_p": 0.95,
16
+ "top_k": 64,
17
+ "max_output_tokens": 8192,
18
+ }
19
+ safety_settings = [
20
+ {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
21
+ {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
22
+ {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
23
+ {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
24
+ ]
25
+ model = genai.GenerativeModel(
26
+ model_name="gemini-1.5-pro",
27
+ generation_config=generation_config,
28
+ safety_settings=safety_settings,
29
+ )
30
 
31
+ app = Flask(__name__)
 
 
 
 
 
 
 
32
 
33
+ # Dossier pour les images temporaires
34
+ app.config['UPLOAD_FOLDER'] = 'static/temp_images'
35
+ if not os.path.exists(app.config['UPLOAD_FOLDER']):
36
+ os.makedirs(app.config['UPLOAD_FOLDER'])
37
+
38
+ # Fonction pour extraire et traiter les structures chimiques
39
+ def process_chemfig(text):
40
+ chemfig_pattern = r"\\chemfig{(.*?)}"
41
+ matches = re.findall(chemfig_pattern, text)
42
+ image_paths = []
43
+
44
+ for match in matches:
45
+ # Supposons que la syntaxe est du SMILES simplifié ou une représentation compatible RDKit
46
+ try:
47
+ # mol = MolFromSmiles(match)
48
+ mol=MolFromSmiles(match)
49
+
50
+ if mol:
51
+ d = rdMolDraw2D.MolDraw2DCairo(500,500)
52
+ d.DrawMolecule(mol)
53
+ d.FinishDrawing()
54
+ image_filename = str(uuid.uuid4()) + '.png'
55
+ image_path = os.path.join(app.config['UPLOAD_FOLDER'], image_filename)
56
+ d.WriteDrawingText(image_path)
57
+ image_paths.append(image_path)
58
+ text = text.replace(f"\\chemfig{{{match}}}", f'<img src="/temp_images/{image_filename}" style="width:100%; height:auto;" alt="Structure Chimique">')
59
+ else:
60
+ text = text.replace(f"\\chemfig{{{match}}}", f'Structure Chimique non valide : {match}')
61
+ except Exception as e:
62
+ text = text.replace(f"\\chemfig{{{match}}}", f'Erreur lors du rendu de la structure : {e}')
63
+
64
+ return text, image_paths
65
+
66
+ # Route principale
67
+ @app.route('/', methods=['GET', 'POST'])
68
  def index():
69
+ generated_content = ""
70
+ image_paths = []
71
+ if request.method == 'POST':
72
+ image_file = request.files.get('image')
73
+ mm = """ resous cet exercice. tu répondras en détaillant au maximum ton procédé de calcul. réponse attendue uniquement en Latex
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
+ """
76
+ if image_file :
77
+ image_bytes = image_file.read()
78
+ parts=[
79
+ {
80
+ "mime_type":"image/jpeg",
81
+ "data": image_bytes
82
+ },
83
+ mm
84
+ ]
85
+ response = model.generate_content(parts)
86
+ generated_content = response.text
87
+ else:
88
+ text_input= request.form.get('text_input')
89
+ response = model.generate_content(mm+text_input)
90
+ generated_content = response.text
91
+
92
+ generated_content, image_paths = process_chemfig(generated_content)
93
+
94
+ return render_template('index.html', generated_content=generated_content, image_paths=image_paths)
95
+
96
+ # Route pour servir les images temporaires
97
+ @app.route('/temp_images/<filename>')
98
+ def temp_image(filename):
99
+ return send_file(os.path.join(app.config['UPLOAD_FOLDER'], filename), mimetype='image/png')
100
+
101
+ if __name__ == '__main__':
102
  app.run(debug=True)