File size: 3,942 Bytes
c5bddce
 
6ca0885
c5bddce
 
 
 
6ca0885
c5bddce
d3e3794
cac21d1
c5bddce
6ca0885
c5bddce
 
6ca0885
c5bddce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ca0885
c5bddce
6ca0885
 
 
 
c5bddce
 
 
 
 
533067f
 
c5bddce
 
 
6ca0885
 
c5bddce
 
 
 
 
 
 
 
 
 
786c98a
c5bddce
 
 
 
 
 
6ca0885
c5bddce
 
90e991c
c5bddce
 
 
533067f
c5bddce
 
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
# 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
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 ---
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:
        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():
    return render_template("philosophie.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()
    if not sujet:
        return jsonify({"error": "Le champ 'question' est obligatoire."}), 400

    try:
        prompt_template = load_prompt('philo_dissertation_json.txt')
        final_prompt = prompt_template.format(phi_prompt=sujet)

        config = types.GenerateContentConfig(
            safety_settings=SAFETY_SETTINGS,
            response_mime_type="application/json",
            response_schema=Dissertation,
        )

        response = client.models.generate_content(
            model="gemini-2.5-flash",
            contents=final_prompt,
            config=config
        )

        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=5000)