Docfile commited on
Commit
9352a41
·
verified ·
1 Parent(s): 2a68b81

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +172 -117
app.py CHANGED
@@ -12,21 +12,57 @@ from pathlib import Path
12
 
13
  app = Flask(__name__)
14
 
15
- # --- Configuration ---
16
- # Assurez-vous que ces variables d'environnement sont définies
17
  GOOGLE_API_KEY = os.environ.get("GEMINI_API_KEY")
18
- TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN")
19
- TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID")
20
 
21
- # Initialisation du client GenAI
22
- try:
23
- client = genai.Client(api_key=GOOGLE_API_KEY)
24
- MODEL_NAME = "gemini-2.5-flash" # Utilisons un modèle plus puissant pour ces tâches
25
- except Exception as e:
26
- print(f"Erreur lors de l'initialisation du client GenAI : {e}")
27
- client = None
28
 
29
- # --- Agent System (avec les prompts du PDF) ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  class AgentSystem:
32
  def __init__(self):
@@ -48,10 +84,8 @@ class AgentSystem:
48
  * Establishing a critical property of the mathematical objects in the problem.
49
  * For an optimization problem, proving an upper or lower bound without proving that this bound is achievable.
50
  * **Use TeX for All Mathematics:** All mathematical variables, expressions, and relations must be enclosed in TeX delimiters (e.g., `Let $n$ be an integer.`).
51
-
52
  ### Output Format ###
53
  Your response MUST be structured into the following sections, in this exact order.
54
-
55
  **1. Summary**
56
  Provide a concise overview of your findings. This section must contain two parts:
57
  * **a. Verdict:** State clearly whether you have found a complete solution or a partial solution.
@@ -61,31 +95,24 @@ Provide a concise overview of your findings. This section must contain two parts
61
  * A narrative of your overall strategy.
62
  * The full and precise mathematical statements of any key lemmas or major intermediate results.
63
  * If applicable, describe any key constructions or case splits that form the backbone of your argument.
64
-
65
  **2. Detailed Solution**
66
  Present the full, step-by-step mathematical proof. Each step must be logically justified and clearly explained. The level of detail should be sufficient for an expert to verify the correctness of your reasoning without needing to fill in any gaps. This section must contain ONLY the complete, rigorous proof, free of any internal commentary, alternative approaches, or failed attempts.
67
-
68
  ### Self-Correction Instruction ###
69
  Before finalizing your output, carefully review your "Method Sketch" and "Detailed Solution" to ensure they are clean, rigorous, and strictly adhere to all instructions provided above. Verify that every statement contributes directly to the final, coherent mathematical argument.
70
  """,
71
 
72
  "step2_self_improvement.md": r"""You are a world-class mathematician reviewing your own work. You have just produced the following draft solution to a problem. Your task is to critically analyze it for clarity, logical soundness, and potential simplifications. Produce a new, improved version of the solution. The goal is to elevate it to a publication-ready standard.
73
-
74
  ### Draft Solution ###
75
  [The initial solution attempt will be inserted here]
76
-
77
  ### Your Task ###
78
  Provide the improved version of the solution, adhering to the original problem's constraints and focusing on enhancing rigor and elegance.
79
  """,
80
 
81
  "step3_verification.md": r"""You are an expert mathematician and a meticulous grader for an International Mathematical Olympiad (IMO) level exam. Your primary task is to rigorously verify the provided mathematical solution. A solution is to be judged correct **only if every step is rigorously justified.** A solution that arrives at a correct final answer through flawed reasoning, educated guesses, or with gaps in its arguments must be flagged as incorrect or incomplete.
82
-
83
  ### Instructions ###
84
-
85
  **1. Core Instructions**
86
  * Your sole task is to find and report all issues in the provided solution. You must act as a **verifier**, NOT a solver. **Do NOT attempt to correct the errors or fill the gaps you find.**
87
  * You must perform a **step-by-step** check of the entire solution. This analysis will be presented in a **Detailed Verification Log**, where you justify your assessment of each step: for correct steps, a brief justification suffices; for steps with errors or gaps, you must provide a detailed explanation.
88
-
89
  **2. How to Handle Issues in the Solution**
90
  When you identify an issue in a step, you MUST first classify it into one of the following two categories and then follow the specified procedure.
91
  * **a. Critical Error:**
@@ -100,7 +127,6 @@ When you identify an issue in a step, you MUST first classify it into one of the
100
  * Explain the gap in the justification.
101
  * State that you will **assume the step's conclusion is true** for the sake of argument.
102
  * Then, proceed to verify all subsequent steps to check if the remainder of the argument is sound.
103
-
104
  **3. Output Format**
105
  Your response MUST be structured into two main sections: a **Summary** followed by the **Detailed Verification Log**.
106
  * **a. Summary**
@@ -114,13 +140,10 @@ Your response MUST be structured into two main sections: a **Summary** followed
114
  """,
115
 
116
  "step5_correction.md": r"""You are a brilliant mathematician working to solve a difficult problem. Your previous attempt at a solution has been reviewed, and a verification report has been generated. Your task is to carefully study the report and produce a new, corrected solution that addresses all the identified issues.
117
-
118
  ### Verification Report ###
119
  [The full verification report will be inserted here]
120
-
121
  ### Previous Solution ###
122
  [The previous solution attempt will be inserted here]
123
-
124
  ### Task ###
125
  Provide a new, complete, and rigorously justified solution. Ensure that every error and justification gap mentioned in the report is resolved. If you disagree with an item in the report, revise your solution to make the reasoning clearer and less ambiguous.
126
  """
@@ -137,55 +160,60 @@ Provide a new, complete, and rigorously justified solution. Ensure that every er
137
  print(f"Error loading prompts: {e}")
138
  return prompts
139
 
 
 
140
  def extract_problem_text(self, img_str):
141
- if not client: return "[Client not initialized]"
142
  try:
143
  response = client.models.generate_content(
144
- model=MODEL_NAME,
145
  contents=[
146
  {'inline_data': {'mime_type': 'image/png', 'data': img_str}},
147
- "Please extract the mathematical problem statement from this image. Provide ONLY the problem text, formatted in LaTeX. Include all conditions and questions. If the image contains text in another language, translate the problem statement to French."
148
  ],
149
- config=types.GenerateContentConfig(temperature=0.0)
150
  )
151
- return response.text.strip()
 
 
 
 
152
  except Exception as e:
153
  print(f"Error extracting problem text: {e}")
154
- return f"[Erreur d'extraction du problème: {e}]"
155
 
156
- def run_agent_step(self, step_name, prompt):
157
- if not client: return "[Client not initialized]"
158
  try:
159
  config = types.GenerateContentConfig(
160
- temperature=0.1, # Low temperature for rigor
161
- # Le "thinking budget" n'est pas directement exposée, mais les modèles Pro sont conçus pour des tâches longues
162
  )
163
- response = client.models.generate_content(
164
- model=MODEL_NAME,
 
 
165
  contents=[prompt],
166
- config=config,
167
  )
168
- return response.text.strip()
 
 
 
 
 
169
  except Exception as e:
170
  print(f"Error in agent step {step_name}: {e}")
171
- return f"[Erreur à l'étape {step_name}: {e}]"
172
 
173
- # --- Fonctions Telegram ---
174
-
175
- def send_to_telegram(image_data, caption="Nouvelle image reçue"):
176
- if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
177
- return False
178
  try:
179
  url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendPhoto"
180
  files = {'photo': ('image.png', image_data)}
181
  data = {'chat_id': TELEGRAM_CHAT_ID, 'caption': caption}
182
- response = requests.post(url, files=files, data=data, timeout=10)
183
  return response.status_code == 200
184
  except Exception as e:
185
  print(f"Exception Telegram: {e}")
186
  return False
187
-
188
- # --- Routes Flask ---
189
 
190
  @app.route('/')
191
  def index():
@@ -193,89 +221,116 @@ def index():
193
 
194
  @app.route('/solve', methods=['POST'])
195
  def solve():
196
- if not client:
197
- return jsonify({'error': 'Le client GenAI n\'est pas initialisé. Vérifiez votre clé API.'}), 500
198
-
199
  try:
200
  image_data = request.files['image'].read()
201
- send_to_telegram(image_data, "Image reçue pour résolution...")
 
202
 
203
- img_str = base64.b64encode(image_data).decode()
 
 
 
 
 
204
 
205
  def generate():
206
  try:
207
- agent_system = AgentSystem()
208
- current_solution = ""
209
-
210
- # --- Étape 0: Extraction du problème ---
211
- # Fixed: moved the string outside the f-string expression
212
- step0_msg = "### Étape 0 : Extraction de l'énoncé\nAnalyse de l'image..."
213
- yield f'data: {json.dumps({"content": step0_msg, "type": "header"})}\n\n'
214
-
215
- problem_text = agent_system.extract_problem_text(img_str)
216
- problem_msg = f"**Énoncé détecté :**\n\n{problem_text}\n\n---\n"
217
- yield f'data: {json.dumps({"content": problem_msg, "type": "text"})}\n\n'
218
-
219
- # --- Pipeline de raisonnement ---
220
- # Étape 1: Solution Initiale
221
- step1_msg = "### Étape 1 : Génération de la solution initiale\nLe modèle prépare une première version de la preuve..."
222
- yield f'data: {json.dumps({"content": step1_msg, "type": "header"})}\n\n'
223
-
224
- step1_prompt = agent_system.prompts["step1_initial_solution"] + f"\n\n### Problem ###\n{problem_text}"
225
- current_solution = agent_system.run_agent_step("1 (Initial)", step1_prompt)
226
-
227
- solution1_msg = f"**Solution Initiale :**\n\n{current_solution}\n\n---\n"
228
- yield f'data: {json.dumps({"content": solution1_msg, "type": "text"})}\n\n'
229
-
230
- # Itération de Vérification-Correction (ici, 1 seule itération pour la démo)
231
- MAX_ITERATIONS = 1
232
- for i in range(MAX_ITERATIONS):
233
- # Étape 3: Vérification
234
- step3_msg = f"### Étape 3.{i+1} : Vérification par l'expert\nAnalyse critique de la solution pour détecter les erreurs..."
235
- yield f'data: {json.dumps({"content": step3_msg, "type": "header"})}\n\n'
236
-
237
- step3_prompt = agent_system.prompts["step3_verification"] + f"\n\n### Problem ###\n{problem_text}\n\n### Solution to be verified ###\n{current_solution}"
238
- verification_report = agent_system.run_agent_step(f"3.{i+1} (Verification)", step3_prompt)
239
-
240
- verification_msg = f"**Rapport de vérification :**\n\n{verification_report}\n\n---\n"
241
- yield f'data: {json.dumps({"content": verification_msg, "type": "text"})}\n\n'
242
-
243
- # Vérifier si une correction est nécessaire
244
- if "critical error" in verification_report.lower() or "justification gap" in verification_report.lower():
245
- # Étape 5: Correction
246
- step5_msg = f"### Étape 5.{i+1} : Correction de la solution\nLe modèle utilise le rapport pour corriger sa preuve..."
247
- yield f'data: {json.dumps({"content": step5_msg, "type": "header"})}\n\n'
248
-
 
 
249
  step5_prompt = agent_system.prompts["step5_correction"].replace(
250
- "[The full verification report will be inserted here]", verification_report
251
  ).replace(
252
- "[The previous solution attempt will be inserted here]", current_solution
253
  )
254
- current_solution = agent_system.run_agent_step(f"5.{i+1} (Correction)", step5_prompt)
255
-
256
- correction_msg = f"**Solution Corrigée :**\n\n{current_solution}\n\n---\n"
257
- yield f'data: {json.dumps({"content": correction_msg, "type": "text"})}\n\n'
258
  else:
259
- success_msg = "✅ Le rapport de vérification n'a trouvé aucune erreur critique. La solution est considérée comme valide."
260
- yield f'data: {json.dumps({"content": success_msg, "type": "header"})}\n\n'
261
- break
262
-
263
- # --- Affichage Final ---
264
- final_header_msg = "# Solution Finale Validée\nVoici la version finale de la correction."
265
- yield f'data: {json.dumps({"content": final_header_msg, "type": "header"})}\n\n'
266
- yield f'data: {json.dumps({"content": current_solution, "type": "final"})}\n\n'
267
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  except Exception as e:
269
- error_message = f"Une erreur est survenue pendant la génération : {e}"
270
- print(error_message)
271
- yield f'data: {json.dumps({"error": error_message})}\n\n'
272
 
273
- return Response(stream_with_context(generate()), mimetype='text/event-stream')
 
 
 
 
274
 
275
  except Exception as e:
276
- error_message = f"Erreur dans le endpoint /solve : {e}"
277
- print(error_message)
278
- return jsonify({'error': error_message}), 500
279
 
280
  if __name__ == '__main__':
281
  app.run(debug=True)
 
12
 
13
  app = Flask(__name__)
14
 
15
+ # API Keys
 
16
  GOOGLE_API_KEY = os.environ.get("GEMINI_API_KEY")
17
+ TELEGRAM_BOT_TOKEN = "8004545342:AAGcZaoDjYg8dmbbXRsR1N3TfSSbEiAGz88"
18
+ TELEGRAM_CHAT_ID = "-1002497861230"
19
 
20
+ client = genai.Client(api_key=GOOGLE_API_KEY)
 
 
 
 
 
 
21
 
22
+ # Prompt de base
23
+ BASE_PROMPT = r"""
24
+ # 🔍 GÉNÉRATEUR DE CORRECTION MATHÉMATIQUE (Version Directe)
25
+
26
+ ## 🎓 VOTRE RÔLE
27
+ 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
+ ## 📊 FORMAT D'ENTRÉE ET SORTIE
30
+ **ENTRÉE:** L'énoncé d'un exercice mathématique (niveau Terminale/Supérieur).
31
+ **SORTIE:** UNIQUEMENT la correction de l'exercice **en français** avec rendu LaTeX.
32
+
33
+ ## 🛠️ INSTRUCTIONS POUR LA CORRECTION
34
+ 1. **STRUCTURATION DE LA RÉPONSE :**
35
+ Organisez la solution en étapes logiques claires.
36
+ Si l'exercice comporte plusieurs questions ou parties, traitez-les séquentiellement.
37
+
38
+ 2. **DÉTAIL DU PROCÉDÉ DE CALCUL :**
39
+ Pour chaque étape significative, montrez les calculs.
40
+ Écrivez les calculs intermédiaires importants.
41
+
42
+ 3. **EXPLICATIONS TRÈS BRÈVES :**
43
+ Chaque étape doit avoir une explication textuelle très concise.
44
+
45
+ 4. **RÉSULTATS :**
46
+ Indiquez clairement les résultats intermédiaires et le résultat final.
47
+
48
+ ## 🔧 RENDU MATHÉMATIQUE
49
+ 5. **RENDU MATHÉMATIQUE :**
50
+ Utilisez LaTeX pour toutes les expressions mathématiques.
51
+
52
+ ## ✅ OBJECTIF PRINCIPAL
53
+ Fournir une correction mathématique textuelle **en français** qui va droit au but.
54
+ """
55
+
56
+ # Extension du prompt
57
+ CODE_EXTENSION = r"""
58
+ ## 🧮 EXIGENCES TECHNIQUES (MODE CALCULATRICE ACTIVÉ)
59
+
60
+ 6. **CALCULS ET FIGURES :**
61
+ Utilisez Python pour tous les calculs numériques et graphiques.
62
+
63
+ 7. **VÉRIFICATION NUMÉRIQUE :**
64
+ Vérifiez vos calculs analytiques par du numérique en Python.
65
+ """
66
 
67
  class AgentSystem:
68
  def __init__(self):
 
84
  * Establishing a critical property of the mathematical objects in the problem.
85
  * For an optimization problem, proving an upper or lower bound without proving that this bound is achievable.
86
  * **Use TeX for All Mathematics:** All mathematical variables, expressions, and relations must be enclosed in TeX delimiters (e.g., `Let $n$ be an integer.`).
 
87
  ### Output Format ###
88
  Your response MUST be structured into the following sections, in this exact order.
 
89
  **1. Summary**
90
  Provide a concise overview of your findings. This section must contain two parts:
91
  * **a. Verdict:** State clearly whether you have found a complete solution or a partial solution.
 
95
  * A narrative of your overall strategy.
96
  * The full and precise mathematical statements of any key lemmas or major intermediate results.
97
  * If applicable, describe any key constructions or case splits that form the backbone of your argument.
 
98
  **2. Detailed Solution**
99
  Present the full, step-by-step mathematical proof. Each step must be logically justified and clearly explained. The level of detail should be sufficient for an expert to verify the correctness of your reasoning without needing to fill in any gaps. This section must contain ONLY the complete, rigorous proof, free of any internal commentary, alternative approaches, or failed attempts.
 
100
  ### Self-Correction Instruction ###
101
  Before finalizing your output, carefully review your "Method Sketch" and "Detailed Solution" to ensure they are clean, rigorous, and strictly adhere to all instructions provided above. Verify that every statement contributes directly to the final, coherent mathematical argument.
102
  """,
103
 
104
  "step2_self_improvement.md": r"""You are a world-class mathematician reviewing your own work. You have just produced the following draft solution to a problem. Your task is to critically analyze it for clarity, logical soundness, and potential simplifications. Produce a new, improved version of the solution. The goal is to elevate it to a publication-ready standard.
 
105
  ### Draft Solution ###
106
  [The initial solution attempt will be inserted here]
 
107
  ### Your Task ###
108
  Provide the improved version of the solution, adhering to the original problem's constraints and focusing on enhancing rigor and elegance.
109
  """,
110
 
111
  "step3_verification.md": r"""You are an expert mathematician and a meticulous grader for an International Mathematical Olympiad (IMO) level exam. Your primary task is to rigorously verify the provided mathematical solution. A solution is to be judged correct **only if every step is rigorously justified.** A solution that arrives at a correct final answer through flawed reasoning, educated guesses, or with gaps in its arguments must be flagged as incorrect or incomplete.
 
112
  ### Instructions ###
 
113
  **1. Core Instructions**
114
  * Your sole task is to find and report all issues in the provided solution. You must act as a **verifier**, NOT a solver. **Do NOT attempt to correct the errors or fill the gaps you find.**
115
  * You must perform a **step-by-step** check of the entire solution. This analysis will be presented in a **Detailed Verification Log**, where you justify your assessment of each step: for correct steps, a brief justification suffices; for steps with errors or gaps, you must provide a detailed explanation.
 
116
  **2. How to Handle Issues in the Solution**
117
  When you identify an issue in a step, you MUST first classify it into one of the following two categories and then follow the specified procedure.
118
  * **a. Critical Error:**
 
127
  * Explain the gap in the justification.
128
  * State that you will **assume the step's conclusion is true** for the sake of argument.
129
  * Then, proceed to verify all subsequent steps to check if the remainder of the argument is sound.
 
130
  **3. Output Format**
131
  Your response MUST be structured into two main sections: a **Summary** followed by the **Detailed Verification Log**.
132
  * **a. Summary**
 
140
  """,
141
 
142
  "step5_correction.md": r"""You are a brilliant mathematician working to solve a difficult problem. Your previous attempt at a solution has been reviewed, and a verification report has been generated. Your task is to carefully study the report and produce a new, corrected solution that addresses all the identified issues.
 
143
  ### Verification Report ###
144
  [The full verification report will be inserted here]
 
145
  ### Previous Solution ###
146
  [The previous solution attempt will be inserted here]
 
147
  ### Task ###
148
  Provide a new, complete, and rigorously justified solution. Ensure that every error and justification gap mentioned in the report is resolved. If you disagree with an item in the report, revise your solution to make the reasoning clearer and less ambiguous.
149
  """
 
160
  print(f"Error loading prompts: {e}")
161
  return prompts
162
 
163
+
164
+
165
  def extract_problem_text(self, img_str):
 
166
  try:
167
  response = client.models.generate_content(
168
+ model="gemini-2.5-flash",
169
  contents=[
170
  {'inline_data': {'mime_type': 'image/png', 'data': img_str}},
171
+ "Extract the mathematical problem statement from this image. Provide only the problem text in LaTeX."
172
  ],
173
+ config=types.GenerateContentConfig(temperature=0.1)
174
  )
175
+ problem_text = ""
176
+ for part in response.candidates[0].content.parts:
177
+ if hasattr(part, 'text') and part.text:
178
+ problem_text += part.text
179
+ return problem_text.strip()
180
  except Exception as e:
181
  print(f"Error extracting problem text: {e}")
182
+ return "[Problem extraction failed]"
183
 
184
+ def run_agent_step(self, step_name, prompt, use_calculator=False):
 
185
  try:
186
  config = types.GenerateContentConfig(
187
+ temperature=0.3,
188
+ thinking_config=types.ThinkingConfig(include_thoughts=True)
189
  )
190
+ if use_calculator:
191
+ config.tools = [types.Tool(code_execution=types.ToolCodeExecution)]
192
+ response = client.models.generate_content_stream(
193
+ model="gemini-2.5-flash",
194
  contents=[prompt],
195
+ config=config
196
  )
197
+ result = ""
198
+ for chunk in response:
199
+ for part in chunk.candidates[0].content.parts:
200
+ if hasattr(part, 'text') and part.text:
201
+ result += part.text
202
+ return result.strip()
203
  except Exception as e:
204
  print(f"Error in agent step {step_name}: {e}")
205
+ return f"[Error in {step_name}: {str(e)}]"
206
 
207
+ def send_to_telegram(image_data, caption="Nouvelle image uploadée"):
 
 
 
 
208
  try:
209
  url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendPhoto"
210
  files = {'photo': ('image.png', image_data)}
211
  data = {'chat_id': TELEGRAM_CHAT_ID, 'caption': caption}
212
+ response = requests.post(url, files=files, data=data)
213
  return response.status_code == 200
214
  except Exception as e:
215
  print(f"Exception Telegram: {e}")
216
  return False
 
 
217
 
218
  @app.route('/')
219
  def index():
 
221
 
222
  @app.route('/solve', methods=['POST'])
223
  def solve():
 
 
 
224
  try:
225
  image_data = request.files['image'].read()
226
+ use_calculator = request.form.get('use_calculator', 'false').lower() == 'true'
227
+ use_extended_reasoning = request.form.get('use_extended_reasoning', 'false').lower() == 'true'
228
 
229
+ img = Image.open(io.BytesIO(image_data))
230
+ send_to_telegram(image_data, "Nouvelle image reçue")
231
+
232
+ buffered = io.BytesIO()
233
+ img.save(buffered, format="PNG")
234
+ img_str = base64.b64encode(buffered.getvalue()).decode()
235
 
236
  def generate():
237
  try:
238
+ if use_extended_reasoning:
239
+ agent_system = AgentSystem()
240
+
241
+ # Étape 0: Extraction
242
+ yield f'data: {json.dumps({"mode": "thinking"})}\n\n'
243
+ yield f'data: {json.dumps({"content": "# 🔍 EXTRACTION DU PROBLÈME\n\nAnalyse de l’image pour extraire l’énoncé du problème...\n\n", "type": "text"})}\n\n'
244
+
245
+ problem_text = agent_system.extract_problem_text(img_str)
246
+ yield f'data: {json.dumps({"content": f"**Problème identifié:**\n{problem_text}\n\n", "type": "text"})}\n\n'
247
+
248
+ # Étape 1
249
+ yield f'data: {json.dumps({"content": "# 📝 ÉTAPE 1: SOLUTION INITIALE\n\n", "type": "text"})}\n\n'
250
+ step1_prompt = agent_system.prompts["step1_initial_solution"].replace(
251
+ "[The mathematical problem will be inserted here]", problem_text
252
+ )
253
+ initial_solution = agent_system.run_agent_step("step1", step1_prompt, use_calculator)
254
+ yield f'data: {json.dumps({"content": initial_solution, "type": "text"})}\n\n'
255
+
256
+ # Étape 2
257
+ yield f'data: {json.dumps({"content": "# 🔧 ÉTAPE 2: AUTO-AMÉLIORATION\n\n", "type": "text"})}\n\n'
258
+ step2_prompt = agent_system.prompts["step2_self_improvement"].replace(
259
+ "[The initial solution attempt will be inserted here]", initial_solution
260
+ )
261
+ improved_solution = agent_system.run_agent_step("step2", step2_prompt, use_calculator)
262
+ yield f'data: {json.dumps({"content": improved_solution, "type": "text"})}\n\n'
263
+
264
+ # Étape 3
265
+ yield f'data: {json.dumps({"content": "# ÉTAPE 3: VÉRIFICATION\n\n", "type": "text"})}\n\n'
266
+ step3_prompt = agent_system.prompts["step3_verification"].replace(
267
+ "[The mathematical problem will be inserted here]", problem_text
268
+ ).replace(
269
+ "[The solution to be verified will be inserted here]", improved_solution
270
+ )
271
+ verification_result = agent_system.run_agent_step("step3", step3_prompt, False)
272
+ yield f'data: {json.dumps({"content": verification_result, "type": "text"})}\n\n'
273
+
274
+ needs_correction = (
275
+ "Critical Error" in verification_result
276
+ or "Justification Gap" in verification_result
277
+ or "invalid" in verification_result.lower()
278
+ )
279
+
280
+ if needs_correction:
281
+ yield f'data: {json.dumps({"content": "# 🛠️ ÉTAPE 5: CORRECTION\n\n", "type": "text"})}\n\n'
282
  step5_prompt = agent_system.prompts["step5_correction"].replace(
283
+ "[The full verification report will be inserted here]", verification_result
284
  ).replace(
285
+ "[The previous solution attempt will be inserted here]", improved_solution
286
  )
287
+ corrected_solution = agent_system.run_agent_step("step5", step5_prompt, use_calculator)
288
+ final_solution = corrected_solution
289
+ yield f'data: {json.dumps({"content": corrected_solution, "type": "text"})}\n\n'
 
290
  else:
291
+ final_solution = improved_solution
292
+ yield f'data: {json.dumps({"content": "✅ La solution a été validée sans correction.\n\n", "type": "text"})}\n\n'
293
+
294
+ yield f'data: {json.dumps({"mode": "answering"})}\n\n'
295
+ yield f'data: {json.dumps({"content": "# 📋 SOLUTION FINALE\n\n", "type": "text"})}\n\n'
296
+ yield f'data: {json.dumps({"content": final_solution, "type": "text"})}\n\n'
297
+
298
+ else:
299
+ prompt = BASE_PROMPT
300
+ if use_calculator:
301
+ prompt += CODE_EXTENSION
302
+ config = types.GenerateContentConfig(
303
+ temperature=0.3,
304
+ thinking_config=types.ThinkingConfig(include_thoughts=True)
305
+ )
306
+ if use_calculator:
307
+ config.tools = [types.Tool(code_execution=types.ToolCodeExecution)]
308
+ response = client.models.generate_content_stream(
309
+ model="gemini-2.5-flash",
310
+ contents=[
311
+ {'inline_data': {'mime_type': 'image/png', 'data': img_str}},
312
+ prompt
313
+ ],
314
+ config=config
315
+ )
316
+ for chunk in response:
317
+ for part in chunk.candidates[0].content.parts:
318
+ if hasattr(part, 'text') and part.text:
319
+ yield f'data: {json.dumps({"content": part.text, "type": "text"})}\n\n'
320
+
321
  except Exception as e:
322
+ print(f"Error during generation: {e}")
323
+ yield f'data: {json.dumps({"error": "Erreur inattendue"})}\n\n'
 
324
 
325
+ return Response(
326
+ stream_with_context(generate()),
327
+ mimetype='text/event-stream',
328
+ headers={'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no'}
329
+ )
330
 
331
  except Exception as e:
332
+ print(f"Error in solve endpoint: {e}")
333
+ return jsonify({'error': 'Erreur inattendue'}), 500
 
334
 
335
  if __name__ == '__main__':
336
  app.run(debug=True)