Update app.py
Browse files
app.py
CHANGED
@@ -175,62 +175,90 @@ def root():
|
|
175 |
"""Sert la page HTML principale."""
|
176 |
return render_template('index.html')
|
177 |
|
178 |
-
|
179 |
@app.route('/api/history', methods=['GET'])
|
180 |
def get_history():
|
181 |
-
|
182 |
-
|
183 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
|
185 |
@app.route('/api/chat', methods=['POST'])
|
186 |
def chat_api():
|
|
|
|
|
|
|
|
|
|
|
187 |
# Récupération des données du formulaire
|
188 |
prompt = request.form.get('prompt', '').strip()
|
189 |
-
use_web_search_str = request.form.get('web_search', 'false')
|
190 |
use_web_search = use_web_search_str.lower() == 'true'
|
191 |
file = request.files.get('file')
|
192 |
-
use_advanced_str = request.form.get('advanced_reasoning', 'false')
|
193 |
use_advanced = use_advanced_str.lower() == 'true'
|
194 |
|
|
|
195 |
if not prompt and not file:
|
196 |
return jsonify({'success': False, 'error': 'Veuillez fournir un message ou un fichier.'}), 400
|
197 |
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
if
|
203 |
-
search_data = perform_web_search(raw_user_text)
|
204 |
-
if search_data:
|
205 |
-
formatted_results = format_search_results(search_data)
|
206 |
-
final_prompt_for_gemini = f"""Voici la question originale de l'utilisateur:
|
207 |
-
"{raw_user_text}"
|
208 |
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
--- FIN RESULTATS WEB ---
|
213 |
|
214 |
-
|
215 |
-
|
216 |
-
#
|
217 |
-
current_gemini_parts = [final_prompt_for_gemini]
|
218 |
-
# (Gestion de fichier si applicable...)
|
219 |
-
|
220 |
-
try:
|
221 |
-
# Appel à Gemini avec current_gemini_parts et sans historique précédent
|
222 |
-
active_model = genai.GenerativeModel(
|
223 |
-
model_name=MODEL_PRO if use_advanced else MODEL_FLASH,
|
224 |
-
safety_settings=SAFETY_SETTINGS,
|
225 |
-
system_instruction=SYSTEM_INSTRUCTION
|
226 |
-
)
|
227 |
-
response = active_model.generate_content(current_gemini_parts)
|
228 |
-
response_text_raw = response.text
|
229 |
-
response_html = markdown.markdown(response_text_raw, extensions=['fenced_code', 'tables', 'nl2br'])
|
230 |
-
return jsonify({'success': True, 'message': response_html})
|
231 |
-
except Exception as e:
|
232 |
-
return jsonify({'success': False, 'error': f"Erreur interne: {e}"}), 500
|
233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
|
235 |
# --- Préparation du message utilisateur pour l'historique et Gemini ---
|
236 |
# Texte brut pour Gemini (et pour l'historique interne)
|
|
|
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."""
|
181 |
+
if 'chat_history' not in session:
|
182 |
+
session['chat_history'] = []
|
183 |
+
|
184 |
+
# Préparer l'historique pour l'affichage (contient déjà le HTML pour l'assistant)
|
185 |
+
display_history = [
|
186 |
+
{'role': msg.get('role', 'unknown'), 'text': msg.get('text', '')}
|
187 |
+
for msg in session.get('chat_history', [])
|
188 |
+
]
|
189 |
+
print(f"API: Récupération de l'historique ({len(display_history)} messages)")
|
190 |
+
return jsonify({'success': True, 'history': display_history})
|
191 |
|
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:
|
209 |
return jsonify({'success': False, 'error': 'Veuillez fournir un message ou un fichier.'}), 400
|
210 |
|
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
|
218 |
+
if 'chat_history' not in session:
|
219 |
+
session['chat_history'] = []
|
|
|
220 |
|
221 |
+
uploaded_gemini_file = None # L'objet fichier retourné par genai.upload_file
|
222 |
+
uploaded_filename = None # Juste le nom du fichier pour référence/affichage
|
223 |
+
filepath_to_delete = None # Chemin du fichier local à supprimer après traitement
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
|
225 |
+
# --- Gestion de l'upload de fichier ---
|
226 |
+
if file and file.filename != '':
|
227 |
+
if allowed_file(file.filename):
|
228 |
+
try:
|
229 |
+
filename = secure_filename(file.filename)
|
230 |
+
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
231 |
+
file.save(filepath)
|
232 |
+
filepath_to_delete = filepath # Marquer pour suppression
|
233 |
+
uploaded_filename = filename
|
234 |
+
print(f"Fichier '{filename}' sauvegardé temporairement dans '{filepath}'")
|
235 |
+
|
236 |
+
# Détecter le MimeType pour Gemini
|
237 |
+
mime_type = mimetypes.guess_type(filepath)[0]
|
238 |
+
if not mime_type:
|
239 |
+
mime_type = 'application/octet-stream' # Fallback
|
240 |
+
print(f"AVERTISSEMENT: Impossible de deviner le MimeType pour '{filename}', utilisation de '{mime_type}'.")
|
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 |
+
|
248 |
+
except Exception as e:
|
249 |
+
print(f"ERREUR Critique lors du traitement/upload du fichier '{filename}': {e}")
|
250 |
+
# Supprimer le fichier local même en cas d'erreur d'upload Gemini
|
251 |
+
if filepath_to_delete and os.path.exists(filepath_to_delete):
|
252 |
+
try:
|
253 |
+
os.remove(filepath_to_delete)
|
254 |
+
print(f"Fichier temporaire '{filepath_to_delete}' supprimé après erreur.")
|
255 |
+
except OSError as del_e:
|
256 |
+
print(f"Erreur lors de la suppression du fichier temporaire après erreur: {del_e}")
|
257 |
+
# Renvoyer une erreur claire au client
|
258 |
+
return jsonify({'success': False, 'error': f"Erreur lors du traitement du fichier: {e}"}), 500
|
259 |
+
else:
|
260 |
+
print(f"ERREUR: Type de fichier non autorisé: {file.filename}")
|
261 |
+
return jsonify({'success': False, 'error': f"Type de fichier non autorisé. Extensions permises: {', '.join(ALLOWED_EXTENSIONS)}"}), 400
|
262 |
|
263 |
# --- Préparation du message utilisateur pour l'historique et Gemini ---
|
264 |
# Texte brut pour Gemini (et pour l'historique interne)
|