Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -12,21 +12,57 @@ from pathlib import Path
|
|
12 |
|
13 |
app = Flask(__name__)
|
14 |
|
15 |
-
#
|
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 =
|
19 |
-
TELEGRAM_CHAT_ID =
|
20 |
|
21 |
-
|
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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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=
|
145 |
contents=[
|
146 |
{'inline_data': {'mime_type': 'image/png', 'data': img_str}},
|
147 |
-
"
|
148 |
],
|
149 |
-
config=types.GenerateContentConfig(temperature=0.
|
150 |
)
|
151 |
-
|
|
|
|
|
|
|
|
|
152 |
except Exception as e:
|
153 |
print(f"Error extracting problem text: {e}")
|
154 |
-
return
|
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.
|
161 |
-
|
162 |
)
|
163 |
-
|
164 |
-
|
|
|
|
|
165 |
contents=[prompt],
|
166 |
-
config=config
|
167 |
)
|
168 |
-
|
|
|
|
|
|
|
|
|
|
|
169 |
except Exception as e:
|
170 |
print(f"Error in agent step {step_name}: {e}")
|
171 |
-
return f"[
|
172 |
|
173 |
-
|
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
|
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 |
-
|
|
|
202 |
|
203 |
-
|
|
|
|
|
|
|
|
|
|
|
204 |
|
205 |
def generate():
|
206 |
try:
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
# Étape 3
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
yield f'data: {json.dumps({"content":
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
|
|
|
|
249 |
step5_prompt = agent_system.prompts["step5_correction"].replace(
|
250 |
-
"[The full verification report will be inserted here]",
|
251 |
).replace(
|
252 |
-
"[The previous solution attempt will be inserted here]",
|
253 |
)
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
yield f'data: {json.dumps({"content": correction_msg, "type": "text"})}\n\n'
|
258 |
else:
|
259 |
-
|
260 |
-
yield f'data: {json.dumps({"content":
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
except Exception as e:
|
269 |
-
|
270 |
-
|
271 |
-
yield f'data: {json.dumps({"error": error_message})}\n\n'
|
272 |
|
273 |
-
return Response(
|
|
|
|
|
|
|
|
|
274 |
|
275 |
except Exception as e:
|
276 |
-
|
277 |
-
|
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)
|