Docfile commited on
Commit
0f75c3f
·
verified ·
1 Parent(s): 67ff1a0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -39
app.py CHANGED
@@ -1,7 +1,7 @@
1
  import os
2
  import json
3
  import mimetypes
4
- from flask import Flask, request, session, jsonify, redirect, url_for, flash, render_template # Ajout de render_template au cas où
5
  from dotenv import load_dotenv
6
  import google.generativeai as genai
7
  import requests
@@ -27,31 +27,35 @@ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
27
  print(f"Dossier d'upload configuré : {os.path.abspath(UPLOAD_FOLDER)}")
28
 
29
  # --- Configuration de l'API Gemini ---
30
- model = None # Initialiser à None
 
 
 
 
 
 
 
 
 
31
  try:
32
  gemini_api_key = os.getenv("GOOGLE_API_KEY")
33
  if not gemini_api_key:
34
  print("ERREUR: Clé API GOOGLE_API_KEY manquante dans le fichier .env")
35
  else:
36
  genai.configure(api_key=gemini_api_key)
37
-
38
- safety_settings = [
39
- {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
40
- {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
41
- {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
42
- {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
43
- ]
44
-
45
- # Utiliser un modèle stable comme gemini-1.5-flash
46
- model = genai.GenerativeModel(
47
- 'gemini-2.0-flash',
48
- safety_settings=safety_settings,
49
- system_instruction="Tu es un assistant intelligent et amical nommé Mariam. Tu assistes les utilisateurs au mieux de tes capacités. Tu as été créé par Aenir."
50
- )
51
- print("Modèle Gemini (gemini-1.5-flash-latest) chargé avec succès.")
52
 
53
  except Exception as e:
54
- print(f"ERREUR Critique lors de la configuration de Gemini : {e}")
55
  print("L'application fonctionnera sans les fonctionnalités IA.")
56
 
57
  # --- Fonctions Utilitaires ---
@@ -168,10 +172,9 @@ def prepare_gemini_history(chat_history):
168
 
169
  @app.route('/')
170
  def root():
171
- """Route racine simple, confirme que le serveur est actif."""
172
- # On pourrait aussi servir index.html ici si on le met dans 'templates'
173
  return render_template('index.html')
174
-
175
  @app.route('/api/history', methods=['GET'])
176
  def get_history():
177
  """Fournit l'historique de chat stocké en session au format JSON."""
@@ -189,15 +192,17 @@ def get_history():
189
  @app.route('/api/chat', methods=['POST'])
190
  def chat_api():
191
  """Gère les nouvelles requêtes de chat via AJAX."""
192
- if not model:
193
- print("API ERREUR: Tentative d'appel à /api/chat sans modèle Gemini chargé.")
194
- return jsonify({'success': False, 'error': "Le service IA n'est pas disponible."}), 503 # Service Unavailable
195
 
196
  # Récupération des données du formulaire
197
  prompt = request.form.get('prompt', '').strip()
198
  use_web_search_str = request.form.get('web_search', 'false') # 'true' ou 'false'
199
  use_web_search = use_web_search_str.lower() == 'true'
200
  file = request.files.get('file')
 
 
201
 
202
  # Validation simple
203
  if not prompt and not file:
@@ -206,6 +211,7 @@ def chat_api():
206
  print(f"\n--- Nouvelle requête /api/chat ---")
207
  print(f"Prompt reçu: '{prompt[:50]}...'")
208
  print(f"Recherche Web activée: {use_web_search}")
 
209
  print(f"Fichier reçu: {file.filename if file else 'Aucun'}")
210
 
211
  # Initialiser l'historique de session si nécessaire
@@ -235,6 +241,7 @@ def chat_api():
235
 
236
  # Uploader vers Google AI (peut prendre du temps)
237
  print(f"Upload du fichier vers Google AI (MimeType: {mime_type})...")
 
238
  uploaded_gemini_file = genai.upload_file(path=filepath, mime_type=mime_type)
239
  print(f"Fichier '{uploaded_gemini_file.name}' uploadé avec succès vers Google AI.")
240
 
@@ -305,23 +312,48 @@ En te basant sur ces informations ET sur ta connaissance générale, fournis une
305
  # Préparer l'historique des messages PRÉCÉDENTS
306
  gemini_history = prepare_gemini_history(session['chat_history'][:-1]) # Exclut le message actuel
307
  print(f"Préparation de l'appel Gemini avec {len(gemini_history)} messages d'historique.")
308
-
309
  # Construire le contenu complet pour l'appel
310
  contents_for_gemini = gemini_history + [{'role': 'user', 'parts': current_gemini_parts}]
311
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  # Appel API
313
- print("Envoi de la requête à Gemini...")
314
  # Utilisation de generate_content en mode non-streamé
315
- response = model.generate_content(contents_for_gemini)
316
  # print(response) # Décommenter pour voir la réponse brute de l'API
317
 
318
- # Extraire le texte de la réponse
319
- response_text_raw = response.text
320
- print(f"Réponse reçue de Gemini (brute, début): '{response_text_raw[:100]}...'")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
 
322
- # Convertir la réponse Markdown en HTML pour l'affichage
323
- response_html = markdown.markdown(response_text_raw, extensions=['fenced_code', 'tables', 'nl2br'])
324
- print("Réponse convertie en HTML.")
325
 
326
  # Ajouter la réponse de l'assistant à l'historique de session
327
  assistant_history_entry = {
@@ -340,9 +372,14 @@ En te basant sur ces informations ET sur ta connaissance générale, fournis une
340
  print(f"ERREUR Critique lors de l'appel à Gemini ou du traitement de la réponse : {e}")
341
  # En cas d'erreur, retirer le dernier message utilisateur de l'historique
342
  # pour éviter les boucles d'erreur si le message lui-même pose problème.
343
- session['chat_history'].pop()
344
- session.modified = True
345
- print("Le dernier message utilisateur a été retiré de l'historique suite à l'erreur.")
 
 
 
 
 
346
  # Renvoyer une erreur générique mais informative
347
  return jsonify({'success': False, 'error': f"Une erreur interne est survenue lors de la génération de la réponse. Détails: {e}"}), 500
348
 
@@ -360,13 +397,13 @@ En te basant sur ces informations ET sur ta connaissance générale, fournis une
360
  def clear_chat():
361
  """Efface l'historique de chat dans la session."""
362
  session.pop('chat_history', None)
363
- session.pop('web_search', None) # Réinitialiser aussi le toggle web si besoin
364
  print("API: Historique de chat effacé via /clear.")
365
 
366
  # Adapter la réponse selon si c'est une requête AJAX (fetch) ou une soumission classique
367
  # Vérification si la requête vient probablement de fetch (simple)
368
  is_ajax = 'XMLHttpRequest' == request.headers.get('X-Requested-With') or \
369
- request.headers.get('Accept') == 'application/json'
370
 
371
  if is_ajax:
372
  return jsonify({'success': True, 'message': 'Historique effacé.'})
@@ -382,4 +419,6 @@ if __name__ == '__main__':
382
  # Utiliser host='0.0.0.0' pour rendre accessible sur le réseau local
383
  # debug=True est pratique pour le développement, mais à désactiver en production !
384
  # Changer le port si nécessaire (ex: 5000, 5001, 8080)
385
- app.run(debug=True, host='0.0.0.0', port=5001)
 
 
 
1
  import os
2
  import json
3
  import mimetypes
4
+ from flask import Flask, request, session, jsonify, redirect, url_for, flash, render_template
5
  from dotenv import load_dotenv
6
  import google.generativeai as genai
7
  import requests
 
27
  print(f"Dossier d'upload configuré : {os.path.abspath(UPLOAD_FOLDER)}")
28
 
29
  # --- Configuration de l'API Gemini ---
30
+ MODEL_FLASH = 'gemini-1.5-flash-latest' # Default model
31
+ MODEL_PRO = 'gemini-1.5-pro-latest' # Advanced model
32
+ SYSTEM_INSTRUCTION = "Tu es un assistant intelligent et amical nommé Mariam. Tu assistes les utilisateurs au mieux de tes capacités. Tu as été créé par Aenir."
33
+ SAFETY_SETTINGS = [
34
+ {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
35
+ {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
36
+ {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
37
+ {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
38
+ ]
39
+ GEMINI_CONFIGURED = False
40
  try:
41
  gemini_api_key = os.getenv("GOOGLE_API_KEY")
42
  if not gemini_api_key:
43
  print("ERREUR: Clé API GOOGLE_API_KEY manquante dans le fichier .env")
44
  else:
45
  genai.configure(api_key=gemini_api_key)
46
+ # Just configure, don't create model instance yet
47
+ # Check if we can list models as a basic configuration test
48
+ models_list = [m.name for m in genai.list_models()]
49
+ if f'models/{MODEL_FLASH}' in models_list and f'models/{MODEL_PRO}' in models_list:
50
+ print(f"Configuration Gemini effectuée. Modèles requis ({MODEL_FLASH}, {MODEL_PRO}) disponibles.")
51
+ print(f"System instruction: {SYSTEM_INSTRUCTION}")
52
+ GEMINI_CONFIGURED = True
53
+ else:
54
+ print(f"ERREUR: Les modèles requis ({MODEL_FLASH}, {MODEL_PRO}) ne sont pas tous disponibles via l'API.")
55
+ print(f"Modèles trouvés: {models_list}")
 
 
 
 
 
56
 
57
  except Exception as e:
58
+ print(f"ERREUR Critique lors de la configuration initiale de Gemini : {e}")
59
  print("L'application fonctionnera sans les fonctionnalités IA.")
60
 
61
  # --- Fonctions Utilitaires ---
 
172
 
173
  @app.route('/')
174
  def root():
175
+ """Sert la page HTML principale."""
 
176
  return render_template('index.html')
177
+
178
  @app.route('/api/history', methods=['GET'])
179
  def get_history():
180
  """Fournit l'historique de chat stocké en session au format JSON."""
 
192
  @app.route('/api/chat', methods=['POST'])
193
  def chat_api():
194
  """Gère les nouvelles requêtes de chat via AJAX."""
195
+ if not GEMINI_CONFIGURED:
196
+ print("API ERREUR: Tentative d'appel à /api/chat sans configuration Gemini valide.")
197
+ return jsonify({'success': False, 'error': "Le service IA n'est pas configuré correctement."}), 503 # Service Unavailable
198
 
199
  # Récupération des données du formulaire
200
  prompt = request.form.get('prompt', '').strip()
201
  use_web_search_str = request.form.get('web_search', 'false') # 'true' ou 'false'
202
  use_web_search = use_web_search_str.lower() == 'true'
203
  file = request.files.get('file')
204
+ use_advanced_str = request.form.get('advanced_reasoning', 'false') # Get the new flag
205
+ use_advanced = use_advanced_str.lower() == 'true'
206
 
207
  # Validation simple
208
  if not prompt and not file:
 
211
  print(f"\n--- Nouvelle requête /api/chat ---")
212
  print(f"Prompt reçu: '{prompt[:50]}...'")
213
  print(f"Recherche Web activée: {use_web_search}")
214
+ print(f"Raisonnement avancé demandé: {use_advanced}")
215
  print(f"Fichier reçu: {file.filename if file else 'Aucun'}")
216
 
217
  # Initialiser l'historique de session si nécessaire
 
241
 
242
  # Uploader vers Google AI (peut prendre du temps)
243
  print(f"Upload du fichier vers Google AI (MimeType: {mime_type})...")
244
+ # Note: L'API upload_file est générique et ne dépend pas du modèle Flash/Pro
245
  uploaded_gemini_file = genai.upload_file(path=filepath, mime_type=mime_type)
246
  print(f"Fichier '{uploaded_gemini_file.name}' uploadé avec succès vers Google AI.")
247
 
 
312
  # Préparer l'historique des messages PRÉCÉDENTS
313
  gemini_history = prepare_gemini_history(session['chat_history'][:-1]) # Exclut le message actuel
314
  print(f"Préparation de l'appel Gemini avec {len(gemini_history)} messages d'historique.")
 
315
  # Construire le contenu complet pour l'appel
316
  contents_for_gemini = gemini_history + [{'role': 'user', 'parts': current_gemini_parts}]
317
 
318
+ # Choisir le nom du modèle à utiliser
319
+ selected_model_name = MODEL_PRO if use_advanced else MODEL_FLASH
320
+ print(f"Utilisation du modèle Gemini: {selected_model_name}")
321
+
322
+ # Créer l'instance du modèle spécifique pour cette requête
323
+ # Réutiliser les paramètres globaux (safety, system instruction)
324
+ active_model = genai.GenerativeModel(
325
+ model_name=selected_model_name,
326
+ safety_settings=SAFETY_SETTINGS, # defined globally
327
+ system_instruction=SYSTEM_INSTRUCTION # defined globally
328
+ )
329
+
330
  # Appel API
331
+ print(f"Envoi de la requête à {selected_model_name}...")
332
  # Utilisation de generate_content en mode non-streamé
333
+ response = active_model.generate_content(contents_for_gemini)
334
  # print(response) # Décommenter pour voir la réponse brute de l'API
335
 
336
+ # Extraire le texte de la réponse (gestion d'erreur potentielle ici si la réponse est bloquée etc.)
337
+ # Gérer le cas où la réponse est bloquée par les safety settings
338
+ try:
339
+ response_text_raw = response.text
340
+ except ValueError:
341
+ # Si response.text échoue, la réponse a probablement été bloquée.
342
+ print("ERREUR: La réponse de Gemini a été bloquée (probablement par les safety settings).")
343
+ print(f"Détails du blocage : {response.prompt_feedback}")
344
+ # Vous pouvez décider quoi renvoyer au client ici.
345
+ # Soit une erreur spécifique, soit un message générique.
346
+ response_text_raw = "Désolé, ma réponse a été bloquée car elle pourrait enfreindre les règles de sécurité."
347
+ # Convertir ce message d'erreur en HTML aussi pour la cohérence
348
+ response_html = markdown.markdown(response_text_raw)
349
+
350
+ else:
351
+ # Si response.text réussit, continuer normalement
352
+ print(f"Réponse reçue de Gemini (brute, début): '{response_text_raw[:100]}...'")
353
+ # Convertir la réponse Markdown en HTML pour l'affichage
354
+ response_html = markdown.markdown(response_text_raw, extensions=['fenced_code', 'tables', 'nl2br'])
355
+ print("Réponse convertie en HTML.")
356
 
 
 
 
357
 
358
  # Ajouter la réponse de l'assistant à l'historique de session
359
  assistant_history_entry = {
 
372
  print(f"ERREUR Critique lors de l'appel à Gemini ou du traitement de la réponse : {e}")
373
  # En cas d'erreur, retirer le dernier message utilisateur de l'historique
374
  # pour éviter les boucles d'erreur si le message lui-même pose problème.
375
+ # Vérifier si l'historique n'est pas vide avant de pop
376
+ if session.get('chat_history'):
377
+ session['chat_history'].pop()
378
+ session.modified = True
379
+ print("Le dernier message utilisateur a été retiré de l'historique suite à l'erreur.")
380
+ else:
381
+ print("L'historique était déjà vide lors de l'erreur.")
382
+
383
  # Renvoyer une erreur générique mais informative
384
  return jsonify({'success': False, 'error': f"Une erreur interne est survenue lors de la génération de la réponse. Détails: {e}"}), 500
385
 
 
397
  def clear_chat():
398
  """Efface l'historique de chat dans la session."""
399
  session.pop('chat_history', None)
400
+ # session.pop('web_search', None) # On ne stocke pas ça en session
401
  print("API: Historique de chat effacé via /clear.")
402
 
403
  # Adapter la réponse selon si c'est une requête AJAX (fetch) ou une soumission classique
404
  # Vérification si la requête vient probablement de fetch (simple)
405
  is_ajax = 'XMLHttpRequest' == request.headers.get('X-Requested-With') or \
406
+ 'application/json' in request.headers.get('Accept', '') # Plus robuste
407
 
408
  if is_ajax:
409
  return jsonify({'success': True, 'message': 'Historique effacé.'})
 
419
  # Utiliser host='0.0.0.0' pour rendre accessible sur le réseau local
420
  # debug=True est pratique pour le développement, mais à désactiver en production !
421
  # Changer le port si nécessaire (ex: 5000, 5001, 8080)
422
+ # Utiliser un port différent si le port 5000 est déjà pris
423
+ port = int(os.environ.get('PORT', 5001))
424
+ app.run(debug=True, host='0.0.0.0', port=port)