Spaces:
Running
Running
File size: 4,976 Bytes
c5bddce 6ca0885 c5bddce 25460b3 d3e3794 cac21d1 c5bddce 6ca0885 c5bddce 6ca0885 c5bddce 25460b3 c5bddce 25460b3 c5bddce 6ca0885 c5bddce 6ca0885 25460b3 6ca0885 c5bddce 533067f c5bddce 25460b3 c5bddce 25460b3 6ca0885 25460b3 c5bddce 25460b3 c5bddce 25460b3 c5bddce 25460b3 c5bddce 25460b3 c5bddce 6ca0885 c5bddce 90e991c c5bddce 533067f c5bddce 25460b3 |
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 |
# app.py
import os
import logging
import json
from flask import Flask, jsonify, render_template, request
from pydantic import BaseModel, Field
from typing import List, Optional
# import psycopg2 # La base de données n'est pas utilisée
# from psycopg2.extras import RealDictCursor
from google import genai
from google.genai import types
from utils import load_prompt
# --- Configuration ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
app = Flask(__name__)
app.secret_key = os.environ.get("FLASK_SECRET_KEY", "un-secret-par-defaut")
# --- Modèles de Données Pydantic pour la sortie structurée ---
class Argument(BaseModel):
paragraphe_argumentatif: str = Field(description="Un unique paragraphe formant un argument complet. Il doit commencer par un connecteur logique (ex: 'Premièrement,'), suivi de son développement.")
class Partie(BaseModel):
chapeau: str = Field(description="Le paragraphe d'introduction de la partie.")
arguments: list[Argument] = Field(description="La liste des paragraphes argumentatifs qui suivent le chapeau.")
transition: Optional[str] = Field(description="Phrase ou court paragraphe de transition.", default=None)
class Dissertation(BaseModel):
sujet: str = Field(description="Le sujet exact de la dissertation, tel que posé par l'utilisateur.")
prof: str = Field(description="Le nom du professeur, qui est toujours 'Mariam AI'.", default="Mariam AI")
introduction: str = Field(description="L'introduction complète de la dissertation.")
parties: List[Partie]
conclusion: str = Field(description="La conclusion complète de la dissertation.")
# --- Configuration Gemini (Ancien SDK) ---
try:
GOOGLE_API_KEY = os.environ.get("TOKEN")
if not GOOGLE_API_KEY:
logging.warning("La variable d'environnement TOKEN (GOOGLE_API_KEY) n'est pas définie.")
client = None
else:
# On utilise genai.Client comme dans votre code original
client = genai.Client(api_key=GOOGLE_API_KEY)
except Exception as e:
logging.error(f"Erreur lors de l'initialisation du client GenAI: {e}")
client = None
SAFETY_SETTINGS = [
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
]
# --- Route Principale ---
@app.route('/')
def philosophie():
# Assurez-vous que le nom du template correspond à votre fichier HTML
return render_template("philosophie (13).html")
# --- Route API pour la génération de dissertation ---
@app.route('/api/generate_dissertation', methods=['POST'])
def generate_dissertation_api():
if not client:
return jsonify({"error": "Le service IA n'est pas correctement configuré."}), 503
data = request.json
sujet = data.get('question', '').strip()
dissertation_type = data.get('type', 'type1').strip() # Récupère le type
if not sujet:
return jsonify({"error": "Le champ 'question' est obligatoire."}), 400
if dissertation_type not in ['type1', 'type2']:
return jsonify({"error": "Type de méthodologie invalide."}), 400
try:
# Sélection dynamique du fichier de prompt
prompt_filename = f"philo_dissertation_{dissertation_type}.txt"
prompt_template = load_prompt(prompt_filename)
if "Erreur:" in prompt_template:
logging.error(f"Fichier de prompt non trouvé : {prompt_filename}")
return jsonify({"error": "Configuration du prompt introuvable pour ce type."}), 500
final_prompt = prompt_template.format(phi_prompt=sujet)
# Configuration de la réponse structurée (comme dans votre code original)
config = types.GenerateContentConfig(
safety_settings=SAFETY_SETTINGS,
response_mime_type="application/json",
response_schema=Dissertation,
)
# Appel à l'API avec la syntaxe client.models.generate_content
response = client.models.generate_content(
model="gemini-2.5-flash", # Modèle performant compatible avec cette syntaxe
contents=final_prompt,
config=config
)
# Traitement de la réponse (comme dans votre code original)
if response.parsed:
return jsonify(response.parsed.dict())
else:
logging.error(f"Erreur de parsing de la réponse structurée. Réponse brute : {response.text}")
return jsonify({"error": "Le modèle n'a pas pu générer une structure valide."}), 500
except Exception as e:
logging.error(f"Erreur de génération Gemini : {e}")
return jsonify({"error": f"Une erreur est survenue avec le service IA : {e}"}), 500
if __name__ == '__main__':
app.run(debug=True, port=5001) |