Docfile commited on
Commit
3a063f3
·
verified ·
1 Parent(s): aee9275

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -166
app.py CHANGED
@@ -6,24 +6,20 @@ from PIL import Image
6
  import io
7
  import base64
8
  import json
9
- import re
10
  import requests
11
 
12
  app = Flask(__name__)
13
 
 
14
  GOOGLE_API_KEY = os.environ.get("GEMINI_API_KEY")
15
  TELEGRAM_BOT_TOKEN = "8004545342:AAGcZaoDjYg8dmbbXRsR1N3TfSSbEiAGz88"
 
16
 
17
- # Ajouter cette variable d'environnement
18
- TELEGRAM_CHAT_ID = "-1002497861230" # ID du chat où envoyer les images
19
 
20
- client = genai.Client(
21
- api_key=GOOGLE_API_KEY,
22
- )
23
-
24
-
25
- pp =r"""
26
- # 📝 GÉNÉRATEUR DE CORRECTION MATHÉMATIQUE (Version Directe)
27
 
28
  ## 🎓 VOTRE RÔLE
29
  Vous êtes **Mariam-MATHEX-PRO**, un expert en mathématiques chargé de fournir des corrections. Votre objectif est d'être clair, précis et d'aller droit au but.
@@ -32,7 +28,7 @@ Vous êtes **Mariam-MATHEX-PRO**, un expert en mathématiques chargé de fournir
32
 
33
  **ENTRÉE:** L'énoncé d'un exercice mathématique (niveau Terminale/Supérieur).
34
 
35
- **SORTIE:** UNIQUEMENT la correction de l'exercice **en français** avec rendu LaTeX et code Python.
36
 
37
  ## 🛠️ INSTRUCTIONS POUR LA CORRECTION
38
 
@@ -50,35 +46,41 @@ Vous êtes **Mariam-MATHEX-PRO**, un expert en mathématiques chargé de fournir
50
  4. **RÉSULTATS :**
51
  * Indiquez clairement les résultats intermédiaires si pertinent, et énoncez distinctement le résultat final de chaque question ou sous-question.
52
 
53
- ## 🔧 EXIGENCES TECHNIQUES
54
 
55
  5. **RENDU MATHÉMATIQUE :**
56
  * Utilisez le rendu LaTeX pour toutes les expressions mathématiques, équations et formules.
57
  * Formatez correctement les calculs avec la syntaxe LaTeX appropriée.
58
 
 
 
 
 
 
 
 
 
 
59
  6. **CALCULS ET FIGURES :**
60
  * Utilisez Python pour effectuer tous les calculs numériques et créer les graphiques nécessaires.
61
  * Pour chaque figure ou graphique : générez-le avec Python, sauvegardez-le comme fichier image, puis affichez l'image.
62
  * Intégrez le code Python dans la correction pour montrer la démarche de calcul.
 
63
 
64
- ## OBJECTIF PRINCIPAL
65
- Fournir une correction mathématique textuelle **en français** qui va **droit au but**. Chaque étape de calcul doit être détaillée avec rendu LaTeX, chaque explication doit être **très brève** et se concentrer sur le "comment" ou le "pourquoi" immédiat de l'opération mathématique. Utiliser Python pour les calculs numériques et la création de figures.
 
66
  """
67
 
68
  def send_to_telegram(image_data, caption="Nouvelle image uploadée"):
69
  """Envoie l'image à un chat Telegram spécifié"""
70
  try:
71
- # URL de l'API Telegram pour envoyer des photos
72
  url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendPhoto"
73
-
74
- # Préparer les données pour l'envoi
75
  files = {'photo': ('image.png', image_data)}
76
  data = {'chat_id': TELEGRAM_CHAT_ID, 'caption': caption}
77
 
78
- # Envoyer la requête
79
  response = requests.post(url, files=files, data=data)
80
 
81
- # Vérifier si l'envoi a réussi
82
  if response.status_code == 200:
83
  print("Image envoyée avec succès à Telegram")
84
  return True
@@ -89,190 +91,85 @@ def send_to_telegram(image_data, caption="Nouvelle image uploadée"):
89
  print(f"Exception lors de l'envoi à Telegram: {e}")
90
  return False
91
 
92
-
93
-
94
  @app.route('/')
95
  def index():
96
  return render_template('index.html')
97
 
98
- @app.route('/free')
99
- def indexx():
100
- return render_template('maj.html')
101
-
102
- def process_markdown_and_code(text):
103
- """Traite le texte pour identifier et formater le code et le markdown"""
104
- # Convertit le texte en HTML formaté
105
- # Cette fonction pourrait être étendue pour utiliser une bibliothèque de markdown
106
- return text
107
-
108
- def format_code_execution_result(response_parts):
109
- """Formate les résultats d'exécution de code pour l'affichage HTML"""
110
- result = []
111
-
112
- for part in response_parts:
113
- # Traitement du texte (équivalent à display(Markdown(part.text)))
114
- if hasattr(part, 'text') and part.text is not None:
115
- result.append({
116
- 'type': 'markdown',
117
- 'content': part.text
118
- })
119
-
120
- # Traitement du code exécutable
121
- if hasattr(part, 'executable_code') and part.executable_code is not None:
122
- result.append({
123
- 'type': 'code',
124
- 'content': part.executable_code.code
125
- })
126
-
127
- # Traitement des résultats d'exécution
128
- if hasattr(part, 'code_execution_result') and part.code_execution_result is not None:
129
- result.append({
130
- 'type': 'execution_result',
131
- 'content': part.code_execution_result.output
132
- })
133
-
134
- # Traitement des images (équivalent à display(Image(data=part.inline_data.data)))
135
- if hasattr(part, 'inline_data') and part.inline_data is not None:
136
- # Encodage de l'image en base64 pour l'affichage HTML
137
- img_data = base64.b64encode(part.inline_data.data).decode('utf-8')
138
- result.append({
139
- 'type': 'image',
140
- 'content': img_data,
141
- 'format': 'png' # Supposé comme png par défaut
142
- })
143
-
144
- return result
145
-
146
  @app.route('/solve', methods=['POST'])
147
  def solve():
148
  try:
 
149
  image_data = request.files['image'].read()
 
 
150
  img = Image.open(io.BytesIO(image_data))
151
- send_to_telegram(image_data, "Nouvelle image pour résolution (modèle avancé)")
 
 
 
152
 
 
153
  buffered = io.BytesIO()
154
  img.save(buffered, format="PNG")
155
  img_str = base64.b64encode(buffered.getvalue()).decode()
156
 
 
 
 
 
 
157
  def generate():
158
  mode = 'starting'
159
  try:
160
- response = client.models.generate_content_stream(
161
- model="gemini-2.5-pro",
162
- contents=[
163
- {'inline_data': {'mime_type': 'image/png', 'data': img_str}},
164
- pp
165
- ],
166
- config=types.GenerateContentConfig(
167
- thinking_config=types.ThinkingConfig(
168
- include_thoughts=True
169
- ),
170
- # Ajouter l'outil d'exécution de code
171
- tools=[types.Tool(
172
- code_execution=types.ToolCodeExecution
173
- )]
174
- )
175
  )
 
 
 
 
176
 
177
- for chunk in response:
178
- for part in chunk.candidates[0].content.parts:
179
- if hasattr(part, 'thought') and part.thought:
180
- if mode != "thinking":
181
- yield f'data: {json.dumps({"mode": "thinking"})}\n\n'
182
- mode = "thinking"
183
- else:
184
- if mode != "answering":
185
- yield f'data: {json.dumps({"mode": "answering"})}\n\n'
186
- mode = "answering"
187
-
188
- # Gestion des différents types de contenu
189
- if hasattr(part, 'text') and part.text is not None:
190
- yield f'data: {json.dumps({"content": part.text, "type": "text"})}\n\n'
191
-
192
- if hasattr(part, 'executable_code') and part.executable_code is not None:
193
- yield f'data: {json.dumps({"content": part.executable_code.code, "type": "code"})}\n\n'
194
-
195
- if hasattr(part, 'code_execution_result') and part.code_execution_result is not None:
196
- yield f'data: {json.dumps({"content": part.code_execution_result.output, "type": "result"})}\n\n'
197
-
198
- if hasattr(part, 'inline_data') and part.inline_data is not None:
199
- img_data = base64.b64encode(part.inline_data.data).decode('utf-8')
200
- yield f'data: {json.dumps({"content": img_data, "type": "image"})}\n\n'
201
-
202
- except Exception as e:
203
- print(f"Error during generation: {e}")
204
- yield f'data: {json.dumps({"error": "Une erreur inattendue est survenue"})}\n\n'
205
-
206
- return Response(
207
- stream_with_context(generate()),
208
- mimetype='text/event-stream',
209
- headers={
210
- 'Cache-Control': 'no-cache',
211
- 'X-Accel-Buffering': 'no'
212
- }
213
- )
214
-
215
- except Exception as e:
216
- return jsonify({'error':'Une erreur inattendue est survenue' }), 500
217
-
218
- @app.route('/solved', methods=['POST'])
219
- def solved():
220
- try:
221
- image_data = request.files['image'].read()
222
- img = Image.open(io.BytesIO(image_data))
223
- send_to_telegram(image_data, "Nouvelle image pour résolution (modèle standard)")
224
-
225
- buffered = io.BytesIO()
226
- img.save(buffered, format="PNG")
227
- img_str = base64.b64encode(buffered.getvalue()).decode()
228
-
229
- def generate():
230
- mode = 'starting'
231
- try:
232
  response = client.models.generate_content_stream(
233
  model="gemini-2.5-pro",
234
  contents=[
235
  {'inline_data': {'mime_type': 'image/png', 'data': img_str}},
236
- pp],
237
- config=types.GenerateContentConfig(
238
- thinking_config=types.ThinkingConfig(
239
- include_thoughts=True
240
- ),
241
- # Ajouter l'outil d'exécution de code
242
- tools=[types.Tool(
243
- code_execution=types.ToolCodeExecution
244
- )]
245
- )
246
  )
247
 
248
  for chunk in response:
249
  for part in chunk.candidates[0].content.parts:
 
250
  if hasattr(part, 'thought') and part.thought:
251
  if mode != "thinking":
252
  yield f'data: {json.dumps({"mode": "thinking"})}\n\n'
253
  mode = "thinking"
 
254
  else:
255
  if mode != "answering":
256
  yield f'data: {json.dumps({"mode": "answering"})}\n\n'
257
  mode = "answering"
258
-
259
- # Gestion des différents types de contenu
260
- if hasattr(part, 'text') and part.text is not None:
261
- yield f'data: {json.dumps({"content": part.text, "type": "text"})}\n\n'
262
-
263
- if hasattr(part, 'executable_code') and part.executable_code is not None:
264
- yield f'data: {json.dumps({"content": part.executable_code.code, "type": "code"})}\n\n'
265
-
266
- if hasattr(part, 'code_execution_result') and part.code_execution_result is not None:
267
- yield f'data: {json.dumps({"content": part.code_execution_result.output, "type": "result"})}\n\n'
268
-
269
- if hasattr(part, 'inline_data') and part.inline_data is not None:
270
- img_data = base64.b64encode(part.inline_data.data).decode('utf-8')
271
- yield f'data: {json.dumps({"content": img_data, "type": "image"})}\n\n'
272
 
273
  except Exception as e:
274
  print(f"Error during generation: {e}")
275
- yield f'data: {json.dumps({"error":"Une erreur inattendue est survenue"})}\n\n'
276
 
277
  return Response(
278
  stream_with_context(generate()),
@@ -284,7 +181,8 @@ def solved():
284
  )
285
 
286
  except Exception as e:
287
- return jsonify({'error':'Une erreur inattendue est survenue'}), 500
 
288
 
289
  if __name__ == '__main__':
290
  app.run(debug=True)
 
6
  import io
7
  import base64
8
  import json
 
9
  import requests
10
 
11
  app = Flask(__name__)
12
 
13
+ # API Keys
14
  GOOGLE_API_KEY = os.environ.get("GEMINI_API_KEY")
15
  TELEGRAM_BOT_TOKEN = "8004545342:AAGcZaoDjYg8dmbbXRsR1N3TfSSbEiAGz88"
16
+ TELEGRAM_CHAT_ID = "-1002497861230"
17
 
18
+ client = genai.Client(api_key=GOOGLE_API_KEY)
 
19
 
20
+ # Prompt de base pour la correction mathématique
21
+ BASE_PROMPT = r"""
22
+ # 🔍 GÉNÉRATEUR DE CORRECTION MATHÉMATIQUE (Version Directe)
 
 
 
 
23
 
24
  ## 🎓 VOTRE RÔLE
25
  Vous êtes **Mariam-MATHEX-PRO**, un expert en mathématiques chargé de fournir des corrections. Votre objectif est d'être clair, précis et d'aller droit au but.
 
28
 
29
  **ENTRÉE:** L'énoncé d'un exercice mathématique (niveau Terminale/Supérieur).
30
 
31
+ **SORTIE:** UNIQUEMENT la correction de l'exercice **en français** avec rendu LaTeX.
32
 
33
  ## 🛠️ INSTRUCTIONS POUR LA CORRECTION
34
 
 
46
  4. **RÉSULTATS :**
47
  * Indiquez clairement les résultats intermédiaires si pertinent, et énoncez distinctement le résultat final de chaque question ou sous-question.
48
 
49
+ ## 🔧 RENDU MATHÉMATIQUE
50
 
51
  5. **RENDU MATHÉMATIQUE :**
52
  * Utilisez le rendu LaTeX pour toutes les expressions mathématiques, équations et formules.
53
  * Formatez correctement les calculs avec la syntaxe LaTeX appropriée.
54
 
55
+ ## ✅ OBJECTIF PRINCIPAL
56
+ Fournir une correction mathématique textuelle **en français** qui va **droit au but**. Chaque étape de calcul doit être détaillée avec rendu LaTeX, chaque explication doit être **très brève** et se concentrer sur le "comment" ou le "pourquoi" immédiat de l'opération mathématique.
57
+ """
58
+
59
+ # Extension du prompt pour l'exécution de code
60
+ CODE_EXTENSION = r"""
61
+
62
+ ## 🐍 EXIGENCES TECHNIQUES (MODE CALCULATRICE ACTIVÉ)
63
+
64
  6. **CALCULS ET FIGURES :**
65
  * Utilisez Python pour effectuer tous les calculs numériques et créer les graphiques nécessaires.
66
  * Pour chaque figure ou graphique : générez-le avec Python, sauvegardez-le comme fichier image, puis affichez l'image.
67
  * Intégrez le code Python dans la correction pour montrer la démarche de calcul.
68
+ * Utilisez des bibliothèques comme numpy, matplotlib, sympy selon les besoins.
69
 
70
+ 7. **VÉRIFICATION NUMÉRIQUE :**
71
+ * Vérifiez vos calculs analytiques avec des calculs numériques en Python.
72
+ * Créez des visualisations graphiques pour illustrer les concepts mathématiques.
73
  """
74
 
75
  def send_to_telegram(image_data, caption="Nouvelle image uploadée"):
76
  """Envoie l'image à un chat Telegram spécifié"""
77
  try:
 
78
  url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendPhoto"
 
 
79
  files = {'photo': ('image.png', image_data)}
80
  data = {'chat_id': TELEGRAM_CHAT_ID, 'caption': caption}
81
 
 
82
  response = requests.post(url, files=files, data=data)
83
 
 
84
  if response.status_code == 200:
85
  print("Image envoyée avec succès à Telegram")
86
  return True
 
91
  print(f"Exception lors de l'envoi à Telegram: {e}")
92
  return False
93
 
 
 
94
  @app.route('/')
95
  def index():
96
  return render_template('index.html')
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  @app.route('/solve', methods=['POST'])
99
  def solve():
100
  try:
101
+ # Récupération des données
102
  image_data = request.files['image'].read()
103
+ use_calculator = request.form.get('use_calculator', 'false').lower() == 'true'
104
+
105
  img = Image.open(io.BytesIO(image_data))
106
+
107
+ # Envoyer l'image à Telegram avec indication du mode
108
+ caption = f"Nouvelle image pour résolution ({'avec calculatrice' if use_calculator else 'mode standard'})"
109
+ send_to_telegram(image_data, caption)
110
 
111
+ # Traitement pour Gemini
112
  buffered = io.BytesIO()
113
  img.save(buffered, format="PNG")
114
  img_str = base64.b64encode(buffered.getvalue()).decode()
115
 
116
+ # Construction du prompt selon le mode
117
+ prompt = BASE_PROMPT
118
+ if use_calculator:
119
+ prompt += CODE_EXTENSION
120
+
121
  def generate():
122
  mode = 'starting'
123
  try:
124
+ # Configuration de base
125
+ config = types.GenerateContentConfig(
126
+ temperature=0.3,
127
+ thinking_config=types.ThinkingConfig(include_thoughts=True)
 
 
 
 
 
 
 
 
 
 
 
128
  )
129
+
130
+ # Ajout des outils d'exécution de code si calculatrice activée
131
+ if use_calculator:
132
+ config.tools = [types.Tool(code_execution=types.ToolCodeExecution)]
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  response = client.models.generate_content_stream(
135
  model="gemini-2.5-pro",
136
  contents=[
137
  {'inline_data': {'mime_type': 'image/png', 'data': img_str}},
138
+ prompt
139
+ ],
140
+ config=config
 
 
 
 
 
 
 
141
  )
142
 
143
  for chunk in response:
144
  for part in chunk.candidates[0].content.parts:
145
+ # Gestion des pensées
146
  if hasattr(part, 'thought') and part.thought:
147
  if mode != "thinking":
148
  yield f'data: {json.dumps({"mode": "thinking"})}\n\n'
149
  mode = "thinking"
150
+ yield f'data: {json.dumps({"content": part.text, "type": "text"})}\n\n'
151
  else:
152
  if mode != "answering":
153
  yield f'data: {json.dumps({"mode": "answering"})}\n\n'
154
  mode = "answering"
155
+
156
+ # Gestion des différents types de contenu
157
+ if hasattr(part, 'text') and part.text is not None:
158
+ yield f'data: {json.dumps({"content": part.text, "type": "text"})}\n\n'
159
+
160
+ if hasattr(part, 'executable_code') and part.executable_code is not None:
161
+ yield f'data: {json.dumps({"content": part.executable_code.code, "type": "code"})}\n\n'
162
+
163
+ if hasattr(part, 'code_execution_result') and part.code_execution_result is not None:
164
+ yield f'data: {json.dumps({"content": part.code_execution_result.output, "type": "result"})}\n\n'
165
+
166
+ if hasattr(part, 'inline_data') and part.inline_data is not None:
167
+ img_data = base64.b64encode(part.inline_data.data).decode('utf-8')
168
+ yield f'data: {json.dumps({"content": img_data, "type": "image"})}\n\n'
169
 
170
  except Exception as e:
171
  print(f"Error during generation: {e}")
172
+ yield f'data: {json.dumps({"error": "Une erreur inattendue est survenue"})}\n\n'
173
 
174
  return Response(
175
  stream_with_context(generate()),
 
181
  )
182
 
183
  except Exception as e:
184
+ print(f"Error in solve endpoint: {e}")
185
+ return jsonify({'error': 'Une erreur inattendue est survenue'}), 500
186
 
187
  if __name__ == '__main__':
188
  app.run(debug=True)