from flask import Flask, render_template, request, Response from google import genai from google.genai import types import os import logging import json load_prompt =""" Tu es expérimenté en langue française. # Instruction pour travail argumentatif de français niveau lycée ## Paramètres d'entrée attendus : - `sujet` : La question/thème à traiter - `choix` : Type de travail ("discuter", "dissertation", "étayer", "réfuter") - `style` : Style d'écriture souhaité (ex: "raffiné") ## Traitement automatique selon le type : ### Si choix = "discuter" : Produire un travail argumentatif suivant cette méthodologie : **INTRODUCTION:** - Approche par constat - Problématique - Annonce du plan **DÉVELOPPEMENT:** *Partie 1 : Thèse* - Introduction partielle (énonce la thèse) - Argument 1: Explications + Illustration (exemple + explication) - Argument 2: Explications + Illustration (exemple + explication) - Argument 3: Explications + Illustration (exemple + explication) *Phrase de transition vers la deuxième partie* *Partie 2 : Antithèse* - Introduction partielle (énonce l'antithèse) - Argument 1: Explications + Illustration (exemple + explication) - Argument 2: Explications + Illustration (exemple + explication) - Argument 3: Explications + Illustration (exemple + explication) **CONCLUSION:** - Bilan (Synthèse des arguments pour et contre) - Ouverture du sujet (sous forme de phrase interrogative) ### Si choix = "dissertation" : Produire une dissertation suivant cette méthodologie : **Phase 1 : L'Introduction (en un seul paragraphe)** - Amorce : Introduire le thème général - Position du Sujet : Présenter l'auteur/œuvre, citer et reformuler le sujet - Problématique : Poser la question centrale dialectique - Annonce du Plan : Annoncer thèse et antithèse **Phase 2 : Le Développement (en trois parties distinctes)** *Partie 1 : La Thèse* - Explorer et justifier l'affirmation initiale - 2-3 arguments (structure A.I.E : Affirmation-Illustration-Explication) - Exemples littéraires précis et analysés *Partie 2 : L'Antithèse* - Nuancer, critiquer ou présenter le point de vue opposé - 2-3 arguments (structure A.I.E) - Transition cruciale depuis la thèse - Exemples littéraires précis et analysés *Partie 3 : La Synthèse* - Dépasser l'opposition thèse/antithèse - Nouvelle perspective intégrant les éléments valides - 2-3 arguments (structure A.I.E) - Transition depuis l'antithèse - Exemples littéraires précis et analysés **Phase 3 : La Conclusion (en un seul paragraphe)** - Bilan synthétique du parcours dialectique - Réponse claire à la problématique - Ouverture vers contexte plus large ### Si choix = "étayer" ou "réfuter" : Produire un travail argumentatif suivant cette méthodologie : **INTRODUCTION:** - Approche par constat - Problématique - Annonce du plan **DÉVELOPPEMENT:** - Phrase chapeau (énonce la thèse principale : pour étayer ou contre pour réfuter) - Argument 1: Explications + Illustration (exemple + explication) - Argument 2: Explications + Illustration (exemple + explication) - Argument 3: Explications + Illustration (exemple + explication) **CONCLUSION:** - Bilan (rappel de la thèse + arguments principaux) - Ouverture du sujet (sous forme de phrase interrogative) ## Application du style : Adapter l'écriture selon le style demandé (ex: "raffiné" = vocabulaire soutenu, syntaxe élaborée, références culturelles). ## Exemple de traitement : **Entrée :** `sujet='L'homme est inoffensif', choix='étayer', style='raffiné'` **Action :** Générer un travail argumentatif défendant la thèse "L'homme est inoffensif" avec un style raffiné, suivant la méthodologie "étayer". commence directement par l'introduction sans rien expliquer avant. """ logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) app = Flask(__name__) token = os.environ.get("TOKEN") client = genai.Client(api_key=token) default_generation_config = types.GenerateContentConfig( temperature=1, ) STANDARD_MODEL_NAME = "gemini-2.5-flash" DEEPTHINK_MODEL_NAME = "gemini-2.5-pro" # Page d'accueil @app.route('/') def index(): logging.info("Page index demandée.") return render_template('index.html') # API pour génération française @app.route('/api/francais', methods=['POST', 'GET']) def gpt_francais(): logging.info(f"Requête {request.method} reçue sur /api/francais") french_prompt = request.args.get('sujet', '').strip() choix = request.args.get('choix', '').strip() style = request.args.get('style', '').strip() use_deepthink = request.args.get('use_deepthink', 'false').lower() == 'true' logging.info( f"Données reçues : sujet='{french_prompt[:50]}', choix='{choix}', style='{style}', deepthink={use_deepthink}" ) if not french_prompt: logging.warning("Sujet vide, retour erreur.") return Response( "data: " + json.dumps({'type': 'error', 'content': 'Erreur: Le sujet ne peut pas être vide.'}) + "\n\n", mimetype='text/event-stream' ), 400 model_to_use = DEEPTHINK_MODEL_NAME if use_deepthink else STANDARD_MODEL_NAME logging.info(f"Modèle utilisé : {model_to_use}") system_instruction = load_prompt user_prompt = f"Sujet: {french_prompt}\nType: {choix}\nStyle: {style}" config = types.GenerateContentConfig( system_instruction=system_instruction, temperature=1 ) if use_deepthink: config.thinking_config = types.ThinkingConfig(include_thoughts=True) def generate_stream(): try: logging.info("Démarrage du streaming de génération...") thoughts = "" answer = "" for chunk in client.models.generate_content_stream( model=model_to_use, contents=[user_prompt], config=config ): for part in chunk.candidates[0].content.parts: if not part.text: continue elif hasattr(part, 'thought') and part.thought: if not thoughts: logging.info("Premiers éléments de réflexion envoyés.") yield "data: " + json.dumps({'type': 'thoughts_start'}) + "\n\n" thoughts += part.text yield "data: " + json.dumps({'type': 'thought', 'content': part.text}) + "\n\n" else: if not answer: logging.info("Premiers éléments de réponse envoyés.") yield "data: " + json.dumps({'type': 'answer_start'}) + "\n\n" answer += part.text yield "data: " + json.dumps({'type': 'answer', 'content': part.text}) + "\n\n" logging.info("Fin du streaming de génération.") yield "data: " + json.dumps({'type': 'done'}) + "\n\n" except Exception: logging.exception("Erreur pendant la génération de contenu.") yield "data: " + json.dumps({'type': 'error', 'content': 'Erreur serveur pendant la génération.'}) + "\n\n" return Response(generate_stream(), mimetype='text/event-stream') # API pour analyse de texte à partir d'images @app.route('/api/etude-texte', methods=['POST', 'GET']) def gpt_francais_cc(): logging.info("Requête reçue sur /api/etude-texte") if 'images' not in request.files: logging.warning("Aucun fichier image reçu.") return Response( "data: " + json.dumps({'type': 'error', 'content': 'Aucun fichier image envoyé.'}) + "\n\n", mimetype='text/event-stream' ), 400 images = request.files.getlist('images') if not images or not images[0].filename: logging.warning("Liste d'images vide.") return Response( "data: " + json.dumps({'type': 'error', 'content': 'Aucune image sélectionnée.'}) + "\n\n", mimetype='text/event-stream' ), 400 def generate_image_analysis(): try: logging.info(f"Nombre d'images reçues : {len(images)}") system_instruction = "Tu es un assistant spécialisé dans l'analyse de textes et de documents. réponds strictement aux questions." content = ["Réponds aux questions présentes dans les images."] for img in images: if img.filename: logging.info(f"Traitement image : {img.filename}") img_data = img.read() img_part = types.Part.from_bytes( data=img_data, mime_type=img.content_type or 'image/jpeg' ) content.append(img_part) config = types.GenerateContentConfig( system_instruction=system_instruction, temperature=0.7, max_output_tokens=4096 ) logging.info("Démarrage du streaming d'analyse d'image...") for chunk in client.models.generate_content_stream( model=STANDARD_MODEL_NAME, contents=content, config=config ): for part in chunk.candidates[0].content.parts: if part.text: yield "data: " + json.dumps({'type': 'content', 'content': part.text}) + "\n\n" logging.info("Fin du streaming d'analyse d'image.") yield "data: " + json.dumps({'type': 'done'}) + "\n\n" except Exception: logging.exception("Erreur pendant l'analyse d'image.") yield "data: " + json.dumps({'type': 'error', 'content': "Erreur serveur pendant l'analyse de l'image."}) + "\n\n" return Response(generate_image_analysis(), mimetype='text/event-stream') if __name__ == '__main__': logging.info("Démarrage du serveur Flask avec Gemini SDK...") app.run(debug=True)