File size: 25,727 Bytes
51cbadd
f388c93
 
 
5309523
 
 
f388c93
 
 
5309523
f388c93
 
 
f823460
 
 
5309523
f823460
5309523
f388c93
5309523
 
 
58f7bb8
 
 
 
 
 
 
 
5309523
58f7bb8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5309523
 
 
 
 
 
58f7bb8
5309523
 
 
 
 
58f7bb8
5309523
 
 
 
 
 
 
 
 
 
 
58f7bb8
 
5309523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58f7bb8
5309523
 
 
58f7bb8
5309523
 
58f7bb8
5309523
 
 
 
 
 
58f7bb8
5309523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58f7bb8
f823460
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f388c93
 
1382a57
f388c93
 
 
 
5309523
51cbadd
5309523
 
 
f388c93
5309523
 
 
 
 
 
 
 
 
 
f823460
 
f388c93
 
 
 
51cbadd
e79be93
51cbadd
5309523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e79be93
5309523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2ef19ee
5309523
8355eb9
5309523
ba8aa19
dd8fd52
5309523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2ef19ee
 
 
f2c8b1b
5309523
2ef19ee
 
 
 
 
 
 
 
 
 
5309523
 
2ef19ee
f388c93
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
from flask import Flask, render_template, request, jsonify, Response, stream_with_context
from google import genai
from google.genai import types
import os
import json
import requests
import time
from PIL import Image
import io
import base64
from pathlib import Path

app = Flask(__name__)

# API Keys
GOOGLE_API_KEY = os.environ.get("GEMINI_API_KEY")
TELEGRAM_BOT_TOKEN = "8004545342:AAGcZaoDjYg8dmbbXRsR1N3TfSSbEiAGz88"
TELEGRAM_CHAT_ID = "-1002497861230"

client = genai.Client(api_key=GOOGLE_API_KEY)

# Prompt de base pour la correction mathématique
BASE_PROMPT = r"""
# 🔍 GÉNÉRATEUR DE CORRECTION MATHÉMATIQUE (Version Directe)

## 🎓 VOTRE RÔLE
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.

## 📊 FORMAT D'ENTRÉE ET SORTIE

**ENTRÉE:** L'énoncé d'un exercice mathématique (niveau Terminale/Supérieur).

**SORTIE:** UNIQUEMENT la correction de l'exercice **en français** avec rendu LaTeX.

## 🛠️ INSTRUCTIONS POUR LA CORRECTION

1.  **STRUCTURATION DE LA RÉPONSE :**
    *   Organisez la solution en étapes logiques claires. Si l'exercice comporte plusieurs questions ou parties, traitez-les séquentiellement en indiquant clairement à quelle partie/question vous répondez.

2.  **DÉTAIL DU PROCÉDÉ DE CALCUL :**
    *   Pour chaque étape significative du raisonnement ou du calcul, montrez le développement.
    *   Ne sautez pas d'étapes de calcul cruciales pour la compréhension. Écrivez les calculs intermédiaires importants.

3.  **EXPLICATIONS TRÈS BRÈVES :**
    *   Accompagnez chaque étape clé du calcul ou du raisonnement d'une explication textuelle très concise et directe. Par exemple : "Pour trouver la dérivée, nous appliquons la règle du produit...", "En substituant x=2 dans l'équation...", "Après simplification des termes, on obtient...".
    *   Une seule idée principale ou étape de calcul par segment de texte.

4.  **RÉSULTATS :**
    *   Indiquez clairement les résultats intermédiaires si pertinent, et énoncez distinctement le résultat final de chaque question ou sous-question.

## 🔧 RENDU MATHÉMATIQUE

5.  **RENDU MATHÉMATIQUE :**
    *   Utilisez le rendu LaTeX pour toutes les expressions mathématiques, équations et formules.
    *   Formatez correctement les calculs avec la syntaxe LaTeX appropriée.

## ✅ OBJECTIF PRINCIPAL
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.
"""

# Extension du prompt pour l'exécution de code
CODE_EXTENSION = r"""

## 🧮 EXIGENCES TECHNIQUES (MODE CALCULATRICE ACTIVÉ)

6.  **CALCULS ET FIGURES :**
    *   Utilisez Python pour effectuer tous les calculs numériques et créer les graphiques nécessaires.
    *   Pour chaque figure ou graphique : générez-le avec Python, sauvegardez-le comme fichier image, puis affichez l'image.
    *   Intégrez le code Python dans la correction pour montrer la démarche de calcul.
    *   Utilisez des bibliothèques comme numpy, matplotlib, sympy selon les besoins.

7.  **VÉRIFICATION NUMÉRIQUE :**
    *   Vérifiez vos calculs analytiques avec des calculs numériques en Python.
    *   Créez des visualisations graphiques pour illustrer les concepts mathématiques.
"""

class AgentSystem:
    def __init__(self):
        self.prompts_dir = Path("prompts")
        self.prompts = self.load_prompts()
    
    def load_prompts(self):
        """Load all agent prompts from files"""
        prompts = {}
        try:
            # Create prompts directory if it doesn't exist
            self.prompts_dir.mkdir(exist_ok=True)
            
            # Define default prompts if files don't exist
            default_prompts = {
                "step1_initial_solution.md": """### Core Instructions ###

*   **Rigor is Paramount:** Your primary goal is to produce a complete and rigorously justified solution. Every step in your solution must be logically sound and clearly explained. A correct final answer derived from flawed or incomplete reasoning is considered a failure.
*   **Honesty About Completeness:** If you cannot find a complete solution, you must **not** guess or create a solution that appears correct but contains hidden flaws or justification gaps. Instead, you should present only significant partial results that you can rigorously prove. A partial result is considered significant if it represents a substantial advancement toward a full solution. Examples include:
    *   Proving a key lemma.
    *   Fully resolving one or more cases within a logically sound case-based proof.
*   **Use TeX for All Mathematics:** All mathematical variables, expressions, and relations must be enclosed in TeX delimiters (e.g., 'Let $n$ be an integer.').

### Output Format ###

Your response MUST be structured into the following sections, in this exact order.

**1. Summary**

Provide a concise overview of your findings. This section must contain two parts:

*   **a. Verdict:** State clearly whether you have found a complete solution or a partial solution.
    *   **For a complete solution:** State the final answer, e.g., "I have successfully solved the problem. The final answer is..."
    *   **For a partial solution:** State the main rigorous conclusion(s) you were able to prove, e.g., "I have not found a complete solution, but I have rigorously proven that..."
*   **b. Method Sketch:** Present a high-level, conceptual outline of your solution. This sketch should allow an expert to understand the logical flow of your argument without reading the full detail. It should include:
    *   A narrative of your overall strategy.
    *   The full and precise mathematical statements of any key lemmas or major intermediate results.
    *   If applicable, describe any key constructions or case splits that form the backbone of your argument.

**2. Detailed Solution**

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.

### Self-Correction Instruction ###

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.

### Problem ###
[The mathematical problem will be inserted here]""",

                "step2_self_improvement.md": """You are a world-class mathematician. You have just produced the following draft solution.
Your task is to review it carefully, identify any potential flaws, gaps in logic, or areas that could be explained more clearly.
Then, produce a new, improved, and more rigorous version of the solution.

### Draft Solution ###
[The initial solution attempt will be inserted here]

### Your Task ###
Provide the improved and finalized version of the solution. Do not include comments about the changes, just the final, clean proof.""",

                "step3_verification.md": """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.

### Instructions ###

**1. Core Instructions**
*   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.**
*   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.

**2. How to Handle Issues in the Solution**
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.

*   **a. Critical Error:**
    This is any error that breaks the logical chain of the proof. This includes both **logical fallacies** (e.g., claiming that 'A>B, C>D' implies 'A-C>B-D') and **factual errors** (e.g., a calculation error like '2+3=6').
    *   **Procedure:**
        *   Explain the specific error and state that it **invalidates the current line of reasoning**.
        *   Do NOT check any further steps that rely on this error.
        *   You MUST, however, scan the rest of the solution to identify and verify any fully independent parts. For example, if a proof is split into multiple cases, an error in one case does not prevent you from checking the other cases.

*   **b. Justification Gap:**
    This is for steps where the conclusion may be correct, but the provided argument is incomplete, hand-wavy, or lacks sufficient rigor.
    *   **Procedure:**
        *   Explain the gap in the justification.
        *   State that you will **assume the step's conclusion is true** for the sake of argument.
        *   Then, proceed to verify all subsequent steps to check if the remainder of the argument is sound.

**3. Output Format**
Your response MUST be structured into two main sections: a **Summary** followed by the **Detailed Verification Log**.

*   **a. Summary**
    This section MUST be at the very beginning of your response. It must contain two components:
    *   **Final Verdict:** A single, clear sentence declaring the overall validity of the solution. For example: "The solution is correct," "The solution contains a Critical Error and is therefore invalid," or "The solution's approach is viable but contains several Justification Gaps."
    *   **List of Findings:** A bulleted list that summarizes **every** issue you discovered. For each finding, you must provide:
        *   **Location:** A direct quote of the key phrase or equation where the issue occurs.
        *   **Issue:** A brief description of the problem and its classification (**Critical Error** or **Justification Gap**).

*   **b. Detailed Verification Log**
    Following the summary, provide the full, step-by-step verification log as defined in the Core Instructions. When you refer to a specific part of the solution, **quote the relevant text** to make your reference clear before providing your detailed analysis of that part.

---
### Problem ###
[The mathematical problem will be inserted here]

---
### Solution ###
[The solution to be verified will be inserted here]

---
### Verification Task Reminder ###
Your task is to act as an IMO grader. Now, generate the **summary** and the **step-by-step verification log** for the solution above. In your log, justify each correct step and explain in detail any errors or justification gaps you find, as specified in the instructions above.""",

                "step5_correction.md": """You are a brilliant mathematician attempting to solve a difficult problem.
Your previous solution attempt has been reviewed by a verifier, who produced the report below.
Your task is to write a new, corrected version of your solution that meticulously addresses all the issues raised in the report.

### Verification Report on Your Last Attempt ###
[The full verification report will be inserted here]

### Your Previous Flawed Solution ###
[The previous solution attempt will be inserted here]

### Your Task ###
Provide a new, complete, and rigorously correct solution that fixes all identified issues. Remember to follow the structured output format (Summary and Detailed Solution) requested in the original problem."""
            }
            
            # Create prompt files if they don't exist
            for filename, content in default_prompts.items():
                prompt_file = self.prompts_dir / filename
                if not prompt_file.exists():
                    prompt_file.write_text(content, encoding='utf-8')
                
                prompts[filename.replace('.md', '')] = content
                
            # Load existing prompts
            for prompt_file in self.prompts_dir.glob("*.md"):
                prompts[prompt_file.stem] = prompt_file.read_text(encoding='utf-8')
                
        except Exception as e:
            print(f"Error loading prompts: {e}")
            # Fallback to hardcoded prompts
            prompts = {
                "step1_initial_solution": default_prompts["step1_initial_solution.md"],
                "step2_self_improvement": default_prompts["step2_self_improvement.md"],
                "step3_verification": default_prompts["step3_verification.md"],
                "step5_correction": default_prompts["step5_correction.md"]
            }
        
        return prompts
    
    def extract_problem_text(self, img_str):
        """Extract problem text from image using Gemini"""
        try:
            response = client.models.generate_content(
                model="gemini-2.5-flash",
                contents=[
                    {'inline_data': {'mime_type': 'image/png', 'data': img_str}},
                    "Extract the mathematical problem statement from this image. Provide only the problem text in LaTeX format where appropriate, without any solution or commentary."
                ],
                config=types.GenerateContentConfig(temperature=0.1)
            )
            
            problem_text = ""
            for part in response.candidates[0].content.parts:
                if hasattr(part, 'text') and part.text:
                    problem_text += part.text
            
            return problem_text.strip()
        except Exception as e:
            print(f"Error extracting problem text: {e}")
            return "[Problem extraction failed]"
    
    def run_agent_step(self, step_name, prompt, use_calculator=False):
        """Run a single agent step"""
        try:
            config = types.GenerateContentConfig(
                temperature=0.3,
                thinking_config=types.ThinkingConfig(include_thoughts=True)
            )
            
            if use_calculator:
                config.tools = [types.Tool(code_execution=types.ToolCodeExecution)]
            
            response = client.models.generate_content_stream(
                model="gemini-2.5-flash",
                contents=[prompt],
                config=config
            )
            
            result = ""
            for chunk in response:
                for part in chunk.candidates[0].content.parts:
                    if hasattr(part, 'text') and part.text:
                        result += part.text
            
            return result.strip()
            
        except Exception as e:
            print(f"Error in agent step {step_name}: {e}")
            return f"[Error in {step_name}: {str(e)}]"

def send_to_telegram(image_data, caption="Nouvelle image uploadée"):
    """Envoie l'image à un chat Telegram spécifié"""
    try:
        url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendPhoto"
        files = {'photo': ('image.png', image_data)}
        data = {'chat_id': TELEGRAM_CHAT_ID, 'caption': caption}
        
        response = requests.post(url, files=files, data=data)
        
        if response.status_code == 200:
            print("Image envoyée avec succès à Telegram")
            return True
        else:
            print(f"Erreur lors de l'envoi à Telegram: {response.text}")
            return False
    except Exception as e:
        print(f"Exception lors de l'envoi à Telegram: {e}")
        return False

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/solve', methods=['POST'])
def solve():
    try:
        # Récupération des données
        image_data = request.files['image'].read()
        use_calculator = request.form.get('use_calculator', 'false').lower() == 'true'
        use_extended_reasoning = request.form.get('use_extended_reasoning', 'false').lower() == 'true'
        
        img = Image.open(io.BytesIO(image_data))
        
        # Envoyer l'image à Telegram avec indication du mode
        mode_info = []
        if use_calculator:
            mode_info.append("calculatrice")
        if use_extended_reasoning:
            mode_info.append("réflexion étendue")
        
        caption = f"Nouvelle image pour résolution ({', '.join(mode_info) if mode_info else 'mode standard'})"
        send_to_telegram(image_data, caption)

        # Traitement pour Gemini
        buffered = io.BytesIO()
        img.save(buffered, format="PNG")
        img_str = base64.b64encode(buffered.getvalue()).decode()

        def generate():
            mode = 'starting'
            try:
                if use_extended_reasoning:
                    # Mode réflexion étendue - système d'agents
                    agent_system = AgentSystem()
                    
                    # Étape 0: Extraction du problème
                    yield f'data: {json.dumps({"mode": "thinking"})}\n\n'
                    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'
                    
                    problem_text = agent_system.extract_problem_text(img_str)
                    yield f'data: {json.dumps({"content": f"**Problème identifié:**\n{problem_text}\n\n", "type": "text"})}\n\n'
                    
                    # Étape 1: Solution initiale
                    yield f'data: {json.dumps({"content": "---\n\n# 📝 ÉTAPE 1: GÉNÉRATION DE LA SOLUTION INITIALE\n\n", "type": "text"})}\n\n'
                    
                    step1_prompt = agent_system.prompts["step1_initial_solution"].replace(
                        "[The mathematical problem will be inserted here]", problem_text
                    )
                    
                    initial_solution = agent_system.run_agent_step("step1", step1_prompt, use_calculator)
                    yield f'data: {json.dumps({"content": f"{initial_solution}\n\n", "type": "text"})}\n\n'
                    
                    # Étape 2: Auto-amélioration
                    yield f'data: {json.dumps({"content": "---\n\n# 🔧 ÉTAPE 2: AUTO-AMÉLIORATION\n\n", "type": "text"})}\n\n'
                    
                    step2_prompt = agent_system.prompts["step2_self_improvement"].replace(
                        "[The initial solution attempt will be inserted here]", initial_solution
                    )
                    
                    improved_solution = agent_system.run_agent_step("step2", step2_prompt, use_calculator)
                    yield f'data: {json.dumps({"content": f"{improved_solution}\n\n", "type": "text"})}\n\n'
                    
                    # Étape 3: Vérification
                    yield f'data: {json.dumps({"content": "---\n\n# ✅ ÉTAPE 3: VÉRIFICATION RIGOUREUSE\n\n", "type": "text"})}\n\n'
                    
                    step3_prompt = agent_system.prompts["step3_verification"].replace(
                        "[The mathematical problem will be inserted here]", problem_text
                    ).replace(
                        "[The solution to be verified will be inserted here]", improved_solution
                    )
                    
                    verification_result = agent_system.run_agent_step("step3", step3_prompt, False)
                    yield f'data: {json.dumps({"content": f"{verification_result}\n\n", "type": "text"})}\n\n'
                    
                    # Vérifier si des corrections sont nécessaires
                    needs_correction = (
                        "Critical Error" in verification_result or 
                        "Justification Gap" in verification_result or
                        "invalid" in verification_result.lower()
                    )
                    
                    if needs_correction:
                        # Étape 5: Correction
                        yield f'data: {json.dumps({"content": "---\n\n# 🛠️ ÉTAPE 5: CORRECTION DES ERREURS IDENTIFIÉES\n\n", "type": "text"})}\n\n'
                        
                        step5_prompt = agent_system.prompts["step5_correction"].replace(
                            "[The full verification report will be inserted here]", verification_result
                        ).replace(
                            "[The previous solution attempt will be inserted here]", improved_solution
                        )
                        
                        corrected_solution = agent_system.run_agent_step("step5", step5_prompt, use_calculator)
                        yield f'data: {json.dumps({"content": f"{corrected_solution}\n\n", "type": "text"})}\n\n'
                        
                        final_solution = corrected_solution
                    else:
                        yield f'data: {json.dumps({"content": "✅ **La solution a passé la vérification avec succès!**\n\n", "type": "text"})}\n\n'
                        final_solution = improved_solution
                    
                    # Passage à la réponse finale
                    yield f'data: {json.dumps({"mode": "answering"})}\n\n'
                    yield f'data: {json.dumps({"content": "# 📋 SOLUTION FINALE\n\n", "type": "text"})}\n\n'
                    yield f'data: {json.dumps({"content": final_solution, "type": "text"})}\n\n'
                    
                else:
                    # Mode standard
                    prompt = BASE_PROMPT
                    if use_calculator:
                        prompt += CODE_EXTENSION

                    config = types.GenerateContentConfig(
                        temperature=0.3,
                        thinking_config=types.ThinkingConfig(include_thoughts=True)
                    )
                    
                    if use_calculator:
                        config.tools = [types.Tool(code_execution=types.ToolCodeExecution)]

                    response = client.models.generate_content_stream(
                        model="gemini-2.5-flash",
                        contents=[
                            {'inline_data': {'mime_type': 'image/png', 'data': img_str}},
                            prompt
                        ],
                        config=config
                    )

                    for chunk in response:
                        for part in chunk.candidates[0].content.parts:
                            # Gestion des pensées
                            if hasattr(part, 'thought') and part.thought:
                                if mode != "thinking":
                                    yield f'data: {json.dumps({"mode": "thinking"})}\n\n'
                                    mode = "thinking"
                                yield f'data: {json.dumps({"content": part.text, "type": "text"})}\n\n'
                            else:
                                if mode != "answering":
                                    yield f'data: {json.dumps({"mode": "answering"})}\n\n'
                                    mode = "answering"
                                
                                # Gestion des différents types de contenu
                                if hasattr(part, 'text') and part.text is not None:
                                    yield f'data: {json.dumps({"content": part.text, "type": "text"})}\n\n'
                                
                                if hasattr(part, 'executable_code') and part.executable_code is not None:
                                    yield f'data: {json.dumps({"content": part.executable_code.code, "type": "code"})}\n\n'
                                
                                if hasattr(part, 'code_execution_result') and part.code_execution_result is not None:
                                    yield f'data: {json.dumps({"content": part.code_execution_result.output, "type": "result"})}\n\n'
                                
                                if hasattr(part, 'inline_data') and part.inline_data is not None:
                                    img_data = base64.b64encode(part.inline_data.data).decode('utf-8')
                                    yield f'data: {json.dumps({"content": img_data, "type": "image"})}\n\n'

            except Exception as e:
                print(f"Error during generation: {e}")
                yield f'data: {json.dumps({"error": "Une erreur inattendue est survenue"})}\n\n'

        return Response(
            stream_with_context(generate()),
            mimetype='text/event-stream',
            headers={
                'Cache-Control': 'no-cache',
                'X-Accel-Buffering': 'no'
            }
        )

    except Exception as e:
        print(f"Error in solve endpoint: {e}")
        return jsonify({'error': 'Une erreur inattendue est survenue'}), 500

if __name__ == '__main__':
    app.run(debug=True)