File size: 25,418 Bytes
e254214
13d9c52
e254214
 
13d9c52
 
7bfe8df
 
 
 
 
 
13d9c52
 
 
e254214
13d9c52
 
e254214
13d9c52
e254214
13d9c52
7bfe8df
 
 
18d1c29
7bfe8df
 
 
7bb4c4a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18d1c29
7bb4c4a
281e951
b17325a
281e951
2ad2919
281e951
2ad2919
 
281e951
 
7bb4c4a
281e951
7bb4c4a
281e951
 
b17325a
e254214
 
281e951
18d1c29
7bfe8df
a5f1988
7bfe8df
e254214
7bfe8df
a5f1988
e254214
 
 
 
 
 
 
 
7bfe8df
 
 
 
a5f1988
13d9c52
 
7bfe8df
 
a09ba33
13d9c52
 
 
2ad2919
13d9c52
 
 
7bfe8df
 
 
13d9c52
 
7bb4c4a
83396a4
13d9c52
 
 
7bb4c4a
7bfe8df
 
e254214
7bb4c4a
 
 
e254214
13d9c52
7bfe8df
e254214
7bfe8df
2ad2919
13d9c52
e254214
13d9c52
7bfe8df
13d9c52
 
e254214
 
 
 
 
 
 
7bb4c4a
e254214
 
 
 
7bb4c4a
e254214
 
 
7bb4c4a
 
 
e254214
 
 
 
 
 
 
 
 
 
 
 
 
13d9c52
 
7bfe8df
 
 
13d9c52
 
7bb4c4a
13d9c52
 
 
 
7bb4c4a
7bfe8df
 
e254214
7bb4c4a
 
 
e254214
13d9c52
7bfe8df
13d9c52
e254214
7bfe8df
e254214
13d9c52
e254214
13d9c52
7bfe8df
83396a4
d3f6eaa
e254214
 
 
 
 
 
 
7bb4c4a
e254214
 
 
 
7bb4c4a
e254214
 
 
7bb4c4a
 
 
e254214
 
 
 
 
 
 
 
 
 
 
 
 
d3f6eaa
 
7bfe8df
 
 
e254214
 
7bfe8df
 
e254214
 
 
 
7bfe8df
e254214
 
 
7bfe8df
 
 
 
 
 
d3f6eaa
 
7bfe8df
 
 
d3f6eaa
 
 
 
7bfe8df
d3f6eaa
 
 
 
 
7bfe8df
d3f6eaa
 
 
 
 
7bfe8df
d3f6eaa
 
 
 
 
7bfe8df
d3f6eaa
7bfe8df
d3f6eaa
 
 
 
 
83396a4
a5f1988
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d3f6eaa
 
 
e254214
d3f6eaa
 
 
7bfe8df
d3f6eaa
e254214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83396a4
d3f6eaa
 
7bfe8df
 
 
d3f6eaa
 
 
 
7bfe8df
d3f6eaa
 
 
 
 
7bfe8df
d3f6eaa
 
 
 
 
7bfe8df
b1c6513
 
 
 
 
7bfe8df
b1c6513
7bfe8df
b1c6513
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e254214
b1c6513
 
 
7bfe8df
b1c6513
7bfe8df
e254214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7bfe8df
e254214
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
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
from flask import Flask, request, render_template, jsonify, Response
import PIL.Image
from google import genai
from google.genai import types
import os
from tempfile import NamedTemporaryFile
import logging
import traceback  # Import traceback

# Configuration du logging
logging.basicConfig(level=logging.DEBUG,  # Définir le niveau de logging à DEBUG
                    format='%(asctime)s - %(levelname)s - %(message)s')

app = Flask(__name__)



GOOGLE_API_KEY = os.environ.get("TOKEN")
os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY

client = genai.Client()

logging.info("Gemini API configuré.")


def generer_histoire(sujet, points):
    """Génère une histoire à partir d'un sujet et de points donnés."""
    logging.info(f"Début de la génération de l'histoire avec sujet: {sujet} et points: {points}")

    num_points = len(points)
    development = ""
    for i in range(num_points):
        part_num = i + 1
        development += f"""

{part_num}eme partie

Phrase chapeau ( Avec annonce des deux arguments)
Argument 1+ explication+ exemple
Argument 2 + explication + exemple
"""
        if i < num_points - 1:
            development += "Transition\n"

    prompt = f"""
    je souhaite faire mon travail d'histoire sous forme de dissertation. le thème {sujet} et les différents point a détaillé sont : {', '.join(points)}

Voici la méthodologie que tu devras scrupuleusement respecté pour la dissertation et assure toi d'intégrer les connecteur logique pour débuter les arguments Je veux un travail bien détaillé. commence directement ta réponse par l'introduction :

Introduction

Amorce
Problématique
Annonce du plan(les points )

Développement(il y a {num_points} points et donc une partie pour chaque points )

{development}

Conclusion
bilan
question d'ouverture

    """

    logging.debug(f"Prompt utilisé pour Gemini: {prompt}")

    try:
        config = types.GenerateContentConfig(temperature=1)
        logging.info("Modèle Gemini initialisé.")

        response = client.models.generate_content_stream(
            model="gemini-2.5-flash",
            contents=prompt,
            config=config
        )
        logging.info("Stream de Gemini initialisé.")
        for chunk in response:
            yield chunk.text
    except Exception as e:
        logging.error(f"Erreur lors de la génération de l'histoire: {e}")
        logging.error(traceback.format_exc()) # Log the full traceback
        raise

@app.route('/')
def index():
    """Route pour la page d'accueil."""
    logging.info("Accès à la page d'accueil.")
    return render_template('histoire.html')
    




@app.route('/api/histoire', methods=['POST'])
def submit_histoire():
    """Route pour soumettre un sujet d'histoire et générer une dissertation."""
    logging.info("Requête POST reçue sur /api/histoire")

    # Récupération des données
    sujet = request.form.get('sujet-histoire', '').strip()
    points_list = [
        request.form.get('pointt1-histoire', '').strip(),
        request.form.get('point2-histoire', '').strip(),
        request.form.get('point3-histoire', '').strip()
    ]
    points = [p for p in points_list if p]

    logging.debug(f"Sujet reçu: {sujet}, Points reçus: {points}")

    if not sujet or len(points) < 2:
        logging.warning("Le sujet et au moins deux points sont obligatoires.")
        return jsonify({"error": "Le sujet et au moins deux points sont obligatoires"}), 400

    try:
        logging.info("Début de la génération de la dissertation.")
        dissertation = ''.join(generer_histoire(sujet,points))
        logging.info("Dissertation générée avec succès.")

        return jsonify({"output": dissertation}), 200

    except Exception as e:
        logging.exception("Erreur lors du traitement de la requête /api/histoire") # Use logging.exception to log the exception with traceback
        return jsonify({"error": str(e)}), 500

@app.route('/api/histoire/stream', methods=['POST'])
def submit_histoire_stream():
    """Route pour soumettre un sujet d'histoire et générer une dissertation en streaming."""
    logging.info("Requête POST reçue sur /api/histoire/stream")

    # Récupération des données
    sujet = request.form.get('sujet-histoire', '').strip()
    points_list = [
        request.form.get('pointt1-histoire', '').strip(),
        request.form.get('point2-histoire', '').strip(),
        request.form.get('point3-histoire', '').strip()
    ]
    points = [p for p in points_list if p]

    logging.debug(f"Sujet reçu: {sujet}, Points reçus: {points}")

    if not sujet or len(points) < 2:
        logging.warning("Le sujet et au moins deux points sont obligatoires.")
        return Response(f"data: {{\"error\": \"Le sujet et au moins deux points sont obligatoires\"}}\n\n", mimetype='text/event-stream')

    def generate():
        try:
            logging.info("Début de la génération de la dissertation en streaming.")
            for chunk in generer_histoire(sujet, points):
                yield f"data: {chunk}\n\n"
            yield "data: [END]\n\n"
        except Exception as e:
            logging.exception("Erreur lors du traitement de la requête /api/histoire/stream")
            yield f"data: {{\"error\": \"{str(e)}\"}}\n\n"

    return Response(generate(), mimetype='text/event-stream')

@app.route('/api/geographie', methods=['POST'])
def submit_geographie():
    """Route pour soumettre un sujet de géographie et générer une dissertation."""
    logging.info("Requête POST reçue sur /api/geographie")

    # Récupération des données
    sujet = request.form.get('sujet-geographie', '').strip()
    points_list = [
        request.form.get('point1-geographie', '').strip(),
        request.form.get('point2-geographie', '').strip(),
        request.form.get('point3-geographie', '').strip()
    ]
    points = [p for p in points_list if p]

    logging.debug(f"Sujet reçu: {sujet}, Points reçus: {points}")

    if not sujet or len(points) < 2:
        logging.warning("Le sujet et au moins deux points sont obligatoires.")
        return jsonify({"error": "Le sujet et au moins deux points sont obligatoires"}), 400

    try:
        logging.info("Début de la génération de la dissertation.")
        # Génération de l'introduction
        dissertation = ''.join(generer_histoire(sujet,points))
        logging.info("Dissertation générée avec succès.")

        return jsonify({"output": dissertation}), 200

    except Exception as e:
        logging.exception("Erreur lors du traitement de la requête /api/geographie") # Use logging.exception to log the exception with traceback
        return jsonify({"error": str(e)}), 500

@app.route('/api/geographie/stream', methods=['POST'])
def submit_geographie_stream():
    """Route pour soumettre un sujet de géographie et générer une dissertation en streaming."""
    logging.info("Requête POST reçue sur /api/geographie/stream")

    # Récupération des données
    sujet = request.form.get('sujet-geographie', '').strip()
    points_list = [
        request.form.get('point1-geographie', '').strip(),
        request.form.get('point2-geographie', '').strip(),
        request.form.get('point3-geographie', '').strip()
    ]
    points = [p for p in points_list if p]

    logging.debug(f"Sujet reçu: {sujet}, Points reçus: {points}")

    if not sujet or len(points) < 2:
        logging.warning("Le sujet et au moins deux points sont obligatoires.")
        return Response(f"data: {{\"error\": \"Le sujet et au moins deux points sont obligatoires\"}}\n\n", mimetype='text/event-stream')

    def generate():
        try:
            logging.info("Début de la génération de la dissertation en streaming.")
            for chunk in generer_histoire(sujet, points):
                yield f"data: {chunk}\n\n"
            yield "data: [END]\n\n"
        except Exception as e:
            logging.exception("Erreur lors du traitement de la requête /api/geographie/stream")
            yield f"data: {{\"error\": \"{str(e)}\"}}\n\n"

    return Response(generate(), mimetype='text/event-stream')

def analyze_images(images, prompt):
    """Analyse les images fournies et génère une réponse textuelle."""
    logging.info("Début de l'analyse des images.")
    logging.debug(f"Prompt utilisé pour l'analyse d'images: {prompt}")
    try:
        config = types.GenerateContentConfig(temperature=1)

        logging.info("Modèle Gemini initialisé pour l'analyse d'images.")

        response = client.models.generate_content_stream(
            model="gemini-2.5-flash",
            contents=[prompt, *images],
            config=config
        )
        logging.info("Stream de Gemini initialisé pour l'analyse d'images.")
        for chunk in response:
            yield chunk.text
    except Exception as e:
        logging.error(f"Erreur lors de l'analyse des images: {e}")
        logging.error(traceback.format_exc()) # Log the full traceback
        raise


@app.route('/api/histoire-type2', methods=['POST'])
def submit_histoire_type2():
    """Route pour soumettre un sujet d'histoire et des images et générer une dissertation."""
    logging.info("Requête POST reçue sur /api/histoire-type2")

    # Récupération des données
    sujet = request.form.get('sujet-histoire-type2', '').strip()
    
    if 'images-histoire-type2' not in request.files:
        logging.warning("Aucune image n'a été envoyée.")
        return jsonify({"error": "Aucune image n'a été envoyée."}), 400

    files = request.files.getlist('images-histoire-type2')
    
    if not sujet:
        logging.warning("Le champ sujet est obligatoire.")
        return jsonify({"error": "Le champ sujet est obligatoire"}), 400
    
    images = []
    for file in files:
        if file.filename == '':
            logging.warning("Un ou plusieurs fichiers n'ont pas de nom.")
            return jsonify({"error": "Un ou plusieurs fichiers n'ont pas de nom."}), 400

        try:
            img = PIL.Image.open(file)
            images.append(img)
            logging.debug(f"Image {file.filename} chargée avec succès.")
        except Exception as e:
            logging.error(f"Impossible de lire l'image : {file.filename}. Erreur : {str(e)}")
            return jsonify({"error": f"Impossible de lire l'image : {file.filename}. Erreur : {str(e)}"}), 400

    try:
        # Prompt pour l'analyse d'images en histoire
        prompt = f"""
        
        je souhaite faire mon travail d'histoire sous forme de dissertation. le thème est {sujet}.

Voici la méthodologie que tu devras scrupuleusement respecté pour la dissertation et assure toi d'intégrer les connecteur logique pour débuter les arguments Je veux un travail bien détaillé. commence directement ta réponse par l'introduction :


Introduction:

1er Paragraphe: Présentation des documents (Natures et auteurs au programme). Cela signifie qu'il faut identifier la nature des documents (ex : texte, image, graphique) et mentionner les auteurs, si disponibles, en lien avec le programme.

2ème Paragraphe: Contexte historique. Il faut situer les documents dans leur contexte historique, c'est-à-dire l'époque, les événements, et les grandes tendances associées.

3ème Paragraphe: Résumé des idées majeures. En quelques phrases, il faut synthétiser les principaux thèmes ou les grandes idées qui ressortent des documents et du contexte.

Note: Il est recommandé de sauter 2 ou 3 lignes entre l'introduction et le développement.

Développement :

Le développement est structuré autour de plusieurs consignes, chacune ayant la même structure :

Pour chaque consigne (n°1, n°2, n°3):

1er Paragraphe: Constat. Il s'agit de présenter ce qui est observable, un fait, une situation, une information tirée du document.

2ème Paragraphe: Explication. Il faut analyser et expliquer le constat fait dans le paragraphe précédent. Pourquoi observe-t-on cela ? Quels sont les mécanismes, les causes, les facteurs à l'œuvre ?

3ème Paragraphe: Critique. Il faut prendre du recul, analyser de manière critique les informations, les sources ou le contexte. Peut-on nuancer ou remettre en cause certaines affirmations ?

4ème Paragraphe: Phrase de transition. Il s'agit d'une phrase courte pour faire le lien avec la consigne suivante.

Note: Il est recommandé de sauter 1 ligne entre chaque consigne du développement.

Conclusion
bilan 
phrase d'ouverture

 
        
        """

        # Analyse des images et génération de la réponse
        response_text = ''.join(analyze_images(images, prompt))
        return jsonify({"output": response_text}), 200

    except Exception as e:
        logging.exception("Erreur lors du traitement de la requête /api/histoire-type2") # Use logging.exception to log the exception with traceback
        return jsonify({"error": str(e)}), 500

@app.route('/api/histoire-type2/stream', methods=['POST'])
def submit_histoire_type2_stream():
    """Route pour soumettre un sujet d'histoire et des images et générer une dissertation en streaming."""
    logging.info("Requête POST reçue sur /api/histoire-type2/stream")

    # Récupération des données
    sujet = request.form.get('sujet-histoire-type2', '').strip()

    if 'images-histoire-type2' not in request.files:
        logging.warning("Aucune image n'a été envoyée.")
        return Response(f"data: {{\"error\": \"Aucune image n'a été envoyée.\"}}\n\n", mimetype='text/event-stream')

    files = request.files.getlist('images-histoire-type2')

    if not sujet:
        logging.warning("Le champ sujet est obligatoire.")
        return Response(f"data: {{\"error\": \"Le champ sujet est obligatoire\"}}\n\n", mimetype='text/event-stream')

    images = []
    for file in files:
        if file.filename == '':
            logging.warning("Un ou plusieurs fichiers n'ont pas de nom.")
            return Response(f"data: {{\"error\": \"Un ou plusieurs fichiers n'ont pas de nom.\"}}\n\n", mimetype='text/event-stream')

        try:
            img = PIL.Image.open(file)
            images.append(img)
            logging.debug(f"Image {file.filename} chargée avec succès.")
        except Exception as e:
            logging.error(f"Impossible de lire l'image : {file.filename}. Erreur : {str(e)}")
            return Response(f"data: {{\"error\": \"Impossible de lire l'image : {file.filename}. Erreur : {str(e)}\"}}\n\n", mimetype='text/event-stream')

    def generate():
        try:
            # Prompt pour l'analyse d'images en histoire
            prompt = f"""


            je souhaite faire mon travail d'histoire sous forme de dissertation. le thème est {sujet}.

Voici la méthodologie que tu devras scrupuleusement respecté pour la dissertation et assure toi d'intégrer les connecteur logique pour débuter les arguments Je veux un travail bien détaillé. commence directement ta réponse par l'introduction :


Introduction:

1er Paragraphe: Présentation des documents (Natures et auteurs au programme). Cela signifie qu'il faut identifier la nature des documents (ex : texte, image, graphique) et mentionner les auteurs, si disponibles, en lien avec le programme.

2ème Paragraphe: Contexte historique. Il faut situer les documents dans leur contexte historique, c'est-à-dire l'époque, les événements, et les grandes tendances associées.

3ème Paragraphe: Résumé des idées majeures. En quelques phrases, il faut synthétiser les principaux thèmes ou les grandes idées qui ressortent des documents et du contexte.

Note: Il est recommandé de sauter 2 ou 3 lignes entre l'introduction et le développement.

Développement :

Le développement est structuré autour de plusieurs consignes, chacune ayant la même structure :

Pour chaque consigne (n°1, n°2, n°3):

1er Paragraphe: Constat. Il s'agit de présenter ce qui est observable, un fait, une situation, une information tirée du document.

2ème Paragraphe: Explication. Il faut analyser et expliquer le constat fait dans le paragraphe précédent. Pourquoi observe-t-on cela ? Quels sont les mécanismes, les causes, les facteurs à l'œuvre ?

3ème Paragraphe: Critique. Il faut prendre du recul, analyser de manière critique les informations, les sources ou le contexte. Peut-on nuancer ou remettre en cause certaines affirmations ?

4ème Paragraphe: Phrase de transition. Il s'agit d'une phrase courte pour faire le lien avec la consigne suivante.

Note: Il est recommandé de sauter 1 ligne entre chaque consigne du développement.

Conclusion
bilan
phrase d'ouverture


            """

            logging.info("Début de l'analyse des images en streaming.")
            for chunk in analyze_images(images, prompt):
                yield f"data: {chunk}\n\n"
            yield "data: [END]\n\n"
        except Exception as e:
            logging.exception("Erreur lors du traitement de la requête /api/histoire-type2/stream")
            yield f"data: {{\"error\": \"{str(e)}\"}}\n\n"

    return Response(generate(), mimetype='text/event-stream')
        
@app.route('/api/geographie-type2', methods=['POST'])
def submit_geographie_type2():
    """Route pour soumettre un sujet de géographie et des images et générer une dissertation."""
    logging.info("Requête POST reçue sur /api/geographie-type2")

    # Récupération des données
    sujet = request.form.get('sujet-geographie-type2', '').strip()
    
    if 'images-geographie-type2' not in request.files:
        logging.warning("Aucune image n'a été envoyée.")
        return jsonify({"error": "Aucune image n'a été envoyée."}), 400

    files = request.files.getlist('images-geographie-type2')
    
    if not sujet:
        logging.warning("Le champ sujet est obligatoire.")
        return jsonify({"error": "Le champ sujet est obligatoire"}), 400
    
    images = []
    for file in files:
        if file.filename == '':
            logging.warning("Un ou plusieurs fichiers n'ont pas de nom.")
            return jsonify({"error": "Un ou plusieurs fichiers n'ont pas de nom."}), 400

        try:
            img = PIL.Image.open(file)
            images.append(img)
            logging.debug(f"Image {file.filename} chargée avec succès.")
        except Exception as e:
            logging.error(f"Impossible de lire l'image : {file.filename}. Erreur : {str(e)}")
            return jsonify({"error": f"Impossible de lire l'image : {file.filename}. Erreur : {str(e)}"}), 400

    try:
        # Prompt pour l'analyse d'images en histoire
        prompt = f"""
        
        je souhaite faire mon travail de géographie sous forme de dissertation. le thème est {sujet}.

Voici la méthodologie que tu devras scrupuleusement respecté pour la dissertation et assure toi d'intégrer les connecteur logique pour débuter les arguments Je veux un travail bien détaillé. commence directement ta réponse par l'introduction :

Introduction:

1er Paragraphe: Définition du thème (ou définition des mots-clés). Il faut commencer par clairement définir le sujet de l'étude. Si nécessaire, il faut définir les mots-clés importants et les concepts liés au thème étudié.

2ème Paragraphe: Présentation des documents (Natures uniquement). Il faut présenter la nature des documents : cartes, graphiques, photos, etc. Contrairement à l'histoire, l'accent est mis ici uniquement sur la nature des documents, sans mention des auteurs.

3ème Paragraphe: Résumé des idées majeures. Il faut synthétiser les principales idées, les tendances ou les problématiques qui se dégagent des documents et de la définition du thème.

Note: Il est recommandé de sauter 2 ou 3 lignes entre l'introduction et le développement.

Développement:

Le développement en géographie suit une structure identique à celle de l'histoire, basée sur des consignes :

Pour chaque consigne (n°1, n°2, n°3):

1er Paragraphe: Constat. Présentez ce qui est observable dans les documents, un fait géographique, une tendance, une répartition spatiale, etc.

2ème Paragraphe: Explication. Analysez les raisons de ce constat. Quels facteurs géographiques (naturels, humains, économiques, politiques...) expliquent ce qui a été observé ?

3ème Paragraphe: Critique. Analysez les limites des documents ou de l'approche, la pertinence des facteurs explicatifs, les éventuelles alternatives ou nuances.

4ème Paragraphe: Phrase de transition. Une courte phrase pour passer en douceur à la consigne suivante.

Note: Il est recommandé de sauter 1 ligne entre chaque consigne du développement.


Conclusion
bilan 
phrase d'ouverture

 
        
        """

        # Analyse des images et génération de la réponse
        response_text = ''.join(analyze_images(images, prompt))
        return jsonify({"output": response_text}), 200

    except Exception as e:
        logging.exception("Erreur lors du traitement de la requête /api/geographie-type2") # Use logging.exception to log the exception with traceback
        return jsonify({"error": str(e)}), 500

@app.route('/api/geographie-type2/stream', methods=['POST'])
def submit_geographie_type2_stream():
    """Route pour soumettre un sujet de géographie et des images et générer une dissertation en streaming."""
    logging.info("Requête POST reçue sur /api/geographie-type2/stream")

    # Récupération des données
    sujet = request.form.get('sujet-geographie-type2', '').strip()

    if 'images-geographie-type2' not in request.files:
        logging.warning("Aucune image n'a été envoyée.")
        return Response(f"data: {{\"error\": \"Aucune image n'a été envoyée.\"}}\n\n", mimetype='text/event-stream')

    files = request.files.getlist('images-geographie-type2')

    if not sujet:
        logging.warning("Le champ sujet est obligatoire.")
        return Response(f"data: {{\"error\": \"Le champ sujet est obligatoire\"}}\n\n", mimetype='text/event-stream')

    images = []
    for file in files:
        if file.filename == '':
            logging.warning("Un ou plusieurs fichiers n'ont pas de nom.")
            return Response(f"data: {{\"error\": \"Un ou plusieurs fichiers n'ont pas de nom.\"}}\n\n", mimetype='text/event-stream')

        try:
            img = PIL.Image.open(file)
            images.append(img)
            logging.debug(f"Image {file.filename} chargée avec succès.")
        except Exception as e:
            logging.error(f"Impossible de lire l'image : {file.filename}. Erreur : {str(e)}")
            return Response(f"data: {{\"error\": \"Impossible de lire l'image : {file.filename}. Erreur : {str(e)}\"}}\n\n", mimetype='text/event-stream')

    def generate():
        try:
            # Prompt pour l'analyse d'images en histoire
            prompt = f"""


            je souhaite faire mon travail de géographie sous forme de dissertation. le thème est {sujet}.

Voici la méthodologie que tu devras scrupuleusement respecté pour la dissertation et assure toi d'intégrer les connecteur logique pour débuter les arguments Je veux un travail bien détaillé. commence directement ta réponse par l'introduction :

Introduction:

1er Paragraphe: Définition du thème (ou définition des mots-clés). Il faut commencer par clairement définir le sujet de l'étude. Si nécessaire, il faut définir les mots-clés importants et les concepts liés au thème étudié.

2ème Paragraphe: Présentation des documents (Natures uniquement). Il faut présenter la nature des documents : cartes, graphiques, photos, etc. Contrairement à l'histoire, l'accent est mis ici uniquement sur la nature des documents, sans mention des auteurs.

3ème Paragraphe: Résumé des idées majeures. Il faut synthétiser les principales idées, les tendances ou les problématiques qui se dégagent des documents et de la définition du thème.

Note: Il est recommandé de sauter 2 ou 3 lignes entre l'introduction et le développement.

Développement:

Le développement en géographie suit une structure identique à celle de l'histoire, basée sur des consignes :

Pour chaque consigne (n°1, n°2, n°3):

1er Paragraphe: Constat. Présentez ce qui est observable dans les documents, un fait géographique, une tendance, une répartition spatiale, etc.

2ème Paragraphe: Explication. Analysez les raisons de ce constat. Quels facteurs géographiques (naturels, humains, économiques, politiques...) expliquent ce qui a été observé ?

3ème Paragraphe: Critique. Analysez les limites des documents ou de l'approche, la pertinence des facteurs explicatifs, les éventuelles alternatives ou nuances.

4ème Paragraphe: Phrase de transition. Une courte phrase pour passer en douceur à la consigne suivante.

Note: Il est recommandé de sauter 1 ligne entre chaque consigne du développement.


Conclusion
bilan
phrase d'ouverture


            """

            logging.info("Début de l'analyse des images en streaming.")
            for chunk in analyze_images(images, prompt):
                yield f"data: {chunk}\n\n"
            yield "data: [END]\n\n"
        except Exception as e:
            logging.exception("Erreur lors du traitement de la requête /api/geographie-type2/stream")
            yield f"data: {{\"error\": \"{str(e)}\"}}\n\n"

    return Response(generate(), mimetype='text/event-stream')

if __name__ == '__main__':
    app.run(debug=True,host="0.0.0.0")